diff --git a/engine/datamanager_test.go b/engine/datamanager_test.go index 5ac035afa..85b12e287 100644 --- a/engine/datamanager_test.go +++ b/engine/datamanager_test.go @@ -18,6 +18,7 @@ along with this program. If not, see package engine import ( + "reflect" "testing" "time" @@ -2389,7 +2390,6 @@ func TestDMGetThresholdProfileSetThPrfErr2(t *testing.T) { } } -// unfinished set without using cache.set and then go cache.get func TestDMCacheDataFromDBResourceProfilesPrefix(t *testing.T) { tmp := Cache defer func() { @@ -2402,10 +2402,6 @@ func TestDMCacheDataFromDBResourceProfilesPrefix(t *testing.T) { cM := NewConnManager(cfg) dm := NewDataManager(data, cfg.CacheCfg(), cM) - if err := Cache.Set(context.Background(), utils.CachePrefixToInstance[utils.ResourceProfilesPrefix], "cgrates.org:RL2", &ResourceProfile{}, []string{}, true, utils.NonTransactional); err != nil { - t.Error(err) - } - rp := &ResourceProfile{ Tenant: "cgrates.org", ID: "RL2", @@ -2425,8 +2421,345 @@ func TestDMCacheDataFromDBResourceProfilesPrefix(t *testing.T) { t.Error(err) } - if err := dm.CacheDataFromDB(context.Background(), utils.ResourceProfilesPrefix, []string{utils.MetaAny}, true); err != nil { + if _, ok := Cache.Get(utils.CacheResourceProfiles, "cgrates.org:RL2"); ok { + t.Error("expected ok to be false") + } + + if err := dm.CacheDataFromDB(context.Background(), utils.ResourceProfilesPrefix, []string{utils.MetaAny}, false); err != nil { t.Error(err) } + if rcv, ok := Cache.Get(utils.CacheResourceProfiles, "cgrates.org:RL2"); !ok { + t.Error("expected ok to be true") + } else if !reflect.DeepEqual(rcv, rp) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", rp, rcv) + } + +} + +func TestDMCacheDataFromDBResourcesPrefix(t *testing.T) { + tmp := Cache + defer func() { + Cache = tmp + }() + Cache.Clear(nil) + + cfg := config.NewDefaultCGRConfig() + data := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + cM := NewConnManager(cfg) + dm := NewDataManager(data, cfg.CacheCfg(), cM) + + rs := &Resource{ + Tenant: "cgrates.org", + ID: "ResGroup2", + Usages: map[string]*ResourceUsage{ + "RU1": { + Tenant: "cgrates.org", + ID: "RU1", + Units: 9, + }, + }, + tUsage: utils.Float64Pointer(9), + } + + if err := dm.SetResource(context.Background(), rs); err != nil { + t.Error(err) + } + + if _, ok := Cache.Get(utils.CacheResources, "cgrates.org:ResGroup2"); ok { + t.Error("expected ok to be false") + } + + if err := dm.CacheDataFromDB(context.Background(), utils.ResourcesPrefix, []string{utils.MetaAny}, false); err != nil { + t.Error(err) + } + + if rcv, ok := Cache.Get(utils.CacheResources, "cgrates.org:ResGroup2"); !ok { + t.Error("expected ok to be true") + } else if !reflect.DeepEqual(rcv, rs) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", rs, rcv) + } + +} + +func TestDMCacheDataFromDBStatQueueProfilePrefix(t *testing.T) { + tmp := Cache + defer func() { + Cache = tmp + }() + Cache.Clear(nil) + + cfg := config.NewDefaultCGRConfig() + data := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + cM := NewConnManager(cfg) + dm := NewDataManager(data, cfg.CacheCfg(), cM) + + sQP := &StatQueueProfile{ + Tenant: "cgrates.org", + ID: "StatQueueProfile3", + FilterIDs: []string{"fltr_test"}, + QueueLength: 10, + TTL: 10 * time.Second, + Metrics: []*MetricWithFilters{ + { + MetricID: "*sum#~*req.Usage", + }, + }, + ThresholdIDs: []string{}, + Stored: true, + Weights: utils.DynamicWeights{ + { + Weight: 20, + }, + }, + MinItems: 1, + } + + if err := dm.SetStatQueueProfile(context.Background(), sQP, false); err != nil { + t.Error(err) + } + + if _, ok := Cache.Get(utils.CacheStatQueueProfiles, "cgrates.org:StatQueueProfile3"); ok { + t.Error("expected ok to be false") + } + + if err := dm.CacheDataFromDB(context.Background(), utils.StatQueueProfilePrefix, []string{utils.MetaAny}, false); err != nil { + t.Error(err) + } + + if rcv, ok := Cache.Get(utils.CacheStatQueueProfiles, "cgrates.org:StatQueueProfile3"); !ok { + t.Error("expected ok to be true") + } else if !reflect.DeepEqual(rcv, sQP) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", sQP, rcv) + } + +} + +func TestDMCacheDataFromDBStatQueuePrefix(t *testing.T) { + tmp := Cache + defer func() { + Cache = tmp + }() + Cache.Clear(nil) + + cfg := config.NewDefaultCGRConfig() + data := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + cM := NewConnManager(cfg) + dm := NewDataManager(data, cfg.CacheCfg(), cM) + + sq := &StatQueue{ + Tenant: "cgrates.org", + ID: "SQ1", + SQItems: []SQItem{ + { + EventID: "SqProcessEvent", + }, + }, + SQMetrics: make(map[string]StatMetric), + } + + if err := dm.SetStatQueue(context.Background(), sq); err != nil { + t.Error(err) + } + + if _, ok := Cache.Get(utils.CacheStatQueues, "cgrates.org:SQ1"); ok { + t.Error("expected ok to be false") + } + + if err := dm.CacheDataFromDB(context.Background(), utils.StatQueuePrefix, []string{utils.MetaAny}, false); err != nil { + t.Error(err) + } + + if rcv, ok := Cache.Get(utils.CacheStatQueues, "cgrates.org:SQ1"); !ok { + t.Error("expected ok to be true") + } else if !reflect.DeepEqual(rcv, sq) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", sq, rcv) + } + +} + +func TestDMCacheDataFromDBThresholdProfilePrefix(t *testing.T) { + tmp := Cache + defer func() { + Cache = tmp + }() + Cache.Clear(nil) + + cfg := config.NewDefaultCGRConfig() + data := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + cM := NewConnManager(cfg) + dm := NewDataManager(data, cfg.CacheCfg(), cM) + + thP := &ThresholdProfile{ + Tenant: "cgrates.org", + ID: "THD_2", + FilterIDs: []string{"*string:~*req.Account:1001"}, + ActionProfileIDs: []string{"actPrfID"}, + MaxHits: 7, + MinHits: 0, + Weights: utils.DynamicWeights{ + { + Weight: 20, + }, + }, + Async: true, + } + + if err := dm.SetThresholdProfile(context.Background(), thP, false); err != nil { + t.Error(err) + } + + if _, ok := Cache.Get(utils.CacheThresholdProfiles, "cgrates.org:THD_2"); ok { + t.Error("expected ok to be false") + } + + if err := dm.CacheDataFromDB(context.Background(), utils.ThresholdProfilePrefix, []string{utils.MetaAny}, false); err != nil { + t.Error(err) + } + + if rcv, ok := Cache.Get(utils.CacheThresholdProfiles, "cgrates.org:THD_2"); !ok { + t.Error("expected ok to be true") + } else if !reflect.DeepEqual(rcv, thP) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", thP, rcv) + } + +} + +func TestDMCacheDataFromDBThresholdPrefix(t *testing.T) { + tmp := Cache + defer func() { + Cache = tmp + }() + Cache.Clear(nil) + + cfg := config.NewDefaultCGRConfig() + data := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + cM := NewConnManager(cfg) + dm := NewDataManager(data, cfg.CacheCfg(), cM) + + th := &Threshold{ + Tenant: "cgrates.org", + ID: "TH_3", + Hits: 0, + } + + if err := dm.SetThreshold(context.Background(), th); err != nil { + t.Error(err) + } + + if _, ok := Cache.Get(utils.CacheThresholds, "cgrates.org:TH_3"); ok { + t.Error("expected ok to be false") + } + + if err := dm.CacheDataFromDB(context.Background(), utils.ThresholdPrefix, []string{utils.MetaAny}, false); err != nil { + t.Error(err) + } + + if rcv, ok := Cache.Get(utils.CacheThresholds, "cgrates.org:TH_3"); !ok { + t.Error("expected ok to be true") + } else if !reflect.DeepEqual(rcv, th) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", th, rcv) + } + +} + +func TestDMCacheDataFromDBFilterPrefix(t *testing.T) { + tmp := Cache + defer func() { + Cache = tmp + }() + Cache.Clear(nil) + + cfg := config.NewDefaultCGRConfig() + data := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + cM := NewConnManager(cfg) + dm := NewDataManager(data, cfg.CacheCfg(), cM) + + fltr := &Filter{ + Tenant: cfg.GeneralCfg().DefaultTenant, + ID: "FLTR_CP_2", + Rules: []*FilterRule{ + { + Type: utils.MetaString, + Element: "~*req.Charger", + Values: []string{"ChargerProfile2"}, + }, + }, + } + + if err := dm.SetFilter(context.Background(), fltr, false); err != nil { + t.Error(err) + } + + if _, ok := Cache.Get(utils.CacheFilters, "cgrates.org:FLTR_CP_2"); ok { + t.Error("expected ok to be false") + } + + if err := dm.CacheDataFromDB(context.Background(), utils.FilterPrefix, []string{utils.MetaAny}, false); err != nil { + t.Error(err) + } + + if rcv, ok := Cache.Get(utils.CacheFilters, "cgrates.org:FLTR_CP_2"); !ok { + t.Error("expected ok to be true") + } else if !reflect.DeepEqual(rcv, fltr) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", fltr, rcv) + } + +} + +func TestDMCacheDataFromDBRouteProfilePrefix(t *testing.T) { + tmp := Cache + defer func() { + Cache = tmp + }() + Cache.Clear(nil) + + cfg := config.NewDefaultCGRConfig() + data := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + cM := NewConnManager(cfg) + dm := NewDataManager(data, cfg.CacheCfg(), cM) + + routeProf := &RouteProfile{ + + Tenant: "cgrates.org", + ID: "RP_1", + FilterIDs: []string{"fltr_test"}, + Weights: utils.DynamicWeights{{}}, + Sorting: utils.MetaQOS, + SortingParameters: []string{"param"}, + Routes: []*Route{{ + ID: "RT1", + FilterIDs: []string{"fltr1"}, + AccountIDs: []string{"acc1"}, + RateProfileIDs: []string{"rp1"}, + ResourceIDs: []string{"res1"}, + StatIDs: []string{"stat1"}, + Weights: utils.DynamicWeights{{}}, + Blockers: utils.DynamicBlockers{ + { + Blocker: true, + }, + }, + RouteParameters: "params", + }}, + } + + if err := dm.SetRouteProfile(context.Background(), routeProf, false); err != nil { + t.Error(err) + } + + if _, ok := Cache.Get(utils.CacheRouteProfiles, "cgrates.org:RP_1"); ok { + t.Error("expected ok to be false") + } + + if err := dm.CacheDataFromDB(context.Background(), utils.RouteProfilePrefix, []string{utils.MetaAny}, false); err != nil { + t.Error(err) + } + + if rcv, ok := Cache.Get(utils.CacheRouteProfiles, "cgrates.org:RP_1"); !ok { + t.Error("expected ok to be true") + } else if !reflect.DeepEqual(rcv, routeProf) { + t.Errorf("\nExpected <%+v>, \nReceived <%+v>", routeProf, rcv) + } + } diff --git a/engine/thresholds_test.go b/engine/thresholds_test.go index 18c0df195..092ec54c5 100644 --- a/engine/thresholds_test.go +++ b/engine/thresholds_test.go @@ -3362,3 +3362,158 @@ func TestThresholdProfileMerge(t *testing.T) { t.Errorf("Expected %v \n but received \n %v", utils.ToJSON(exp), utils.ToJSON(dp)) } } + +func TestThresholdSmatchingThresholdsForEventGetOptsErr(t *testing.T) { + + cfg := config.NewDefaultCGRConfig() + cfg.ThresholdSCfg().Opts.ProfileIDs = []*utils.DynamicStringSliceOpt{ + { + FilterIDs: []string{"*string"}, + Tenant: "cgrates.org", + Value: []string{"ProfIdVal"}, + }, + } + + dataDB := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + cM := NewConnManager(cfg) + dm := NewDataManager(dataDB, cfg.CacheCfg(), cM) + filterS := NewFilterS(cfg, cM, dm) + tS := &ThresholdS{ + dm: dm, + storedTdIDs: utils.StringSet{ + "Th1": struct{}{}, + }, + cfg: cfg, + fltrS: filterS, + loopStopped: make(chan struct{}, 1), + stopBackup: make(chan struct{}), + } + + args := &utils.CGREvent{ + ID: "TestV1DebitID", + Tenant: "cgrates.org", + Event: map[string]interface{}{ + utils.AccountField: "1004", + }, + APIOpts: map[string]interface{}{ + utils.MetaUsage: "3m", + }, + } + + expErr := "inline parse error for string: <*string>" + if _, err := tS.matchingThresholdsForEvent(context.Background(), args.Tenant, args); err.Error() != expErr || err == nil { + t.Errorf("Expected error <%v>, Received <%v>", expErr, err) + } + +} + +func TestThresholdSmatchingThresholdsForEventWeightErr(t *testing.T) { + cfg := config.NewDefaultCGRConfig() + cfg.ThresholdSCfg().Opts.ProfileIDs = []*utils.DynamicStringSliceOpt{ + { + Tenant: "cgrates.org", + Value: []string{"ACC1"}, + }, + } + cfg.ThresholdSCfg().Opts.ProfileIgnoreFilters = []*utils.DynamicBoolOpt{ + { + Tenant: "cgrates.org", + Value: true, + }, + } + dataDB := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + cM := NewConnManager(cfg) + dm := NewDataManager(dataDB, cfg.CacheCfg(), cM) + dm.dataDB = &DataDBMock{ + GetThresholdProfileDrvF: func(ctx *context.Context, tenant, id string) (tp *ThresholdProfile, err error) { + return &ThresholdProfile{ + Tenant: "cgrates.org", + ID: "THD_2", + FilterIDs: []string{"*string:~*req.Account:1001"}, + ActionProfileIDs: []string{"actPrfID"}, + MaxHits: 7, + MinHits: 0, + Weights: []*utils.DynamicWeight{ + { + FilterIDs: []string{"*stirng:~*req.Account:1001"}, + Weight: 64, + }, + }, + Async: true, + }, nil + }, + GetThresholdDrvF: func(ctx *context.Context, tenant, id string) (*Threshold, error) { return &Threshold{}, nil }, + } + filterS := NewFilterS(cfg, cM, dm) + tS := &ThresholdS{ + dm: dm, + storedTdIDs: utils.StringSet{ + "Th1": struct{}{}, + }, + cfg: cfg, + fltrS: filterS, + loopStopped: make(chan struct{}, 1), + stopBackup: make(chan struct{}), + } + + args := &utils.CGREvent{ + ID: "EvID", + Tenant: "cgrates.org", + Event: map[string]interface{}{ + utils.AccountField: "1004", + }, + APIOpts: map[string]interface{}{ + utils.MetaUsage: "3m", + }, + } + + expErr := "NOT_IMPLEMENTED:*stirng" + if _, err := tS.matchingThresholdsForEvent(context.Background(), args.Tenant, args); err.Error() != expErr || err == nil { + t.Errorf("Expected error <%v>, Received <%v>", expErr, err) + } +} + +func TestThresholdsV1ResetThresholdStoreErr(t *testing.T) { + + tmp := Cache + tmpC := config.CgrConfig() + tmpCM := connMgr + defer func() { + Cache = tmp + config.SetCgrConfig(tmpC) + connMgr = tmpCM + + }() + + cfg := config.NewDefaultCGRConfig() + cfg.ThresholdSCfg().StoreInterval = -1 + cfg.CacheCfg().ReplicationConns = []string{"test"} + cfg.CacheCfg().Partitions[utils.CacheThresholds].Replicate = true + cfg.RPCConns()["test"] = &config.RPCConn{Conns: []*config.RemoteHost{{}}} + config.SetCgrConfig(cfg) + data := NewInternalDB(nil, nil, cfg.DataDbCfg().Items) + dm := NewDataManager(data, cfg.CacheCfg(), nil) + connMgr = NewConnManager(cfg) + Cache = NewCacheS(cfg, dm, nil, nil) + filterS := NewFilterS(cfg, nil, dm) + tS := NewThresholdService(dm, cfg, filterS, connMgr) + th := &Threshold{ + Hits: 2, + Tenant: "cgrates.org", + ID: "TH1", + dirty: utils.BoolPointer(true), + } + if err := dm.SetThreshold(context.Background(), th); err != nil { + t.Error(err) + } + Cache.SetWithoutReplicate(utils.CacheThresholds, th.TenantID(), th, nil, true, utils.NonTransactional) + + var reply string + if err := tS.V1ResetThreshold(context.Background(), &utils.TenantIDWithAPIOpts{ + TenantID: &utils.TenantID{ + ID: "TH1", + }, + }, &reply); err == nil || err.Error() != utils.ErrDisconnected.Error() { + t.Errorf("Expected error <%+v>, Received error <%+v>", utils.ErrDisconnected, err) + } +}