From 91e2563a7781456c2c19a00ffda75a1e02ab303c Mon Sep 17 00:00:00 2001 From: ionutboangiu Date: Mon, 21 Mar 2022 18:33:45 +0200 Subject: [PATCH] Repair tests in general_tests --- .../samples/filters_internal/cgrates.json | 46 +- data/conf/samples/filters_mongo/cgrates.json | 44 +- data/conf/samples/filters_mysql/cgrates.json | 51 +- general_tests/filter_update_it_test.go | 676 ++--- general_tests/filters_it_test.go | 2166 +++++++++-------- 5 files changed, 1579 insertions(+), 1404 deletions(-) diff --git a/data/conf/samples/filters_internal/cgrates.json b/data/conf/samples/filters_internal/cgrates.json index c31b20798..1d5c85561 100644 --- a/data/conf/samples/filters_internal/cgrates.json +++ b/data/conf/samples/filters_internal/cgrates.json @@ -1,42 +1,36 @@ { -// CGRateS Configuration file -// - "general": { "log_level": 7, - "node_id": "CGRFilterS", + "node_id": "CGRFilterS" }, "listen": { "rpc_json": ":2012", "rpc_gob": ":2013", - "http": ":2080", + "http": ":2080" }, "data_db": { - "db_type": "*internal", + "db_type": "*internal" }, - - - "rals": { "enabled": true, - "thresholds_conns": ["*localhost"], + "thresholds_conns": ["*localhost"] }, "schedulers": { - "enabled": true, + "enabled": true }, "filters": { "stats_conns": ["*localhost"], "resources_conns": ["*localhost"], - "accounts_conns": ["*localhost"], + "accounts_conns": ["*localhost"] }, "accounts": { @@ -46,42 +40,58 @@ "resources": { "enabled": true, "indexed_selects":false, - "store_interval": "-1", + "store_interval": "-1" }, "stats": { "enabled": true, "indexed_selects":false, - "store_interval": "-1", + "store_interval": "-1" }, "thresholds": { "enabled": true, "indexed_selects":false, - "store_interval": "-1", + "actions_conns": ["*localhost"], + "store_interval": "-1" +}, + +"actions": { + "enabled": true }, "attributes": { "enabled": true, - "prefix_indexed_fields": ["*req.CustomField"], + "prefix_indexed_fields": ["*req.CustomField"] }, "chargers": { "enabled": true, "suffix_indexed_fields": ["*req.Subject"], - "attributes_conns": ["*internal"], + "attributes_conns": ["*internal"] }, "admins": { "enabled": true, "caches_conns":["*localhost"], - "scheduler_conns": ["*internal"], + "scheduler_conns": ["*internal"] }, +"loaders": [ + { + "id": "*default", + "enabled": true, + "tenant": "cgrates.org", + "lockfile_path": ".cgr.lck", + "tp_in_dir": "/usr/share/cgrates/tariffplans/testit", + "tp_out_dir": "" + } +] + } diff --git a/data/conf/samples/filters_mongo/cgrates.json b/data/conf/samples/filters_mongo/cgrates.json index dc9680bdd..8ed170312 100644 --- a/data/conf/samples/filters_mongo/cgrates.json +++ b/data/conf/samples/filters_mongo/cgrates.json @@ -1,18 +1,15 @@ { -// CGRateS Configuration file -// - "general": { "log_level": 7, - "node_id": "CGRFilterS", + "node_id": "CGRFilterS" }, "listen": { "rpc_json": ":2012", "rpc_gob": ":2013", - "http": ":2080", + "http": ":2080" }, @@ -20,26 +17,25 @@ "data_db": { "db_type": "mongo", "db_name": "10", - "db_port": 27017, + "db_port": 27017 }, - "rals": { "enabled": true, - "thresholds_conns": ["*localhost"], + "thresholds_conns": ["*localhost"] }, "schedulers": { - "enabled": true, + "enabled": true }, "filters": { "stats_conns": ["*localhost"], "resources_conns": ["*localhost"], - "accounts_conns": ["*localhost"], + "accounts_conns": ["*localhost"] }, "accounts": { @@ -50,42 +46,58 @@ "resources": { "enabled": true, "indexed_selects":false, - "store_interval": "1s", + "store_interval": "1s" }, "stats": { "enabled": true, "indexed_selects":false, - "store_interval": "1s", + "store_interval": "1s" }, "thresholds": { "enabled": true, "indexed_selects":false, - "store_interval": "1s", + "actions_conns": ["*localhost"], + "store_interval": "1s" }, "attributes": { "enabled": true, - "prefix_indexed_fields": ["*req.CustomField"], + "prefix_indexed_fields": ["*req.CustomField"] }, "chargers": { "enabled": true, "suffix_indexed_fields": ["*req.Subject"], - "attributes_conns": ["*internal"], + "attributes_conns": ["*internal"] }, "admins": { "enabled": true, "caches_conns":["*localhost"], - "scheduler_conns": ["*internal"], + "scheduler_conns": ["*internal"] }, +"loaders": [ + { + "id": "*default", + "enabled": true, + "tenant": "cgrates.org", + "lockfile_path": ".cgr.lck", + "tp_in_dir": "/usr/share/cgrates/tariffplans/testit", + "tp_out_dir": "" + } +], + +"actions": { + "enabled": true +} + } diff --git a/data/conf/samples/filters_mysql/cgrates.json b/data/conf/samples/filters_mysql/cgrates.json index 2102a3e67..b916e9d03 100644 --- a/data/conf/samples/filters_mysql/cgrates.json +++ b/data/conf/samples/filters_mysql/cgrates.json @@ -1,25 +1,22 @@ { -// CGRateS Configuration file -// - "general": { "log_level": 7, - "node_id": "CGRFilterS", + "node_id": "CGRFilterS" }, "listen": { "rpc_json": ":2012", "rpc_gob": ":2013", - "http": ":2080", + "http": ":2080" }, -"data_db": { // database used to store runtime data (eg: accounts, cdr stats) - "db_type": "redis", // data_db type: - "db_port": 6379, // data_db port to reach the database - "db_name": "10", // data_db database name to connect to +"data_db": { + "db_type": "redis", + "db_port": 6379, + "db_name": "10" }, @@ -27,17 +24,17 @@ "rals": { "enabled": true, - "thresholds_conns": ["*localhost"], + "thresholds_conns": ["*localhost"] }, "schedulers": { - "enabled": true, + "enabled": true }, "filters": { "stats_conns": ["*localhost"], "resources_conns": ["*localhost"], - "accounts_conns": ["*localhost"], + "accounts_conns": ["*localhost"] }, "accounts": { @@ -48,42 +45,58 @@ "resources": { "enabled": true, "indexed_selects":false, - "store_interval": "1s", + "store_interval": "1s" }, "stats": { "enabled": true, "indexed_selects":false, - "store_interval": "1s", + "store_interval": "1s" }, "thresholds": { "enabled": true, - "indexed_selects":false, - "store_interval": "1s", + "indexed_selects":false, + "actions_conns": ["*localhost"], + "store_interval": "1s" +}, + +"actions": { + "enabled": true }, "attributes": { "enabled": true, - "prefix_indexed_fields": ["*req.CustomField"], + "prefix_indexed_fields": ["*req.CustomField"] }, "chargers": { "enabled": true, "suffix_indexed_fields": ["*req.Subject"], - "attributes_conns": ["*internal"], + "attributes_conns": ["*internal"] }, "admins": { "enabled": true, "caches_conns":["*localhost"], - "scheduler_conns": ["*internal"], + "scheduler_conns": ["*internal"] }, +"loaders": [ + { + "id": "*default", + "enabled": true, + "tenant": "cgrates.org", + "lockfile_path": ".cgr.lck", + "tp_in_dir": "/usr/share/cgrates/tariffplans/testit", + "tp_out_dir": "" + } +] + } diff --git a/general_tests/filter_update_it_test.go b/general_tests/filter_update_it_test.go index 0638d38d8..6b13d3d42 100644 --- a/general_tests/filter_update_it_test.go +++ b/general_tests/filter_update_it_test.go @@ -21,361 +21,381 @@ along with this program. If not, see package general_tests -// import ( -// "os/exec" -// "path" -// "reflect" -// "testing" +import ( + "os/exec" + "path" + "reflect" + "testing" -// "github.com/cgrates/birpc" -// "github.com/cgrates/birpc/context" -// "github.com/cgrates/cgrates/config" -// "github.com/cgrates/cgrates/engine" -// "github.com/cgrates/cgrates/utils" -// ) + "github.com/cgrates/birpc" + "github.com/cgrates/birpc/context" + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) -// var ( -// fltrUpdateCfgPath1, fltrUpdateCfgPath2 string -// fltrUpdateCfgDIR1, fltrUpdateCfgDIR2 string -// fltrUpdateCfg1, fltrUpdateCfg2 *config.CGRConfig -// fltrUpdateRPC1, fltrUpdateRPC2 *birpc.Client -// testEng1 *exec.Cmd -// sTestsFilterUpdate = []func(t *testing.T){ -// testFilterUpdateInitCfg, -// testFilterUpdateResetDB, -// testFilterUpdateStartEngine, -// testFilterUpdateRpcConn, -// testFilterUpdateSetFilterE1, -// testFilterUpdateSetAttrProfileE1, -// testFilterUpdateGetAttrProfileForEventEv1E1, -// testFilterUpdateGetAttrProfileForEventEv1E2, -// testFilterUpdateGetAttrProfileForEventEv2E1NotMatching, -// testFilterUpdateGetAttrProfileForEventEv2E2NotMatching, -// testFilterUpdateSetFilterAfterAttrE1, -// testFilterUpdateGetAttrProfileForEventEv1E1NotMatching, -// testFilterUpdateGetAttrProfileForEventEv1E2NotMatching, -// testFilterUpdateGetAttrProfileForEventEv2E1, -// testFilterUpdateGetAttrProfileForEventEv2E2, -// testFilterUpdateStopEngine, -// } -// ev1 = &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "Event1", -// Event: map[string]interface{}{ -// utils.AccountField: "1001", -// }, -// } -// ev2 = &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "Event2", -// Event: map[string]interface{}{ -// utils.AccountField: "1002", -// }, -// } -// ) +var ( + fltrUpdateCfgPath1, fltrUpdateCfgPath2 string + fltrUpdateCfgDIR1, fltrUpdateCfgDIR2 string + fltrUpdateCfg1, fltrUpdateCfg2 *config.CGRConfig + fltrUpdateRPC1, fltrUpdateRPC2 *birpc.Client + testEng1 *exec.Cmd + sTestsFilterUpdate = []func(t *testing.T){ + testFilterUpdateInitCfg, + testFilterUpdateResetDB, + testFilterUpdateStartEngine, + testFilterUpdateRpcConn, + testFilterUpdateSetFilterE1, + testFilterUpdateSetAttrProfileE1, + testFilterUpdateGetAttrProfileForEventEv1E1, + testFilterUpdateGetAttrProfileForEventEv1E2, + testFilterUpdateGetAttrProfileForEventEv2E1NotMatching, + testFilterUpdateGetAttrProfileForEventEv2E2NotMatching, + testFilterUpdateSetFilterAfterAttrE1, + testFilterUpdateGetAttrProfileForEventEv1E1NotMatching, + testFilterUpdateGetAttrProfileForEventEv1E2NotMatching, + testFilterUpdateGetAttrProfileForEventEv2E1, + testFilterUpdateGetAttrProfileForEventEv2E2, + testFilterUpdateStopEngine, + } + ev1 = &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "Event1", + Event: map[string]interface{}{ + utils.AccountField: "1001", + }, + } + ev2 = &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "Event2", + Event: map[string]interface{}{ + utils.AccountField: "1002", + }, + } +) -// func TestFilterUpdateIT(t *testing.T) { -// switch *dbType { -// case utils.MetaInternal: -// t.SkipNow() -// case utils.MetaMySQL: -// fltrUpdateCfgDIR1 = "fltr_update_e1_mysql" -// fltrUpdateCfgDIR2 = "tutmysql" -// case utils.MetaMongo: -// fltrUpdateCfgDIR1 = "fltr_update_e1_mongo" -// fltrUpdateCfgDIR2 = "tutmongo" -// case utils.MetaPostgres: -// t.SkipNow() -// default: -// t.Fatal("Unknown Database type") -// } +func TestFilterUpdateIT(t *testing.T) { + switch *dbType { + case utils.MetaInternal: + t.SkipNow() + case utils.MetaMySQL: + fltrUpdateCfgDIR1 = "fltr_update_e1_mysql" + fltrUpdateCfgDIR2 = "tutmysql" + case utils.MetaMongo: + fltrUpdateCfgDIR1 = "fltr_update_e1_mongo" + fltrUpdateCfgDIR2 = "tutmongo" + case utils.MetaPostgres: + t.SkipNow() + default: + t.Fatal("Unknown Database type") + } -// for _, stest1 := range sTestsFilterUpdate { -// t.Run(*dbType, stest1) -// } -// } + for _, stest1 := range sTestsFilterUpdate { + t.Run(*dbType, stest1) + } +} -// //Init Config -// func testFilterUpdateInitCfg(t *testing.T) { -// var err error -// fltrUpdateCfgPath1 = path.Join(*dataDir, "conf", "samples", "cache_replicate", fltrUpdateCfgDIR1) -// if fltrUpdateCfg1, err = config.NewCGRConfigFromPath(fltrUpdateCfgPath1); err != nil { -// t.Fatal(err) -// } -// fltrUpdateCfgPath2 = path.Join(*dataDir, "conf", "samples", fltrUpdateCfgDIR2) -// if fltrUpdateCfg2, err = config.NewCGRConfigFromPath(fltrUpdateCfgPath2); err != nil { -// t.Fatal(err) -// } -// } +//Init Config +func testFilterUpdateInitCfg(t *testing.T) { + var err error + fltrUpdateCfgPath1 = path.Join(*dataDir, "conf", "samples", "cache_replicate", fltrUpdateCfgDIR1) + if fltrUpdateCfg1, err = config.NewCGRConfigFromPath(context.Background(), fltrUpdateCfgPath1); err != nil { + t.Fatal(err) + } + fltrUpdateCfgPath2 = path.Join(*dataDir, "conf", "samples", fltrUpdateCfgDIR2) + if fltrUpdateCfg2, err = config.NewCGRConfigFromPath(context.Background(), fltrUpdateCfgPath2); err != nil { + t.Fatal(err) + } +} -// // Remove data in both rating and accounting db -// func testFilterUpdateResetDB(t *testing.T) { -// if err := engine.InitDataDB(fltrUpdateCfg1); err != nil { -// t.Fatal(err) -// } -// } +// Remove data in both rating and accounting db +func testFilterUpdateResetDB(t *testing.T) { + if err := engine.InitDataDB(fltrUpdateCfg1); err != nil { + t.Fatal(err) + } +} -// // Start CGR Engine -// func testFilterUpdateStartEngine(t *testing.T) { -// var err error -// if _, err = engine.StopStartEngine(fltrUpdateCfgPath1, *waitRater); err != nil { -// t.Fatal(err) -// } -// if testEng1, err = engine.StartEngine(fltrUpdateCfgPath2, *waitRater); err != nil { -// t.Fatal(err) -// } +// Start CGR Engine +func testFilterUpdateStartEngine(t *testing.T) { + var err error + if _, err = engine.StopStartEngine(fltrUpdateCfgPath1, *waitRater); err != nil { + t.Fatal(err) + } + if testEng1, err = engine.StartEngine(fltrUpdateCfgPath2, *waitRater); err != nil { + t.Fatal(err) + } -// } +} -// // Connect rpc client to rater -// func testFilterUpdateRpcConn(t *testing.T) { -// var err error -// if fltrUpdateRPC1, err = newRPCClient(fltrUpdateCfg1.ListenCfg()); err != nil { -// t.Fatal(err) -// } -// if fltrUpdateRPC2, err = newRPCClient(fltrUpdateCfg2.ListenCfg()); err != nil { -// t.Fatal(err) -// } -// } +// Connect rpc client to rater +func testFilterUpdateRpcConn(t *testing.T) { + var err error + if fltrUpdateRPC1, err = newRPCClient(fltrUpdateCfg1.ListenCfg()); err != nil { + t.Fatal(err) + } + if fltrUpdateRPC2, err = newRPCClient(fltrUpdateCfg2.ListenCfg()); err != nil { + t.Fatal(err) + } +} -// func testFilterUpdateStopEngine(t *testing.T) { -// if err := engine.KillEngine(100); err != nil { -// t.Error(err) -// } -// } +func testFilterUpdateStopEngine(t *testing.T) { + if err := engine.KillEngine(100); err != nil { + t.Error(err) + } +} -// func testFilterUpdateSetFilterE1(t *testing.T) { -// fltr := &engine.FilterWithAPIOpts{ -// Filter: &engine.Filter{ -// ID: "FLTR_ID", -// Tenant: "cgrates.org", -// Rules: []*engine.FilterRule{ -// { -// Type: utils.MetaString, -// Element: "~*req.Account", -// Values: []string{"1001"}, -// }, -// }, -// }, -// APIOpts: map[string]interface{}{ -// utils.CacheOpt: utils.MetaLoad, -// }, -// } +func testFilterUpdateSetFilterE1(t *testing.T) { + fltr := &engine.FilterWithAPIOpts{ + Filter: &engine.Filter{ + ID: "FLTR_ID", + Tenant: "cgrates.org", + Rules: []*engine.FilterRule{ + { + Type: utils.MetaString, + Element: "~*req.Account", + Values: []string{"1001"}, + }, + }, + }, + APIOpts: map[string]interface{}{ + utils.MetaCache: utils.MetaLoad, + }, + } -// var reply string -// if err := fltrUpdateRPC1.Call(context.Background(), utils.AdminSv1SetFilter, fltr, &reply); err != nil { -// t.Error(err) -// } else if reply != utils.OK { -// t.Error("Unexpected reply returned", reply) -// } + var reply string + if err := fltrUpdateRPC1.Call(context.Background(), utils.AdminSv1SetFilter, fltr, &reply); err != nil { + t.Error(err) + } else if reply != utils.OK { + t.Error("Unexpected reply returned", reply) + } -// var result *engine.Filter -// if err := fltrUpdateRPC1.Call(context.Background(), utils.AdminSv1GetFilter, -// &utils.TenantID{Tenant: "cgrates.org", ID: "FLTR_ID"}, &result); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(fltr.Filter, result) { -// t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(fltr.Filter), utils.ToJSON(result)) -// } -// } + var result *engine.Filter + if err := fltrUpdateRPC1.Call(context.Background(), utils.AdminSv1GetFilter, + &utils.TenantID{Tenant: "cgrates.org", ID: "FLTR_ID"}, &result); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(fltr.Filter, result) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(fltr.Filter), utils.ToJSON(result)) + } +} -// func testFilterUpdateSetAttrProfileE1(t *testing.T) { -// attrPrf := &engine.APIAttributeProfileWithAPIOpts{ -// APIAttributeProfile: &engine.APIAttributeProfile{ -// FilterIDs: []string{"FLTR_ID"}, -// ID: "ATTR_ID", -// Tenant: "cgrates.org", -// Weight: 10, -// Attributes: []*engine.ExternalAttribute{ -// { -// Path: "*req.Account", -// Value: "1003", -// Type: utils.MetaConstant, -// }, -// }, -// }, -// APIOpts: map[string]interface{}{ -// utils.CacheOpt: utils.MetaNone, -// }, -// } +func testFilterUpdateSetAttrProfileE1(t *testing.T) { + attrPrf := &engine.APIAttributeProfileWithAPIOpts{ + APIAttributeProfile: &engine.APIAttributeProfile{ + FilterIDs: []string{"FLTR_ID"}, + ID: "ATTR_ID", + Tenant: "cgrates.org", + Weights: utils.DynamicWeights{ + { + Weight: 10, + }, + }, + Attributes: []*engine.ExternalAttribute{ + { + Path: "*req.Account", + Value: "1003", + Type: utils.MetaConstant, + }, + }, + }, + APIOpts: map[string]interface{}{ + utils.MetaCache: utils.MetaNone, + }, + } -// var reply string -// if err := fltrUpdateRPC1.Call(context.Background(), utils.AdminSv1SetAttributeProfile, attrPrf, &reply); err != nil { -// t.Error(err) -// } else if reply != utils.OK { -// t.Error("Unexpected reply returned", reply) -// } -// var result *engine.APIAttributeProfile -// if err := fltrUpdateRPC1.Call(context.Background(), utils.AdminSv1GetAttributeProfile, -// utils.TenantIDWithAPIOpts{TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "ATTR_ID"}}, &result); err != nil { -// t.Fatal(err) -// } -// if !reflect.DeepEqual(attrPrf.APIAttributeProfile, result) { -// t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(attrPrf.APIAttributeProfile), utils.ToJSON(result)) -// } -// } + var reply string + if err := fltrUpdateRPC1.Call(context.Background(), utils.AdminSv1SetAttributeProfile, attrPrf, &reply); err != nil { + t.Error(err) + } else if reply != utils.OK { + t.Error("Unexpected reply returned", reply) + } + var result *engine.APIAttributeProfile + if err := fltrUpdateRPC1.Call(context.Background(), utils.AdminSv1GetAttributeProfile, + utils.TenantIDWithAPIOpts{TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "ATTR_ID"}}, &result); err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(attrPrf.APIAttributeProfile, result) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(attrPrf.APIAttributeProfile), utils.ToJSON(result)) + } +} -// func testFilterUpdateGetAttrProfileForEventEv1E1(t *testing.T) { -// eAttrPrf := &engine.APIAttributeProfile{ -// Tenant: "cgrates.org", -// FilterIDs: []string{"FLTR_ID"}, -// ID: "ATTR_ID", -// Weight: 10, -// Attributes: []*engine.ExternalAttribute{ -// { -// Path: "*req.Account", -// Value: "1003", -// Type: utils.MetaConstant, -// }, -// }, -// } +func testFilterUpdateGetAttrProfileForEventEv1E1(t *testing.T) { + eAttrPrf := &engine.APIAttributeProfile{ + Tenant: "cgrates.org", + FilterIDs: []string{"FLTR_ID"}, + ID: "ATTR_ID", + Weights: utils.DynamicWeights{ + { + Weight: 10, + }, + }, + Attributes: []*engine.ExternalAttribute{ + { + Path: "*req.Account", + Value: "1003", + Type: utils.MetaConstant, + }, + }, + } -// var attrReply *engine.APIAttributeProfile -// if err := fltrUpdateRPC1.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, -// ev1, &attrReply); err != nil { -// t.Fatal(err) -// } -// if !reflect.DeepEqual(eAttrPrf, attrReply) { -// t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(eAttrPrf), utils.ToJSON(attrReply)) -// } -// } + var attrReply *engine.APIAttributeProfile + if err := fltrUpdateRPC1.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, + ev1, &attrReply); err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(eAttrPrf, attrReply) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(eAttrPrf), utils.ToJSON(attrReply)) + } +} -// func testFilterUpdateGetAttrProfileForEventEv1E2(t *testing.T) { -// eAttrPrf := &engine.APIAttributeProfile{ -// Tenant: "cgrates.org", -// FilterIDs: []string{"FLTR_ID"}, -// ID: "ATTR_ID", -// Weight: 10, -// Attributes: []*engine.ExternalAttribute{ -// { -// Path: "*req.Account", -// Value: "1003", -// Type: utils.MetaConstant, -// }, -// }, -// } +func testFilterUpdateGetAttrProfileForEventEv1E2(t *testing.T) { + eAttrPrf := &engine.APIAttributeProfile{ + Tenant: "cgrates.org", + FilterIDs: []string{"FLTR_ID"}, + ID: "ATTR_ID", + Weights: utils.DynamicWeights{ + { + Weight: 10, + }, + }, + Attributes: []*engine.ExternalAttribute{ + { + Path: "*req.Account", + Value: "1003", + Type: utils.MetaConstant, + }, + }, + } -// var attrReply *engine.APIAttributeProfile -// if err := fltrUpdateRPC2.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, -// ev1, &attrReply); err != nil { -// t.Fatal(err) -// } -// if !reflect.DeepEqual(eAttrPrf, attrReply) { -// t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(eAttrPrf), utils.ToJSON(attrReply)) -// } -// } + var attrReply *engine.APIAttributeProfile + if err := fltrUpdateRPC2.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, + ev1, &attrReply); err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(eAttrPrf, attrReply) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(eAttrPrf), utils.ToJSON(attrReply)) + } +} -// func testFilterUpdateGetAttrProfileForEventEv2E1(t *testing.T) { -// eAttrPrf := &engine.APIAttributeProfile{ -// Tenant: "cgrates.org", -// FilterIDs: []string{"FLTR_ID"}, -// ID: "ATTR_ID", -// Weight: 10, -// Attributes: []*engine.ExternalAttribute{ -// { -// Path: "*req.Account", -// Value: "1003", -// Type: utils.MetaConstant, -// }, -// }, -// } +func testFilterUpdateGetAttrProfileForEventEv2E1(t *testing.T) { + eAttrPrf := &engine.APIAttributeProfile{ + Tenant: "cgrates.org", + FilterIDs: []string{"FLTR_ID"}, + ID: "ATTR_ID", + Weights: utils.DynamicWeights{ + { + Weight: 10, + }, + }, + Attributes: []*engine.ExternalAttribute{ + { + Path: "*req.Account", + Value: "1003", + Type: utils.MetaConstant, + }, + }, + } -// var attrReply *engine.APIAttributeProfile -// if err := fltrUpdateRPC1.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, -// ev2, &attrReply); err != nil { -// t.Fatal(err) -// } -// if !reflect.DeepEqual(eAttrPrf, attrReply) { -// t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(eAttrPrf), utils.ToJSON(attrReply)) -// } -// } + var attrReply *engine.APIAttributeProfile + if err := fltrUpdateRPC1.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, + ev2, &attrReply); err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(eAttrPrf, attrReply) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(eAttrPrf), utils.ToJSON(attrReply)) + } +} -// func testFilterUpdateGetAttrProfileForEventEv2E2(t *testing.T) { -// eAttrPrf := &engine.APIAttributeProfile{ -// Tenant: "cgrates.org", -// FilterIDs: []string{"FLTR_ID"}, -// ID: "ATTR_ID", -// Weight: 10, -// Attributes: []*engine.ExternalAttribute{ -// { -// Path: "*req.Account", -// Value: "1003", -// Type: utils.MetaConstant, -// }, -// }, -// } +func testFilterUpdateGetAttrProfileForEventEv2E2(t *testing.T) { + eAttrPrf := &engine.APIAttributeProfile{ + Tenant: "cgrates.org", + FilterIDs: []string{"FLTR_ID"}, + ID: "ATTR_ID", + Weights: utils.DynamicWeights{ + { + Weight: 10, + }, + }, + Attributes: []*engine.ExternalAttribute{ + { + Path: "*req.Account", + Value: "1003", + Type: utils.MetaConstant, + }, + }, + } -// var attrReply *engine.APIAttributeProfile -// if err := fltrUpdateRPC2.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, -// ev2, &attrReply); err != nil { -// t.Fatal(err) -// } -// if !reflect.DeepEqual(eAttrPrf, attrReply) { -// t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(eAttrPrf), utils.ToJSON(attrReply)) -// } -// } + var attrReply *engine.APIAttributeProfile + if err := fltrUpdateRPC2.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, + ev2, &attrReply); err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(eAttrPrf, attrReply) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(eAttrPrf), utils.ToJSON(attrReply)) + } +} -// func testFilterUpdateSetFilterAfterAttrE1(t *testing.T) { -// fltr := &engine.FilterWithAPIOpts{ -// Filter: &engine.Filter{ -// ID: "FLTR_ID", -// Tenant: "cgrates.org", -// Rules: []*engine.FilterRule{ -// { -// Type: utils.MetaString, -// Element: "~*req.Account", -// Values: []string{"1002"}, -// }, -// }, -// }, -// APIOpts: map[string]interface{}{ -// utils.CacheOpt: utils.MetaLoad, -// }, -// } +func testFilterUpdateSetFilterAfterAttrE1(t *testing.T) { + fltr := &engine.FilterWithAPIOpts{ + Filter: &engine.Filter{ + ID: "FLTR_ID", + Tenant: "cgrates.org", + Rules: []*engine.FilterRule{ + { + Type: utils.MetaString, + Element: "~*req.Account", + Values: []string{"1002"}, + }, + }, + }, + APIOpts: map[string]interface{}{ + utils.MetaCache: utils.MetaLoad, + }, + } -// var reply string -// if err := fltrUpdateRPC1.Call(context.Background(), utils.AdminSv1SetFilter, fltr, &reply); err != nil { -// t.Error(err) -// } else if reply != utils.OK { -// t.Error("Unexpected reply returned", reply) -// } + var reply string + if err := fltrUpdateRPC1.Call(context.Background(), utils.AdminSv1SetFilter, fltr, &reply); err != nil { + t.Error(err) + } else if reply != utils.OK { + t.Error("Unexpected reply returned", reply) + } -// var result *engine.Filter -// if err := fltrUpdateRPC1.Call(context.Background(), utils.AdminSv1GetFilter, -// &utils.TenantID{Tenant: "cgrates.org", ID: "FLTR_ID"}, &result); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(fltr.Filter, result) { -// t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(fltr.Filter), utils.ToJSON(result)) -// } -// } + var result *engine.Filter + if err := fltrUpdateRPC1.Call(context.Background(), utils.AdminSv1GetFilter, + &utils.TenantID{Tenant: "cgrates.org", ID: "FLTR_ID"}, &result); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(fltr.Filter, result) { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(fltr.Filter), utils.ToJSON(result)) + } +} -// func testFilterUpdateGetAttrProfileForEventEv1E1NotMatching(t *testing.T) { -// var attrReply *engine.APIAttributeProfile -// if err := fltrUpdateRPC1.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, -// ev1, &attrReply); err == nil || err.Error() != utils.ErrNotFound.Error() { -// t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) -// } -// } +func testFilterUpdateGetAttrProfileForEventEv1E1NotMatching(t *testing.T) { + var attrReply *engine.APIAttributeProfile + if err := fltrUpdateRPC1.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, + ev1, &attrReply); err == nil || err.Error() != utils.ErrNotFound.Error() { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) + } +} -// func testFilterUpdateGetAttrProfileForEventEv1E2NotMatching(t *testing.T) { -// var attrReply *engine.APIAttributeProfile -// if err := fltrUpdateRPC2.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, -// ev1, &attrReply); err == nil || err.Error() != utils.ErrNotFound.Error() { -// t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) -// } -// } +func testFilterUpdateGetAttrProfileForEventEv1E2NotMatching(t *testing.T) { + var attrReply *engine.APIAttributeProfile + if err := fltrUpdateRPC2.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, + ev1, &attrReply); err == nil || err.Error() != utils.ErrNotFound.Error() { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) + } +} -// func testFilterUpdateGetAttrProfileForEventEv2E1NotMatching(t *testing.T) { -// var attrReply *engine.APIAttributeProfile -// if err := fltrUpdateRPC1.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, -// ev2, &attrReply); err == nil || err.Error() != utils.ErrNotFound.Error() { -// t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) -// } -// } +func testFilterUpdateGetAttrProfileForEventEv2E1NotMatching(t *testing.T) { + var attrReply *engine.APIAttributeProfile + if err := fltrUpdateRPC1.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, + ev2, &attrReply); err == nil || err.Error() != utils.ErrNotFound.Error() { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) + } +} -// func testFilterUpdateGetAttrProfileForEventEv2E2NotMatching(t *testing.T) { -// var attrReply *engine.APIAttributeProfile -// if err := fltrUpdateRPC2.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, -// ev2, &attrReply); err == nil || err.Error() != utils.ErrNotFound.Error() { -// t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) -// } -// } +func testFilterUpdateGetAttrProfileForEventEv2E2NotMatching(t *testing.T) { + var attrReply *engine.APIAttributeProfile + if err := fltrUpdateRPC2.Call(context.Background(), utils.AttributeSv1GetAttributeForEvent, + ev2, &attrReply); err == nil || err.Error() != utils.ErrNotFound.Error() { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) + } +} diff --git a/general_tests/filters_it_test.go b/general_tests/filters_it_test.go index df8a80415..8cba39fea 100644 --- a/general_tests/filters_it_test.go +++ b/general_tests/filters_it_test.go @@ -21,1026 +21,1146 @@ along with this program. If not, see package general_tests -// import ( -// "net/rpc" -// "path" -// "reflect" -// "testing" -// "time" - -// "github.com/cgrates/cgrates/config" -// "github.com/cgrates/cgrates/engine" -// "github.com/cgrates/cgrates/utils" -// ) - -// var ( -// fltrCfgPath string -// fltrCfg *config.CGRConfig -// fltrRpc *rpc.Client -// fltrConfDIR string //run tests for specific configuration -// fltrDelay int - -// sTestsFltr = []func(t *testing.T){ -// testV1FltrLoadConfig, -// testV1FltrInitDataDb, -// testV1FltrStartEngine, -// testV1FltrRpcConn, -// testV1FltrLoadTarrifPlans, -// testV1FltrAddStats, -// testV1FltrPopulateThreshold, -// testV1FltrGetThresholdForEvent, -// testV1FltrGetThresholdForEvent2, -// testV1FltrPopulateResources, -// testV1FltrPopulateResourcesAvailableUnits, -// testV1FltrAccounts, -// testV1FltrAccountsExistsDynamicaly, -// testV1FltrAttributesPrefix, -// testV1FltrInitDataDb, -// testV1FltrChargerSuffix, -// testV1FltrStopEngine, -// } -// ) - -// // Test start here -// func TestFltrIT(t *testing.T) { -// switch *dbType { -// case utils.MetaInternal: -// fltrConfDIR = "filters_internal" -// case utils.MetaMySQL: -// fltrConfDIR = "filters_mysql" -// case utils.MetaMongo: -// fltrConfDIR = "filters_mongo" -// case utils.MetaPostgres: -// t.SkipNow() -// default: -// t.Fatal("Unknown Database type") -// } - -// for _, stest := range sTestsFltr { -// t.Run(fltrConfDIR, stest) -// } -// } - -// func testV1FltrLoadConfig(t *testing.T) { -// var err error -// fltrCfgPath = path.Join(*dataDir, "conf", "samples", fltrConfDIR) -// if *encoding == utils.MetaGOB { -// cdrsCfgPath = path.Join(*dataDir, "conf", "samples", fltrConfDIR+"_gob") -// } -// if fltrCfg, err = config.NewCGRConfigFromPath(fltrCfgPath); err != nil { -// t.Error(err) -// } -// fltrDelay = 1000 -// } - -// func testV1FltrInitDataDb(t *testing.T) { -// if err := engine.InitDataDB(fltrCfg); err != nil { -// t.Fatal(err) -// } -// } - -// func testV1FltrStartEngine(t *testing.T) { -// if _, err := engine.StopStartEngine(fltrCfgPath, fltrDelay); err != nil { -// t.Fatal(err) -// } -// } - -// func testV1FltrRpcConn(t *testing.T) { -// var err error -// fltrRpc, err = newRPCClient(fltrCfg.ListenCfg()) // We connect over JSON so we can also troubleshoot if needed -// if err != nil { -// t.Fatal("Could not connect to rater: ", err.Error()) -// } -// } - -// func testV1FltrLoadTarrifPlans(t *testing.T) { -// var reply string -// attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "testit")} -// if err := fltrRpc.Call(utils.APIerSv1LoadTariffPlanFromFolder, attrs, &reply); err != nil { -// t.Error(err) -// } else if reply != utils.OK { -// t.Error("Unexpected reply returned", reply) -// } -// time.Sleep(100 * time.Millisecond) -// } - -// func testV1FltrAddStats(t *testing.T) { -// var reply []string -// expected := []string{"Stat_1"} -// ev1 := &engine.StatsArgsProcessEvent{ - -// CGREvent: &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "event1", -// Event: map[string]interface{}{ -// utils.AccountField: "1001", -// utils.AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), -// utils.Usage: 11 * time.Second, -// utils.Cost: 10.0, -// }, -// }, -// } -// if err := fltrRpc.Call(utils.StatSv1ProcessEvent, &ev1, &reply); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(reply, expected) { -// t.Errorf("Expecting: %+v, received: %+v", expected, reply) -// } - -// expected = []string{"Stat_1"} -// ev1.CGREvent = &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "event2", -// Event: map[string]interface{}{ -// utils.AccountField: "1001", -// utils.AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), -// utils.Usage: 11 * time.Second, -// utils.Cost: 10.5, -// }, -// } -// if err := fltrRpc.Call(utils.StatSv1ProcessEvent, &ev1, &reply); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(reply, expected) { -// t.Errorf("Expecting: %+v, received: %+v", expected, reply) -// } - -// expected = []string{"Stat_2"} -// ev1.CGREvent = &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "event2", -// Event: map[string]interface{}{ -// utils.AccountField: "1002", -// utils.AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), -// utils.Usage: 5 * time.Second, -// utils.Cost: 12.5, -// }, -// } -// if err := fltrRpc.Call(utils.StatSv1ProcessEvent, &ev1, &reply); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(reply, expected) { -// t.Errorf("Expecting: %+v, received: %+v", expected, reply) -// } - -// expected = []string{"Stat_2"} -// ev1.CGREvent = &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "event2", -// Event: map[string]interface{}{ -// utils.AccountField: "1002", -// utils.AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), -// utils.Usage: 6 * time.Second, -// utils.Cost: 17.5, -// }, -// } -// if err := fltrRpc.Call(utils.StatSv1ProcessEvent, &ev1, &reply); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(reply, expected) { -// t.Errorf("Expecting: %+v, received: %+v", expected, reply) -// } - -// expected = []string{"Stat_3"} -// ev1.CGREvent = &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "event3", -// Event: map[string]interface{}{ -// utils.AccountField: "1003", -// utils.AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), -// utils.Usage: 11 * time.Second, -// utils.Cost: 12.5, -// }, -// } -// if err := fltrRpc.Call(utils.StatSv1ProcessEvent, &ev1, &reply); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(reply, expected) { -// t.Errorf("Expecting: %+v, received: %+v", expected, reply) -// } - -// expected = []string{"Stat_1_1"} -// ev1.CGREvent = &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "event3", -// Event: map[string]interface{}{ -// "Stat": "Stat1_1", -// utils.AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), -// utils.Usage: 11 * time.Second, -// utils.Cost: 12.5, -// utils.PDD: 12 * time.Second, -// }, -// } -// if err := fltrRpc.Call(utils.StatSv1ProcessEvent, &ev1, &reply); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(reply, expected) { -// t.Errorf("Expecting: %+v, received: %+v", expected, reply) -// } - -// expected = []string{"Stat_1_1"} -// ev1.CGREvent = &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "event3", -// Event: map[string]interface{}{ -// "Stat": "Stat1_1", -// utils.AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), -// utils.Usage: 15 * time.Second, -// utils.Cost: 15.5, -// utils.PDD: 15 * time.Second, -// }, -// } -// if err := fltrRpc.Call(utils.StatSv1ProcessEvent, &ev1, &reply); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(reply, expected) { -// t.Errorf("Expecting: %+v, received: %+v", expected, reply) -// } -// } - -// func testV1FltrPopulateThreshold(t *testing.T) { -// //Add a filter of type *stats and check if acd metric is minim 10 ( greater than 10) -// //we expect that acd from Stat_1 to be 11 so the filter should pass (11 > 10) -// filter := &engine.FilterWithAPIOpts{ -// Filter: &engine.Filter{ -// Tenant: "cgrates.org", -// ID: "FLTR_TH_Stats1", -// Rules: []*engine.FilterRule{ -// { -// Type: "*gt", -// Element: "~*stats.Stat_1.*acd", -// Values: []string{"10.0"}, -// }, -// }, -// }, -// } - -// var result string -// if err := fltrRpc.Call(utils.AdminSv1SetFilter, filter, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } - -// // Add a disable and log action -// attrsAA := &utils.AttrSetActions{ActionsId: "LOG", Actions: []*utils.TPAction{ -// {Identifier: utils.MetaLog}, -// }} -// if err := fltrRpc.Call(utils.APIerSv2SetActions, attrsAA, &result); err != nil && err.Error() != utils.ErrExists.Error() { -// t.Error("Got error on APIerSv2.SetActions: ", err.Error()) -// } else if result != utils.OK { -// t.Errorf("Calling APIerSv2.SetActions received: %s", result) -// } - -// //Add a threshold with filter from above and an inline filter for Account 1010 -// tPrfl := &engine.ThresholdProfileWithAPIOpts{ -// ThresholdProfile: &engine.ThresholdProfile{ -// Tenant: "cgrates.org", -// ID: "TH_Stats1", -// FilterIDs: []string{"FLTR_TH_Stats1", "*string:~*req.Account:1010", "*ai:~*req.AnswerTime:2014-07-14T14:35:00Z|2014-07-14T14:36:00Z"}, -// MaxHits: -1, -// MinSleep: time.Millisecond, -// Weight: 10.0, -// ActionProfileIDs: []string{"LOG"}, -// Async: true, -// }, -// } -// if err := fltrRpc.Call(utils.AdminSv1SetThresholdProfile, tPrfl, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } -// var rcvTh *engine.ThresholdProfile -// if err := fltrRpc.Call(utils.AdminSv1GetThresholdProfile, -// &utils.TenantID{Tenant: tPrfl.Tenant, ID: tPrfl.ID}, &rcvTh); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(tPrfl.ThresholdProfile, rcvTh) { -// t.Errorf("Expecting: %+v, received: %+v", tPrfl.ThresholdProfile, rcvTh) -// } -// } - -// func testV1FltrGetThresholdForEvent(t *testing.T) { -// // check the event -// tEv := &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "event1", -// Event: map[string]interface{}{ -// utils.AccountField: "1010"}, -// } -// var ids []string -// eIDs := []string{"TH_Stats1"} -// if err := fltrRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &ids); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(ids, eIDs) { -// t.Errorf("Expecting ids: %s, received: %s", eIDs, ids) -// } -// } - -// func testV1FltrGetThresholdForEvent2(t *testing.T) { -// //Add a filter of type *stats and check if acd metric is maximum 10 ( lower than 10) -// //we expect that acd from Stat_1 to be 11 so the filter should not pass (11 > 10) -// filter := &engine.FilterWithAPIOpts{ -// Filter: &engine.Filter{ -// Tenant: "cgrates.org", -// ID: "FLTR_TH_Stats1", -// Rules: []*engine.FilterRule{ -// { -// Type: "*lt", -// Element: "~*stats.Stat_1.*acd", -// Values: []string{"10.0"}, -// }, -// }, -// }, -// } - -// var result string -// if err := fltrRpc.Call(utils.AdminSv1SetFilter, filter, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } - -// //update the threshold with new filter -// tPrfl := &engine.ThresholdProfileWithAPIOpts{ -// ThresholdProfile: &engine.ThresholdProfile{ -// Tenant: "cgrates.org", -// ID: "TH_Stats1", -// FilterIDs: []string{"FLTR_TH_Stats1", "*string:~*req.Account:1010", "*ai:~*req.AnswerTime:2014-07-14T14:35:00Z|2014-07-14T14:36:00Z"}, -// MaxHits: -1, -// MinSleep: time.Millisecond, -// Weight: 10.0, -// ActionProfileIDs: []string{"LOG"}, -// }, -// } -// if err := fltrRpc.Call(utils.AdminSv1SetThresholdProfile, tPrfl, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } - -// tEv := &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "event1", -// Event: map[string]interface{}{ -// utils.AccountField: "1010"}, -// } -// var ids []string -// if err := fltrRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &ids); err == nil || -// err.Error() != utils.ErrNotFound.Error() { -// t.Error(err) -// } -// } - -// func testV1FltrPopulateResources(t *testing.T) { -// //create a resourceProfile -// rlsConfig := &engine.ResourceProfile{ -// Tenant: "cgrates.org", -// ID: "ResTest", -// UsageTTL: time.Minute, -// Limit: 10, -// AllocationMessage: "MessageAllocation", -// Stored: true, -// Weight: 20, -// ThresholdIDs: []string{utils.MetaNone}, -// } - -// var result string -// if err := fltrRpc.Call(utils.AdminSv1SetResourceProfile, &engine.ResourceProfileWithAPIOpts{ResourceProfile: rlsConfig}, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } - -// var reply *engine.ResourceProfile -// if err := fltrRpc.Call(utils.AdminSv1GetResourceProfile, -// &utils.TenantID{Tenant: "cgrates.org", ID: rlsConfig.ID}, &reply); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(reply, rlsConfig) { -// t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(rlsConfig), utils.ToJSON(reply)) -// } - -// // Allocate 3 units for resource ResTest -// argsRU := utils.ArgRSv1ResourceUsage{ -// CGREvent: &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: utils.UUIDSha1Prefix(), -// Event: map[string]interface{}{ -// "Account": "3001", -// "Destination": "3002" -// }, -// APIOpts: map[string]interface{}{ -// utils.OptsResourcesUsageID: "651a8db2-4f67-4cf8-b622-169e8a482e21", -// utils.OptsResourcesUnits: 3, -// }, -// }, -// } -// if err := fltrRpc.Call(utils.ResourceSv1AllocateResources, -// argsRU, &result); err != nil { -// t.Error(err) -// } - -// //we allocate 3 units to resource and add a filter for Usages > 2 -// //should match (3>2) -// filter := engine.FilterWithAPIOpts{ -// Filter: &engine.Filter{ -// Tenant: "cgrates.org", -// ID: "FLTR_TH_Resource", -// Rules: []*engine.FilterRule{ -// { -// Type: "*gt", -// Element: "~*resources.ResTest.TotalUsage", -// Values: []string{"2.0"}, -// }, -// }, -// }, -// } - -// if err := fltrRpc.Call(utils.AdminSv1SetFilter, filter, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } - -// tPrfl := &engine.ThresholdProfileWithAPIOpts{ -// ThresholdProfile: &engine.ThresholdProfile{ -// Tenant: "cgrates.org", -// ID: "TH_ResTest", -// FilterIDs: []string{"FLTR_TH_Resource", "*string:~*req.Account:2020"}, -// MaxHits: -1, -// MinSleep: time.Millisecond, -// Weight: 10.0, -// ActionProfileIDs: []string{"LOG"}, -// Async: true, -// }, -// } -// if err := fltrRpc.Call(utils.AdminSv1SetThresholdProfile, tPrfl, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } -// var rcvTh *engine.ThresholdProfile -// if err := fltrRpc.Call(utils.AdminSv1GetThresholdProfile, -// &utils.TenantID{Tenant: tPrfl.Tenant, ID: tPrfl.ID}, &rcvTh); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(tPrfl.ThresholdProfile, rcvTh) { -// t.Errorf("Expecting: %+v, received: %+v", tPrfl.ThresholdProfile, rcvTh) -// } - -// // check the event -// tEv := &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "event1", -// Event: map[string]interface{}{ -// utils.AccountField: "2020"}, -// } - -// var ids []string -// eIDs := []string{"TH_ResTest"} -// if err := fltrRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &ids); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(ids, eIDs) { -// t.Errorf("Expecting ids: %s, received: %s", eIDs, ids) -// } - -// //change the filter -// //we allocate 3 units to resource and add a filter for Usages < 2 -// //should fail (3<2) -// filter.Filter = &engine.Filter{ -// Tenant: "cgrates.org", -// ID: "FLTR_TH_Resource", -// Rules: []*engine.FilterRule{ -// { -// Type: "*lt", -// Element: "~*resources.ResTest.TotalUsage", -// Values: []string{"2.0"}, -// }, -// }, -// } - -// if err := fltrRpc.Call(utils.AdminSv1SetFilter, filter, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } - -// //Overwrite the threshold -// if err := fltrRpc.Call(utils.AdminSv1SetThresholdProfile, tPrfl, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } - -// //expect NotFound error because filter doesn't match -// if err := fltrRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &ids); err == nil || -// err.Error() != utils.ErrNotFound.Error() { -// t.Error(err) -// } -// } - -// func testV1FltrPopulateResourcesAvailableUnits(t *testing.T) { -// //create a resourceProfile -// rlsConfig := &engine.ResourceProfile{ -// Tenant: "cgrates.org", -// ID: "RES_TEST", -// UsageTTL: time.Minute, -// Limit: 23, -// AllocationMessage: "Test_Available", -// Stored: true, -// Weight: 25, -// ThresholdIDs: []string{utils.MetaNone}, -// } - -// var result string -// if err := fltrRpc.Call(utils.AdminSv1SetResourceProfile, &engine.ResourceProfileWithAPIOpts{ResourceProfile: rlsConfig}, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } - -// var reply *engine.ResourceProfile -// if err := fltrRpc.Call(utils.AdminSv1GetResourceProfile, -// &utils.TenantID{Tenant: "cgrates.org", ID: rlsConfig.ID}, &reply); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(reply, rlsConfig) { -// t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(rlsConfig), utils.ToJSON(reply)) -// } - -// //Allocate 9 units for resource ResTest -// argsRU := utils.ArgRSv1ResourceUsage{ -// CGREvent: &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: utils.UUIDSha1Prefix(), -// Event: map[string]interface{}{ -// "Account": "3001", -// "Destination": "3002"}, -// APIOpts: map[string]interface{}{ -// utils.OptsResourcesUsageID: "651a8db2-4f67-4cf8-b622-169e8a482e21", -// utils.OptsResourcesUnits: 9, -// }, -// }, -// } -// if err := fltrRpc.Call(utils.ResourceSv1AllocateResources, argsRU, &result); err != nil { -// t.Error(err) -// } else if result != "Test_Available" { -// t.Error("Unexpected reply returned", result) -// } - -// //as we allocate 9 units, there should be available 14 more -// //our filter should match for *gt or *gte -// filter := engine.FilterWithAPIOpts{ -// Filter: &engine.Filter{ -// Tenant: "cgrates.org", -// ID: "FLTR_ST_Resource1", -// Rules: []*engine.FilterRule{ -// { -// Type: "*gt", -// Element: "~*resources.RES_TEST.Available", -// Values: []string{"13.0"}, -// }, -// { -// Type: "*gte", -// Element: "~*resources.RES_TEST.Available", -// Values: []string{"14.0"}, -// }, -// }, -// }, -// } - -// if err := fltrRpc.Call(utils.AdminSv1SetFilter, filter, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } - -// //set a statQueueProfile with that filter -// statsPrf := &engine.StatQueueProfileWithAPIOpts{ -// StatQueueProfile: &engine.StatQueueProfile{ -// Tenant: "cgrates.org", -// ID: "STATS_RES_TEST12", -// FilterIDs: []string{"FLTR_ST_Resource1", "*string:~*req.Account:1001"}, -// Weight: 50, -// }, -// } -// if err := fltrRpc.Call(utils.AdminSv1SetStatQueueProfile, statsPrf, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } - -// var replyStats *engine.StatQueueProfile -// if err := fltrRpc.Call(utils.AdminSv1GetStatQueueProfile, &utils.TenantID{Tenant: "cgrates.org", -// ID: "STATS_RES_TEST12"}, &replyStats); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(statsPrf.StatQueueProfile, replyStats) { -// t.Errorf("Expected %+v, received %+v", utils.ToJSON(statsPrf.StatQueueProfile), utils.ToJSON(replyStats)) -// } - -// //here will check the event -// statsEv := &engine.StatsArgsProcessEvent{ -// CGREvent: &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "event_nr2", -// Event: map[string]interface{}{ -// utils.AccountField: "1001", -// utils.Usage: "1", -// }, -// }, -// } -// var ids []string -// expectedIDs := []string{"STATS_RES_TEST12", "Stat_1"} -// if err := fltrRpc.Call(utils.StatSv1ProcessEvent, statsEv, &ids); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(expectedIDs, ids) { -// t.Errorf("Expected %+v, received %+v", expectedIDs, ids) -// } - -// //set another filter that will not match -// filter = engine.FilterWithAPIOpts{ -// Filter: &engine.Filter{ -// Tenant: "cgrates.org", -// ID: "FLTR_ST_Resource1", -// Rules: []*engine.FilterRule{ -// { -// Type: "*gt", -// Element: "~*resources.RES_TEST.Available", -// Values: []string{"17.0"}, -// }, -// }, -// }, -// } - -// if err := fltrRpc.Call(utils.AdminSv1SetFilter, filter, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } - -// //overwrite the StatQueueProfile -// if err := fltrRpc.Call(utils.AdminSv1GetStatQueueProfile, &utils.TenantID{Tenant: "cgrates.org", -// ID: "STATS_RES_TEST12"}, &replyStats); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(statsPrf.StatQueueProfile, replyStats) { -// t.Errorf("Expected %+v, received %+v", utils.ToJSON(statsPrf.StatQueueProfile), utils.ToJSON(replyStats)) -// } - -// //This filter won't match -// expectedIDs = []string{"Stat_1"} -// if err := fltrRpc.Call(utils.StatSv1ProcessEvent, statsEv, &ids); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(expectedIDs, ids) { -// t.Errorf("Expected %+v, received %+v", expectedIDs, ids) -// } -// } - -// func testV1FltrAccounts(t *testing.T) { -// var resp string -// if err := fltrRpc.Call(utils.AdminSv1RemoveThresholdProfile, -// &utils.TenantIDWithAPIOpts{TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "THD_ACNT_1001"}}, &resp); err != nil { -// t.Error(err) -// } else if resp != utils.OK { -// t.Error("Unexpected reply returned", resp) -// } -// // Add a filter with fieldName taken value from account 1001 -// // and check if *monetary balance is minim 9 ( greater than 9) -// // we expect that the balance to be 10 so the filter should pass (10 > 9) -// filter := engine.FilterWithAPIOpts{ -// Filter: &engine.Filter{ -// Tenant: "cgrates.org", -// ID: "FLTR_TH_Accounts", -// Rules: []*engine.FilterRule{ -// { -// Type: "*gt", -// Element: "~*accounts.1001.BalanceMap.*monetary[0].Value", -// Values: []string{"9"}, -// }, -// }, -// }, -// } - -// var result string -// if err := fltrRpc.Call(utils.AdminSv1SetFilter, filter, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } -// // Add a log action -// attrsAA := &utils.AttrSetActions{ActionsId: "LOG", Actions: []*utils.TPAction{ -// {Identifier: utils.MetaLog}, -// }} -// if err := fltrRpc.Call(utils.APIerSv2SetActions, attrsAA, &result); err != nil && err.Error() != utils.ErrExists.Error() { -// t.Error("Got error on APIerSv2.SetActions: ", err.Error()) -// } else if result != utils.OK { -// t.Errorf("Calling APIerSv2.SetActions received: %s", result) -// } -// //Add a threshold with filter from above and an inline filter for Account 1010 -// tPrfl := &engine.ThresholdProfileWithAPIOpts{ -// ThresholdProfile: &engine.ThresholdProfile{ -// Tenant: "cgrates.org", -// ID: "TH_Account", -// FilterIDs: []string{"FLTR_TH_Accounts", "*string:~*req.Account:1001"}, -// MaxHits: -1, -// MinSleep: time.Millisecond, -// Weight: 90.0, -// ActionProfileIDs: []string{"LOG"}, -// Async: true, -// }, -// } -// if err := fltrRpc.Call(utils.AdminSv1SetThresholdProfile, tPrfl, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } -// var rcvTh *engine.ThresholdProfile -// if err := fltrRpc.Call(utils.AdminSv1GetThresholdProfile, -// &utils.TenantID{Tenant: tPrfl.Tenant, ID: tPrfl.ID}, &rcvTh); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(tPrfl.ThresholdProfile, rcvTh) { -// t.Errorf("Expecting: %+v, received: %+v", tPrfl.ThresholdProfile, rcvTh) -// } - -// tEv := &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "event1", -// Event: map[string]interface{}{ -// utils.AccountField: "1001"}, -// } -// var ids []string -// if err := fltrRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &ids); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(ids, []string{"TH_Account"}) { -// t.Error("Unexpected reply returned", ids) -// } - -// // update the filter -// // Add a filter with fieldName taken value from account 1001 -// // and check if *monetary balance is is minim 11 ( greater than 11) -// // we expect that the balance to be 10 so the filter should not pass (10 > 11) -// filter.Filter = &engine.Filter{ -// Tenant: "cgrates.org", -// ID: "FLTR_TH_Accounts", -// Rules: []*engine.FilterRule{ -// { -// Type: "*gt", -// Element: "~*accounts.1001.BalanceMap.*monetary[0].Value", -// Values: []string{"11"}, -// }, -// }, -// } - -// if err := fltrRpc.Call(utils.AdminSv1SetFilter, filter, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } - -// if err := fltrRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &ids); err == nil || -// err.Error() != utils.ErrNotFound.Error() { -// t.Error(err) -// } -// } - -// func testV1FltrAccountsExistsDynamicaly(t *testing.T) { -// var resp string -// if err := fltrRpc.Call(utils.AdminSv1RemoveThresholdProfile, -// &utils.TenantIDWithAPIOpts{TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "TH_Account"}}, &resp); err != nil { -// if err.Error() != utils.ErrNotFound.Error() { // no error if the threshold is already removed -// t.Error(err) -// } -// } else if resp != utils.OK { -// t.Error("Unexpected reply returned", resp) -// } - -// var result string -// // Add a log action -// attrsAA := &utils.AttrSetActions{ActionsId: "LOG", Actions: []*utils.TPAction{ -// {Identifier: utils.MetaLog}, -// }} -// if err := fltrRpc.Call(utils.APIerSv2SetActions, attrsAA, &result); err != nil && err.Error() != utils.ErrExists.Error() { -// t.Error("Got error on APIerSv2.SetActions: ", err.Error()) -// } -// //Add a threshold with filter from above and an inline filter for Account 1010 -// tPrfl := &engine.ThresholdProfileWithAPIOpts{ -// ThresholdProfile: &engine.ThresholdProfile{ -// Tenant: "cgrates.org", -// ID: "TH_AccountDinamic", -// FilterIDs: []string{"*exists:~*accounts.<~*req.Account>:"}, -// MaxHits: -1, -// MinSleep: time.Millisecond, -// Weight: 90.0, -// ActionProfileIDs: []string{"LOG"}, -// Async: true, -// }, -// } -// if err := fltrRpc.Call(utils.AdminSv1SetThresholdProfile, tPrfl, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } -// var rcvTh *engine.ThresholdProfile -// if err := fltrRpc.Call(utils.AdminSv1GetThresholdProfile, -// &utils.TenantID{Tenant: tPrfl.Tenant, ID: tPrfl.ID}, &rcvTh); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(tPrfl.ThresholdProfile, rcvTh) { -// t.Errorf("Expecting: %+v, received: %+v", tPrfl.ThresholdProfile, rcvTh) -// } - -// tEv := &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "event1", -// Event: map[string]interface{}{ -// utils.AccountField: "1001"}, -// } -// var ids []string -// if err := fltrRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &ids); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(ids, []string{"TH_AccountDinamic"}) { -// t.Error("Unexpected reply returned", ids) -// } - -// tEv = &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "event2", -// Event: map[string]interface{}{ -// utils.AccountField: "non"}, -// } -// ids = nil -// if err := fltrRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &ids); err == nil || err.Error() != utils.ErrNotFound.Error() { -// t.Error(err) -// } -// } - -// func testV1FltrChargerSuffix(t *testing.T) { -// var reply string -// if err := fltrRpc.Call(utils.CacheSv1Clear, &utils.AttrCacheIDsWithAPIOpts{ -// CacheIDs: nil, -// }, &reply); err != nil { -// t.Error(err) -// } else if reply != utils.OK { -// t.Error("Reply: ", reply) -// } -// chargerProfile := &v1.ChargerWithAPIOpts{ -// ChargerProfile: &engine.ChargerProfile{ -// Tenant: "cgrates.org", -// ID: "IntraCharger", -// FilterIDs: []string{"*suffix:~*req.Subject:intra"}, -// RunID: "Intra", -// AttributeIDs: []string{"*constant:*req.Subject:intraState"}, -// Weight: 20, -// }, -// } -// var result string -// if err := fltrRpc.Call(utils.AdminSv1SetChargerProfile, chargerProfile, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } - -// chargerProfile2 := &v1.ChargerWithAPIOpts{ -// ChargerProfile: &engine.ChargerProfile{ -// Tenant: "cgrates.org", -// ID: "InterCharger", -// FilterIDs: []string{"*suffix:~*req.Subject:inter"}, -// RunID: "Inter", -// AttributeIDs: []string{"*constant:*req.Subject:interState"}, -// Weight: 20, -// }, -// } -// if err := fltrRpc.Call(utils.AdminSv1SetChargerProfile, chargerProfile2, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } - -// processedEv := []*engine.ChrgSProcessEventReply{ -// { -// ChargerSProfile: "IntraCharger", -// AttributeSProfiles: []string{"*constant:*req.Subject:intraState"}, -// AlteredFields: []string{utils.MetaReqRunID, "*req.Subject"}, - -// CGREvent: &utils.CGREvent{ // matching Charger1 -// Tenant: "cgrates.org", -// ID: "event1", -// Event: map[string]interface{}{ -// utils.AccountField: "1010", -// utils.Subject: "intraState", -// utils.RunID: "Intra", -// utils.Destination: "999", -// }, -// APIOpts: map[string]interface{}{ -// utils.Subsys: utils.MetaChargers, -// }, -// }, -// }, -// } -// cgrEv := &utils.CGREvent{ -// Tenant: "cgrates.org", -// ID: "event1", -// Event: map[string]interface{}{ -// utils.AccountField: "1010", -// utils.Subject: "Something_intra", -// utils.Destination: "999", -// }, -// } -// var result2 []*engine.ChrgSProcessEventReply -// if err := fltrRpc.Call(utils.ChargerSv1ProcessEvent, cgrEv, &result2); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(result2, processedEv) { -// t.Errorf("Expecting : %s, \n received: %s", utils.ToJSON(processedEv), utils.ToJSON(result2)) -// } - -// processedEv = []*engine.ChrgSProcessEventReply{ -// { -// ChargerSProfile: "InterCharger", -// AttributeSProfiles: []string{"*constant:*req.Subject:interState"}, -// AlteredFields: []string{utils.MetaReqRunID, "*req.Subject"}, - -// CGREvent: &utils.CGREvent{ // matching Charger1 -// Tenant: "cgrates.org", -// ID: "event1", -// Event: map[string]interface{}{ -// utils.AccountField: "1010", -// utils.Subject: "interState", -// utils.RunID: "Inter", -// utils.Destination: "999", -// }, -// APIOpts: map[string]interface{}{ -// utils.Subsys: utils.MetaChargers, -// }, -// }, -// }, -// } -// cgrEv = &utils.CGREvent{ - -// Tenant: "cgrates.org", -// ID: "event1", -// Event: map[string]interface{}{ -// utils.AccountField: "1010", -// utils.Subject: "Something_inter", -// utils.Destination: "999", -// }, -// } -// if err := fltrRpc.Call(utils.ChargerSv1ProcessEvent, cgrEv, &result2); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(result2, processedEv) { -// t.Errorf("Expecting : %s, \n received: %s", utils.ToJSON(processedEv), utils.ToJSON(result2)) -// } -// } - -// func testV1FltrAttributesPrefix(t *testing.T) { -// chargerProfile := &engine.AttributeProfileWithAPIOpts{ -// AttributeProfile: &engine.AttributeProfile{ -// Tenant: "cgrates.new", -// ID: "ATTR_1001", -// FilterIDs: []string{"*prefix:~*req.CustomField:2007|+2007", "*prefix:~*req.CustomField2:2007|+2007", "FLTR_1", "*string:~*opts.*context:prefix"}, -// Attributes: []*engine.Attribute{ -// { -// FilterIDs: []string{}, -// Path: utils.MetaReq + utils.NestingSep + "CustomField", -// Type: utils.MetaConstant, -// Value: config.NewRSRParsersMustCompile("2007", utils.InfieldSep), -// }, -// }, -// Weight: 20.0, -// }, -// } -// var result string -// if err := fltrRpc.Call(utils.AdminSv1SetAttributeProfile, chargerProfile, &result); err != nil { -// t.Error(err) -// } else if result != utils.OK { -// t.Error("Unexpected reply returned", result) -// } - -// processedEv := &engine.AttrSProcessEventReply{ -// AlteredFields: []string{"*req.CustomField"}, -// MatchedProfiles: []string{"cgrates.new:ATTR_1001"}, - -// CGREvent: &utils.CGREvent{ -// Tenant: "cgrates.new", -// ID: "event1", -// Event: map[string]interface{}{ -// "CustomField": "2007", -// "CustomField2": "+2007", -// utils.Destination: "+1207", -// }, -// APIOpts: map[string]interface{}{}, -// }, -// } -// cgrEv := &utils.CGREvent{ -// Tenant: "cgrates.new", -// ID: "event1", -// Event: map[string]interface{}{ -// "CustomField": "+2007", -// "CustomField2": "+2007", -// utils.Destination: "+1207", -// }, -// APIOpts: map[string]interface{}{ -// utils.OptsContext: "prefix", -// }, -// } -// var result2 *engine.AttrSProcessEventReply -// if err := fltrRpc.Call(utils.AttributeSv1ProcessEvent, cgrEv, &result2); err != nil { -// t.Error(err) -// } else if !reflect.DeepEqual(result2, processedEv) { -// t.Errorf("Expecting : %s, \n received: %s", utils.ToJSON(processedEv), utils.ToJSON(result2)) -// } - -// } - -// func testV1FltrStopEngine(t *testing.T) { -// if err := engine.KillEngine(accDelay); err != nil { -// t.Error(err) -// } -// } +import ( + "path" + "reflect" + "testing" + "time" + + "github.com/cgrates/birpc" + "github.com/cgrates/birpc/context" + "github.com/cgrates/cgrates/apis" + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/loaders" + "github.com/cgrates/cgrates/utils" +) + +var ( + fltrCfgPath string + fltrCfg *config.CGRConfig + fltrRpc *birpc.Client + fltrConfDIR string //run tests for specific configuration + fltrDelay int + + sTestsFltr = []func(t *testing.T){ + testV1FltrLoadConfig, + testV1FltrInitDataDb, + testV1FltrStartEngine, + testV1FltrRpcConn, + testV1FltrLoadTarrifPlans, + testV1FltrAddStats, + testV1FltrPopulateThreshold, + testV1FltrGetThresholdForEvent, + testV1FltrGetThresholdForEvent2, + testV1FltrPopulateResources, + testV1FltrPopulateResourcesAvailableUnits, + testV1FltrAccounts, + testV1FltrAccountsExistsDynamicaly, + testV1FltrAttributesPrefix, + testV1FltrInitDataDb, + testV1FltrChargerSuffix, + testV1FltrStopEngine, + } +) + +// Test start here +func TestFltrIT(t *testing.T) { + switch *dbType { + case utils.MetaInternal: + fltrConfDIR = "filters_internal" + case utils.MetaMySQL: + fltrConfDIR = "filters_mysql" + case utils.MetaMongo: + fltrConfDIR = "filters_mongo" + case utils.MetaPostgres: + t.SkipNow() + default: + t.Fatal("Unknown Database type") + } + + for _, stest := range sTestsFltr { + t.Run(fltrConfDIR, stest) + } +} + +func testV1FltrLoadConfig(t *testing.T) { + var err error + fltrCfgPath = path.Join(*dataDir, "conf", "samples", fltrConfDIR) + if *encoding == utils.MetaGOB { + cdrsCfgPath = path.Join(*dataDir, "conf", "samples", fltrConfDIR+"_gob") + } + if fltrCfg, err = config.NewCGRConfigFromPath(context.Background(), fltrCfgPath); err != nil { + t.Error(err) + } + fltrDelay = 1000 +} + +func testV1FltrInitDataDb(t *testing.T) { + if err := engine.InitDataDB(fltrCfg); err != nil { + t.Fatal(err) + } +} + +func testV1FltrStartEngine(t *testing.T) { + if _, err := engine.StopStartEngine(fltrCfgPath, fltrDelay); err != nil { + t.Fatal(err) + } +} + +func testV1FltrRpcConn(t *testing.T) { + var err error + fltrRpc, err = newRPCClient(fltrCfg.ListenCfg()) // We connect over JSON so we can also troubleshoot if needed + if err != nil { + t.Fatal("Could not connect to rater: ", err.Error()) + } +} + +func testV1FltrLoadTarrifPlans(t *testing.T) { + + caching := utils.MetaReload + if fltrCfg.DataDbCfg().Type == utils.Internal { + caching = utils.MetaNone + } + var reply string + if err := fltrRpc.Call(context.Background(), utils.LoaderSv1Run, + &loaders.ArgsProcessFolder{ + APIOpts: map[string]interface{}{ + utils.MetaStopOnError: true, + utils.MetaCache: caching, + }, + }, &reply); err != nil { + t.Error(err) + } else if reply != utils.OK { + t.Error("Unexpected reply returned:", reply) + } + time.Sleep(200 * time.Millisecond) +} + +func testV1FltrAddStats(t *testing.T) { + var reply []string + expected := []string{"Stat_1"} + ev1 := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event1", + Event: map[string]interface{}{ + utils.AccountField: "1001", + utils.AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + utils.Usage: 11 * time.Second, + utils.Cost: 10.0, + }, + } + if err := fltrRpc.Call(context.Background(), utils.StatSv1ProcessEvent, &ev1, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply) + } + + expected = []string{"Stat_1"} + ev1 = &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event2", + Event: map[string]interface{}{ + utils.AccountField: "1001", + utils.AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + utils.Usage: 11 * time.Second, + utils.Cost: 10.5, + }, + } + if err := fltrRpc.Call(context.Background(), utils.StatSv1ProcessEvent, &ev1, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply) + } + + expected = []string{"Stat_2"} + ev1 = &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event2", + Event: map[string]interface{}{ + utils.AccountField: "1002", + utils.AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + utils.Usage: 5 * time.Second, + utils.Cost: 12.5, + }, + } + if err := fltrRpc.Call(context.Background(), utils.StatSv1ProcessEvent, &ev1, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply) + } + + expected = []string{"Stat_2"} + ev1 = &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event2", + Event: map[string]interface{}{ + utils.AccountField: "1002", + utils.AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + utils.Usage: 6 * time.Second, + utils.Cost: 17.5, + }, + } + if err := fltrRpc.Call(context.Background(), utils.StatSv1ProcessEvent, &ev1, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply) + } + + expected = []string{"Stat_3"} + ev1 = &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event3", + Event: map[string]interface{}{ + utils.AccountField: "1003", + utils.AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + utils.Usage: 11 * time.Second, + utils.Cost: 12.5, + }, + } + if err := fltrRpc.Call(context.Background(), utils.StatSv1ProcessEvent, &ev1, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply) + } + + expected = []string{"Stat_1_1"} + ev1 = &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event3", + Event: map[string]interface{}{ + "Stat": "Stat1_1", + utils.AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + utils.Usage: 11 * time.Second, + utils.Cost: 12.5, + utils.PDD: 12 * time.Second, + }, + } + if err := fltrRpc.Call(context.Background(), utils.StatSv1ProcessEvent, &ev1, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply) + } + + expected = []string{"Stat_1_1"} + ev1 = &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event3", + Event: map[string]interface{}{ + "Stat": "Stat1_1", + utils.AnswerTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), + utils.Usage: 15 * time.Second, + utils.Cost: 15.5, + utils.PDD: 15 * time.Second, + }, + } + if err := fltrRpc.Call(context.Background(), utils.StatSv1ProcessEvent, &ev1, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, expected) { + t.Errorf("Expecting: %+v, received: %+v", expected, reply) + } +} + +func testV1FltrPopulateThreshold(t *testing.T) { + //Add a filter of type *stats and check if acd metric is minim 10 ( greater than 10) + //we expect that acd from Stat_1 to be 11 so the filter should pass (11 > 10) + filter := &engine.FilterWithAPIOpts{ + Filter: &engine.Filter{ + Tenant: "cgrates.org", + ID: "FLTR_TH_Stats1", + Rules: []*engine.FilterRule{ + { + Type: "*gt", + Element: "~*stats.Stat_1.*acd", + Values: []string{"10.0"}, + }, + }, + }, + } + + var result string + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetFilter, filter, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + // Add a disable and log action + argsAP := &engine.ActionProfileWithAPIOpts{ + ActionProfile: &engine.ActionProfile{ + ID: "LOG", + Actions: []*engine.APAction{ + { + ID: "LogAction", + Type: utils.MetaLog, + }, + }, + }, + } + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetActionProfile, argsAP, &result); err != nil && err.Error() != utils.ErrExists.Error() { + t.Error("Got error on APIerSv2.SetActions: ", err.Error()) + } else if result != utils.OK { + t.Errorf("Calling APIerSv2.SetActions received: %s", result) + } + + //Add a threshold with filter from above and an inline filter for Account 1010 + tPrfl := &engine.ThresholdProfileWithAPIOpts{ + ThresholdProfile: &engine.ThresholdProfile{ + Tenant: "cgrates.org", + ID: "TH_Stats1", + FilterIDs: []string{"FLTR_TH_Stats1", "*string:~*req.Account:1010"}, + MaxHits: -1, + MinSleep: time.Millisecond, + Weights: utils.DynamicWeights{ + { + Weight: 10, + }, + }, + ActionProfileIDs: []string{"LOG"}, + Async: true, + }, + } + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetThresholdProfile, tPrfl, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + var rcvTh *engine.ThresholdProfile + if err := fltrRpc.Call(context.Background(), utils.AdminSv1GetThresholdProfile, + &utils.TenantIDWithAPIOpts{ + TenantID: &utils.TenantID{ + Tenant: tPrfl.Tenant, + ID: tPrfl.ID, + }, + }, &rcvTh); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(tPrfl.ThresholdProfile, rcvTh) { + t.Errorf("Expecting: %+v, received: %+v", tPrfl.ThresholdProfile, rcvTh) + } +} + +func testV1FltrGetThresholdForEvent(t *testing.T) { + // check the event + tEv := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event1", + Event: map[string]interface{}{ + utils.AccountField: "1010"}, + } + var ids []string + eIDs := []string{"TH_Stats1"} + if err := fltrRpc.Call(context.Background(), utils.ThresholdSv1ProcessEvent, tEv, &ids); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(ids, eIDs) { + t.Errorf("Expecting ids: %s, received: %s", eIDs, ids) + } +} + +func testV1FltrGetThresholdForEvent2(t *testing.T) { + //Add a filter of type *stats and check if acd metric is maximum 10 ( lower than 10) + //we expect that acd from Stat_1 to be 11 so the filter should not pass (11 > 10) + filter := &engine.FilterWithAPIOpts{ + Filter: &engine.Filter{ + Tenant: "cgrates.org", + ID: "FLTR_TH_Stats1", + Rules: []*engine.FilterRule{ + { + Type: "*lt", + Element: "~*stats.Stat_1.*acd", + Values: []string{"10.0"}, + }, + }, + }, + } + + var result string + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetFilter, filter, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + //update the threshold with new filter + tPrfl := &engine.ThresholdProfileWithAPIOpts{ + ThresholdProfile: &engine.ThresholdProfile{ + Tenant: "cgrates.org", + ID: "TH_Stats1", + FilterIDs: []string{"FLTR_TH_Stats1", "*string:~*req.Account:1010", "*ai:~*req.AnswerTime:2014-07-14T14:35:00Z|2014-07-14T14:36:00Z"}, + MaxHits: -1, + MinSleep: time.Millisecond, + Weights: utils.DynamicWeights{ + { + Weight: 10, + }, + }, + ActionProfileIDs: []string{"LOG"}, + }, + } + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetThresholdProfile, tPrfl, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + tEv := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event1", + Event: map[string]interface{}{ + utils.AccountField: "1010"}, + } + var ids []string + if err := fltrRpc.Call(context.Background(), utils.ThresholdSv1ProcessEvent, tEv, &ids); err == nil || + err.Error() != utils.ErrNotFound.Error() { + t.Error(err) + } +} + +func testV1FltrPopulateResources(t *testing.T) { + //create a resourceProfile + rlsConfig := &engine.ResourceProfile{ + Tenant: "cgrates.org", + ID: "ResTest", + UsageTTL: time.Minute, + Limit: 10, + AllocationMessage: "MessageAllocation", + Stored: true, + Weights: utils.DynamicWeights{ + { + Weight: 20, + }, + }, + ThresholdIDs: []string{utils.MetaNone}, + } + + var result string + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetResourceProfile, &engine.ResourceProfileWithAPIOpts{ResourceProfile: rlsConfig}, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + var reply *engine.ResourceProfile + if err := fltrRpc.Call(context.Background(), utils.AdminSv1GetResourceProfile, + &utils.TenantIDWithAPIOpts{ + TenantID: &utils.TenantID{ + Tenant: "cgrates.org", + ID: rlsConfig.ID, + }, + }, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, rlsConfig) { + t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(rlsConfig), utils.ToJSON(reply)) + } + + // Allocate 3 units for resource ResTest + argsRU := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: utils.UUIDSha1Prefix(), + Event: map[string]interface{}{ + "Account": "3001", + "Destination": "3002", + }, + APIOpts: map[string]interface{}{ + utils.OptsResourcesUsageID: "651a8db2-4f67-4cf8-b622-169e8a482e21", + utils.OptsResourcesUnits: 3, + }, + } + if err := fltrRpc.Call(context.Background(), utils.ResourceSv1AllocateResources, + argsRU, &result); err != nil { + t.Error(err) + } + + //we allocate 3 units to resource and add a filter for Usages > 2 + //should match (3>2) + filter := engine.FilterWithAPIOpts{ + Filter: &engine.Filter{ + Tenant: "cgrates.org", + ID: "FLTR_TH_Resource", + Rules: []*engine.FilterRule{ + { + Type: "*gt", + Element: "~*resources.ResTest.TotalUsage", + Values: []string{"2.0"}, + }, + }, + }, + } + + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetFilter, filter, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + tPrfl := &engine.ThresholdProfileWithAPIOpts{ + ThresholdProfile: &engine.ThresholdProfile{ + Tenant: "cgrates.org", + ID: "TH_ResTest", + FilterIDs: []string{"FLTR_TH_Resource", "*string:~*req.Account:2020"}, + MaxHits: -1, + MinSleep: time.Millisecond, + Weights: utils.DynamicWeights{ + { + Weight: 10, + }, + }, + ActionProfileIDs: []string{"LOG"}, + Async: true, + }, + } + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetThresholdProfile, tPrfl, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + var rcvTh *engine.ThresholdProfile + if err := fltrRpc.Call(context.Background(), utils.AdminSv1GetThresholdProfile, + &utils.TenantIDWithAPIOpts{ + TenantID: &utils.TenantID{ + Tenant: tPrfl.Tenant, + ID: tPrfl.ID}, + }, &rcvTh); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(tPrfl.ThresholdProfile, rcvTh) { + t.Errorf("Expecting: %+v, received: %+v", tPrfl.ThresholdProfile, rcvTh) + } + + // check the event + tEv := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event1", + Event: map[string]interface{}{ + utils.AccountField: "2020"}, + } + + var ids []string + eIDs := []string{"TH_ResTest"} + if err := fltrRpc.Call(context.Background(), utils.ThresholdSv1ProcessEvent, tEv, &ids); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(ids, eIDs) { + t.Errorf("Expecting ids: %s, received: %s", eIDs, ids) + } + + //change the filter + //we allocate 3 units to resource and add a filter for Usages < 2 + //should fail (3<2) + filter.Filter = &engine.Filter{ + Tenant: "cgrates.org", + ID: "FLTR_TH_Resource", + Rules: []*engine.FilterRule{ + { + Type: "*lt", + Element: "~*resources.ResTest.TotalUsage", + Values: []string{"2.0"}, + }, + }, + } + + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetFilter, filter, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + //Overwrite the threshold + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetThresholdProfile, tPrfl, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + //expect NotFound error because filter doesn't match + if err := fltrRpc.Call(context.Background(), utils.ThresholdSv1ProcessEvent, tEv, &ids); err == nil || + err.Error() != utils.ErrNotFound.Error() { + t.Error(err) + } +} + +func testV1FltrPopulateResourcesAvailableUnits(t *testing.T) { + //create a resourceProfile + rlsConfig := &engine.ResourceProfile{ + Tenant: "cgrates.org", + ID: "RES_TEST", + UsageTTL: time.Minute, + Limit: 23, + AllocationMessage: "Test_Available", + Stored: true, + Weights: utils.DynamicWeights{ + { + Weight: 25, + }, + }, + ThresholdIDs: []string{utils.MetaNone}, + } + + var result string + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetResourceProfile, &engine.ResourceProfileWithAPIOpts{ResourceProfile: rlsConfig}, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + var reply *engine.ResourceProfile + if err := fltrRpc.Call(context.Background(), utils.AdminSv1GetResourceProfile, + &utils.TenantIDWithAPIOpts{ + TenantID: &utils.TenantID{ + Tenant: "cgrates.org", + ID: rlsConfig.ID}, + }, &reply); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(reply, rlsConfig) { + t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(rlsConfig), utils.ToJSON(reply)) + } + + //Allocate 9 units for resource ResTest + argsRU := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: utils.UUIDSha1Prefix(), + Event: map[string]interface{}{ + "Account": "3001", + "Destination": "3002"}, + APIOpts: map[string]interface{}{ + utils.OptsResourcesUsageID: "651a8db2-4f67-4cf8-b622-169e8a482e21", + utils.OptsResourcesUnits: 9, + }, + } + if err := fltrRpc.Call(context.Background(), utils.ResourceSv1AllocateResources, argsRU, &result); err != nil { + t.Error(err) + } else if result != "Test_Available" { + t.Error("Unexpected reply returned", result) + } + + //as we allocate 9 units, there should be available 14 more + //our filter should match for *gt or *gte + filter := engine.FilterWithAPIOpts{ + Filter: &engine.Filter{ + Tenant: "cgrates.org", + ID: "FLTR_ST_Resource1", + Rules: []*engine.FilterRule{ + { + Type: "*gt", + Element: "~*resources.RES_TEST.Available", + Values: []string{"13.0"}, + }, + { + Type: "*gte", + Element: "~*resources.RES_TEST.Available", + Values: []string{"14.0"}, + }, + }, + }, + } + + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetFilter, filter, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + //set a statQueueProfile with that filter + statsPrf := &engine.StatQueueProfileWithAPIOpts{ + StatQueueProfile: &engine.StatQueueProfile{ + Tenant: "cgrates.org", + ID: "STATS_RES_TEST12", + FilterIDs: []string{"FLTR_ST_Resource1", "*string:~*req.Account:1001"}, + Weights: utils.DynamicWeights{ + { + Weight: 50, + }, + }, + }, + } + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetStatQueueProfile, statsPrf, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + var replyStats *engine.StatQueueProfile + if err := fltrRpc.Call(context.Background(), utils.AdminSv1GetStatQueueProfile, &utils.TenantIDWithAPIOpts{ + TenantID: &utils.TenantID{ + Tenant: "cgrates.org", + ID: "STATS_RES_TEST12"}, + }, &replyStats); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(statsPrf.StatQueueProfile, replyStats) { + t.Errorf("Expected %+v, received %+v", utils.ToJSON(statsPrf.StatQueueProfile), utils.ToJSON(replyStats)) + } + + //here will check the event + statsEv := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event_nr2", + Event: map[string]interface{}{ + utils.AccountField: "1001", + utils.Usage: "1", + }, + } + var ids []string + expectedIDs := []string{"STATS_RES_TEST12", "Stat_1"} + if err := fltrRpc.Call(context.Background(), utils.StatSv1ProcessEvent, statsEv, &ids); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expectedIDs, ids) { + t.Errorf("Expected %+v, received %+v", expectedIDs, ids) + } + + //set another filter that will not match + filter = engine.FilterWithAPIOpts{ + Filter: &engine.Filter{ + Tenant: "cgrates.org", + ID: "FLTR_ST_Resource1", + Rules: []*engine.FilterRule{ + { + Type: "*gt", + Element: "~*resources.RES_TEST.Available", + Values: []string{"17.0"}, + }, + }, + }, + } + + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetFilter, filter, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + //overwrite the StatQueueProfile + if err := fltrRpc.Call(context.Background(), utils.AdminSv1GetStatQueueProfile, &utils.TenantIDWithAPIOpts{ + TenantID: &utils.TenantID{ + Tenant: "cgrates.org", + ID: "STATS_RES_TEST12"}, + }, &replyStats); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(statsPrf.StatQueueProfile, replyStats) { + t.Errorf("Expected %+v, received %+v", utils.ToJSON(statsPrf.StatQueueProfile), utils.ToJSON(replyStats)) + } + + //This filter won't match + expectedIDs = []string{"Stat_1"} + if err := fltrRpc.Call(context.Background(), utils.StatSv1ProcessEvent, statsEv, &ids); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expectedIDs, ids) { + t.Errorf("Expected %+v, received %+v", expectedIDs, ids) + } +} + +func testV1FltrAccounts(t *testing.T) { + var resp string + if err := fltrRpc.Call(context.Background(), utils.AdminSv1RemoveThresholdProfile, + &utils.TenantIDWithAPIOpts{TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "THD_ACNT_1001"}}, &resp); err != nil { + t.Error(err) + } else if resp != utils.OK { + t.Error("Unexpected reply returned", resp) + } + // Add a filter with fieldName taken value from account 1001 + // and check if *monetary balance is minim 9 ( greater than 9) + // we expect that the balance to be 10 so the filter should pass (10 > 9) + filter := engine.FilterWithAPIOpts{ + Filter: &engine.Filter{ + Tenant: "cgrates.org", + ID: "FLTR_TH_Accounts", + Rules: []*engine.FilterRule{ + { + Type: "*gt", + Element: "~*accounts.1001.Balances.VoiceBalance.Units", + // Element: "~*accounts.1001.BalanceMap.*monetary[0].Value", + Values: []string{"1m"}, + }, + }, + }, + } + + var result string + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetFilter, filter, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + // Add a log action + argsAP := &engine.ActionProfileWithAPIOpts{ + ActionProfile: &engine.ActionProfile{ + ID: "LOG", + Actions: []*engine.APAction{ + { + ID: "LogAction", + Type: utils.MetaLog, + }, + }, + }, + } + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetActionProfile, argsAP, &result); err != nil && err.Error() != utils.ErrExists.Error() { + t.Error("Got error on APIerSv2.SetActions: ", err.Error()) + } else if result != utils.OK { + t.Errorf("Calling APIerSv2.SetActions received: %s", result) + } + //Add a threshold with filter from above and an inline filter for Account 1010 + tPrfl := &engine.ThresholdProfileWithAPIOpts{ + ThresholdProfile: &engine.ThresholdProfile{ + Tenant: "cgrates.org", + ID: "TH_Account", + FilterIDs: []string{"FLTR_TH_Accounts", "*string:~*req.Account:1001"}, + MaxHits: -1, + MinSleep: time.Millisecond, + Weights: utils.DynamicWeights{ + { + Weight: 90, + }, + }, + ActionProfileIDs: []string{"LOG"}, + Async: true, + }, + } + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetThresholdProfile, tPrfl, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + var rcvTh *engine.ThresholdProfile + if err := fltrRpc.Call(context.Background(), utils.AdminSv1GetThresholdProfile, + &utils.TenantIDWithAPIOpts{ + TenantID: &utils.TenantID{ + Tenant: tPrfl.Tenant, + ID: tPrfl.ID}, + }, &rcvTh); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(tPrfl.ThresholdProfile, rcvTh) { + t.Errorf("Expecting: %+v, received: %+v", tPrfl.ThresholdProfile, rcvTh) + } + + tEv := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event1", + Event: map[string]interface{}{ + utils.AccountField: "1001"}, + } + var ids []string + if err := fltrRpc.Call(context.Background(), utils.ThresholdSv1ProcessEvent, tEv, &ids); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(ids, []string{"TH_Account"}) { + t.Error("Unexpected reply returned", ids) + } + + // update the filter + // Add a filter with fieldName taken value from account 1001 + // and check if *monetary balance is is minim 11 ( greater than 11) + // we expect that the balance to be 10 so the filter should not pass (10 > 11) + filter.Filter = &engine.Filter{ + Tenant: "cgrates.org", + ID: "FLTR_TH_Accounts", + Rules: []*engine.FilterRule{ + { + Type: "*gt", + Element: "~*accounts.1001.BalanceMap.*monetary[0].Value", + Values: []string{"11"}, + }, + }, + } + + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetFilter, filter, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + if err := fltrRpc.Call(context.Background(), utils.ThresholdSv1ProcessEvent, tEv, &ids); err == nil || + err.Error() != utils.ErrNotFound.Error() { + t.Error(err) + } +} + +func testV1FltrAccountsExistsDynamicaly(t *testing.T) { + var resp string + if err := fltrRpc.Call(context.Background(), utils.AdminSv1RemoveThresholdProfile, + &utils.TenantIDWithAPIOpts{TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "TH_Account"}}, &resp); err != nil { + if err.Error() != utils.ErrNotFound.Error() { // no error if the threshold is already removed + t.Error(err) + } + } else if resp != utils.OK { + t.Error("Unexpected reply returned", resp) + } + + var result string + // Add a log action + argsAP := &engine.ActionProfileWithAPIOpts{ + ActionProfile: &engine.ActionProfile{ + ID: "LOG", + Actions: []*engine.APAction{ + { + ID: "LogAction", + Type: utils.MetaLog, + }, + }, + }, + } + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetActionProfile, argsAP, &result); err != nil && err.Error() != utils.ErrExists.Error() { + t.Error("Got error on AdminSv1.SetActionProfile: ", err.Error()) + } + //Add a threshold with filter from above and an inline filter for Account 1010 + tPrfl := &engine.ThresholdProfileWithAPIOpts{ + ThresholdProfile: &engine.ThresholdProfile{ + Tenant: "cgrates.org", + ID: "TH_AccountDinamic", + FilterIDs: []string{"*exists:~*accounts.<~*req.Account>:"}, + MaxHits: -1, + MinSleep: time.Millisecond, + Weights: utils.DynamicWeights{ + { + Weight: 90, + }, + }, + ActionProfileIDs: []string{"LOG"}, + Async: true, + }, + } + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetThresholdProfile, tPrfl, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + var rcvTh *engine.ThresholdProfile + if err := fltrRpc.Call(context.Background(), utils.AdminSv1GetThresholdProfile, + &utils.TenantIDWithAPIOpts{ + TenantID: &utils.TenantID{ + Tenant: tPrfl.Tenant, + ID: tPrfl.ID, + }, + }, &rcvTh); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(tPrfl.ThresholdProfile, rcvTh) { + t.Errorf("Expecting: %+v, received: %+v", tPrfl.ThresholdProfile, rcvTh) + } + + tEv := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event1", + Event: map[string]interface{}{ + utils.AccountField: "1001"}, + } + var ids []string + if err := fltrRpc.Call(context.Background(), utils.ThresholdSv1ProcessEvent, tEv, &ids); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(ids, []string{"TH_AccountDinamic"}) { + t.Error("Unexpected reply returned", ids) + } + + tEv = &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event2", + Event: map[string]interface{}{ + utils.AccountField: "non"}, + } + ids = nil + if err := fltrRpc.Call(context.Background(), utils.ThresholdSv1ProcessEvent, tEv, &ids); err == nil || err.Error() != utils.ErrNotFound.Error() { + t.Error(err) + } +} + +func testV1FltrChargerSuffix(t *testing.T) { + var reply string + if err := fltrRpc.Call(context.Background(), utils.CacheSv1Clear, &utils.AttrCacheIDsWithAPIOpts{ + CacheIDs: nil, + }, &reply); err != nil { + t.Error(err) + } else if reply != utils.OK { + t.Error("Reply: ", reply) + } + chargerProfile := &apis.ChargerWithAPIOpts{ + ChargerProfile: &engine.ChargerProfile{ + Tenant: "cgrates.org", + ID: "IntraCharger", + FilterIDs: []string{"*suffix:~*req.Subject:intra"}, + RunID: "Intra", + AttributeIDs: []string{"*constant:*req.Subject:intraState"}, + Weights: utils.DynamicWeights{ + { + Weight: 20, + }, + }, + }, + } + var result string + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetChargerProfile, chargerProfile, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + chargerProfile2 := &apis.ChargerWithAPIOpts{ + ChargerProfile: &engine.ChargerProfile{ + Tenant: "cgrates.org", + ID: "InterCharger", + FilterIDs: []string{"*suffix:~*req.Subject:inter"}, + RunID: "Inter", + AttributeIDs: []string{"*constant:*req.Subject:interState"}, + Weights: utils.DynamicWeights{ + { + Weight: 20, + }, + }, + }, + } + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetChargerProfile, chargerProfile2, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + processedEv := []*engine.ChrgSProcessEventReply{ + { + ChargerSProfile: "IntraCharger", + AttributeSProfiles: []string{"*constant:*req.Subject:intraState"}, + AlteredFields: []string{"*opts.*runID", "*opts.*chargeID", "*req.Subject"}, + + CGREvent: &utils.CGREvent{ // matching Charger1 + Tenant: "cgrates.org", + ID: "event1", + Event: map[string]interface{}{ + utils.AccountField: "1010", + utils.Subject: "intraState", + utils.Destination: "999", + }, + APIOpts: map[string]interface{}{ + utils.MetaRunID: "Intra", + utils.OptsAttributesProfileIDs: []string{"*constant:*req.Subject:intraState"}, + utils.Subsys: utils.MetaChargers, + utils.OptsContext: "*chargers", + }, + }, + }, + } + cgrEv := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event1", + Event: map[string]interface{}{ + utils.AccountField: "1010", + utils.Subject: "Something_intra", + utils.Destination: "999", + }, + } + var result2 []*engine.ChrgSProcessEventReply + if err := fltrRpc.Call(context.Background(), utils.ChargerSv1ProcessEvent, cgrEv, &result2); err != nil { + t.Error(err) + } else { + processedEv[0].CGREvent.APIOpts[utils.MetaChargeID] = result2[0].CGREvent.APIOpts[utils.MetaChargeID] + if utils.ToJSON(result2) != utils.ToJSON(processedEv) { + t.Errorf("Expecting : %s, \n received: %s", utils.ToJSON(processedEv), utils.ToJSON(result2)) + } + } + + processedEv = []*engine.ChrgSProcessEventReply{ + { + ChargerSProfile: "InterCharger", + AttributeSProfiles: []string{"*constant:*req.Subject:interState"}, + AlteredFields: []string{"*opts.*runID", "*opts.*chargeID", "*req.Subject"}, + + CGREvent: &utils.CGREvent{ // matching Charger1 + Tenant: "cgrates.org", + ID: "event1", + Event: map[string]interface{}{ + utils.AccountField: "1010", + utils.Subject: "interState", + utils.Destination: "999", + }, + APIOpts: map[string]interface{}{ + utils.Subsys: utils.MetaChargers, + utils.MetaRunID: "Inter", + utils.OptsContext: "*chargers", + utils.OptsAttributesProfileIDs: []string{"*constant:*req.Subject:interState"}, + }, + }, + }, + } + cgrEv = &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "event1", + Event: map[string]interface{}{ + utils.AccountField: "1010", + utils.Subject: "Something_inter", + utils.Destination: "999", + }, + } + if err := fltrRpc.Call(context.Background(), utils.ChargerSv1ProcessEvent, cgrEv, &result2); err != nil { + t.Error(err) + } else { + processedEv[0].CGREvent.APIOpts[utils.MetaChargeID] = result2[0].CGREvent.APIOpts[utils.MetaChargeID] + if utils.ToJSON(result2) != utils.ToJSON(processedEv) { + t.Errorf("Expecting : %s, \n received: %s", utils.ToJSON(processedEv), utils.ToJSON(result2)) + } + } +} + +func testV1FltrAttributesPrefix(t *testing.T) { + attributeProfile := &engine.APIAttributeProfileWithAPIOpts{ + APIAttributeProfile: &engine.APIAttributeProfile{ + Tenant: "cgrates.new", + ID: "ATTR_1001", + FilterIDs: []string{"*prefix:~*req.CustomField:2007|+2007", "*prefix:~*req.CustomField2:2007|+2007", "FLTR_1", "*string:~*opts.*context:prefix"}, + Attributes: []*engine.ExternalAttribute{ + { + FilterIDs: []string{}, + Path: utils.MetaReq + utils.NestingSep + "CustomField", + Type: utils.MetaConstant, + Value: "2007", + }, + }, + Weights: utils.DynamicWeights{ + { + Weight: 20, + }, + }, + }, + } + var result string + if err := fltrRpc.Call(context.Background(), utils.AdminSv1SetAttributeProfile, attributeProfile, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + + processedEv := &engine.AttrSProcessEventReply{ + AlteredFields: []*engine.FieldsAltered{ + { + MatchedProfileID: "cgrates.new:ATTR_1001", + Fields: []string{"*req.CustomField"}, + }, + }, + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.new", + ID: "event1", + Event: map[string]interface{}{ + "CustomField": "2007", + "CustomField2": "+2007", + utils.Destination: "+1207", + }, + APIOpts: map[string]interface{}{ + utils.OptsContext: "prefix", + }, + }, + } + cgrEv := &utils.CGREvent{ + Tenant: "cgrates.new", + ID: "event1", + Event: map[string]interface{}{ + "CustomField": "+2007", + "CustomField2": "+2007", + utils.Destination: "+1207", + }, + APIOpts: map[string]interface{}{ + utils.OptsContext: "prefix", + }, + } + var result2 *engine.AttrSProcessEventReply + if err := fltrRpc.Call(context.Background(), utils.AttributeSv1ProcessEvent, cgrEv, &result2); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(result2, processedEv) { + t.Errorf("Expecting : %s, \n received: %s", utils.ToJSON(processedEv), utils.ToJSON(result2)) + } + +} + +func testV1FltrStopEngine(t *testing.T) { + if err := engine.KillEngine(accDelay); err != nil { + t.Error(err) + } +}