Files
cgrates/engine/calldesc_test.go
Radu Ioan Fericean 9006c5ed18 removed logs from tests
2014-03-01 00:11:05 +02:00

500 lines
18 KiB
Go

/*
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 <http://www.gnu.org/licenses/>
*/
package engine
import (
"log"
"reflect"
"testing"
"time"
"github.com/cgrates/cgrates/history"
)
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, RateSubject: "rif"},
&Balance{Value: 100, DestinationId: "RET", 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, RateSubject: "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)
} 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", TOR: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2}
cd.LoadRatingPlans()
timespans := cd.splitInTimeSpans(nil)
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", TOR: "0", Tenant: "test", Subject: "trp", Destination: "0256", TimeStart: t1, TimeEnd: t2, CallDuration: 132 * time.Second}
cd.LoadRatingPlans()
timespans := cd.splitInTimeSpans(nil)
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", TOR: "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", TOR: "0", Tenant: "test", Subject: "trp", Destination: "0256", TimeStart: t1, TimeEnd: t2, LoopIndex: 0, CallDuration: 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", TOR: "0", Tenant: "CUSTOMER_1", Subject: "rif:from:tm", Destination: "49178", TimeStart: t1, TimeEnd: t2, LoopIndex: 0, CallDuration: 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", TOR: "0", Tenant: "CUSTOMER_1", Subject: "rif:from:tm", Destination: "49178", TimeStart: t1, TimeEnd: t2, LoopIndex: 0, CallDuration: 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", TOR: "0", Tenant: "test", Subject: "trp", Destination: "0256", TimeStart: t1, TimeEnd: t2, CallDuration: 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", TOR: "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", TOR: "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", TOR: "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", TOR: "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", TOR: "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", TOR: "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", TOR: "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", TOR: "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", TOR: "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",
TOR: "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",
TOR: "0",
Tenant: "vdf",
Subject: "minu",
Destination: "0723",
Amount: 1000}
result, err := cd.GetMaxSessionDuration()
expected := time.Minute
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",
TOR: "0",
Tenant: "vdf",
Subject: "a1",
Destination: "0723",
Amount: 1000}
result, err := cd.GetMaxSessionDuration()
expected := time.Minute
if result != expected || err != nil {
t.Errorf("Expected %v was %v", expected, result)
}
}
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",
TOR: "0",
Tenant: "vdf",
Subject: "minu_from_tm",
Account: "minu",
Destination: "0723",
Amount: 1000}
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",
TOR: "0",
Tenant: "vdf",
Subject: "broker",
Destination: "0723",
Amount: 5400}
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",
TOR: "0",
Tenant: "vdf",
Subject: "minu_from_tm",
Account: "minu",
Destination: "0723",
CallDuration: t2.Sub(t1),
Amount: 5400}
initial := cd.Clone()
cd.GetMaxSessionDuration()
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",
TOR: "0",
Tenant: "vdf",
Subject: "minu_from_tm",
Account: "minu",
Destination: "0723",
Amount: 1000}
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",
TOR: "0",
Tenant: "vdf",
Subject: "minu_from_tm",
Account: "minu",
Destination: "0723",
Amount: 5400}
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)
}
}
/*********************************** 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", TOR: "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", TOR: "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", TOR: "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", TOR: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2}
cd.LoadRatingPlans()
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.splitInTimeSpans(nil)
}
}
func BenchmarkStorageSingleGetSessionTime(b *testing.B) {
b.StopTimer()
cd := &CallDescriptor{Tenant: "vdf", Subject: "minutosu", Destination: "0723", Amount: 100}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.GetMaxSessionDuration()
}
}
func BenchmarkStorageMultipleGetSessionTime(b *testing.B) {
b.StopTimer()
cd := &CallDescriptor{Direction: "*out", TOR: "0", Tenant: "vdf", Subject: "minutosu", Destination: "0723", Amount: 5400}
b.StartTimer()
for i := 0; i < b.N; i++ {
cd.GetMaxSessionDuration()
}
}