diff --git a/data/conf/samples/loaders_indexes_internal_db/cgrates.json b/data/conf/samples/loaders_indexes_internal_db/cgrates.json new file mode 100644 index 000000000..6c2aebc76 --- /dev/null +++ b/data/conf/samples/loaders_indexes_internal_db/cgrates.json @@ -0,0 +1,79 @@ +{ +"general": { + "node_id" : "IntenalLoaders", + "log_level": 7 +}, + +"listen": { + "rpc_json": ":2022", + "rpc_gob": ":2023", + "http": ":2280" +}, + +"rpc_conns": { + "engine": { + "strategy": "*first", + "conns": [{"address": "127.0.0.1:2013", "transport":"*gob"}] + } +}, + +"data_db": { + "db_type": "*internal", + "remote_conns": ["engine"], + "replication_conns": ["engine"], + "items":{ + "*accounts": {"remote":true, "replicate":true}, + "*reverse_destinations": {"remote":true, "replicate":true}, + "*destinations": {"remote":true, "replicate":true}, + "*rating_plans": {"remote":true, "replicate":true}, + "*rating_profiles": {"remote":true, "replicate":true}, + "*actions": {"remote":true, "replicate":true}, + "*action_plans": {"remote":true, "replicate":true}, + "*account_action_plans": {"remote":true, "replicate":true}, + "*action_triggers": {"remote":true, "replicate":true}, + "*shared_groups": {"remote":true, "replicate":true}, + "*timings": {"remote":true, "replicate":true}, + "*resource_profiles": {"remote":true, "replicate":true}, + "*resources": {"remote":true, "replicate":true}, + "*statqueue_profiles": {"remote":true, "replicate":true}, + "*statqueues": {"remote":true, "replicate":true}, + "*threshold_profiles": {"remote":true, "replicate":true}, + "*thresholds": {"remote":true, "replicate":true}, + "*filters": {"remote":true, "replicate":true}, + "*route_profiles": {"remote":true, "replicate":true}, + "*attribute_profiles": {"remote":true, "replicate":true}, + "*charger_profiles": {"remote":true, "replicate":true}, + "*dispatcher_profiles": {"remote":true, "replicate":true}, + "*dispatcher_hosts": {"remote":true, "replicate":true}, + "*load_ids": {"remote":true, "replicate":true}, + "*versions": {"remote":true, "replicate":true}, + // no remote for indexes + "*resource_filter_indexes" : {"replicate":true}, + "*stat_filter_indexes" : {"replicate":true}, + "*threshold_filter_indexes" : {"replicate":true}, + "*route_filter_indexes" : {"replicate":true}, + "*attribute_filter_indexes" : {"replicate":true}, + "*charger_filter_indexes" : {"replicate":true}, + "*dispatcher_filter_indexes" : {"replicate":true}, + "*reverse_filter_indexes" : {"replicate":true} + } +}, + +"stor_db": { + "db_type": "*internal" +}, + +"loaders": [{ + "id": "*default", + "enabled": true, + "caches_conns": ["engine"], + "tp_in_dir": "/usr/share/cgrates/tariffplans/tutorial/", + "tp_out_dir": "" +}], + +"apiers": { + "enabled": true, + "caches_conns":["engine"] +} + +} \ No newline at end of file diff --git a/general_tests/loaders_internal_indexes_it_test.go b/general_tests/loaders_internal_indexes_it_test.go new file mode 100644 index 000000000..52a168913 --- /dev/null +++ b/general_tests/loaders_internal_indexes_it_test.go @@ -0,0 +1,170 @@ +//go:build integration +// +build integration + +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ +package general_tests + +import ( + "net/rpc" + "path" + "reflect" + "sort" + "testing" + "time" + + v1 "github.com/cgrates/cgrates/apier/v1" + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +var ( + loadersIDBIdxCfgDir string + loadersIDBIdxCfgPath string + loadersIDBIdxCfgPathInternal = path.Join(*dataDir, "conf", "samples", "loaders_indexes_internal_db") + loadersIDBIdxCfg, loadersIDBIdxCfgInternal *config.CGRConfig + loadersIDBIdxRPC, loadersIDBIdxRPCInternal *rpc.Client + + LoadersIDBIdxTests = []func(t *testing.T){ + testLoadersIDBIdxItLoadConfig, + testLoadersIDBIdxItDB, + testLoadersIDBIdxItStartEngines, + testLoadersIDBIdxItRPCConn, + testLoadersIDBIdxItLoad, + testLoadersIDBIdxCheckAttributes, + testLoadersIDBIdxCheckAttributesIndexes, + testLoadersIDBIdxItStopCgrEngine, + } +) + +func TestLoadersIDBIdxIt(t *testing.T) { + switch *dbType { + case utils.MetaInternal: + loadersIDBIdxCfgDir = "tutinternal" + case utils.MetaMySQL: + loadersIDBIdxCfgDir = "tutmysql" + case utils.MetaMongo: + loadersIDBIdxCfgDir = "tutmongo" + case utils.MetaPostgres: + t.SkipNow() + default: + t.Fatal("Unknown Database type") + } + for _, stest := range LoadersIDBIdxTests { + t.Run(loadersIDBIdxCfgDir, stest) + } +} + +func testLoadersIDBIdxItLoadConfig(t *testing.T) { + loadersIDBIdxCfgPath = path.Join(*dataDir, "conf", "samples", loadersIDBIdxCfgDir) + if loadersIDBIdxCfg, err = config.NewCGRConfigFromPath(loadersIDBIdxCfgPath); err != nil { + t.Error(err) + } + if loadersIDBIdxCfgInternal, err = config.NewCGRConfigFromPath(loadersIDBIdxCfgPathInternal); err != nil { + t.Error(err) + } +} + +func testLoadersIDBIdxItDB(t *testing.T) { + if err := engine.InitDataDb(loadersIDBIdxCfg); err != nil { + t.Fatal(err) + } + if err := engine.InitStorDb(loadersIDBIdxCfg); err != nil { + t.Fatal(err) + } +} + +func testLoadersIDBIdxItStartEngines(t *testing.T) { + if _, err := engine.StopStartEngine(loadersIDBIdxCfgPath, *waitRater); err != nil { + t.Fatal(err) + } + if _, err := engine.StartEngine(loadersIDBIdxCfgPathInternal, *waitRater); err != nil { + t.Fatal(err) + } +} + +func testLoadersIDBIdxItRPCConn(t *testing.T) { + var err error + if loadersIDBIdxRPC, err = newRPCClient(loadersIDBIdxCfg.ListenCfg()); err != nil { + t.Fatal(err) + } + if loadersIDBIdxRPCInternal, err = newRPCClient(loadersIDBIdxCfgInternal.ListenCfg()); err != nil { + t.Fatal(err) + } +} + +func testLoadersIDBIdxItLoad(t *testing.T) { + var loadInst utils.LoadInstance + if err := loadersIDBIdxRPCInternal.Call(utils.APIerSv2LoadTariffPlanFromFolder, + &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "tutorial")}, + &loadInst); err != nil { + t.Error(err) + } + time.Sleep(100 * time.Millisecond) +} + +func testLoadersIDBIdxCheckAttributes(t *testing.T) { + exp := &engine.AttributeProfile{ + Tenant: "cgrates.org", + ID: "ATTR_1001_SIMPLEAUTH", + FilterIDs: []string{"*string:~*req.Account:1001"}, + Contexts: []string{"simpleauth"}, + Attributes: []*engine.Attribute{ + { + Path: utils.MetaReq + utils.NestingSep + "Password", + Type: utils.MetaConstant, + Value: config.NewRSRParsersMustCompile("CGRateS.org", utils.InfieldSep), + }, + }, + Weight: 20.0, + } + + var reply *engine.AttributeProfile + if err := loadersIDBIdxRPC.Call(utils.APIerSv1GetAttributeProfile, + utils.TenantIDWithAPIOpts{TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "ATTR_1001_SIMPLEAUTH"}}, + &reply); err != nil { + t.Error(err) + } else if reply.Compile(); !reflect.DeepEqual(exp, reply) { + t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(exp), utils.ToJSON(reply)) + } +} + +func testLoadersIDBIdxCheckAttributesIndexes(t *testing.T) { + expIdx := []string{ + "*string:*req.Account:1001:ATTR_1001_SIMPLEAUTH", + "*string:*req.Account:1002:ATTR_1002_SIMPLEAUTH", + "*string:*req.Account:1003:ATTR_1003_SIMPLEAUTH", + } + var indexes []string + if err := loadersIDBIdxRPC.Call(utils.APIerSv1GetFilterIndexes, &v1.AttrGetFilterIndexes{ + ItemType: utils.MetaAttributes, Tenant: "cgrates.org", FilterType: utils.MetaString, + Context: "simpleauth"}, + &indexes); err != nil { + t.Error(err) + } else if sort.Strings(indexes); !reflect.DeepEqual(indexes, expIdx) { + t.Errorf("Expecting: %+v, received: %+v", + utils.ToJSON(expIdx), utils.ToJSON(indexes)) + } +} + +func testLoadersIDBIdxItStopCgrEngine(t *testing.T) { + if err := engine.KillEngine(100); err != nil { + t.Error(err) + } +}