mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
tests for rating info activation times
This commit is contained in:
@@ -21,6 +21,7 @@ package engine
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/cgrates/cgrates/cache2go"
|
||||
"github.com/cgrates/cgrates/history"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
@@ -136,12 +137,10 @@ func (cd *CallDescriptor) getUserBalance() (ub *UserBalance, err error) {
|
||||
Restores the activation periods for the specified prefix from storage.
|
||||
*/
|
||||
func (cd *CallDescriptor) LoadRatingPlans() (err error) {
|
||||
err = cd.getRatingPlansForPrefix(cd.GetKey(), 1)
|
||||
if err != nil {
|
||||
// try general fallback
|
||||
fallbackKey := fmt.Sprintf("%s:%s:%s:%s", cd.Direction, cd.Tenant, cd.TOR, FALLBACK_SUBJECT)
|
||||
err = cd.getRatingPlansForPrefix(cd.GetKey(cd.Subject), 1)
|
||||
if err != nil || !cd.continousRatingInfos() {
|
||||
// use the default subject
|
||||
err = cd.getRatingPlansForPrefix(fallbackKey, 1)
|
||||
err = cd.getRatingPlansForPrefix(cd.GetKey(FALLBACK_SUBJECT), 1)
|
||||
}
|
||||
//load the rating plans
|
||||
if err != nil || !cd.continousRatingInfos() {
|
||||
@@ -164,6 +163,7 @@ func (cd *CallDescriptor) getRatingPlansForPrefix(key string, recursionDepth int
|
||||
}
|
||||
if err = rp.GetRatingPlansForPrefix(cd); err != nil || !cd.continousRatingInfos() {
|
||||
// try rating profile fallback
|
||||
recursionDepth++
|
||||
for index := 0; index < len(cd.RatingInfos); index++ {
|
||||
ri := cd.RatingInfos[index]
|
||||
if len(ri.RateIntervals) > 0 {
|
||||
@@ -171,8 +171,12 @@ func (cd *CallDescriptor) getRatingPlansForPrefix(key string, recursionDepth int
|
||||
continue
|
||||
}
|
||||
if len(ri.FallbackKeys) > 0 {
|
||||
recursionDepth++
|
||||
tempCD := &CallDescriptor{}
|
||||
tempCD := &CallDescriptor{
|
||||
TOR: cd.TOR,
|
||||
Direction: cd.Direction,
|
||||
Tenant: cd.Tenant,
|
||||
Destination: cd.Destination,
|
||||
}
|
||||
if index == 0 {
|
||||
tempCD.TimeStart = cd.TimeStart
|
||||
} else {
|
||||
@@ -189,6 +193,10 @@ func (cd *CallDescriptor) getRatingPlansForPrefix(key string, recursionDepth int
|
||||
}
|
||||
// extract the rate infos and break
|
||||
for newIndex, newRI := range tempCD.RatingInfos {
|
||||
// check if the new ri is filled
|
||||
if len(newRI.RateIntervals) == 0 {
|
||||
continue
|
||||
}
|
||||
if newIndex == 0 {
|
||||
cd.RatingInfos[index] = newRI
|
||||
} else {
|
||||
@@ -254,8 +262,8 @@ func (cd *CallDescriptor) addRatingInfos(ris RatingInfos) bool {
|
||||
Constructs the key for the storage lookup.
|
||||
The prefixLen is limiting the length of the destination prefix.
|
||||
*/
|
||||
func (cd *CallDescriptor) GetKey() string {
|
||||
return fmt.Sprintf("%s:%s:%s:%s", cd.Direction, cd.Tenant, cd.TOR, cd.Subject)
|
||||
func (cd *CallDescriptor) GetKey(subject string) string {
|
||||
return fmt.Sprintf("%s:%s:%s:%s", cd.Direction, cd.Tenant, cd.TOR, subject)
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -341,7 +341,7 @@ func BenchmarkStorageGetting(b *testing.B) {
|
||||
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())
|
||||
storageGetter.GetRatingProfile(cd.GetKey(cd.Subject))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,6 +88,8 @@ EVENING,P2,WORKDAYS_18,10
|
||||
EVENING,P2,WEEKENDS,10
|
||||
TDRT,T1,WORKDAYS_00,10
|
||||
TDRT,T2,WORKDAYS_00,10
|
||||
G,RT_STANDARD,WORKDAYS_00,10
|
||||
R,P1,WORKDAYS_00,10
|
||||
`
|
||||
ratingProfiles = `
|
||||
CUSTOMER_1,0,*out,rif:from:tm,2012-01-01T00:00:00Z,PREMIUM,danb
|
||||
@@ -102,6 +104,10 @@ vdf,0,*out,one,2012-02-28T00:00:00Z,STANDARD,
|
||||
vdf,0,*out,inf,2012-02-28T00:00:00Z,STANDARD,inf
|
||||
vdf,0,*out,fall,2012-02-28T00:00:00Z,PREMIUM,rif
|
||||
test,0,*out,trp,2013-10-01T00:00:00Z,TDRT,rif;danb
|
||||
vdf,0,*out,fallback1,2013-11-18T13:45:00Z,G,fallback2
|
||||
vdf,0,*out,fallback1,2013-11-18T13:46:00Z,G,fallback2
|
||||
vdf,0,*out,fallback1,2013-11-18T13:47:00Z,G,fallback2
|
||||
vdf,0,*out,fallback2,2013-11-18T13:45:00Z,R,rif
|
||||
`
|
||||
actions = `
|
||||
MINI,*topup_reset,*monetary,*out,10,*unlimited,,,10,,10
|
||||
@@ -240,68 +246,68 @@ func TestLoadRates(t *testing.T) {
|
||||
t.Error("Failed to load rates: ", csvr.rates)
|
||||
}
|
||||
rate := csvr.rates["R1"].RateSlots[0]
|
||||
expctRs,err := utils.NewRateSlot(0, 0.2, "60s", "1s", "0", utils.ROUNDING_MIDDLE, 2)
|
||||
expctRs, err := utils.NewRateSlot(0, 0.2, "60s", "1s", "0", utils.ROUNDING_MIDDLE, 2)
|
||||
if err != nil {
|
||||
t.Error("Error loading rate: ", rate, err.Error())
|
||||
} else if !reflect.DeepEqual(rate, expctRs) ||
|
||||
rate.RateUnitDuration() != expctRs.RateUnitDuration() ||
|
||||
rate.RateIncrementDuration() != expctRs.RateIncrementDuration() ||
|
||||
rate.GroupIntervalStartDuration() != expctRs.GroupIntervalStartDuration() {
|
||||
t.Error("Error loading rate: ", rate, expctRs)
|
||||
t.Error("Error loading rate: ", rate, expctRs)
|
||||
}
|
||||
rate = csvr.rates["R2"].RateSlots[0]
|
||||
if expctRs,err = utils.NewRateSlot(0, 0.1, "60s", "1s", "0", utils.ROUNDING_MIDDLE, 2); err != nil {
|
||||
if expctRs, err = utils.NewRateSlot(0, 0.1, "60s", "1s", "0", utils.ROUNDING_MIDDLE, 2); err != nil {
|
||||
t.Error("Error loading rate: ", rate, err.Error())
|
||||
} else if !reflect.DeepEqual(rate, expctRs) ||
|
||||
rate.RateUnitDuration() != expctRs.RateUnitDuration() ||
|
||||
rate.RateIncrementDuration() != expctRs.RateIncrementDuration() ||
|
||||
rate.GroupIntervalStartDuration() != expctRs.GroupIntervalStartDuration() {
|
||||
t.Error("Error loading rate: ", rate)
|
||||
t.Error("Error loading rate: ", rate)
|
||||
}
|
||||
rate = csvr.rates["R3"].RateSlots[0]
|
||||
if expctRs, err = utils.NewRateSlot( 0, 0.05, "60s", "1s", "0", utils.ROUNDING_MIDDLE, 2 ); err != nil {
|
||||
if expctRs, err = utils.NewRateSlot(0, 0.05, "60s", "1s", "0", utils.ROUNDING_MIDDLE, 2); err != nil {
|
||||
t.Error("Error loading rate: ", rate, err.Error())
|
||||
} else if !reflect.DeepEqual(rate, expctRs) ||
|
||||
rate.RateUnitDuration() != expctRs.RateUnitDuration() ||
|
||||
rate.RateIncrementDuration() != expctRs.RateIncrementDuration() ||
|
||||
rate.GroupIntervalStartDuration() != expctRs.GroupIntervalStartDuration() {
|
||||
t.Error("Error loading rate: ", rate)
|
||||
t.Error("Error loading rate: ", rate)
|
||||
}
|
||||
rate = csvr.rates["R4"].RateSlots[0]
|
||||
if expctRs, err = utils.NewRateSlot( 1, 1.0, "1s", "1s", "0", utils.ROUNDING_UP, 2 ); err != nil {
|
||||
if expctRs, err = utils.NewRateSlot(1, 1.0, "1s", "1s", "0", utils.ROUNDING_UP, 2); err != nil {
|
||||
t.Error("Error loading rate: ", rate, err.Error())
|
||||
} else if !reflect.DeepEqual(rate, expctRs) ||
|
||||
rate.RateUnitDuration() != expctRs.RateUnitDuration() ||
|
||||
rate.RateIncrementDuration() != expctRs.RateIncrementDuration() ||
|
||||
rate.GroupIntervalStartDuration() != expctRs.GroupIntervalStartDuration() {
|
||||
t.Error("Error loading rate: ", rate)
|
||||
t.Error("Error loading rate: ", rate)
|
||||
}
|
||||
rate = csvr.rates["R5"].RateSlots[0]
|
||||
if expctRs, err = utils.NewRateSlot( 0, 0.5, "1s", "1s", "0", utils.ROUNDING_DOWN, 2 ); err != nil {
|
||||
if expctRs, err = utils.NewRateSlot(0, 0.5, "1s", "1s", "0", utils.ROUNDING_DOWN, 2); err != nil {
|
||||
t.Error("Error loading rate: ", rate, err.Error())
|
||||
} else if !reflect.DeepEqual(rate, expctRs) ||
|
||||
rate.RateUnitDuration() != expctRs.RateUnitDuration() ||
|
||||
rate.RateIncrementDuration() != expctRs.RateIncrementDuration() ||
|
||||
rate.GroupIntervalStartDuration() != expctRs.GroupIntervalStartDuration() {
|
||||
t.Error("Error loading rate: ", rate)
|
||||
t.Error("Error loading rate: ", rate)
|
||||
}
|
||||
rate = csvr.rates["LANDLINE_OFFPEAK"].RateSlots[0]
|
||||
if expctRs, err = utils.NewRateSlot( 0, 1, "1s", "60s", "0s", utils.ROUNDING_UP, 4 ); err != nil {
|
||||
if expctRs, err = utils.NewRateSlot(0, 1, "1s", "60s", "0s", utils.ROUNDING_UP, 4); err != nil {
|
||||
t.Error("Error loading rate: ", rate, err.Error())
|
||||
} else if !reflect.DeepEqual(rate, expctRs) ||
|
||||
rate.RateUnitDuration() != expctRs.RateUnitDuration() ||
|
||||
rate.RateIncrementDuration() != expctRs.RateIncrementDuration() ||
|
||||
rate.GroupIntervalStartDuration() != expctRs.GroupIntervalStartDuration() {
|
||||
t.Error("Error loading rate: ", rate)
|
||||
t.Error("Error loading rate: ", rate)
|
||||
}
|
||||
rate = csvr.rates["LANDLINE_OFFPEAK"].RateSlots[1]
|
||||
if expctRs, err = utils.NewRateSlot( 0, 1, "1s", "1s", "60s", utils.ROUNDING_UP, 4 ); err != nil {
|
||||
if expctRs, err = utils.NewRateSlot(0, 1, "1s", "1s", "60s", utils.ROUNDING_UP, 4); err != nil {
|
||||
t.Error("Error loading rate: ", rate, err.Error())
|
||||
} else if !reflect.DeepEqual(rate, expctRs) ||
|
||||
rate.RateUnitDuration() != expctRs.RateUnitDuration() ||
|
||||
rate.RateIncrementDuration() != expctRs.RateIncrementDuration() ||
|
||||
rate.GroupIntervalStartDuration() != expctRs.GroupIntervalStartDuration() {
|
||||
t.Error("Error loading rate: ", rate)
|
||||
t.Error("Error loading rate: ", rate)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,7 +424,7 @@ func TestLoadDestinationRates(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLoadDestinationRateTimings(t *testing.T) {
|
||||
if len(csvr.ratingPlans) != 5 {
|
||||
if len(csvr.ratingPlans) != 7 {
|
||||
t.Error("Failed to load rate timings: ", csvr.ratingPlans)
|
||||
}
|
||||
rplan := csvr.ratingPlans["STANDARD"]
|
||||
@@ -538,7 +544,7 @@ func TestLoadDestinationRateTimings(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLoadRatingProfiles(t *testing.T) {
|
||||
if len(csvr.ratingProfiles) != 10 {
|
||||
if len(csvr.ratingProfiles) != 12 {
|
||||
t.Error("Failed to load rating profiles: ", len(csvr.ratingProfiles), csvr.ratingProfiles)
|
||||
}
|
||||
rp := csvr.ratingProfiles["*out:test:0:trp"]
|
||||
|
||||
@@ -100,10 +100,9 @@ func (ris RatingInfos) Sort() {
|
||||
sort.Sort(ris)
|
||||
}
|
||||
|
||||
// TODO: what happens if there is no match for part of the call
|
||||
func (rp *RatingProfile) GetRatingPlansForPrefix(cd *CallDescriptor) (err error) {
|
||||
var ris RatingInfos
|
||||
for _, rpa := range rp.RatingPlanActivations.GetActiveForCall(cd) {
|
||||
for index, rpa := range rp.RatingPlanActivations.GetActiveForCall(cd) {
|
||||
rpl, err := storageGetter.GetRatingPlan(rpa.RatingPlanId)
|
||||
if err != nil || rpl == nil {
|
||||
Logger.Err(fmt.Sprintf("Error checking destination: %v", err))
|
||||
@@ -124,6 +123,10 @@ func (rp *RatingProfile) GetRatingPlansForPrefix(cd *CallDescriptor) (err error)
|
||||
rps = rpl.RateIntervalList(dId)
|
||||
}
|
||||
}
|
||||
// check if it's the first ri and add a blank one for the initial part not covered
|
||||
if index == 0 && cd.TimeStart.Before(rpa.ActivationTime) {
|
||||
ris = append(ris, &RatingInfo{"", "", cd.TimeStart, nil, []string{cd.GetKey(FALLBACK_SUBJECT)}})
|
||||
}
|
||||
if bestPrecision > 0 {
|
||||
ris = append(ris, &RatingInfo{rp.Id, cd.Destination[:bestPrecision], rpa.ActivationTime, rps, rpa.FallbackKeys})
|
||||
} else {
|
||||
|
||||
@@ -20,20 +20,44 @@ package engine
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestRpAddAPIfNotPresent(t *testing.T) {
|
||||
/* ap1 := &RatingPlan{Id: "test1"}
|
||||
ap2 := &RatingPlan{Id: "test1"}
|
||||
ap3 := &RatingPlan{Id: "test2"}
|
||||
rp := &RatingProfile{}
|
||||
rp.AddRatingPlanIfNotPresent("test", ap1)
|
||||
rp.AddRatingPlanIfNotPresent("test", ap2)
|
||||
if len(rp.DestinationMap["test"]) != 1 {
|
||||
t.Error("Wronfully appended activation period ;)", len(rp.DestinationMap["test"]))
|
||||
}
|
||||
rp.AddRatingPlanIfNotPresent("test", ap3)
|
||||
if len(rp.DestinationMap["test"]) != 2 {
|
||||
t.Error("Wronfully not appended activation period ;)", len(rp.DestinationMap["test"]))
|
||||
}*/
|
||||
func TestGetRatingProfileForPrefix(t *testing.T) {
|
||||
cd := &CallDescriptor{
|
||||
TimeStart: time.Date(2013, 11, 18, 13, 45, 1, 0, time.UTC),
|
||||
TimeEnd: time.Date(2013, 11, 18, 13, 47, 30, 0, time.UTC),
|
||||
Tenant: "vdf",
|
||||
TOR: "0",
|
||||
Direction: OUTBOUND,
|
||||
Subject: "fallback1",
|
||||
Destination: "0256098",
|
||||
}
|
||||
cd.LoadRatingPlans()
|
||||
if len(cd.RatingInfos) != 3 || !cd.continousRatingInfos() {
|
||||
t.Logf("0: %+v", cd.RatingInfos[0])
|
||||
t.Logf("1: %+v", cd.RatingInfos[1])
|
||||
t.Logf("2: %+v", cd.RatingInfos[2])
|
||||
t.Errorf("Error loading rating information: %+v %+v", cd.RatingInfos, cd.continousRatingInfos())
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRatingProfileForPrefixFirstEmpty(t *testing.T) {
|
||||
cd := &CallDescriptor{
|
||||
TimeStart: time.Date(2013, 11, 18, 13, 44, 1, 0, time.UTC),
|
||||
TimeEnd: time.Date(2013, 11, 18, 13, 47, 30, 0, time.UTC),
|
||||
Tenant: "vdf",
|
||||
TOR: "0",
|
||||
Direction: OUTBOUND,
|
||||
Subject: "fallback1",
|
||||
Destination: "0256098",
|
||||
}
|
||||
cd.LoadRatingPlans()
|
||||
if len(cd.RatingInfos) != 4 || !cd.continousRatingInfos() {
|
||||
t.Logf("0: %+v", cd.RatingInfos[0])
|
||||
t.Logf("1: %+v", cd.RatingInfos[1])
|
||||
t.Logf("2: %+v", cd.RatingInfos[2])
|
||||
t.Logf("3: %+v", cd.RatingInfos[3])
|
||||
t.Errorf("Error loading rating information: %+v %+v", cd.RatingInfos, cd.continousRatingInfos())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user