From 66721ba8c04a129fbd121876294fec3b670c29fe Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 3 Feb 2012 16:17:37 +0200 Subject: [PATCH] more tests --- cmd/loader/kyoto/kyoto_loader.go | 40 +++++------ timespans/calldesc.go | 75 ++++++++++--------- timespans/calldesc_test.go | 49 ++++++++----- timespans/interval_test.go | 120 +++++++++++++++---------------- timespans/intervals.go | 107 ++++++++++++++------------- timespans/kyoto_storage.go | 4 +- timespans/redis_storage.go | 6 +- timespans/timespans.go | 6 +- timespans/timespans_test.go | 34 +++++++-- 9 files changed, 246 insertions(+), 195 deletions(-) diff --git a/cmd/loader/kyoto/kyoto_loader.go b/cmd/loader/kyoto/kyoto_loader.go index 25b0368c9..e59fcd6a2 100644 --- a/cmd/loader/kyoto/kyoto_loader.go +++ b/cmd/loader/kyoto/kyoto_loader.go @@ -1,11 +1,11 @@ package main import ( + "flag" "fmt" "github.com/fsouza/gokabinet/kc" - "flag" - "time" "github.com/rif/cgrates/timespans" + "time" ) var ( @@ -15,33 +15,33 @@ var ( func main() { flag.Parse() db, _ := kc.Open(*filename, kc.WRITE) - defer db.Close() + defer db.Close() t1 := time.Date(2012, time.January, 1, 0, 0, 0, 0, time.UTC) cd1 := ×pans.CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256"} - ap1 := ×pans.ActivationPeriod{ActivationTime: t1} + ap1 := ×pans.ActivationPeriod{ActivationTime: t1} ap1.AddInterval(×pans.Interval{ - WeekDays: []time.Weekday{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday}, - EndTime:"18:00:00", - ConnectFee: 0, - Price: 0.2, + WeekDays: []time.Weekday{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday}, + EndTime: "18:00:00", + ConnectFee: 0, + Price: 0.2, BillingUnit: 1.0}) ap1.AddInterval(×pans.Interval{ - WeekDays: []time.Weekday{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday}, - StartTime:"18:00:00", - ConnectFee: 0, - Price: 0.1, - BillingUnit: 1.0}) + WeekDays: []time.Weekday{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday}, + StartTime: "18:00:00", + ConnectFee: 0, + Price: 0.1, + BillingUnit: 1.0}) ap1.AddInterval(×pans.Interval{ - WeekDays: []time.Weekday{time.Saturday, time.Sunday}, - ConnectFee: 0, - Price: 0.1, + WeekDays: []time.Weekday{time.Saturday, time.Sunday}, + ConnectFee: 0, + Price: 0.1, BillingUnit: 1.0}) cd1.AddActivationPeriod(ap1) - key := cd1.GetKey() + key := cd1.GetKey() value := cd1.EncodeValues() - - db.Set(key, string(value)) - fmt.Println("Done!") + + db.Set(key, string(value)) + fmt.Println("Done!") } diff --git a/timespans/calldesc.go b/timespans/calldesc.go index d9a9215c3..55f564bab 100644 --- a/timespans/calldesc.go +++ b/timespans/calldesc.go @@ -1,42 +1,50 @@ package timespans -import ("time"; "encoding/json"; "fmt"; "log") +import ( + "encoding/json" + "fmt" + "log" + "time" +) /* The output structure that will be returned with the call cost information. */ type CallCost struct { - TOR int + TOR int CstmId, Subject, DestinationPrefix string - Cost, ConnectFee float64 -// ratesInfo *RatingProfile + Cost, ConnectFee float64 + // ratesInfo *RatingProfile } +/* +The struture that is saved to storage. +*/ type ActivationPeriod struct { ActivationTime time.Time - Intervals []*Interval + Intervals []*Interval } -func (ap *ActivationPeriod) AddInterval( is ...*Interval) { +func (ap *ActivationPeriod) AddInterval(is ...*Interval) { for _, i := range is { ap.Intervals = append(ap.Intervals, i) - } + } } /* The input stucture that contains call information. */ type CallDescriptor struct { - TOR int + TOR int CstmId, Subject, DestinationPrefix string - TimeStart, TimeEnd time.Time - ActivationPeriods []*ActivationPeriod + TimeStart, TimeEnd time.Time + ActivationPeriods []*ActivationPeriod } -func (cd *CallDescriptor) AddActivationPeriod(aps ...*ActivationPeriod) { +func (cd *CallDescriptor) AddActivationPeriod(aps ...*ActivationPeriod) { for _, ap := range aps { cd.ActivationPeriods = append(cd.ActivationPeriods, ap) - } + } } func (cd *CallDescriptor) EncodeValues() []byte { @@ -55,50 +63,50 @@ func (cd *CallDescriptor) decodeValues(v []byte) { err := json.Unmarshal(v, &cd.ActivationPeriods) if err != nil { log.Print("Cannot decode intervals: ", err) - } + } } -func (cd *CallDescriptor) getActiveIntervals() (is []*Interval) { +func (cd *CallDescriptor) getActiveIntervals() (is []*Interval) { now := time.Now() // add a second in the future to be able to pick the active timestamp // from the very second it becomes active - sec,_ := time.ParseDuration("1s") - now.Add(sec) + sec, _ := time.ParseDuration("1s") + now.Add(sec) bestTime := time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC) for _, ap := range cd.ActivationPeriods { t := ap.ActivationTime if t.After(bestTime) && t.Before(now) { bestTime = t is = ap.Intervals - } + } } - return + return } func (cd *CallDescriptor) splitInTimeSpans(intervals []*Interval) (timespans []*TimeSpan) { ts1 := &TimeSpan{TimeStart: cd.TimeStart, TimeEnd: cd.TimeEnd} - timespans = append(timespans, ts1) + timespans = append(timespans, ts1) for _, interval := range intervals { - for _, ts := range timespans { - newTs := interval.Split(ts) - if newTs != nil { + for _, ts := range timespans { + newTs := interval.Split(ts) + if newTs != nil { timespans = append(timespans, newTs) break } } - } + } return } /* -*/ -func (cd *CallDescriptor) GetCost(sg StorageGetter) (result *CallCost, err error) { - + */ +func (cd *CallDescriptor) GetCost(sg StorageGetter) (result *CallCost, err error) { + key := cd.GetKey() values, err := sg.Get(key) - + cd.decodeValues([]byte(values)) - + intervals := cd.getActiveIntervals() timespans := cd.splitInTimeSpans(intervals) @@ -107,11 +115,10 @@ func (cd *CallDescriptor) GetCost(sg StorageGetter) (result *CallCost, err error cost += ts.GetCost() } cc := &CallCost{TOR: cd.TOR, - CstmId: cd.CstmId, - Subject: cd.Subject, - DestinationPrefix: cd.DestinationPrefix, - Cost: cost, - ConnectFee: timespans[0].Interval.ConnectFee} + CstmId: cd.CstmId, + Subject: cd.Subject, + DestinationPrefix: cd.DestinationPrefix, + Cost: cost, + ConnectFee: timespans[0].Interval.ConnectFee} return cc, err } - diff --git a/timespans/calldesc_test.go b/timespans/calldesc_test.go index 5d30af7df..a3ebf55f1 100644 --- a/timespans/calldesc_test.go +++ b/timespans/calldesc_test.go @@ -1,53 +1,68 @@ package timespans import ( - "testing" - "time" + "testing" + "time" ) -func TestSplitSpans(t *testing.T){ +func TestSplitSpans(t *testing.T) { getter, _ := NewKyotoStorage("test.kch") defer getter.Close() - + t1 := time.Date(2012, time.February, 02, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 02, 18, 30, 0, 0, time.UTC) cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2} key := cd.GetKey() values, _ := getter.Get(key) - + cd.decodeValues([]byte(values)) - + intervals := cd.getActiveIntervals() timespans := cd.splitInTimeSpans(intervals) if len(timespans) != 2 { t.Error("Wrong number of timespans: ", len(timespans)) - } + } } -func ATestGetCost(t *testing.T){ +func ATestGetCost(t *testing.T) { getter, _ := NewKyotoStorage("test.kch") defer getter.Close() - + t1 := time.Date(2012, time.February, 02, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 02, 18, 30, 0, 0, time.UTC) cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2} - result,_ := cd.GetCost(getter) + result, _ := cd.GetCost(getter) expected := &CallCost{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", Cost: 360, ConnectFee: 0} if *result != *expected { - t.Errorf("Expected %v was %v", expected, result) - } + t.Errorf("Expected %v was %v", expected, result) + } } -func BenchmarkGetCost(b *testing.B) { +func BenchmarkGetCost(b *testing.B) { b.StopTimer() getter, _ := NewKyotoStorage("test.kch") defer getter.Close() - + t1 := time.Date(2012, time.February, 02, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 02, 18, 30, 0, 0, time.UTC) cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2} b.StartTimer() - for i := 0; i < b.N; i++ { - cd.GetCost(getter) - } + for i := 0; i < b.N; i++ { + cd.GetCost(getter) + } } + +func BenchmarkDecoding(b *testing.B) { + b.StopTimer() + getter, _ := NewKyotoStorage("test.kch") + defer getter.Close() + + cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256"} + key := cd.GetKey() + values, _ := getter.Get(key) + + b.StartTimer() + for i := 0; i < b.N; i++ { + cd.decodeValues([]byte(values)) + } +} \ No newline at end of file diff --git a/timespans/interval_test.go b/timespans/interval_test.go index 763a0df87..bd039adea 100644 --- a/timespans/interval_test.go +++ b/timespans/interval_test.go @@ -1,89 +1,89 @@ package timespans import ( - "time" "testing" + "time" ) -func TestMonth(t *testing.T){ +func TestMonth(t *testing.T) { i := &Interval{Month: time.February} d := time.Date(2012, time.February, 10, 23, 0, 0, 0, time.UTC) d1 := time.Date(2012, time.January, 10, 23, 0, 0, 0, time.UTC) if !i.Contains(d) { t.Errorf("Date %v shoud be in interval %v", d, i) - } + } if i.Contains(d1) { t.Errorf("Date %v shoud not be in interval %v", d1, i) - } + } } -func TestMonthDay(t *testing.T){ +func TestMonthDay(t *testing.T) { i := &Interval{MonthDay: 10} d := time.Date(2012, time.February, 10, 23, 0, 0, 0, time.UTC) d1 := time.Date(2012, time.February, 11, 23, 0, 0, 0, time.UTC) if !i.Contains(d) { t.Errorf("Date %v shoud be in interval %v", d, i) - } + } if i.Contains(d1) { t.Errorf("Date %v shoud not be in interval %v", d1, i) - } + } } -func TestMonthAndMonthDay(t *testing.T){ +func TestMonthAndMonthDay(t *testing.T) { i := &Interval{Month: time.February, MonthDay: 10} d := time.Date(2012, time.February, 10, 23, 0, 0, 0, time.UTC) d1 := time.Date(2012, time.February, 11, 23, 0, 0, 0, time.UTC) d2 := time.Date(2012, time.January, 10, 23, 0, 0, 0, time.UTC) if !i.Contains(d) { t.Errorf("Date %v shoud be in interval %v", d, i) - } + } if i.Contains(d1) { t.Errorf("Date %v shoud not be in interval %v", d1, i) - } + } if i.Contains(d2) { t.Errorf("Date %v shoud not be in interval %v", d2, i) - } + } } -func TestWeekDays(t *testing.T){ +func TestWeekDays(t *testing.T) { i := &Interval{WeekDays: []time.Weekday{time.Wednesday}} i2 := &Interval{WeekDays: []time.Weekday{time.Wednesday, time.Thursday}} d := time.Date(2012, time.February, 1, 23, 0, 0, 0, time.UTC) d1 := time.Date(2012, time.February, 2, 23, 0, 0, 0, time.UTC) if !i.Contains(d) { t.Errorf("Date %v shoud be in interval %v", d, i) - } + } if i.Contains(d1) { t.Errorf("Date %v shoud not be in interval %v", d1, i) - } + } if !i2.Contains(d) { t.Errorf("Date %v shoud be in interval %v", d, i2) - } + } if !i2.Contains(d1) { t.Errorf("Date %v shoud be in interval %v", d1, i2) - } + } } -func TestMonthAndMonthDayAndWeekDays(t *testing.T){ +func TestMonthAndMonthDayAndWeekDays(t *testing.T) { i := &Interval{Month: time.February, MonthDay: 1, WeekDays: []time.Weekday{time.Wednesday}} i2 := &Interval{Month: time.February, MonthDay: 2, WeekDays: []time.Weekday{time.Wednesday, time.Thursday}} d := time.Date(2012, time.February, 1, 23, 0, 0, 0, time.UTC) d1 := time.Date(2012, time.February, 2, 23, 0, 0, 0, time.UTC) if !i.Contains(d) { t.Errorf("Date %v shoud be in interval %v", d, i) - } + } if i.Contains(d1) { t.Errorf("Date %v shoud not be in interval %v", d1, i) - } + } if i2.Contains(d) { t.Errorf("Date %v shoud be in interval %v", d, i2) - } + } if !i2.Contains(d1) { t.Errorf("Date %v shoud be in interval %v", d1, i2) - } + } } -func TestHours(t *testing.T){ +func TestHours(t *testing.T) { i := &Interval{StartTime: "14:30:00", EndTime: "15:00:00"} d := time.Date(2012, time.February, 10, 14, 30, 1, 0, time.UTC) d1 := time.Date(2012, time.January, 10, 14, 29, 0, 0, time.UTC) @@ -91,43 +91,43 @@ func TestHours(t *testing.T){ d3 := time.Date(2012, time.January, 10, 15, 01, 0, 0, time.UTC) if !i.Contains(d) { t.Errorf("Date %v shoud be in interval %v", d, i) - } + } if i.Contains(d1) { t.Errorf("Date %v shoud not be in interval %v", d1, i) - } + } if !i.Contains(d2) { t.Errorf("Date %v shoud be in interval %v", d2, i) - } + } if i.Contains(d3) { t.Errorf("Date %v shoud not be in interval %v", d3, i) - } + } } -func TestEverything(t *testing.T){ +func TestEverything(t *testing.T) { i := &Interval{Month: time.February, - MonthDay: 1, - WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, - StartTime: "14:30:00", - EndTime: "15:00:00"} + MonthDay: 1, + WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, + StartTime: "14:30:00", + EndTime: "15:00:00"} d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) d1 := time.Date(2012, time.February, 1, 14, 29, 1, 0, time.UTC) d2 := time.Date(2012, time.February, 1, 15, 00, 00, 0, time.UTC) d3 := time.Date(2012, time.February, 1, 15, 0, 1, 0, time.UTC) if !i.Contains(d) { t.Errorf("Date %v shoud be in interval %v", d, i) - } + } if i.Contains(d1) { t.Errorf("Date %v shoud not be in interval %v", d1, i) - } + } if !i.Contains(d2) { t.Errorf("Date %v shoud be in interval %v", d2, i) - } + } if i.Contains(d3) { t.Errorf("Date %v shoud not be in interval %v", d3, i) } } -func TestRightMargin(t *testing.T){ +func TestRightMargin(t *testing.T) { i := &Interval{WeekDays: []time.Weekday{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday}} t1 := time.Date(2012, time.February, 3, 23, 45, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 4, 0, 10, 0, 0, time.UTC) @@ -144,22 +144,22 @@ func TestRightMargin(t *testing.T){ t.Error("Interval not attached correctly") } - if ts.GetDuration().Seconds() != 15 * 60 - 1 || nts.GetDuration().Seconds() != 10 * 60 + 1 { + if ts.GetDuration().Seconds() != 15*60-1 || nts.GetDuration().Seconds() != 10*60+1 { t.Error("Wrong durations.for Intervals", ts.GetDuration().Seconds(), ts.GetDuration().Seconds()) } - if ts.GetDuration().Seconds() + nts.GetDuration().Seconds() != oldDuration.Seconds() { + if ts.GetDuration().Seconds()+nts.GetDuration().Seconds() != oldDuration.Seconds() { t.Errorf("The duration has changed: %v + %v != %v", ts.GetDuration().Seconds(), nts.GetDuration().Seconds(), oldDuration.Seconds()) } } -func TestRightHourMargin(t *testing.T){ +func TestRightHourMargin(t *testing.T) { i := &Interval{WeekDays: []time.Weekday{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday}, EndTime: "17:59:00"} t1 := time.Date(2012, time.February, 3, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 3, 18, 00, 0, 0, time.UTC) ts := &TimeSpan{TimeStart: t1, TimeEnd: t2} oldDuration := ts.GetDuration() - nts := i.Split(ts) + nts := i.Split(ts) if ts.TimeStart != t1 || ts.TimeEnd != time.Date(2012, time.February, 3, 17, 59, 00, 0, time.UTC) { t.Error("Incorrect first half", ts) } @@ -170,21 +170,21 @@ func TestRightHourMargin(t *testing.T){ t.Error("Interval not attached correctly") } - if ts.GetDuration().Seconds() != 29 * 60 || nts.GetDuration().Seconds() != 1 * 60 { + if ts.GetDuration().Seconds() != 29*60 || nts.GetDuration().Seconds() != 1*60 { t.Error("Wrong durations.for Intervals", ts.GetDuration().Seconds(), nts.GetDuration().Seconds()) } - if ts.GetDuration().Seconds() + nts.GetDuration().Seconds() != oldDuration.Seconds() { + if ts.GetDuration().Seconds()+nts.GetDuration().Seconds() != oldDuration.Seconds() { t.Errorf("The duration has changed: %v + %v != %v", ts.GetDuration().Seconds(), nts.GetDuration().Seconds(), oldDuration.Seconds()) } } -func TestLeftMargin(t *testing.T){ +func TestLeftMargin(t *testing.T) { i := &Interval{WeekDays: []time.Weekday{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday}} t1 := time.Date(2012, time.February, 5, 23, 45, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 6, 0, 10, 0, 0, time.UTC) ts := &TimeSpan{TimeStart: t1, TimeEnd: t2} oldDuration := ts.GetDuration() - nts := i.Split(ts) + nts := i.Split(ts) if ts.TimeStart != t1 || ts.TimeEnd != time.Date(2012, time.February, 6, 0, 0, 0, 0, time.UTC) { t.Error("Incorrect first half", ts) } @@ -194,21 +194,21 @@ func TestLeftMargin(t *testing.T){ if nts.Interval != i { t.Error("Interval not attached correctly") } - if ts.GetDuration().Seconds() != 15 * 60 || nts.GetDuration().Seconds() != 10 * 60 { + if ts.GetDuration().Seconds() != 15*60 || nts.GetDuration().Seconds() != 10*60 { t.Error("Wrong durations.for Intervals", ts.GetDuration().Seconds(), nts.GetDuration().Seconds()) } - if ts.GetDuration().Seconds() + nts.GetDuration().Seconds() != oldDuration.Seconds() { + if ts.GetDuration().Seconds()+nts.GetDuration().Seconds() != oldDuration.Seconds() { t.Errorf("The duration has changed: %v + %v != %v", ts.GetDuration().Seconds(), nts.GetDuration().Seconds(), oldDuration.Seconds()) } } -func TestLeftHourMargin(t *testing.T){ +func TestLeftHourMargin(t *testing.T) { i := &Interval{Month: time.December, MonthDay: 1, StartTime: "09:00:00"} t1 := time.Date(2012, time.December, 1, 8, 45, 0, 0, time.UTC) t2 := time.Date(2012, time.December, 1, 9, 20, 0, 0, time.UTC) ts := &TimeSpan{TimeStart: t1, TimeEnd: t2} oldDuration := ts.GetDuration() - nts := i.Split(ts) + nts := i.Split(ts) if ts.TimeStart != t1 || ts.TimeEnd != time.Date(2012, time.December, 1, 9, 0, 0, 0, time.UTC) { t.Error("Incorrect first half", ts) } @@ -218,43 +218,43 @@ func TestLeftHourMargin(t *testing.T){ if nts.Interval != i { t.Error("Interval not attached correctly") } - if ts.GetDuration().Seconds() != 15 * 60 || nts.GetDuration().Seconds() != 20 * 60 { + if ts.GetDuration().Seconds() != 15*60 || nts.GetDuration().Seconds() != 20*60 { t.Error("Wrong durations.for Intervals", ts.GetDuration().Seconds(), nts.GetDuration().Seconds()) } - if ts.GetDuration().Seconds() + nts.GetDuration().Seconds() != oldDuration.Seconds() { + if ts.GetDuration().Seconds()+nts.GetDuration().Seconds() != oldDuration.Seconds() { t.Errorf("The duration has changed: %v + %v != %v", ts.GetDuration().Seconds(), nts.GetDuration().Seconds(), oldDuration.Seconds()) } } -func TestEnclosingMargin(t *testing.T){ +func TestEnclosingMargin(t *testing.T) { i := &Interval{WeekDays: []time.Weekday{time.Sunday}} t1 := time.Date(2012, time.February, 5, 17, 45, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 5, 18, 10, 0, 0, time.UTC) ts := &TimeSpan{TimeStart: t1, TimeEnd: t2} - nts := i.Split(ts) - if ts.TimeStart != t1 || ts.TimeEnd != t2 || nts != nil{ + nts := i.Split(ts) + if ts.TimeStart != t1 || ts.TimeEnd != t2 || nts != nil { t.Error("Incorrect enclosing", ts) - } + } if ts.Interval != i { t.Error("Interval not attached correctly") } } -func TestOutsideMargin(t *testing.T){ +func TestOutsideMargin(t *testing.T) { i := &Interval{WeekDays: []time.Weekday{time.Monday}} t1 := time.Date(2012, time.February, 5, 17, 45, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 5, 18, 10, 0, 0, time.UTC) ts := &TimeSpan{TimeStart: t1, TimeEnd: t2} - result := i.Split(ts) + result := i.Split(ts) if result != nil { t.Error("Interval not split correctly") } } func BenchmarkIntervalFull(b *testing.B) { - i := &Interval{Month: time.February, MonthDay: 1, WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, StartTime: "14:30:00", EndTime: "15:00"} + i := &Interval{Month: time.February, MonthDay: 1, WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, StartTime: "14:30:00", EndTime: "15:00:00"} d := time.Date(2012, time.February, 1, 14, 30, 0, 0, time.UTC) - for x := 0; x < b.N; x++ { - i.Contains(d) - } -} \ No newline at end of file + for x := 0; x < b.N; x++ { + i.Contains(d) + } +} diff --git a/timespans/intervals.go b/timespans/intervals.go index a5a9ce389..95922d457 100644 --- a/timespans/intervals.go +++ b/timespans/intervals.go @@ -1,19 +1,19 @@ package timespans import ( - "time" - "strings" "strconv" + "strings" + "time" ) /* Defines a time interval for which a certain set of prices will apply */ type Interval struct { - Month time.Month - MonthDay int - WeekDays []time.Weekday - StartTime, EndTime string // ##:##:## format + Month time.Month + MonthDay int + WeekDays []time.Weekday + StartTime, EndTime string // ##:##:## format Ponder, ConnectFee, Price, BillingUnit float64 } @@ -22,33 +22,33 @@ Returns true if the received time is inside the interval */ func (i *Interval) Contains(t time.Time) bool { // chec for month - if i.Month > 0 && t.Month() != i.Month { + if i.Month > 0 && t.Month() != i.Month { return false - } + } // check for month day - if i.MonthDay > 0 && t.Day() != i.MonthDay { + if i.MonthDay > 0 && t.Day() != i.MonthDay { return false } // check for weekdays found := false - for _,wd := range i.WeekDays { + for _, wd := range i.WeekDays { if t.Weekday() == wd { found = true - } - } + } + } if len(i.WeekDays) > 0 && !found { - return false + return false } // check for start hour if i.StartTime != "" { - split:= strings.Split(i.StartTime, ":") + split := strings.Split(i.StartTime, ":") sh, _ := strconv.Atoi(split[0]) sm, _ := strconv.Atoi(split[1]) ss, _ := strconv.Atoi(split[2]) // if the hour is before or is the same hour but the minute is before if t.Hour() < sh || (t.Hour() == sh && t.Minute() < sm) || - (t.Hour() == sh && t.Minute() == sm && t.Second() < ss) { + (t.Hour() == sh && t.Minute() == sm && t.Second() < ss) { return false } } @@ -60,9 +60,9 @@ func (i *Interval) Contains(t time.Time) bool { es, _ := strconv.Atoi(split[2]) // if the hour is after or is the same hour but the minute is after if t.Hour() > eh || - (t.Hour() == eh && t.Minute() > em) || - (t.Hour() == eh && t.Minute() == em && t.Second() > es) { - return false + (t.Hour() == eh && t.Minute() > em) || + (t.Hour() == eh && t.Minute() == em && t.Second() > es) { + return false } } return true @@ -78,24 +78,28 @@ func (i *Interval) ContainsSpan(t *TimeSpan) bool { /* Returns true if the timespan is fully enclosed in the interval */ -func (i *Interval) ContainsFullSpan(ts *TimeSpan) bool { +func (i *Interval) ContainsFullSpan(ts *TimeSpan) bool { return i.Contains(ts.TimeStart) && i.Contains(ts.TimeEnd) } /* Returns a time object that represents the end of the interval realtive to the received time */ -func (i *Interval) getRightMargin(t time.Time) (rigthtTime time.Time){ - year, month, day := t.Year(), t.Month(), t.Day() - hour, min, sec, nsec := 23,59,59,0 - loc := t.Location() - if i.Month > 0 { month = i.Month } - if i.MonthDay > 0 { day = i.MonthDay } +func (i *Interval) getRightMargin(t time.Time) (rigthtTime time.Time) { + year, month, day := t.Year(), t.Month(), t.Day() + hour, min, sec, nsec := 23, 59, 59, 0 + loc := t.Location() + if i.Month > 0 { + month = i.Month + } + if i.MonthDay > 0 { + day = i.MonthDay + } if i.EndTime != "" { split := strings.Split(i.EndTime, ":") hour, _ = strconv.Atoi(split[0]) min, _ = strconv.Atoi(split[1]) - sec,_ = strconv.Atoi(split[2]) + sec, _ = strconv.Atoi(split[2]) } return time.Date(year, month, day, hour, min, sec, nsec, loc) } @@ -103,12 +107,16 @@ func (i *Interval) getRightMargin(t time.Time) (rigthtTime time.Time){ /* Returns a time object that represents the start of the interval realtive to the received time */ -func (i *Interval) getLeftMargin(t time.Time) (rigthtTime time.Time){ - year, month, day := t.Year(), t.Month(), t.Day() - hour, min, sec, nsec := 0,0,0,0 - loc := t.Location() - if i.Month > 0 { month = i.Month } - if i.MonthDay > 0 { day = i.MonthDay } +func (i *Interval) getLeftMargin(t time.Time) (rigthtTime time.Time) { + year, month, day := t.Year(), t.Month(), t.Day() + hour, min, sec, nsec := 0, 0, 0, 0 + loc := t.Location() + if i.Month > 0 { + month = i.Month + } + if i.MonthDay > 0 { + day = i.MonthDay + } if i.StartTime != "" { split := strings.Split(i.StartTime, ":") hour, _ = strconv.Atoi(split[0]) @@ -126,41 +134,40 @@ The interval will attach itself to the timespan that overlaps the interval. */ func (i *Interval) Split(ts *TimeSpan) (nts *TimeSpan) { // if the span is not in interval return nil - if !i.ContainsSpan(ts) { + if !i.ContainsSpan(ts) { return } // if the span is enclosed in the interval try to set as new interval and return nil - if i.ContainsFullSpan(ts){ - ts.SetInterval(i) + if i.ContainsFullSpan(ts) { + ts.SetInterval(i) return } // if only the start time is in the interval split he interval - if i.Contains(ts.TimeStart){ - splitTime := i.getRightMargin(ts.TimeStart) - ts.SetInterval(i) - if splitTime == ts.TimeEnd { + if i.Contains(ts.TimeStart) { + splitTime := i.getRightMargin(ts.TimeStart) + ts.SetInterval(i) + if splitTime == ts.TimeStart { return } oldTimeEnd := ts.TimeEnd - ts.TimeEnd = splitTime - - nts = &TimeSpan{TimeStart: splitTime, TimeEnd: oldTimeEnd} + ts.TimeEnd = splitTime + + nts = &TimeSpan{TimeStart: splitTime, TimeEnd: oldTimeEnd} return } // if only the end time is in the interval split the interval - if i.Contains(ts.TimeEnd){ - splitTime := i.getLeftMargin(ts.TimeEnd) - if splitTime == ts.TimeEnd { + if i.Contains(ts.TimeEnd) { + splitTime := i.getLeftMargin(ts.TimeEnd) + if splitTime == ts.TimeEnd { ts.SetInterval(i) - return + return } oldTimeEnd := ts.TimeEnd - ts.TimeEnd = splitTime + ts.TimeEnd = splitTime - nts = &TimeSpan{TimeStart: splitTime, TimeEnd: oldTimeEnd} + nts = &TimeSpan{TimeStart: splitTime, TimeEnd: oldTimeEnd} nts.SetInterval(i) return } - return + return } - diff --git a/timespans/kyoto_storage.go b/timespans/kyoto_storage.go index e9faad555..ff5517292 100644 --- a/timespans/kyoto_storage.go +++ b/timespans/kyoto_storage.go @@ -12,10 +12,9 @@ type KyotoStorage struct { func NewKyotoStorage(filaName string) (*KyotoStorage, error) { ndb, err := kc.Open(filaName, kc.READ) //log.Print("Starting kyoto storage") - return &KyotoStorage{db: ndb}, err + return &KyotoStorage{db: ndb}, err } - func (ks *KyotoStorage) Close() { //log.Print("Closing kyoto storage") ks.db.Close() @@ -24,4 +23,3 @@ func (ks *KyotoStorage) Close() { func (ks *KyotoStorage) Get(key string) (value string, err error) { return ks.db.Get(key) } - diff --git a/timespans/redis_storage.go b/timespans/redis_storage.go index ab72be7af..68f02fa4e 100644 --- a/timespans/redis_storage.go +++ b/timespans/redis_storage.go @@ -1,8 +1,8 @@ package timespans import ( + "github.com/simonz05/godis" "log" - "github.com/simonz05/godis" ) type RedisStorage struct { @@ -10,12 +10,11 @@ type RedisStorage struct { } func NewRedisStorage(address string) (*RedisStorage, error) { - ndb:= godis.New(address, 10, "") + ndb := godis.New(address, 10, "") log.Print("Starting redis storage") return &RedisStorage{db: ndb}, nil } - func (rs *RedisStorage) Close() { log.Print("Closing redis storage") rs.db.Quit() @@ -25,4 +24,3 @@ func (rs *RedisStorage) Get(key string) (string, error) { elem, err := rs.db.Get(key) return elem.String(), err } - diff --git a/timespans/timespans.go b/timespans/timespans.go index f806fe773..188657772 100644 --- a/timespans/timespans.go +++ b/timespans/timespans.go @@ -1,7 +1,7 @@ package timespans import ( - "time" + "time" ) /* @@ -9,7 +9,7 @@ A unit in which a call will be split that has a specific price related interval */ type TimeSpan struct { TimeStart, TimeEnd time.Time - Interval *Interval + Interval *Interval } /* @@ -46,3 +46,5 @@ func (ts *TimeSpan) SetInterval(i *Interval) { ts.Interval = i } } + + diff --git a/timespans/timespans_test.go b/timespans/timespans_test.go index 62e043914..4ef7f7ea0 100644 --- a/timespans/timespans_test.go +++ b/timespans/timespans_test.go @@ -1,14 +1,38 @@ package timespans import ( - //"time" + "time" "testing" ) -func TestStorageEncoding(t *testing.T){ +func TestGetCost(t *testing.T) { + t1 := time.Date(2012, time.February, 5, 17, 45, 0, 0, time.UTC) + t2 := time.Date(2012, time.February, 5, 17, 55, 0, 0, time.UTC) + ts1 := TimeSpan{TimeStart: t1, TimeEnd: t2} + if ts1.GetCost() != 0 { + t.Error("No interval and still kicking") + } + ts1.Interval = &Interval{Price: 1} + if ts1.GetCost() != 600 { + t.Error("Expected 10 got ", ts1.GetCost()) + } + ts1.Interval.BillingUnit = .1 + if ts1.GetCost() != 6000 { + t.Error("Expected 6000 got ", ts1.GetCost()) + } } -func BenchmarkDecoding(b *testing.B) { - for i := 0; i < b.N; i++ { - } +func TestSetInterval(t *testing.T) { + i1 := &Interval{Price: 1} + ts1 := TimeSpan{Interval: i1} + i2 := &Interval{Price: 2} + ts1.SetInterval(i2) + if ts1.Interval != i1 { + t.Error("Smaller price interval should win") + } + i2.Ponder = 1 + ts1.SetInterval(i2) + if ts1.Interval != i2 { + t.Error("Bigger ponder interval should win") + } } \ No newline at end of file