From 35091a5538ab005d44feee0d554b98690bf50426 Mon Sep 17 00:00:00 2001 From: gezimbll Date: Thu, 16 Mar 2023 11:58:45 -0400 Subject: [PATCH] Adding unit tests at engine --- engine/caches_test.go | 48 +++++++++++++- engine/calldesc_test.go | 75 ++++++++++++++------- engine/cdrs_test.go | 1 - engine/responder_test.go | 59 ++++++++++++++++- engine/storage_test.go | 35 +++++++++- engine/thresholds_test.go | 134 ++++++++++++++++++++++++++++++++++++-- 6 files changed, 315 insertions(+), 37 deletions(-) diff --git a/engine/caches_test.go b/engine/caches_test.go index 94c39be72..226345c14 100644 --- a/engine/caches_test.go +++ b/engine/caches_test.go @@ -69,10 +69,56 @@ func TestCacheV1ReloadCache(t *testing.T) { attrs := utils.AttrReloadCacheWithArgDispatcher{ AttrReloadCache: utils.AttrReloadCache{ ArgsCache: utils.ArgsCache{ - FilterIDs: []string{"DSP_FLT"}, + FilterIDs: []string{"DSP_FLT"}, + DestinationIDs: []string{"CRUDDestination2"}, + ReverseDestinationIDs: []string{"CRUDDestination2"}, + RatingPlanIDs: []string{"RP_DFLT"}, + RatingProfileIDs: []string{"*out:cgrates:call:1001"}, }, }, } + dst := &Destination{Id: "CRUDDestination2", Prefixes: []string{"+491", "+492", "+493"}} + dm.SetDestination(dst, utils.NonTransactional) + dm.SetReverseDestination(dst, utils.NonTransactional) + rp := &RatingPlan{ + Id: "RP_DFLT", + Timings: map[string]*RITiming{ + "30eab301": { + StartTime: "00:00:00", + }, + }, + Ratings: map[string]*RIRate{ + "b457f861": { + Rates: []*Rate{ + { + GroupIntervalStart: 0, + Value: 0.01, + RateIncrement: time.Second, + RateUnit: time.Second, + }, + }, + RoundingMethod: utils.ROUNDING_MIDDLE, + RoundingDecimals: 4, + }, + }, + DestinationRates: map[string]RPRateList{ + "CRUDDestination2": []*RPRate{ + { + Timing: "30eab301", + Rating: "b457f861", + Weight: 10, + }, + }, + }, + } + dm.SetRatingPlan(rp, utils.NonTransactional) + rP := &RatingProfile{Id: utils.ConcatenatedKey(utils.META_OUT, "cgrates", "call", "1001"), + RatingPlanActivations: RatingPlanActivations{&RatingPlanActivation{ + ActivationTime: time.Date(2015, 01, 01, 8, 0, 0, 0, time.UTC), + RatingPlanId: rp.Id, + }}, + } + dm.SetRatingProfile(rP, utils.NonTransactional) fltr := &Filter{ Tenant: "cgrates.org", ID: "DSP_FLT", diff --git a/engine/calldesc_test.go b/engine/calldesc_test.go index f977d3bd3..a9ff49e51 100644 --- a/engine/calldesc_test.go +++ b/engine/calldesc_test.go @@ -24,6 +24,7 @@ import ( "testing" "time" + "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" ) @@ -2044,28 +2045,54 @@ func TestCDRefundIncrementspanic(t *testing.T) { } } -// func TestCallDescRefundRounding(t *testing.T) { -// cgrEv := &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "Generated", -// Event: map[string]interface{}{ -// "Account": "acc1", -// "AnswerTime": time.Date(2015, 3, 23, 6, 0, 0, 0, time.UTC), -// "Category": "call", -// "Destination": "0723123113", -// "Subject": "acc1", -// "Tenant": "cgrates.org", -// "ToR": "", -// "Usage": time.Duration(30) * time.Minute, -// }, -// } -// cd, err := NewCallDescriptorFromCGREvent(cgrEv, "UTC") -// if err != nil { -// t.Error(err) -// } +func TestCallDescRefundRounding(t *testing.T) { + tmpDm := dm + cfg, _ := config.NewDefaultCGRConfig() + db := NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items) + defer func() { + SetDataStorage(tmpDm) + }() + dm := NewDataManager(db, cfg.CacheCfg(), nil) -// if _, err := cd.RefundRounding(); err != nil { -// t.Error(err) -// } -// } -// unfinished + cgrEv := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "Generated", + Event: map[string]interface{}{ + "Account": "1001", + "AnswerTime": time.Date(2018, 3, 23, 6, 0, 0, 0, time.UTC), + "Category": "call", + "Destination": "1002", + "Subject": "1001", + "Tenant": "cgrates.org", + "ToR": "", + "Usage": time.Duration(30) * time.Minute, + "SetupTime": time.Date(2017, 3, 23, 6, 0, 0, 0, time.UTC), + }, + } + cd, err := NewCallDescriptorFromCGREvent(cgrEv, "UTC") + if err != nil { + t.Error(err) + } + cd.Increments = Increments{ + {Cost: 2, BalanceInfo: &DebitInfo{ + Monetary: &MonetaryInfo{UUID: "moneya"}, AccountID: "cgrates.org:1001"}}, + {Cost: 2, Duration: 3 * time.Second, BalanceInfo: &DebitInfo{ + Unit: &UnitInfo{UUID: "minutea"}, + Monetary: &MonetaryInfo{UUID: "moneya"}, AccountID: "cgrates.org:1002"}}, + &Increment{Duration: 4 * time.Second, BalanceInfo: &DebitInfo{ + Unit: &UnitInfo{UUID: "minuteb"}, AccountID: "cgrates.org:1003"}}, + } + expAcc := &Account{ + ID: "cgrates.org:1001", + } + SetDataStorage(dm) + if err := dm.SetAccount(expAcc); err != nil { + t.Error(err) + } + + if acc, err := cd.RefundRounding(); err != nil { + t.Error(err) + } else if expAcc.ID != acc.ID { + t.Errorf("Expected %v,Received %v", utils.ToJSON(expAcc), utils.ToJSON(acc)) + } +} diff --git a/engine/cdrs_test.go b/engine/cdrs_test.go index 0aa37287e..d8ed47b01 100644 --- a/engine/cdrs_test.go +++ b/engine/cdrs_test.go @@ -274,7 +274,6 @@ func TestCDRSStoreSessionCost22(t *testing.T) { cfg, _ := config.NewDefaultCGRConfig() db := NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items) dm := NewDataManager(db, cfg.CacheCfg(), nil) - cdrS := &CDRServer{ cgrCfg: cfg, cdrDb: db, diff --git a/engine/responder_test.go b/engine/responder_test.go index 5d76805ac..d55e1bd47 100644 --- a/engine/responder_test.go +++ b/engine/responder_test.go @@ -768,7 +768,7 @@ func TestResponderMaxDebit11(t *testing.T) { Subject: "1001", Account: "1001", Destination: "1002", - DurationIndex: 90, + DurationIndex: 30, TimeStart: tStart, TimeEnd: tEnd, ToR: utils.MONETARY, @@ -805,7 +805,7 @@ func TestResponderMaxDebit11(t *testing.T) { }, }, RoundingMethod: utils.ROUNDING_MIDDLE, - RoundingDecimals: 2, + RoundingDecimals: 4, }, }, Timings: map[string]*RITiming{ @@ -826,6 +826,9 @@ func TestResponderMaxDebit11(t *testing.T) { }, }, } + rsponder.MaxComputedUsage = map[string]time.Duration{ + utils.MONETARY: 90 * time.Second, + } if err := dm.SetRatingPlan(rp, utils.NonTransactional); err != nil { t.Error(err) @@ -843,7 +846,7 @@ func TestResponderMaxDebit11(t *testing.T) { t.Error(err) } var reply CallCost - if err := rsponder.MaxDebit(cd, &reply); err == nil { + if err := rsponder.MaxDebit(cd, &reply); err != nil { t.Error(err) } @@ -907,3 +910,53 @@ func TestResponderRefundRounding33(t *testing.T) { t.Error(err) } } + +func TestResponderRounding(t *testing.T) { + cfg, _ := config.NewDefaultCGRConfig() + db := NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items) + tmpDm := dm + dm := NewDataManager(db, cfg.CacheCfg(), nil) + defer func() { + SetDataStorage(tmpDm) + }() + tStart, _ := utils.ParseTimeDetectLayout("2020-08-07T17:30:00Z", utils.EmptyString) + tEnd, _ := utils.ParseTimeDetectLayout("2020-08-07T17:31:30Z", utils.EmptyString) + arg := &CallDescriptorWithArgDispatcher{ + CallDescriptor: &CallDescriptor{ + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1002", + DurationIndex: 90, + TimeStart: tStart, + TimeEnd: tEnd, + ToR: utils.VOICE, + Increments: Increments{ + &Increment{ + Duration: time.Minute, + Cost: 10.4, + BalanceInfo: &DebitInfo{ + Unit: &UnitInfo{UUID: "1", DestinationID: "1", Consumed: 2.3, ToR: utils.VOICE, RateInterval: &RateInterval{Rating: &RIRate{Rates: RateGroups{&Rate{GroupIntervalStart: 0, Value: 100, RateIncrement: 10 * time.Second, RateUnit: time.Second}}}}}, + Monetary: &MonetaryInfo{UUID: "2"}, + AccountID: "cgrates.org:1001"}, + }, + }, + }, + } + SetDataStorage(dm) + dm.SetAccount(&Account{ + ID: "cgrates.org:1001", + BalanceMap: map[string]Balances{ + utils.MONETARY: { + &Balance{Value: 11, Weight: 20, DestinationIDs: utils.NewStringMap("1002")}, + }}, + }) + rsponder.MaxComputedUsage = map[string]time.Duration{ + utils.VOICE: 2 * time.Minute, + } + var reply Account + if err := rsponder.RefundRounding(arg, &reply); err != nil { + t.Error(err) + } +} diff --git a/engine/storage_test.go b/engine/storage_test.go index 99e90735b..6414f14a5 100644 --- a/engine/storage_test.go +++ b/engine/storage_test.go @@ -18,6 +18,7 @@ along with this program. If not, see package engine import ( + "reflect" "testing" "time" @@ -409,7 +410,6 @@ func TestIDBGetTpSuppliers(t *testing.T) { func TestTPDispatcherHosts(t *testing.T) { cfg, _ := config.NewDefaultCGRConfig() db := NewInternalDB(nil, nil, false, cfg.StorDbCfg().Items) - dpp := []*utils.TPDispatcherHost{ { TPid: "TP1", @@ -428,12 +428,41 @@ func TestTPDispatcherHosts(t *testing.T) { }, }}, } - if err := db.SetTPDispatcherHosts(dpp); err != nil { t.Error(err) } if _, err := db.GetTPDispatcherHosts("TP1", "cgrates.org", "ALL1"); err != nil { t.Error(err) } - +} + +func TestTPThresholds(t *testing.T) { + cfg, _ := config.NewDefaultCGRConfig() + db := NewInternalDB(nil, nil, false, cfg.StorDbCfg().Items) + thresholds := []*utils.TPThresholdProfile{ + { + TPid: "TH1", + Tenant: "cgrates.org", + ID: "Threshold", + FilterIDs: []string{"FLTR_1", "FLTR_2"}, + ActivationInterval: &utils.TPActivationInterval{ + ActivationTime: "2014-07-29T15:00:00Z", + ExpiryTime: "", + }, + MaxHits: -1, + MinSleep: "1s", + Blocker: true, + Weight: 10, + ActionIDs: []string{"Thresh1"}, + Async: true, + }, + } + if err := db.SetTPThresholds(thresholds); err != nil { + t.Error(err) + } + if thds, err := db.GetTPThresholds("TH1", "cgrates.org", "Threshold"); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(thresholds, thds) { + t.Errorf("Expected %v,Received %v", utils.ToJSON(thresholds), utils.ToJSON(thds)) + } } diff --git a/engine/thresholds_test.go b/engine/thresholds_test.go index a50eb5afa..dc02f3e06 100644 --- a/engine/thresholds_test.go +++ b/engine/thresholds_test.go @@ -19,6 +19,7 @@ package engine import ( "reflect" + "sort" "testing" "time" @@ -388,16 +389,18 @@ func TestThresholdsProcessEvent2(t *testing.T) { func TestThresholdSProcessEvent22(t *testing.T) { cfg, _ := config.NewDefaultCGRConfig() + Cache.Clear(nil) db := NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items) tmpDm := dm - dm := NewDataManager(db, cfg.CacheCfg(), nil) - thS, err := NewThresholdService(dm, cfg, NewFilterS(cfg, nil, dm)) defer func() { SetDataStorage(tmpDm) }() + dm := NewDataManager(db, cfg.CacheCfg(), nil) + thS, err := NewThresholdService(dm, cfg, NewFilterS(cfg, nil, dm)) if err != nil { t.Error(err) } + args := &ArgsProcessEvent{ CGREvent: &utils.CGREvent{ Tenant: "cgrates.org", @@ -421,6 +424,7 @@ func TestThresholdSProcessEvent22(t *testing.T) { }, }, } + SetDataStorage(dm) dm.SetFilter(fltr) thP := &ThresholdProfile{ Tenant: "cgrates.org", @@ -431,6 +435,7 @@ func TestThresholdSProcessEvent22(t *testing.T) { Blocker: false, Weight: 20.0, Async: false, + ActionIDs: []string{"ACT_LOG"}, } dm.SetThresholdProfile(thP, true) dm.SetThreshold(&Threshold{Tenant: thP.Tenant, ID: thP.ID}) @@ -442,10 +447,129 @@ func TestThresholdSProcessEvent22(t *testing.T) { Weight: utils.Float64Pointer(20)}}, } dm.SetActions("ACT_LOG", acs, utils.NonTransactional) - SetDataStorage(dm) - var reply []string - if err := thS.V1ProcessEvent(args, &reply); err == nil { + if err := thS.V1ProcessEvent(args, &reply); err != nil { t.Error(err) } } + +func TestThresholdForEvent(t *testing.T) { + cfg, _ := config.NewDefaultCGRConfig() + db := NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items) + tmpDm := dm + defer func() { + SetDataStorage(tmpDm) + }() + dm := NewDataManager(db, cfg.CacheCfg(), nil) + thS, err := NewThresholdService(dm, cfg, NewFilterS(cfg, nil, dm)) + if err != nil { + t.Error(err) + } + args := &ArgsProcessEvent{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "TestSesItProccesCDR", + Event: map[string]interface{}{ + utils.Tenant: "cgrates.org", + utils.Category: "call", + utils.ToR: utils.VOICE, + utils.OriginID: "TestTerminate", + utils.RequestType: utils.META_PREPAID, + utils.Account: "1002", + utils.Subject: "1001", + utils.Destination: "1001", + utils.SetupTime: time.Date(2018, time.January, 7, 16, 60, 0, 0, time.UTC), + utils.AnswerTime: time.Date(2018, time.January, 7, 16, 60, 10, 0, time.UTC), + utils.Usage: 2 * time.Second, + }, + }, + } + fltrs := []*Filter{ + { + Tenant: "cgrates.org", + ID: "FLTR_1", + Rules: []*FilterRule{ + { + Type: utils.MetaString, + Element: utils.DynamicDataPrefix + utils.MetaReq + utils.NestingSep + utils.ToR, + Values: []string{utils.VOICE}, + }, + { + Type: utils.MetaString, + Element: utils.DynamicDataPrefix + utils.MetaReq + utils.NestingSep + utils.RequestType, + Values: []string{utils.META_PREPAID}, + }, + }, + }, + { + Tenant: "cgrates.org", + ID: "FLTR_2", + Rules: []*FilterRule{ + { + Type: utils.MetaString, + Element: utils.DynamicDataPrefix + utils.MetaReq + utils.NestingSep + utils.OriginID, + Values: []string{"TestTerminate"}, + }, + }, + }, + } + for _, fltr := range fltrs { + dm.SetFilter(fltr) + } + thp := &ThresholdProfile{Tenant: "cgrates.org", + ID: "TH_1", + FilterIDs: []string{"FLTR_1"}, + ActivationInterval: &utils.ActivationInterval{ + ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), + ExpiryTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), + }, + MaxHits: -1, + MinSleep: time.Duration(1 * time.Millisecond), + Weight: 10.0} + dm.SetThresholdProfile(thp, true) + thp2 := &ThresholdProfile{ + Tenant: "cgrates.org", + ID: "TH_2", + FilterIDs: []string{"FLTR_2"}, + MaxHits: -1, + MinSleep: time.Duration(1 * time.Millisecond), + Weight: 90.0, + Async: true, + } + dm.SetThresholdProfile(thp2, true) + ths := Thresholds{ + &Threshold{ + Tenant: thp.Tenant, + ID: thp.ID, + }, + &Threshold{ + Tenant: thp2.Tenant, + ID: thp2.ID, + }, + } + for _, th := range ths { + dm.SetThreshold(th) + } + var reply Thresholds + if err := thS.V1GetThresholdsForEvent(args, &reply); err != nil { + t.Error(err) + } + + sort.Slice(reply, func(i, j int) bool { + return reply[i].ID < reply[j].ID + }) + if !reflect.DeepEqual(ths, reply) { + t.Errorf("Expected %v,Received %v", utils.ToJSON(ths), utils.ToJSON(reply)) + } + expID := []string{"TH_1", "TH_2"} + var tIDs []string + if err := thS.V1GetThresholdIDs("cgrates.org", &tIDs); err != nil { + t.Error(err) + } + sort.Slice(tIDs, func(i, j int) bool { + return tIDs[i] < tIDs[j] + }) + if !reflect.DeepEqual(tIDs, expID) { + t.Errorf("Expected %v,Received %v", expID, tIDs) + } +}