From 1f7e47248c087c1bb69300b856dba9b9b6cbe789 Mon Sep 17 00:00:00 2001 From: TeoV Date: Thu, 28 Jan 2021 12:10:21 +0200 Subject: [PATCH] Add test for *reset_threshold and *reset_stat_queue actions --- actions/actions_test.go | 298 ++++++++++++++++++++++++++++++++++++++++ actions/libactions.go | 24 +++- 2 files changed, 318 insertions(+), 4 deletions(-) diff --git a/actions/actions_test.go b/actions/actions_test.go index 05aae4a24..c9f37b42c 100644 --- a/actions/actions_test.go +++ b/actions/actions_test.go @@ -838,3 +838,301 @@ func TestExportActionWithEeIDs(t *testing.T) { t.Error(err) } } + +func TestExportActionResetThresholdStaticTenantID(t *testing.T) { + // Clear cache because connManager sets the internal connection in cache + engine.Cache.Clear([]string{utils.CacheRPCConnections}) + sMock2 := &testMockCDRsConn{ + calls: map[string]func(arg interface{}, rply interface{}) error{ + utils.ThresholdSv1ResetThreshold: func(arg interface{}, rply interface{}) error { + argConv, can := arg.(*utils.TenantIDWithOpts) + if !can { + return fmt.Errorf("Wrong argument type: %T", arg) + } + if argConv.Tenant != "cgrates.org" { + return fmt.Errorf("Expected %+v, received %+v", "cgrates.org", argConv.Tenant) + } + if argConv.ID != "TH1" { + return fmt.Errorf("Expected %+v, received %+v", "TH1", argConv.ID) + } + return nil + }, + }, + } + internalChann := make(chan rpcclient.ClientConnector, 1) + internalChann <- sMock2 + cfg := config.NewDefaultCGRConfig() + cfg.ActionSCfg().ThresholdSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaThresholds)} + + connMgr := engine.NewConnManager(config.CgrConfig(), map[string]chan rpcclient.ClientConnector{ + utils.ConcatenatedKey(utils.MetaInternal, utils.MetaThresholds): internalChann, + }) + apA := &engine.APAction{ + ID: "ACT_RESET_TH", + Type: utils.MetaResetThreshold, + Value: config.NewRSRParsersMustCompile("cgrates.org;:;TH1", utils.InfieldSep), + } + exportAction := &actResetThreshold{ + tnt: "cgrates.org", + config: cfg, + connMgr: connMgr, + aCfg: apA, + } + evNM := utils.MapStorage{ + utils.MetaOpts: map[string]interface{}{}, + } + if err := exportAction.execute(nil, evNM); err != nil { + t.Error(err) + } +} + +func TestExportActionResetThresholdStaticID(t *testing.T) { + // Clear cache because connManager sets the internal connection in cache + engine.Cache.Clear([]string{utils.CacheRPCConnections}) + sMock2 := &testMockCDRsConn{ + calls: map[string]func(arg interface{}, rply interface{}) error{ + utils.ThresholdSv1ResetThreshold: func(arg interface{}, rply interface{}) error { + argConv, can := arg.(*utils.TenantIDWithOpts) + if !can { + return fmt.Errorf("Wrong argument type: %T", arg) + } + if argConv.Tenant != "cgrates.org" { + return fmt.Errorf("Expected %+v, received %+v", "cgrates.org", argConv.Tenant) + } + if argConv.ID != "TH1" { + return fmt.Errorf("Expected %+v, received %+v", "TH1", argConv.ID) + } + return nil + }, + }, + } + internalChann := make(chan rpcclient.ClientConnector, 1) + internalChann <- sMock2 + cfg := config.NewDefaultCGRConfig() + cfg.ActionSCfg().ThresholdSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaThresholds)} + + connMgr := engine.NewConnManager(config.CgrConfig(), map[string]chan rpcclient.ClientConnector{ + utils.ConcatenatedKey(utils.MetaInternal, utils.MetaThresholds): internalChann, + }) + apA := &engine.APAction{ + ID: "ACT_RESET_TH", + Type: utils.MetaResetThreshold, + Value: config.NewRSRParsersMustCompile("TH1", utils.InfieldSep), + } + exportAction := &actResetThreshold{ + tnt: "cgrates.org", + config: cfg, + connMgr: connMgr, + aCfg: apA, + } + evNM := utils.MapStorage{ + utils.MetaOpts: map[string]interface{}{}, + } + if err := exportAction.execute(nil, evNM); err != nil { + t.Error(err) + } +} + +func TestExportActionResetThresholdVariableID(t *testing.T) { + // Clear cache because connManager sets the internal connection in cache + engine.Cache.Clear([]string{utils.CacheRPCConnections}) + sMock2 := &testMockCDRsConn{ + calls: map[string]func(arg interface{}, rply interface{}) error{ + utils.ThresholdSv1ResetThreshold: func(arg interface{}, rply interface{}) error { + argConv, can := arg.(*utils.TenantIDWithOpts) + if !can { + return fmt.Errorf("Wrong argument type: %T", arg) + } + if argConv.Tenant != "cgrates.org" { + return fmt.Errorf("Expected %+v, received %+v", "cgrates.org", argConv.Tenant) + } + if argConv.ID != "TH1" { + return fmt.Errorf("Expected %+v, received %+v", "TH1", argConv.ID) + } + return nil + }, + }, + } + internalChann := make(chan rpcclient.ClientConnector, 1) + internalChann <- sMock2 + cfg := config.NewDefaultCGRConfig() + cfg.ActionSCfg().ThresholdSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaThresholds)} + + connMgr := engine.NewConnManager(config.CgrConfig(), map[string]chan rpcclient.ClientConnector{ + utils.ConcatenatedKey(utils.MetaInternal, utils.MetaThresholds): internalChann, + }) + apA := &engine.APAction{ + ID: "ACT_RESET_TH", + Type: utils.MetaResetThreshold, + Value: config.NewRSRParsersMustCompile("~*req.RandomName", utils.InfieldSep), + } + exportAction := &actResetThreshold{ + tnt: "cgrates.org", + config: cfg, + connMgr: connMgr, + aCfg: apA, + } + evNM := utils.MapStorage{ + utils.MetaReq: map[string]interface{}{ + utils.AccountField: "10", + utils.Tenant: "cgrates.org", + utils.BalanceType: utils.MetaConcrete, + utils.Cost: 0.15, + utils.ActionType: utils.MetaTopUp, + "RandomName": "TH1", + }, + utils.MetaOpts: map[string]interface{}{}, + } + if err := exportAction.execute(nil, evNM); err != nil { + t.Error(err) + } +} + +func TestExportActionResetStatStaticTenantID(t *testing.T) { + // Clear cache because connManager sets the internal connection in cache + engine.Cache.Clear([]string{utils.CacheRPCConnections}) + sMock2 := &testMockCDRsConn{ + calls: map[string]func(arg interface{}, rply interface{}) error{ + utils.StatSv1ResetStatQueue: func(arg interface{}, rply interface{}) error { + argConv, can := arg.(*utils.TenantIDWithOpts) + if !can { + return fmt.Errorf("Wrong argument type: %T", arg) + } + if argConv.Tenant != "cgrates.org" { + return fmt.Errorf("Expected %+v, received %+v", "cgrates.org", argConv.Tenant) + } + if argConv.ID != "ST1" { + return fmt.Errorf("Expected %+v, received %+v", "TH1", argConv.ID) + } + return nil + }, + }, + } + internalChann := make(chan rpcclient.ClientConnector, 1) + internalChann <- sMock2 + cfg := config.NewDefaultCGRConfig() + cfg.ActionSCfg().StatSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats)} + + connMgr := engine.NewConnManager(config.CgrConfig(), map[string]chan rpcclient.ClientConnector{ + utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats): internalChann, + }) + apA := &engine.APAction{ + ID: "ACT_RESET_ST", + Type: utils.MetaResetStatQueue, + Value: config.NewRSRParsersMustCompile("cgrates.org;:;ST1", utils.InfieldSep), + } + exportAction := &actResetStat{ + tnt: "cgrates.org", + config: cfg, + connMgr: connMgr, + aCfg: apA, + } + evNM := utils.MapStorage{ + utils.MetaOpts: map[string]interface{}{}, + } + if err := exportAction.execute(nil, evNM); err != nil { + t.Error(err) + } +} + +func TestExportActionResetStatStaticID(t *testing.T) { + // Clear cache because connManager sets the internal connection in cache + engine.Cache.Clear([]string{utils.CacheRPCConnections}) + sMock2 := &testMockCDRsConn{ + calls: map[string]func(arg interface{}, rply interface{}) error{ + utils.StatSv1ResetStatQueue: func(arg interface{}, rply interface{}) error { + argConv, can := arg.(*utils.TenantIDWithOpts) + if !can { + return fmt.Errorf("Wrong argument type: %T", arg) + } + if argConv.Tenant != "cgrates.org" { + return fmt.Errorf("Expected %+v, received %+v", "cgrates.org", argConv.Tenant) + } + if argConv.ID != "ST1" { + return fmt.Errorf("Expected %+v, received %+v", "TH1", argConv.ID) + } + return nil + }, + }, + } + internalChann := make(chan rpcclient.ClientConnector, 1) + internalChann <- sMock2 + cfg := config.NewDefaultCGRConfig() + cfg.ActionSCfg().StatSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats)} + + connMgr := engine.NewConnManager(config.CgrConfig(), map[string]chan rpcclient.ClientConnector{ + utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats): internalChann, + }) + apA := &engine.APAction{ + ID: "ACT_RESET_ST", + Type: utils.MetaResetStatQueue, + Value: config.NewRSRParsersMustCompile("ST1", utils.InfieldSep), + } + exportAction := &actResetStat{ + tnt: "cgrates.org", + config: cfg, + connMgr: connMgr, + aCfg: apA, + } + evNM := utils.MapStorage{ + utils.MetaOpts: map[string]interface{}{}, + } + if err := exportAction.execute(nil, evNM); err != nil { + t.Error(err) + } +} + +func TestExportActionResetStatVariableID(t *testing.T) { + // Clear cache because connManager sets the internal connection in cache + engine.Cache.Clear([]string{utils.CacheRPCConnections}) + sMock2 := &testMockCDRsConn{ + calls: map[string]func(arg interface{}, rply interface{}) error{ + utils.StatSv1ResetStatQueue: func(arg interface{}, rply interface{}) error { + argConv, can := arg.(*utils.TenantIDWithOpts) + if !can { + return fmt.Errorf("Wrong argument type: %T", arg) + } + if argConv.Tenant != "cgrates.org" { + return fmt.Errorf("Expected %+v, received %+v", "cgrates.org", argConv.Tenant) + } + if argConv.ID != "ST1" { + return fmt.Errorf("Expected %+v, received %+v", "TH1", argConv.ID) + } + return nil + }, + }, + } + internalChann := make(chan rpcclient.ClientConnector, 1) + internalChann <- sMock2 + cfg := config.NewDefaultCGRConfig() + cfg.ActionSCfg().StatSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats)} + + connMgr := engine.NewConnManager(config.CgrConfig(), map[string]chan rpcclient.ClientConnector{ + utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats): internalChann, + }) + apA := &engine.APAction{ + ID: "ACT_RESET_ST", + Type: utils.MetaResetStatQueue, + Value: config.NewRSRParsersMustCompile("~*req.RandomName", utils.InfieldSep), + } + exportAction := &actResetStat{ + tnt: "cgrates.org", + config: cfg, + connMgr: connMgr, + aCfg: apA, + } + evNM := utils.MapStorage{ + utils.MetaReq: map[string]interface{}{ + utils.AccountField: "10", + utils.Tenant: "cgrates.org", + utils.BalanceType: utils.MetaConcrete, + utils.Cost: 0.15, + utils.ActionType: utils.MetaTopUp, + "RandomName": "ST1", + }, + utils.MetaOpts: map[string]interface{}{}, + } + if err := exportAction.execute(nil, evNM); err != nil { + t.Error(err) + } +} diff --git a/actions/libactions.go b/actions/libactions.go index 971976d93..95ddd46bd 100644 --- a/actions/libactions.go +++ b/actions/libactions.go @@ -110,9 +110,9 @@ func newActioner(cfg *config.CGRConfig, fltrS *engine.FilterS, dm *engine.DataMa case utils.MetaExport: return &actExport{config: cfg, connMgr: connMgr, aCfg: aCfg, tnt: tnt}, nil case utils.MetaResetStatQueue: - return &actResetStat{config: cfg, connMgr: connMgr, aCfg: aCfg}, nil + return &actResetStat{config: cfg, connMgr: connMgr, aCfg: aCfg, tnt: tnt}, nil case utils.MetaResetThreshold: - return &actResetThreshold{config: cfg, connMgr: connMgr, aCfg: aCfg}, nil + return &actResetThreshold{config: cfg, connMgr: connMgr, aCfg: aCfg, tnt: tnt}, nil default: return nil, fmt.Errorf("unsupported action type: <%s>", aCfg.Type) @@ -293,6 +293,7 @@ func (aL *actExport) execute(ctx context.Context, data utils.MapStorage) (err er } type actResetStat struct { + tnt string config *config.CGRConfig connMgr *engine.ConnManager aCfg *engine.APAction @@ -312,12 +313,20 @@ func (aL *actResetStat) execute(ctx context.Context, data utils.MapStorage) (err if tenID, err = aL.cfg().Value.ParseDataProvider(data); err != nil { return } + args := &utils.TenantIDWithOpts{ + TenantID: utils.NewTenantID(tenID), + Opts: data[utils.MetaOpts].(map[string]interface{}), + } + if args.Tenant == utils.EmptyString { // in case that user pass only ID we populate the tenant from the event + args.Tenant = aL.tnt + } var rply string return aL.connMgr.Call(aL.config.ActionSCfg().StatSConns, nil, - utils.StatSv1ResetStatQueue, &utils.TenantIDWithOpts{TenantID: utils.NewTenantID(tenID)}, &rply) + utils.StatSv1ResetStatQueue, args, &rply) } type actResetThreshold struct { + tnt string config *config.CGRConfig connMgr *engine.ConnManager aCfg *engine.APAction @@ -337,7 +346,14 @@ func (aL *actResetThreshold) execute(ctx context.Context, data utils.MapStorage) if tenID, err = aL.cfg().Value.ParseDataProvider(data); err != nil { return } + args := &utils.TenantIDWithOpts{ + TenantID: utils.NewTenantID(tenID), + Opts: data[utils.MetaOpts].(map[string]interface{}), + } + if args.Tenant == utils.EmptyString { // in case that user pass only ID we populate the tenant from the event + args.Tenant = aL.tnt + } var rply string return aL.connMgr.Call(aL.config.ActionSCfg().ThresholdSConns, nil, - utils.ThresholdSv1ResetThreshold, &utils.TenantIDWithOpts{TenantID: utils.NewTenantID(tenID)}, &rply) + utils.ThresholdSv1ResetThreshold, args, &rply) }