mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
399 lines
15 KiB
Go
399 lines
15 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 (
|
|
"github.com/cgrates/cgrates/history"
|
|
"log"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
marsh = NewCodecMsgpackMarshaler()
|
|
)
|
|
|
|
func init() {
|
|
populateDB()
|
|
historyScribe, _ = history.NewMockScribe()
|
|
}
|
|
|
|
func populateDB() {
|
|
minu := &UserBalance{
|
|
Id: "*out:vdf:minu",
|
|
Type: UB_TYPE_PREPAID,
|
|
BalanceMap: map[string]BalanceChain{
|
|
CREDIT: BalanceChain{&Balance{Value: 0}},
|
|
MINUTES + OUTBOUND: BalanceChain{
|
|
&Balance{Value: 200, DestinationId: "NAT", Weight: 10},
|
|
&Balance{Value: 100, DestinationId: "RET", Weight: 20},
|
|
}},
|
|
}
|
|
broker := &UserBalance{
|
|
Id: "*out:vdf:broker",
|
|
Type: UB_TYPE_PREPAID,
|
|
BalanceMap: map[string]BalanceChain{
|
|
MINUTES + OUTBOUND: BalanceChain{
|
|
&Balance{Value: 20, DestinationId: "NAT", Weight: 10, RateSubject: "rif"},
|
|
&Balance{Value: 100, DestinationId: "RET", Weight: 20},
|
|
}},
|
|
}
|
|
if storageGetter != nil {
|
|
storageGetter.(Storage).Flush()
|
|
storageGetter.SetUserBalance(broker)
|
|
storageGetter.SetUserBalance(minu)
|
|
} 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()
|
|
t.Logf("%+v", cd)
|
|
timespans := cd.splitInTimeSpans(nil)
|
|
if len(timespans) != 2 {
|
|
t.Log(cd.RatingInfos)
|
|
t.Error("Wrong number of timespans: ", len(timespans))
|
|
}
|
|
var d time.Duration
|
|
for _, ts := range timespans {
|
|
d += ts.GetDuration()
|
|
t.Log(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: 2700, ConnectFee: 1}
|
|
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
|
|
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, ConnectFee: 0}
|
|
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee || 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, ConnectFee: 0}
|
|
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
|
|
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: 2700, ConnectFee: 1}
|
|
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
|
|
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: 2700, ConnectFee: 1}
|
|
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
|
|
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: 2700, ConnectFee: 1}
|
|
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
|
|
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: 2700, ConnectFee: 1}
|
|
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
|
|
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.ConnectFee != 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, ConnectFee: 0}
|
|
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
|
|
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, ConnectFee: 0}
|
|
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
|
|
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, ConnectFee: 0}
|
|
if result.Cost != expected.Cost || result.ConnectFee != expected.ConnectFee {
|
|
t.Errorf("Expected %v was %v", expected, result)
|
|
}
|
|
}
|
|
|
|
func TestMaxSessionTimeNoUserBalance(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: "rif",
|
|
Destination: "0723", Amount: 1000}
|
|
result, err := cd.GetMaxSessionTime(time.Now())
|
|
if result != 1000 || err == nil {
|
|
t.Errorf("Expected %v was %v (%v)", 1000, result, err)
|
|
}
|
|
}
|
|
|
|
func TestMaxSessionTimeWithUserBalance(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.GetMaxSessionTime(time.Now())
|
|
expected := 300.0
|
|
if result != expected || err != nil {
|
|
t.Errorf("Expected %v was %v", expected, result)
|
|
}
|
|
}
|
|
|
|
func TestMaxSessionTimeWithUserBalanceAccount(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.GetMaxSessionTime(time.Now())
|
|
expected := 300.0
|
|
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.GetMaxSessionTime(time.Now())
|
|
if result != 100 || err != nil {
|
|
t.Errorf("Expected %v was %v", 100, result)
|
|
}
|
|
}
|
|
|
|
/*********************************** 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++ {
|
|
storageGetter.GetRatingProfile(cd.GetKey(cd.Subject))
|
|
}
|
|
}
|
|
|
|
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.GetMaxSessionTime(time.Now())
|
|
}
|
|
}
|
|
|
|
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.GetMaxSessionTime(time.Now())
|
|
}
|
|
}
|