From 938f2fada066065c2f6eaeba9c673344b23ac8f7 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Mon, 23 Mar 2015 16:52:24 +0200 Subject: [PATCH] test for max cost strategy --- engine/account.go | 4 ++-- engine/balances.go | 46 +++++++++++++++++++++++++-------------- engine/calldesc.go | 5 +++-- engine/calldesc_test.go | 46 +++++++++++++++++++++++++++++++-------- engine/loader_csv_test.go | 18 ++++++++++----- engine/ratingplan.go | 1 - engine/timespans.go | 8 +++++-- 7 files changed, 90 insertions(+), 38 deletions(-) diff --git a/engine/account.go b/engine/account.go index 97e524d5d..3df7f04e4 100644 --- a/engine/account.go +++ b/engine/account.go @@ -256,7 +256,7 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo unitBalanceChecker = true generalBalanceChecker = true // check for max cost disconnect - if dryRun && cc.maxCostDisconect { + if dryRun && partCC.maxCostDisconect { // only return if we are in dry run (max call duration) return } @@ -294,7 +294,7 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo } moneyBalanceChecker = true generalBalanceChecker = true - if dryRun && cc.maxCostDisconect { + if dryRun && partCC.maxCostDisconect { // only return if we are in dry run (max call duration) return } diff --git a/engine/balances.go b/engine/balances.go index cec25e401..d3454d846 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -325,20 +325,26 @@ func (b *Balance) DebitUnits(cd *CallDescriptor, ub *Account, moneyBalances Bala } //log.Printf("TS: %+v", ts) maxCost, strategy := ts.RateInterval.GetMaxCost() - if strategy == utils.MAX_COST_DISCONNECT && cd.MaxCostSoFar >= maxCost { - // cat the entire current timespan - cc.maxCostDisconect = true - if dryRun { - cc.Timespans = cc.Timespans[:tsIndex] - return cc, nil - } - } for incIndex, inc := range ts.Increments { // debit minutes and money seconds := inc.Duration.Seconds() cost := inc.Cost //log.Printf("INC: %+v", inc) inc.paid = false + if strategy == utils.MAX_COST_DISCONNECT && cd.MaxCostSoFar >= maxCost { + // cat the entire current timespan + cc.maxCostDisconect = true + if dryRun { + if incIndex == 0 { + // cat the entire current timespan + cc.Timespans = cc.Timespans[:tsIndex] + } else { + ts.SplitByIncrement(incIndex) + cc.Timespans = cc.Timespans[:tsIndex+1] + } + return cc, nil + } + } if strategy == utils.MAX_COST_FREE && cd.MaxCostSoFar >= maxCost { cost, inc.Cost = 0.0, 0.0 inc.BalanceInfo.MoneyBalanceUuid = b.Uuid @@ -415,19 +421,27 @@ func (b *Balance) DebitMoney(cd *CallDescriptor, ub *Account, count bool, dryRun } //log.Printf("TS: %+v", ts) maxCost, strategy := ts.RateInterval.GetMaxCost() - if strategy == utils.MAX_COST_DISCONNECT && cd.MaxCostSoFar >= maxCost { - // cat the entire current timespan - cc.maxCostDisconect = true - if dryRun { - cc.Timespans = cc.Timespans[:tsIndex] - return cc, nil - } - } + //log.Printf("Timing: %+v", ts.RateInterval.Timing) + //log.Printf("Rate: %+v", ts.RateInterval.Rating) for incIndex, inc := range ts.Increments { // check standard subject tags //log.Printf("INC: %+v", inc) amount := inc.Cost inc.paid = false + if strategy == utils.MAX_COST_DISCONNECT && cd.MaxCostSoFar >= maxCost { + // cat the entire current timespan + cc.maxCostDisconect = true + if dryRun { + if incIndex == 0 { + // cat the entire current timespan + cc.Timespans = cc.Timespans[:tsIndex] + } else { + ts.SplitByIncrement(incIndex) + cc.Timespans = cc.Timespans[:tsIndex+1] + } + return cc, nil + } + } if strategy == utils.MAX_COST_FREE && cd.MaxCostSoFar >= maxCost { amount, inc.Cost = 0.0, 0.0 inc.BalanceInfo.MoneyBalanceUuid = b.Uuid diff --git a/engine/calldesc.go b/engine/calldesc.go index f2bb4960e..310742029 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -360,10 +360,10 @@ func (cd *CallDescriptor) splitInTimeSpans() (timespans []*TimeSpan) { } //Logger.Debug(fmt.Sprintf("After SplitByRateInterval: %+v", timespans)) - //log.Printf("After SplitByRateInterval: %+v", timespans) + //log.Printf("After SplitByRateInterval: %+v", timespans[0].RateInterval.Timing) timespans = cd.roundTimeSpansToIncrement(timespans) // Logger.Debug(fmt.Sprintf("After round: %+v", timespans)) - //log.Printf("After round: %+v", timespans) + //log.Printf("After round: %+v", timespans[0].RateInterval.Timing) return } @@ -417,6 +417,7 @@ func (cd *CallDescriptor) GetCost() (*CallCost, error) { for i, ts := range timespans { // only add connect fee if this is the first/only call cost request + //log.Printf("Interval: %+v", ts.RateInterval.Timing) if cd.LoopIndex == 0 && i == 0 && ts.RateInterval != nil { cost += ts.RateInterval.Rating.ConnectFee } diff --git a/engine/calldesc_test.go b/engine/calldesc_test.go index 0e47e5d35..e5ffef1fc 100644 --- a/engine/calldesc_test.go +++ b/engine/calldesc_test.go @@ -83,6 +83,13 @@ func populateDB() { }, }, } + max := &Account{ + Id: "*out:cgrates.org:max", + BalanceMap: map[string]BalanceChain{ + CREDIT + OUTBOUND: BalanceChain{ + &Balance{Value: 11, Weight: 20}, + }}, + } if accountingStorage != nil { accountingStorage.SetActions("TEST_ACTIONS", ats) accountingStorage.SetActions("TEST_ACTIONS_ORDER", ats1) @@ -90,6 +97,7 @@ func populateDB() { accountingStorage.SetAccount(minu) accountingStorage.SetAccount(minitsboy) accountingStorage.SetAccount(luna) + accountingStorage.SetAccount(max) } else { log.Fatal("Could not connect to db!") } @@ -355,8 +363,6 @@ func TestMaxSessionTimeWithMaxRate(t *testing.T) { } } -/* - func TestMaxSessionTimeWithMaxCost(t *testing.T) { ap, _ := accountingStorage.GetActionTimings("TOPUP10_AT") for _, at := range ap { @@ -366,20 +372,42 @@ func TestMaxSessionTimeWithMaxCost(t *testing.T) { Direction: "*out", Category: "call", Tenant: "cgrates.org", - Subject: "12345", - Account: "12345", - Destination: "447956", - TimeStart: time.Date(2014, 3, 4, 6, 0, 0, 0, time.UTC), - TimeEnd: time.Date(2014, 3, 4, 6, 1, 0, 0, time.UTC), + Subject: "max", + Account: "max", + Destination: "0723123113", + TimeStart: time.Date(2015, 3, 23, 6, 0, 0, 0, time.UTC), + TimeEnd: time.Date(2015, 3, 23, 6, 30, 0, 0, time.UTC), MaxCostSoFar: 0, } result, err := cd.GetMaxSessionDuration() - expected := 45 * time.Second + expected := 10 * time.Second + if result != expected || err != nil { + t.Errorf("Expected %v was %v", expected, result) + } +} + +func TestMaxSessionTimeWithMaxCostFree(t *testing.T) { + ap, _ := accountingStorage.GetActionTimings("TOPUP10_AT") + for _, at := range ap { + at.Execute() + } + cd := &CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "max", + Account: "max", + Destination: "0723123113", + TimeStart: time.Date(2015, 3, 23, 19, 0, 0, 0, time.UTC), + TimeEnd: time.Date(2015, 3, 23, 19, 30, 0, 0, time.UTC), + MaxCostSoFar: 0, + } + result, err := cd.GetMaxSessionDuration() + expected := 30 * time.Minute if result != expected || err != nil { t.Errorf("Expected %v was %v", expected, result) } } -*/ func TestMaxSessionTimeWithAccountAlias(t *testing.T) { cd := &CallDescriptor{ diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 5c0901c01..4933b4a14 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -68,6 +68,7 @@ GBP_70,0.000000,1,1,1,0 RT_UK_Mobile_BIG5_PKG,0.01,0,20s,20s,0s RT_UK_Mobile_BIG5,0.01,0.10,1s,1s,0s R_URG,0,0,1,1,0 +MX,0,1,1s,1s,0 ` destinationRates = ` RT_STANDARD,GERMANY,R1,*middle,4,0, @@ -86,6 +87,8 @@ DR_UK_Mobile_BIG5_PKG,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5_PKG,*middle,4,0, DR_UK_Mobile_BIG5,DST_UK_Mobile_BIG5,RT_UK_Mobile_BIG5,*middle,4,0, DATA_RATE,*any,LANDLINE_OFFPEAK,*middle,4,0, RT_URG,URG,R_URG,*middle,4,0, +MX_FREE,RET,MX,*middle,4,10,*free +MX_DISC,RET,MX,*middle,4,10,*disconnect ` ratingPlans = ` STANDARD,RT_STANDARD,WORKDAYS_00,10 @@ -106,6 +109,8 @@ R,P1,WORKDAYS_00,10 RP_UK_Mobile_BIG5_PKG,DR_UK_Mobile_BIG5_PKG,ALWAYS,10 RP_UK,DR_UK_Mobile_BIG5,ALWAYS,10 RP_DATA,DATA_RATE,ALWAYS,10 +RP_MX,MX_DISC,WORKDAYS_00,10 +RP_MX,MX_FREE,WORKDAYS_18,10 ` ratingProfiles = ` *out,CUSTOMER_1,0,rif:from:tm,2012-01-01T00:00:00Z,PREMIUM,danb @@ -127,6 +132,7 @@ RP_DATA,DATA_RATE,ALWAYS,10 *out,cgrates.org,call,*any,2013-01-06T00:00:00Z,RP_UK, *out,cgrates.org,call,discounted_minutes,2013-01-06T00:00:00Z,RP_UK_Mobile_BIG5_PKG, *out,cgrates.org,data,rif,2013-01-06T00:00:00Z,RP_DATA, +*out,cgrates.org,call,max,2013-03-23T00:00:00Z,RP_MX, ` sharedGroups = ` SG1,*any,*lowest, @@ -319,8 +325,8 @@ func TestLoadTimimgs(t *testing.T) { } func TestLoadRates(t *testing.T) { - if len(csvr.rates) != 12 { - t.Error("Failed to load rates: ", csvr.rates) + if len(csvr.rates) != 13 { + t.Error("Failed to load rates: ", len(csvr.rates)) } rate := csvr.rates["R1"].RateSlots[0] expctRs, err := utils.NewRateSlot(0, 0.2, "60", "1", "0") @@ -389,8 +395,8 @@ func TestLoadRates(t *testing.T) { } func TestLoadDestinationRates(t *testing.T) { - if len(csvr.destinationRates) != 11 { - t.Error("Failed to load destinationrates: ", csvr.destinationRates) + if len(csvr.destinationRates) != 13 { + t.Error("Failed to load destinationrates: ", len(csvr.destinationRates)) } drs := csvr.destinationRates["RT_STANDARD"] dr := &utils.TPDestinationRate{ @@ -525,7 +531,7 @@ func TestLoadDestinationRates(t *testing.T) { } func TestLoadRatingPlans(t *testing.T) { - if len(csvr.ratingPlans) != 10 { + if len(csvr.ratingPlans) != 11 { t.Error("Failed to load rating plans: ", len(csvr.ratingPlans)) } rplan := csvr.ratingPlans["STANDARD"] @@ -672,7 +678,7 @@ func TestLoadRatingPlans(t *testing.T) { } func TestLoadRatingProfiles(t *testing.T) { - if len(csvr.ratingProfiles) != 15 { + if len(csvr.ratingProfiles) != 16 { t.Error("Failed to load rating profiles: ", len(csvr.ratingProfiles), csvr.ratingProfiles) } rp := csvr.ratingProfiles["*out:test:0:trp"] diff --git a/engine/ratingplan.go b/engine/ratingplan.go index 8c4b3e839..c98a276f5 100644 --- a/engine/ratingplan.go +++ b/engine/ratingplan.go @@ -83,7 +83,6 @@ func (rp *RatingPlan) AddRateInterval(dId string, ris ...*RateInterval) { } if ri.Rating != nil { ratingTag := ri.Rating.Stringify() - rp.Ratings[ratingTag] = ri.Rating rpr.Rating = ratingTag } diff --git a/engine/timespans.go b/engine/timespans.go index fe9bb18c0..0ff4a0b71 100644 --- a/engine/timespans.go +++ b/engine/timespans.go @@ -247,15 +247,18 @@ Will set the interval as spans's interval if new Weight is lower then span's int or if the Weights are equal and new price is lower then spans's interval price */ func (ts *TimeSpan) SetRateInterval(i *RateInterval) { + //log.Printf("SETRATEINTERVAL: %+v", i.Timing) if ts.RateInterval == nil || ts.RateInterval.Weight < i.Weight { ts.RateInterval = i + //log.Printf("RET TS: %+v", ts.RateInterval.Timing) return } iPrice, _, _ := i.GetRateParameters(ts.GetGroupStart()) tsPrice, _, _ := ts.RateInterval.GetRateParameters(ts.GetGroupStart()) - if ts.RateInterval.Weight == i.Weight && iPrice < tsPrice { + if ts.RateInterval.Weight == i.Weight && iPrice <= tsPrice { ts.RateInterval = i } + //log.Printf("END TS: %+v", ts.RateInterval.Timing) } // Returns the cost of the timespan according to the relevant cost interval. @@ -363,8 +366,9 @@ func (ts *TimeSpan) SplitByRateInterval(i *RateInterval, data bool) (nts *TimeSp return } // if the span is enclosed in the interval try to set as new interval and return nil + //log.Printf("Timing: %+v", i.Timing) if i.Contains(ts.TimeStart, false) && i.Contains(ts.TimeEnd, true) { - //Logger.Debug("All in interval") + //log.Print("All in interval") ts.SetRateInterval(i) return }