From a0d76f5cb9f4e3a88513b476965a5733e6e751d7 Mon Sep 17 00:00:00 2001 From: porosnicuadrian Date: Thu, 22 Oct 2020 13:00:16 +0300 Subject: [PATCH] Covered rateprofile and librates to 100% --- engine/rateprofile_test.go | 2 +- rates/librates.go | 29 +++-- rates/librates_test.go | 248 ++++++++++++++++++++++++++++++++----- 3 files changed, 237 insertions(+), 42 deletions(-) diff --git a/engine/rateprofile_test.go b/engine/rateprofile_test.go index 050919925..e2ba42440 100644 --- a/engine/rateprofile_test.go +++ b/engine/rateprofile_test.go @@ -440,7 +440,7 @@ func TestRateProfileRunTimesMaxIterations(t *testing.T) { } } -func TestRateProfileRunTimesPaasinActivationTIme(t *testing.T) { +func TestRateProfileRunTimesPassingActivationTIme(t *testing.T) { rt := &Rate{ ID: "RATE0", IntervalRates: []*IntervalRate{ diff --git a/rates/librates.go b/rates/librates.go index 54898f640..a39e43971 100644 --- a/rates/librates.go +++ b/rates/librates.go @@ -108,9 +108,6 @@ func orderRatesOnIntervals(aRts []*engine.Rate, sTime time.Time, usage time.Dura aTime: rTimeSet[0], iTime: rTimeSet[1], } - if rTimeSet[0].IsZero() { // the rate will never be active - continue - } allRates[rIt.id()] = rIt if _, hasKey := rtIdx[rTimeSet[0]]; !hasKey { rtIdx[rTimeSet[0]] = initRatesWithWinner() @@ -124,9 +121,6 @@ func orderRatesOnIntervals(aRts []*engine.Rate, sTime time.Time, usage time.Dura } } } - if err != nil && len(rtIdx) != 0 { - err = nil // overwrite only if there is at least one rate found - } // add the active rates to all time samples for tm, rWw := range rtIdx { for _, rIt := range allRates { @@ -172,8 +166,27 @@ func orderRatesOnIntervals(aRts []*engine.Rate, sTime time.Time, usage time.Dura if sTime.Before(aTime) { usageIndx = aTime.Sub(sTime) } - if len(ordRts) == 0 || wnr.rt.ID != ordRts[len(ordRts)-1].Rate.ID { // only add the winner if not already active - ordRts = append(ordRts, &orderedRate{usageIndx, rtIdx[aTime].winner().rt}) + } + } else { // only first rate is considered for units + oRts = []*rateWithTimes{rtIdx[sortedATimes[0]].winner()} + } + // add the Intervals and Increments + var usageSIdx, usageEIdx time.Duration + for i, rWt := range oRts { + if sTime.Before(rWt.aTime) { + usageSIdx = rWt.aTime.Sub(sTime) + } + if i != len(sortedATimes)-1 { // not the last one + usageEIdx = sortedATimes[i+1].Sub(sTime) + } else { + usageEIdx = usage + } + // append the valid increments + var rtIcmts []*engine.RateSIncrement + rt := rtIdx[rWt.aTime].winner().rt + for j, ivlRt := range rt.IntervalRates { + if ivlRt.IntervalStart > usageEIdx { + break } } } else { // only first rate is considered for units diff --git a/rates/librates_test.go b/rates/librates_test.go index 96d25da57..9e9c21e08 100644 --- a/rates/librates_test.go +++ b/rates/librates_test.go @@ -23,8 +23,9 @@ import ( "testing" "time" - "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" + + "github.com/cgrates/cgrates/engine" ) func TestOrderRatesOnIntervals(t *testing.T) { @@ -131,38 +132,6 @@ func TestOrderRatesOnIntervals(t *testing.T) { } } -/* -func TestOrderRatesOnIntervalsCase1(t *testing.T) { - rt0 := &engine.Rate{ - ID: "RATE0", - Weight: 0, - IntervalRates: []*engine.IntervalRate{ - { - IntervalStart: time.Duration(0), - }, - }, - } - rt0.Compile() - rtChristmas := &engine.Rate{ - ID: "RT_CHRISTMAS", - ActivationTimes: "* * 24 12 *", - Weight: 50, - IntervalRates: []*engine.IntervalRate{ - { - IntervalStart: time.Duration(0), - }, - }, - } - rtChristmas.Compile() - aRts := []*engine.Rate{rt0, rtChristmas} - sTime := time.Date(2020, time.December, 23, 23, 59, 05, 0, time.UTC) - usage := 2 * time.Minute - expectedErr := "maximum iterations reached" - if _, err := orderRatesOnIntervals(aRts, sTime, usage, true, 0); err == nil || err.Error() != expectedErr { - t.Errorf("Expected %+v, received %+v", expectedErr, err) - } -} -*/ func TestNewRatesWithWinner(t *testing.T) { rt := &rateWithTimes{ uId: "randomID", @@ -177,3 +146,216 @@ func TestNewRatesWithWinner(t *testing.T) { t.Errorf("Expected %+v, received %+v", expected, newRatesWithWinner(rt)) } } + +func TestOrderRatesOnIntervalCaseMaxIterations(t *testing.T) { + rt1 := &engine.Rate{ + ID: "RT_1", + ActivationTimes: "1 * * * *", + IntervalRates: []*engine.IntervalRate{ + { + IntervalStart: time.Duration(0), + }, + }, + } + err := rt1.Compile() + if err != nil { + t.Error(err) + } + aRts := []*engine.Rate{rt1} + sTime := time.Date(2020, 01, 02, 0, 1, 0, 0, time.UTC) + usage := 96 * time.Hour + expectedErr := "maximum iterations reached" + if _, err := orderRatesOnIntervals(aRts, sTime, usage, false, 1); err == nil || err.Error() != expectedErr { + t.Errorf("Expected %+v, received %+v", expectedErr, err) + } +} + +func TestOrderRatesOnIntervalIsDirectionFalse(t *testing.T) { + rt1 := &engine.Rate{ + ID: "RT_1", + ActivationTimes: "* * 27 02 *", + IntervalRates: []*engine.IntervalRate{ + { + IntervalStart: time.Duration(0), + }, + }, + } + err := rt1.Compile() + if err != nil { + t.Error(err) + } + expected := []*engine.RateSInterval{ + { + UsageStart: 0, + Increments: []*engine.RateSIncrement{ + { + Rate: &engine.Rate{ + ID: "RT_1", + ActivationTimes: "* * 27 02 *", + IntervalRates: []*engine.IntervalRate{ + { + IntervalStart: time.Duration(0), + }, + }, + }, + }, + }, + }, + } + err = expected[0].Increments[0].Rate.Compile() + if err != nil { + t.Error(err) + } + aRts := []*engine.Rate{rt1} + sTime := time.Date(0001, 02, 27, 0, 0, 0, 0, time.UTC) + usage := 48 * time.Hour + if ordRts, err := orderRatesOnIntervals(aRts, sTime, usage, false, 5); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(ordRts, expected) { + t.Errorf("Expected %+v, received %+v", utils.ToJSON(expected), utils.ToJSON(ordRts)) + } +} + +func TestOrderRatesOnIntervalWinnNill(t *testing.T) { + rt1 := &engine.Rate{ + ID: "RT_1", + ActivationTimes: "* * 1 * *", + IntervalRates: []*engine.IntervalRate{ + { + IntervalStart: time.Duration(0), + }, + }, + } + err := rt1.Compile() + if err != nil { + t.Error(err) + } + expected := []*engine.RateSInterval{ + { + UsageStart: 0, + Increments: []*engine.RateSIncrement{ + { + Rate: &engine.Rate{ + ID: "RT_1", + ActivationTimes: "* * 1 * *", + IntervalRates: []*engine.IntervalRate{ + { + IntervalStart: time.Duration(0), + }, + }, + }, + }, + }, + }, + } + err = expected[0].Increments[0].Rate.Compile() + if err != nil { + t.Error(err) + } + aRts := []*engine.Rate{rt1} + sTime := time.Date(2020, 12, 1, 0, 0, 0, 0, time.UTC) + usage := 96 * time.Hour + if ordRts, err := orderRatesOnIntervals(aRts, sTime, usage, true, 4); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(ordRts, expected) { + t.Errorf("Expected %+v, received %+v", utils.ToJSON(expected), utils.ToJSON(ordRts)) + } +} + +func TestOrderRatesOnIntervalIntervalStartHigherThanEndIdx(t *testing.T) { + rt1 := &engine.Rate{ + ID: "RT_1", + ActivationTimes: "* * 1 * *", + IntervalRates: []*engine.IntervalRate{ + { + IntervalStart: 48 * time.Hour, + }, + }, + } + err := rt1.Compile() + if err != nil { + t.Error(err) + } + expected := []*engine.RateSInterval{ + { + UsageStart: 0, + Increments: []*engine.RateSIncrement{ + { + Rate: &engine.Rate{ + ID: "RT_1", + ActivationTimes: "* * 1 * *", + IntervalRates: []*engine.IntervalRate{ + { + IntervalStart: 48 * time.Hour, + }, + }, + }, + IntervalRateIndex: 1, + }, + }, + }, + } + err = expected[0].Increments[0].Rate.Compile() + if err != nil { + t.Error(err) + } + aRts := []*engine.Rate{rt1} + sTime := time.Date(2020, 12, 1, 0, 0, 0, 0, time.UTC) + usage := 48 * time.Hour + if _, err := orderRatesOnIntervals(aRts, sTime, usage, false, 4); err != nil { + t.Error(err) + } +} + +func TestOrderRatesOnIntervalStartLowerThanEndIdx(t *testing.T) { + rt1 := &engine.Rate{ + ID: "RT_1", + ActivationTimes: "* * 1 * *", + IntervalRates: []*engine.IntervalRate{ + { + IntervalStart: 23 * time.Hour, + }, + { + IntervalStart: -time.Hour, + }, + }, + } + err := rt1.Compile() + if err != nil { + t.Error(err) + } + expected := []*engine.RateSInterval{ + { + UsageStart: 0, + Increments: []*engine.RateSIncrement{ + { + Rate: &engine.Rate{ + ID: "RT_1", + ActivationTimes: "* * 1 * *", + IntervalRates: []*engine.IntervalRate{ + { + IntervalStart: 23 * time.Hour, + }, + { + IntervalStart: -time.Hour, + }, + }, + }, + IntervalRateIndex: 1, + }, + }, + }, + } + err = expected[0].Increments[0].Rate.Compile() + if err != nil { + t.Error(err) + } + aRts := []*engine.Rate{rt1} + sTime := time.Date(2020, 12, 1, 0, 0, 0, 0, time.UTC) + usage := 48 * time.Hour + if ordRts, err := orderRatesOnIntervals(aRts, sTime, usage, false, 4); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(ordRts, expected) { + t.Errorf("Expected %+v, received %+v", utils.ToJSON(expected), utils.ToJSON(ordRts)) + } +}