/* Rating system designed to be used in VoIP Carriers World Copyright (C) 2013 ITsysCOM This program is free software: you can Storagetribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITH*out ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see */ package engine import ( "log" "reflect" "testing" "time" "github.com/cgrates/cgrates/history" "github.com/cgrates/cgrates/utils" ) var ( marsh = NewCodecMsgpackMarshaler() ) func init() { historyScribe, _ = history.NewMockScribe() populateDB() } func populateDB() { ats := []*Action{ &Action{ActionType: "*topup", BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}}, &Action{ActionType: "*topup", BalanceType: MINUTES, Direction: OUTBOUND, Balance: &Balance{Weight: 20, Value: 10, DestinationId: "NAT"}}, } ats1 := []*Action{ &Action{ActionType: "*topup", BalanceType: CREDIT, Direction: OUTBOUND, Balance: &Balance{Value: 10}, Weight: 20}, &Action{ActionType: "*reset_account", Weight: 10}, } minu := &Account{ Id: "*out:vdf:minu", BalanceMap: map[string]BalanceChain{ CREDIT + OUTBOUND: BalanceChain{&Balance{Value: 50}}, MINUTES + OUTBOUND: BalanceChain{ &Balance{Value: 200, DestinationId: "NAT", Weight: 10}, &Balance{Value: 100, DestinationId: "RET", Weight: 20}, }}, } broker := &Account{ Id: "*out:vdf:broker", BalanceMap: map[string]BalanceChain{ MINUTES + OUTBOUND: BalanceChain{ &Balance{Value: 20, DestinationId: "NAT", Weight: 10, RatingSubject: "rif"}, &Balance{Value: 100, DestinationId: "RET", Weight: 20}, }}, } luna := &Account{ Id: "*out:vdf:luna", BalanceMap: map[string]BalanceChain{ CREDIT + OUTBOUND: BalanceChain{ &Balance{Value: 0, Weight: 20}, }}, } // this is added to test if csv load tests account will not overwrite balances minitsboy := &Account{ Id: "*out:vdf:minitsboy", BalanceMap: map[string]BalanceChain{ MINUTES + OUTBOUND: BalanceChain{ &Balance{Value: 20, DestinationId: "NAT", Weight: 10, RatingSubject: "rif"}, &Balance{Value: 100, DestinationId: "RET", Weight: 20}, }, CREDIT + OUTBOUND: BalanceChain{ &Balance{Value: 100, Weight: 10}, }, }, } if accountingStorage != nil { accountingStorage.SetActions("TEST_ACTIONS", ats) accountingStorage.SetActions("TEST_ACTIONS_ORDER", ats1) accountingStorage.SetAccount(broker) accountingStorage.SetAccount(minu) accountingStorage.SetAccount(minitsboy) accountingStorage.SetAccount(luna) } else { log.Fatal("Could not connect to db!") } } func TestSplitSpans(t *testing.T) { t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2} cd.LoadRatingPlans() timespans := cd.splitInTimeSpans() if len(timespans) != 2 { t.Log(cd.RatingInfos) t.Error("Wrong number of timespans: ", len(timespans)) } } func TestSplitSpansRoundToIncrements(t *testing.T) { t1 := time.Date(2013, time.October, 7, 14, 50, 0, 0, time.UTC) t2 := time.Date(2013, time.October, 7, 14, 52, 12, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "test", Subject: "trp", Destination: "0256", TimeStart: t1, TimeEnd: t2, DurationIndex: 132 * time.Second} cd.LoadRatingPlans() timespans := cd.splitInTimeSpans() if len(timespans) != 2 { t.Logf("%+v", cd) t.Log(cd.RatingInfos) t.Error("Wrong number of timespans: ", len(timespans)) } var d time.Duration for _, ts := range timespans { d += ts.GetDuration() } if d != 132*time.Second { t.Error("Wrong duration for timespans: ", d) } } func TestGetCost(t *testing.T) { t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2, LoopIndex: 0} result, _ := cd.GetCost() expected := &CallCost{Tenant: "vdf", Subject: "rif", Destination: "0256", Cost: 2701} if result.Cost != expected.Cost || result.GetConnectFee() != 1 { t.Errorf("Expected %v was %v", expected, result) } } func TestGetCostTimespans(t *testing.T) { t1 := time.Date(2013, time.October, 8, 9, 23, 2, 0, time.UTC) t2 := time.Date(2013, time.October, 8, 9, 24, 27, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "test", Subject: "trp", Destination: "0256", TimeStart: t1, TimeEnd: t2, LoopIndex: 0, DurationIndex: 85 * time.Second} result, _ := cd.GetCost() expected := &CallCost{Tenant: "test", Subject: "trp", Destination: "0256", Cost: 85} if result.Cost != expected.Cost || result.GetConnectFee() != 0 || len(result.Timespans) != 2 { t.Errorf("Expected %+v was %+v", expected, result) } } func TestGetCostRatingPlansAndRatingIntervals(t *testing.T) { t1 := time.Date(2012, time.February, 27, 23, 50, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 28, 18, 10, 0, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "CUSTOMER_1", Subject: "rif:from:tm", Destination: "49178", TimeStart: t1, TimeEnd: t2, LoopIndex: 0, DurationIndex: t2.Sub(t1)} result, _ := cd.GetCost() if len(result.Timespans) != 3 || !result.Timespans[0].TimeEnd.Equal(result.Timespans[1].TimeStart) || !result.Timespans[1].TimeEnd.Equal(result.Timespans[2].TimeStart) { for _, ts := range result.Timespans { t.Logf("TS %+v", ts) } t.Errorf("Expected %+v was %+v", 3, len(result.Timespans)) } } func TestGetCostRatingPlansAndRatingIntervalsMore(t *testing.T) { t1 := time.Date(2012, time.February, 27, 9, 50, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 28, 18, 10, 0, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "CUSTOMER_1", Subject: "rif:from:tm", Destination: "49178", TimeStart: t1, TimeEnd: t2, LoopIndex: 0, DurationIndex: t2.Sub(t1)} result, _ := cd.GetCost() if len(result.Timespans) != 4 || !result.Timespans[0].TimeEnd.Equal(result.Timespans[1].TimeStart) || !result.Timespans[1].TimeEnd.Equal(result.Timespans[2].TimeStart) || !result.Timespans[2].TimeEnd.Equal(result.Timespans[3].TimeStart) { for _, ts := range result.Timespans { t.Logf("TS %+v", ts) } t.Errorf("Expected %+v was %+v", 4, len(result.Timespans)) } } func TestGetCostRateGroups(t *testing.T) { t1 := time.Date(2013, time.October, 7, 14, 50, 0, 0, time.UTC) t2 := time.Date(2013, time.October, 7, 14, 52, 12, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "test", Subject: "trp", Destination: "0256", TimeStart: t1, TimeEnd: t2, DurationIndex: 132 * time.Second} result, err := cd.GetCost() if err != nil { t.Error("Error getting cost: ", err) } if result.Cost != 132 { t.Error("Error calculating cost: ", result.Timespans) } } func TestGetCostNoConnectFee(t *testing.T) { t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2, LoopIndex: 1} result, _ := cd.GetCost() expected := &CallCost{Tenant: "vdf", Subject: "rif", Destination: "0256", Cost: 2700} // connect fee is not added because LoopIndex is 1 if result.Cost != expected.Cost || result.GetConnectFee() != 1 { t.Errorf("Expected %v was %v", expected, result) } } func TestGetCostAccount(t *testing.T) { t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Account: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2} result, _ := cd.GetCost() expected := &CallCost{Tenant: "vdf", Subject: "rif", Destination: "0256", Cost: 2701} if result.Cost != expected.Cost || result.GetConnectFee() != 1 { t.Errorf("Expected %v was %v", expected, result) } } func TestFullDestNotFound(t *testing.T) { t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Destination: "0256308200", TimeStart: t1, TimeEnd: t2} result, _ := cd.GetCost() expected := &CallCost{Tenant: "vdf", Subject: "rif", Destination: "0256", Cost: 2701} if result.Cost != expected.Cost || result.GetConnectFee() != 1 { t.Log(cd.RatingInfos) t.Errorf("Expected %v was %v", expected, result) } } func TestSubjectNotFound(t *testing.T) { t1 := time.Date(2013, time.February, 1, 17, 30, 0, 0, time.UTC) t2 := time.Date(2013, time.February, 1, 18, 30, 0, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "not_exiting", Destination: "025740532", TimeStart: t1, TimeEnd: t2} result, _ := cd.GetCost() expected := &CallCost{Tenant: "vdf", Subject: "rif", Destination: "0257", Cost: 2701} if result.Cost != expected.Cost || result.GetConnectFee() != 1 { t.Logf("%+v", result.Timespans[0].RateInterval) t.Errorf("Expected %v was %v", expected, result) } } func TestMultipleRatingPlans(t *testing.T) { t1 := time.Date(2012, time.February, 8, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 8, 18, 30, 0, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Destination: "0257308200", TimeStart: t1, TimeEnd: t2} result, _ := cd.GetCost() expected := &CallCost{Tenant: "vdf", Subject: "rif", Destination: "0257", Cost: 2701} if result.Cost != expected.Cost || result.GetConnectFee() != 1 { t.Log(result.Timespans) t.Errorf("Expected %v was %v", expected, result) } } func TestSpansMultipleRatingPlans(t *testing.T) { t1 := time.Date(2012, time.February, 7, 23, 50, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 8, 0, 30, 0, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Destination: "0257308200", TimeStart: t1, TimeEnd: t2} result, _ := cd.GetCost() if result.Cost != 1200 || result.GetConnectFee() != 0 { t.Errorf("Expected %v was %v", 1200, result) } } func TestLessThanAMinute(t *testing.T) { t1 := time.Date(2012, time.February, 8, 23, 50, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 8, 23, 50, 30, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Destination: "0257308200", TimeStart: t1, TimeEnd: t2} result, _ := cd.GetCost() expected := &CallCost{Tenant: "vdf", Subject: "rif", Destination: "0257", Cost: 15} if result.Cost != expected.Cost || result.GetConnectFee() != 0 { t.Errorf("Expected %v was %v", expected, result) } } func TestUniquePrice(t *testing.T) { t1 := time.Date(2012, time.February, 8, 22, 50, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 8, 23, 50, 21, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Destination: "0723045326", TimeStart: t1, TimeEnd: t2} result, _ := cd.GetCost() expected := &CallCost{Tenant: "vdf", Subject: "rif", Destination: "0723", Cost: 1810.5} if result.Cost != expected.Cost || result.GetConnectFee() != 0 { t.Errorf("Expected %v was %v", expected, result) } } func TestMinutesCost(t *testing.T) { t1 := time.Date(2012, time.February, 8, 22, 50, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 8, 22, 51, 50, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Destination: "0723", TimeStart: t1, TimeEnd: t2} result, _ := cd.GetCost() expected := &CallCost{Tenant: "vdf", Subject: "minutosu", Destination: "0723", Cost: 55} if result.Cost != expected.Cost || result.GetConnectFee() != 0 { t.Errorf("Expected %v was %v", expected, result) } } func TestMaxSessionTimeNoAccount(t *testing.T) { cd := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC), Direction: "*out", Category: "0", Tenant: "vdf", Subject: "ttttttt", Destination: "0723"} result, err := cd.GetMaxSessionDuration() if result != 0 || err == nil { t.Errorf("Expected %v was %v (%v)", 0, result, err) } } func TestMaxSessionTimeWithAccount(t *testing.T) { cd := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC), Direction: "*out", Category: "0", Tenant: "vdf", Subject: "minu", Destination: "0723", } result, err := cd.GetMaxSessionDuration() expected := time.Minute if result != expected || err != nil { t.Errorf("Expected %v was %v", expected, result) } } func TestMaxSessionTimeWithMaxRate(t *testing.T) { ap, _ := accountingStorage.GetActionTimings("TOPUP10_AT") for _, at := range ap { at.Execute() } cd := &CallDescriptor{ 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), MaxRate: 1.0, MaxRateUnit: time.Minute, } result, err := cd.GetMaxSessionDuration() expected := 40 * time.Second if result != expected || err != nil { t.Errorf("Expected %v was %v", expected, result) } } func TestMaxSessionTimeWithMaxCost(t *testing.T) { ap, _ := accountingStorage.GetActionTimings("TOPUP10_AT") for _, at := range ap { at.Execute() } cd := &CallDescriptor{ 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), MaxCost: 0.5, MaxCostSoFar: 0, } result, err := cd.GetMaxSessionDuration() expected := 45 * time.Second if result != expected || err != nil { t.Errorf("Expected %v was %v", expected, result) } } func TestMaxSessionTimeWithAccountAlias(t *testing.T) { cd := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC), Direction: "*out", Category: "0", Tenant: "vdf", Subject: "a1", Account: "a1", Destination: "0723", } result, err := cd.GetMaxSessionDuration() expected := time.Minute if result != expected || err != nil { t.Errorf("Expected %v was %v, %v", expected, result, err) } } func TestMaxSessionTimeWithAccountShared(t *testing.T) { ap, _ := accountingStorage.GetActionTimings("TOPUP_SHARED0_AT") for _, at := range ap { at.Execute() } ap, _ = accountingStorage.GetActionTimings("TOPUP_SHARED10_AT") for _, at := range ap { at.Execute() } cd0 := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC), Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Account: "empty0", Destination: "0723", } cd1 := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC), Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Account: "empty10", Destination: "0723", } result0, err := cd0.GetMaxSessionDuration() result1, err := cd1.GetMaxSessionDuration() if result0 != result1/2 || err != nil { t.Errorf("Expected %v was %v, %v", result1/2, result0, err) } } func TestMaxDebitWithAccountShared(t *testing.T) { ap, _ := accountingStorage.GetActionTimings("TOPUP_SHARED0_AT") for _, at := range ap { at.Execute() } ap, _ = accountingStorage.GetActionTimings("TOPUP_SHARED10_AT") for _, at := range ap { at.Execute() } cd := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 34, 5, 0, time.UTC), Direction: "*out", Category: "0", Tenant: "vdf", Subject: "minu", Account: "empty0", Destination: "0723", } cc, err := cd.MaxDebit() if err != nil || cc.Cost != 2.5 { t.Errorf("Wrong callcost in shared debit: %+v, %v", cc, err) } acc, _ := cd.getAccount() balanceMap := acc.BalanceMap[CREDIT+OUTBOUND] if len(balanceMap) != 1 || balanceMap[0].Value != 0 { t.Errorf("Wrong shared balance debited: %+v", balanceMap) } other, err := accountingStorage.GetAccount("*out:vdf:empty10") if err != nil || other.BalanceMap[CREDIT+OUTBOUND][0].Value != 7.5 { t.Errorf("Error debiting shared balance: %+v", other.BalanceMap[CREDIT+OUTBOUND][0]) } } func TestMaxSessionTimeWithAccountAccount(t *testing.T) { cd := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC), Direction: "*out", Category: "0", Tenant: "vdf", Subject: "minu_from_tm", Account: "minu", Destination: "0723", } result, err := cd.GetMaxSessionDuration() expected := time.Minute if result != expected || err != nil { t.Errorf("Expected %v was %v", expected, result) } } func TestMaxSessionTimeNoCredit(t *testing.T) { cd := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC), Direction: "*out", Category: "0", Tenant: "vdf", Subject: "broker", Destination: "0723", TOR: MINUTES, } result, err := cd.GetMaxSessionDuration() if result != time.Minute || err != nil { t.Errorf("Expected %v was %v", time.Minute, result) } } func TestMaxSessionModifiesCallDesc(t *testing.T) { t1 := time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC) t2 := time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC) cd := &CallDescriptor{ TimeStart: t1, TimeEnd: t2, Direction: "*out", Category: "0", Tenant: "vdf", Subject: "minu_from_tm", Account: "minu", Destination: "0723", DurationIndex: t2.Sub(t1), TOR: MINUTES, } initial := cd.Clone() cd.GetMaxSessionDuration() cd.account = nil // it's OK to cache the account if !reflect.DeepEqual(cd, initial) { t.Errorf("GetMaxSessionDuration is changing the call descriptor %+v != %+v", cd, initial) } } func TestMaxDebitDurationNoGreatherThanInitialDuration(t *testing.T) { cd := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC), Direction: "*out", Category: "0", Tenant: "vdf", Subject: "minu_from_tm", Account: "minu", Destination: "0723", } initialDuration := cd.TimeEnd.Sub(cd.TimeStart) result, _ := cd.GetMaxSessionDuration() if result > initialDuration { t.Error("max session duration greather than initial duration", initialDuration, result) } } func TestDebitAndMaxDebit(t *testing.T) { cd1 := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC), Direction: "*out", Category: "0", Tenant: "vdf", Subject: "minu_from_tm", Account: "minu", Destination: "0723", } cd2 := cd1.Clone() cc1, err1 := cd1.Debit() cc2, err2 := cd2.MaxDebit() if err1 != nil || err2 != nil { t.Error("Error debiting and/or maxdebiting: ", err1, err2) } if !reflect.DeepEqual(cc1, cc2) { t.Errorf("Debit and MaxDebit differ: %+v != %+v", cc1, cc2) } } func TestMaxSesionTimeEmptyBalance(t *testing.T) { cd := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC), Direction: "*out", Category: "0", Tenant: "vdf", Subject: "minu_from_tm", Account: "luna", Destination: "0723", } acc, _ := accountingStorage.GetAccount("*out:vdf:luna") allowedTime, err := cd.getMaxSessionDuration(acc) if err != nil || allowedTime != 0 { t.Error("Error get max session for 0 acount") } } func TestMaxSesionTimeEmptyBalanceAndNoCost(t *testing.T) { cd := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC), Direction: "*out", Category: "0", Tenant: "vdf", Subject: "one", Account: "luna", Destination: "112", } acc, _ := accountingStorage.GetAccount("*out:vdf:luna") allowedTime, err := cd.getMaxSessionDuration(acc) if err != nil || allowedTime == 0 { t.Error("Error get max session for 0 acount") } } func TestDebitFromShareAndNormal(t *testing.T) { ap, _ := accountingStorage.GetActionTimings("TOPUP_SHARED10_AT") for _, at := range ap { at.Execute() } cd := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 34, 5, 0, time.UTC), Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Account: "empty10", Destination: "0723", } acc, _ := cd.getAccount() balanceMap := acc.BalanceMap[CREDIT+OUTBOUND] cc, err := cd.MaxDebit() if err != nil || cc.Cost != 2.5 { t.Errorf("Debit from share and normal error: %+v, %v", cc, err) } if balanceMap[0].Value != 10 || balanceMap[1].Value != 7.5 { t.Errorf("Error debiting from right balance: %v %v", balanceMap[0].Value, balanceMap[1].Value) } } func TestDebitFromEmptyShare(t *testing.T) { ap, _ := accountingStorage.GetActionTimings("TOPUP_EMPTY_AT") for _, at := range ap { at.Execute() } cd := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 34, 5, 0, time.UTC), Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Account: "emptyX", Destination: "0723", } cc, err := cd.MaxDebit() if err != nil || cc.Cost != 2.5 { t.Errorf("Debit from empty share error: %+v, %v", cc, err) } acc, _ := cd.getAccount() balanceMap := acc.BalanceMap[CREDIT+OUTBOUND] if len(balanceMap) != 2 || balanceMap[0].Value != 0 || balanceMap[1].Value != -2.5 { t.Errorf("Error debiting from empty share: %+v %+v", balanceMap[0], balanceMap[1]) } } func TestMaxDebitZeroDefinedRate(t *testing.T) { ap, _ := accountingStorage.GetActionTimings("TOPUP10_AT") for _, at := range ap { at.Execute() } cd1 := &CallDescriptor{ 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), LoopIndex: 0, DurationIndex: 0} cc, err := cd1.MaxDebit() if err != nil { t.Error("Error maxdebiting: ", err) } if cc.GetDuration() != 49*time.Second { t.Error("Error obtaining max debit duration: ", cc.GetDuration()) } if cc.Cost != 0.91 { t.Error("Error in max debit cost: ", cc.Cost) } } func TestMaxDebitZeroDefinedRateOnlyMinutes(t *testing.T) { ap, _ := accountingStorage.GetActionTimings("TOPUP10_AT") for _, at := range ap { at.Execute() } cd1 := &CallDescriptor{ 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, 0, 40, 0, time.UTC), LoopIndex: 0, DurationIndex: 0} cc, err := cd1.MaxDebit() if err != nil { t.Fatal("Error maxdebiting: ", err) } if cc.GetDuration() != 40*time.Second { t.Error("Error obtaining max debit duration: ", cc.GetDuration()) } if cc.Cost != 0.01 { t.Error("Error in max debit cost: ", cc.Cost) } } func TestMaxDebitConsumesMinutes(t *testing.T) { ap, _ := accountingStorage.GetActionTimings("TOPUP10_AT") for _, at := range ap { at.Execute() } cd1 := &CallDescriptor{ 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, 0, 5, 0, time.UTC), LoopIndex: 0, DurationIndex: 0} cd1.MaxDebit() if cd1.account.BalanceMap[MINUTES+OUTBOUND][0].Value != 20 { t.Error("Error using minutes: ", cd1.account.BalanceMap[MINUTES+OUTBOUND][0].Value) } } func TestCDGetCostANY(t *testing.T) { cd1 := &CallDescriptor{ Direction: "*out", Category: "data", Tenant: "cgrates.org", Subject: "rif", Destination: utils.ANY, TimeStart: time.Date(2014, 3, 4, 6, 0, 0, 0, time.UTC), TimeEnd: time.Date(2014, 3, 4, 6, 0, 1, 0, time.UTC), TOR: DATA, } cc, err := cd1.GetCost() if err != nil || cc.Cost != 60 { t.Errorf("Error getting *any dest: %+v %v", cc, err) } } func TestCDSplitInDataSlots(t *testing.T) { cd := &CallDescriptor{ Direction: "*out", Category: "data", Tenant: "cgrates.org", Subject: "rif", Destination: utils.ANY, TimeStart: time.Date(2014, 3, 4, 6, 0, 0, 0, time.UTC), TimeEnd: time.Date(2014, 3, 4, 6, 1, 5, 0, time.UTC), TOR: DATA, DurationIndex: 65 * time.Second, } cd.LoadRatingPlans() timespans := cd.splitInTimeSpans() if len(timespans) != 2 { t.Log(cd.RatingInfos[0]) t.Error("Wrong number of timespans: ", len(timespans)) } } func TestCDDataGetCost(t *testing.T) { cd := &CallDescriptor{ Direction: "*out", Category: "data", Tenant: "cgrates.org", Subject: "rif", Destination: utils.ANY, TimeStart: time.Date(2014, 3, 4, 6, 0, 0, 0, time.UTC), TimeEnd: time.Date(2014, 3, 4, 6, 1, 5, 0, time.UTC), TOR: DATA, } cc, err := cd.GetCost() if err != nil || cc.Cost != 65 { t.Errorf("Error getting *any dest: %+v %v", cc, err) } } /*************** BENCHMARKS ********************/ func BenchmarkStorageGetting(b *testing.B) { b.StopTimer() t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2} b.StartTimer() for i := 0; i < b.N; i++ { dataStorage.GetRatingProfile(cd.GetKey(cd.Subject), false) } } func BenchmarkStorageRestoring(b *testing.B) { b.StopTimer() t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2} b.StartTimer() for i := 0; i < b.N; i++ { cd.LoadRatingPlans() } } func BenchmarkStorageGetCost(b *testing.B) { b.StopTimer() t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2} b.StartTimer() for i := 0; i < b.N; i++ { cd.GetCost() } } func BenchmarkSplitting(b *testing.B) { b.StopTimer() t1 := time.Date(2012, time.February, 2, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 2, 18, 30, 0, 0, time.UTC) cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2} cd.LoadRatingPlans() b.StartTimer() for i := 0; i < b.N; i++ { cd.splitInTimeSpans() } } func BenchmarkStorageSingleGetSessionTime(b *testing.B) { b.StopTimer() cd := &CallDescriptor{Tenant: "vdf", Subject: "minutosu", Destination: "0723"} b.StartTimer() for i := 0; i < b.N; i++ { cd.GetMaxSessionDuration() } } func BenchmarkStorageMultipleGetSessionTime(b *testing.B) { b.StopTimer() cd := &CallDescriptor{Direction: "*out", Category: "0", Tenant: "vdf", Subject: "minutosu", Destination: "0723"} b.StartTimer() for i := 0; i < b.N; i++ { cd.GetMaxSessionDuration() } }