//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 apis import ( "os" "path" "reflect" "sort" "testing" "time" "github.com/cgrates/birpc" "github.com/cgrates/birpc/context" "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/loaders" "github.com/cgrates/cgrates/utils" ) var ( ldrCfgPath string ldrCfg *config.CGRConfig ldrRPC *birpc.Client ldrConfigDIR string //run tests for specific configuration sTestsLdr = []func(t *testing.T){ testLoadersRemoveFolders, testLoadersCreateFolders, testLoadersInitCfg, testLoadersInitDataDB, testLoadersStartEngine, testLoadersRPCConn, testLoadersWriteCSVs, testLoadersLoad, testLoadersGetAccounts, testLoadersGetActionProfiles, testLoadersGetAttributeProfiles, testLoadersGetChargerProfiles, testLoadersGetDispatcherProfiles, testLoadersGetDispatcherHosts, testLoadersGetFilters, testLoadersGetRateProfiles, testLoadersGetResourceProfiles, testLoadersGetRouteProfiles, testLoadersGetStatQueueProfiles, testLoadersGetThresholdProfiles, testLoadersRemove, testLoadersGetAccountAfterRemove, testLoadersGetActionProfileAfterRemove, testLoadersGetAttributeProfileAfterRemove, testLoadersGetChargerProfileAfterRemove, testLoadersGetDispatcherProfileAfterRemove, testLoadersGetDispatcherHostAfterRemove, testLoadersGetFilterAfterRemove, testLoadersGetRateProfileAfterRemove, testLoadersGetResourceProfileAfterRemove, testLoadersGetRouteProfileAfterRemove, testLoadersGetStatQueueProfileAfterRemove, testLoadersGetThresholdProfileAfterRemove, testLoadersRemoveFolders, testLoadersPing, testLoadersKillEngine, } ) func TestLoadersIT(t *testing.T) { switch *dbType { case utils.MetaInternal: ldrConfigDIR = "apis_loaders_internal" case utils.MetaMongo: ldrConfigDIR = "apis_loaders_mongo" case utils.MetaMySQL: ldrConfigDIR = "apis_loaders_mysql" case utils.MetaPostgres: t.SkipNow() default: t.Fatal("Unknown Database type") } for _, stest := range sTestsLdr { t.Run(ldrConfigDIR, stest) } } func testLoadersInitCfg(t *testing.T) { var err error ldrCfgPath = path.Join(*dataDir, "conf", "samples", ldrConfigDIR) ldrCfg, err = config.NewCGRConfigFromPath(context.Background(), ldrCfgPath) if err != nil { t.Error(err) } } func testLoadersInitDataDB(t *testing.T) { if err := engine.InitDataDB(ldrCfg); err != nil { t.Fatal(err) } } // Start CGR Engine func testLoadersStartEngine(t *testing.T) { if _, err := engine.StopStartEngine(ldrCfgPath, *waitRater); err != nil { t.Fatal(err) } } func testLoadersRPCConn(t *testing.T) { var err error ldrRPC, err = newRPCClient(ldrCfg.ListenCfg()) // We connect over JSON so we can also troubleshoot if needed if err != nil { t.Fatal(err) } } // Kill the engine when it is about to be finished func testLoadersKillEngine(t *testing.T) { if err := engine.KillEngine(100); err != nil { t.Error(err) } } func testLoadersPing(t *testing.T) { var reply string if err := ldrRPC.Call(context.Background(), utils.LoaderSv1Ping, new(utils.CGREvent), &reply); err != nil { t.Error(err) } else if reply != utils.Pong { t.Error("Unexpected reply returned:", reply) } } func testLoadersCreateFolders(t *testing.T) { if err := os.MkdirAll("/tmp/TestLoadersIT/in", 0755); err != nil { t.Error(err) } } func testLoadersRemoveFolders(t *testing.T) { if err := os.RemoveAll("/tmp/TestLoadersIT/in"); err != nil { t.Error(err) } } func testLoadersWriteCSVs(t *testing.T) { writeFile := func(fileName, data string) error { csvAccounts, err := os.Create(path.Join(ldrCfg.LoaderCfg()[0].TpInDir, fileName)) if err != nil { return err } defer csvAccounts.Close() _, err = csvAccounts.WriteString(data) if err != nil { return err } return csvAccounts.Sync() } // Create and populate Accounts.csv if err := writeFile(utils.AccountsCsv, ` #Tenant,ID,FilterIDs,Weights,Blockers,Opts,BalanceID,BalanceFilterIDs,BalanceWeights,BalanceBlockers,BalanceType,BalanceUnits,BalanceUnitFactors,BalanceOpts,BalanceCostIncrements,BalanceAttributeIDs,BalanceRateProfileIDs,ThresholdIDs cgrates.org,1001,,,,,,,,,,,,,,,, cgrates.org,1001,,;20,;false,,,,,,,,,,,,, cgrates.org,1001,,,,,MonetaryBalance,,;10,*string:~*req.Account:1002;true;;false,*monetary,14,fltr1&fltr2;100;fltr3;200,,fltr1&fltr2;1.3;2.3;3.3,attr1;attr2,,*none cgrates.org,1001,,,,,,,,,,,,,,,, cgrates.org,1001,,,,,VoiceBalance,,;10,,*voice,1h,,,,,, cgrates.org,1002,,,,,MonetaryBalance,,;20,,*monetary,1h,,,,,, cgrates.org,1002,,;30,;false,,VoiceBalance,,;10,,*voice,14,fltr3&fltr4;150;fltr5;250,,fltr3&fltr4;1.3;2.3;3.3,attr3;attr4,,*none `); err != nil { t.Fatal(err) } // Create and populate ActionProfiles.csv if err := writeFile(utils.ActionsCsv, ` #Tenant,ID,FilterIDs,Weights,Blockers,Schedule,TargetType,TargetIDs,ActionID,ActionFilterIDs,ActionTTL,ActionType,ActionOpts,ActionPath,ActionValue cgrates.org,ONE_TIME_ACT,,,,,,,,,,,,, cgrates.org,ONE_TIME_ACT,,;10,;true,*asap,*accounts,1001;1002,,,,,,, cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP,,0s,*add_balance,,, cgrates.org,ONE_TIME_ACT,,,,*asap,*accounts,1001;1002,,,,,,, cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP,,,,,*balance.TestBalance.Value,10 cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_DATA,,0s,*set_balance,,*balance.TestDataBalance.Type,*data cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_DATA,,0s,*add_balance,,*balance.TestDataBalance.Value,1024 cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_VOICE,,0s,*set_balance,,*balance.TestVoiceBalance.Type,*voice cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*add_balance,,*balance.TestVoiceBalance.Value,15m15s cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*add_balance,,*balance.TestVoiceBalance2.Value,15m15s `); err != nil { t.Fatal(err) } // Create and populate Attributes.csv if err := writeFile(utils.AttributesCsv, ` #Tenant,ID,FilterIDs,Weights,Blockers,AttributeFilterIDs,AttributeBlockers,Path,Type,Value cgrates.org,ALS1,*string:~*req.Account:1001;*string:~*opts.*context:con1,;20,;true,,,,, cgrates.org,ALS1,,,,*string:~*req.Field1:Initial,,*req.Field1,*variable,Sub1 cgrates.org,ALS1,*string:~*opts.*context:con2|con3,,,,,*req.Field2,*variable,Sub2 cgrates.org,ALS2,*string:~*opts.*context:con2|con3,,;false,,,*req.Field2,*variable,Sub2 cgrates.org,ALS2,*string:~*req.Account:1002;*string:~*opts.*context:con1,;20,,*string:~*req.Field1:Initial,,*req.Field1,*variable,Sub1 `); err != nil { t.Fatal(err) } // Create and populate Chargers.csv if err := writeFile(utils.ChargersCsv, ` #Tenant,ID,FilterIDs,Weights,Blockers,RunID,AttributeIDs cgrates.org,Charger1,*string:~*req.Account:1001,;20,;true,, cgrates.org,Charger1,,,,*rated,ATTR_1001_SIMPLEAUTH cgrates.org,Charger2,,,,*rated,ATTR_1002_SIMPLEAUTH cgrates.org,Charger2,*string:~*req.Account:1002,;15,;false,, `); err != nil { t.Fatal(err) } // Create and populate DispatcherProfiles.csv if err := writeFile(utils.DispatcherProfilesCsv, ` #Tenant,ID,FilterIDs,Weight,Strategy,StrategyParameters,ConnID,ConnFilterIDs,ConnWeight,ConnBlocker,ConnParameters cgrates.org,D1,,,,,,,,, cgrates.org,D1,*string:~*req.Account:1001,20,*first,,,,,, cgrates.org,D1,,,,,C1,fltr1,10,true,*ratio:1;param1:value1 cgrates.org,D1,,,,,,,,, cgrates.org,D1,,,,,C1,fltr2;fltr4,,false,param2:value2 cgrates.org,D2,,,*first,,C3,fltr2,20,true, cgrates.org,D2,*string:~*req.Account:1002,20,,,C2,fltr3,10,,param3:value3 `); err != nil { t.Fatal(err) } // Create and populate DispatcherHosts.csv if err := writeFile(utils.DispatcherHostsCsv, ` #Tenant[0],ID[1],Address[2],Transport[3],ConnectAttempts[4],Reconnects[5],MaxReconnectInterval[6],ConnectTimeout[7],ReplyTimeout[8],Tls[9],ClientKey[10],ClientCertificate[11],CaCertificate[12] cgrates.org,ALL,,,,,5m,,,,,, cgrates.org,ALL,127.0.0.1:6012,,1,3,5m,1m,2m,true,,, cgrates.org,ALL,,*json,1,3,5m,1m,2m,false,,, `); err != nil { t.Fatal(err) } // Create and populate Filters.csv if err := writeFile(utils.FiltersCsv, ` #Tenant[0],ID[1],Type[2],Element[3],Values[4] cgrates.org,FLTR_ACCOUNT_1001,,, cgrates.org,FLTR_ACCOUNT_1001,*string,~*req.Account,1001;1002 cgrates.org,FLTR_ACCOUNT_1001,,, cgrates.org,FLTR_ACCOUNT_1001,*prefix,~*req.Destination,10;20 cgrates.org,FLTR_ACCOUNT_1001,*rsr,~*req.Subject,~^1.*1$ cgrates.org,FLTR_ACCOUNT_1001,*rsr,~*req.Destination,1002 cgrates.org,FLTR_ACNT_dan,*string,~*req.Account,dan `); err != nil { t.Fatal(err) } // Create and populate RateProfiles.csv if err := writeFile(utils.RatesCsv, ` #Tenant,ID,FilterIDs,Weights,MinCost,MaxCost,MaxCostStrategy,RateID,RateFilterIDs,RateActivationStart,RateWeights,RateBlocker,RateIntervalStart,RateFixedFee,RateRecurrentFee,RateUnit,RateIncrement cgrates.org,RP1,,,,,,,,,,,,,,, cgrates.org,RP1,*string:~*req.Subject:1001,;0,0.1,0.6,*free,,,,,,,,,, cgrates.org,RP1,,,,,,RT_WEEK,,"* * * * 1-5",;0,false,0s,0,0.12,1m,1m cgrates.org,RP1,,,,,,RT_WEEK,,,,,1m,1.234,0.06,1m,1s cgrates.org,RP1,,,,,,RT_WEEKEND,,,,true,,0.067,0.03,, cgrates.org,RP1,,,,,,RT_WEEKEND,,"* * * * 0,6",;10,false,0s,0.089,0.06,1m,1s cgrates.org,RP1,,,,,,RT_CHRISTMAS,,* * 24 12 *,;30,false,0s,0.0564,0.06,1m,1s cgrates.org,RP1,,,,,,RT_CHRISTMAS,,,,true,,,,, cgrates.org,RP2,,,,,,RT_WEEK,,,,,1m,1.234,0.06,1m,1s cgrates.org,RP2,*string:~*req.Subject:1002,;10,0.2,0.4,*free,RT_WEEK,,"* * * * 1-5",fltr1;20,false,0s,0,0.24,2m,30s `); err != nil { t.Fatal(err) } // Create and populate Resources.csv if err := writeFile(utils.ResourcesCsv, ` #Tenant[0],Id[1],FilterIDs[2],Weights[3],TTL[4],Limit[5],AllocationMessage[6],Blocker[7],Stored[8],Thresholds[9] cgrates.org,ResGroup21,*string:~*req.Account:1001,;10,1s,2,call,true,true, cgrates.org,ResGroup21,,,,,,,, cgrates.org,ResGroup22,,,,,,,, cgrates.org,ResGroup22,*string:~*req.Account:dan,;10,3600s,2,premium_call,true,true, `); err != nil { t.Fatal(err) } // Create and populate Routes.csv if err := writeFile(utils.RoutesCsv, ` #Tenant[0],ID[1],FilterIDs[2],Weights[3],Blockers[4],Sorting[5],SortingParameters[6],RouteID[7],RouteFilterIDs[8],RouteAccountIDs[9],RouteRateProfileIDs[10],RouteResourceIDs[11],RouteStatIDs[12],RouteWeights[13],RouteBlockers[14],RouteParameters[15] cgrates.org,RoutePrf1,,,,,,,,,,,,,, cgrates.org,RoutePrf1,*string:~*req.Account:1001,;20,;true,*lc,,,,,,,,,, cgrates.org,RoutePrf1,,,,,,route1,fltr1,Account1;Account2,RPL_1,ResGroup1,Stat1,,;true,param1 cgrates.org,RoutePrf1,,,,,,,,,,,,,, cgrates.org,RoutePrf1,,,,,,route1,,,RPL_2,ResGroup2,,;10,, cgrates.org,RoutePrf1,,,,,,route1,fltr2,,RPL_3,ResGroup3,Stat2,,,param2 cgrates.org,RoutePrf1,,,,,,route1,,,,ResGroup4,Stat3,,, cgrates.org,RoutePrf1,,,,,,route2,fltr5,Account1,RPL_1,ResGroup1,Stat1,fltr1;10,;true,param1 cgrates.org,RoutePrf2,,,,,,,,,,,,,, cgrates.org,RoutePrf2,*string:~*req.Account:1002,;20,,*lc,,route1,fltr3,Account3;Account4,RPL_2,ResGroup2,Stat2,;10,;true,param1 `); err != nil { t.Fatal(err) } // Create and populate Stats.csv if err := writeFile(utils.StatsCsv, ` #Tenant[0],ID[1],FilterIDs[2],Weights[3],Blockers[4],QueueLength[5],TTL[6],MinItems[7],Stored[8],ThresholdIDs[9],MetricIDs[10],MetricFilterIDs[11],MetricBlockers[12] cgrates.org,TestStats,*string:~*req.Account:1001,;20,;true,100,1s,2,true,Th1;Th2,*sum#~*req.Value;*average#~*req.Value,fltr1;fltr2, cgrates.org,TestStats,,,,,,2,,,*sum#~*req.Usage,,*string:~*req.Account:1003&fltr2;true;;false cgrates.org,TestStats2,*string:~*req.Account:1002,,;true,100,1s,2,true,Th,*sum#~*req.Value;*sum#~*req.Usage;*average#~*req.Value;*average#~*req.Usage,, cgrates.org,TestStats2,,;20,,,,2,true,,*sum#~*req.Cost;*average#~*req.Cost,,;false cgrates.org,TestStats3,,,,,,,,,,, cgrates.org,TestStats3,*string:~*req.Account:1003,;20,;true,100,1s,2,true,Th1;Th2,*sum#~*req.Value;*average#~*req.Value,,fltr_for_stats;false `); err != nil { t.Fatal(err) } // Create and populate Thresholds.csv if err := writeFile(utils.ThresholdsCsv, ` #Tenant[0],Id[1],FilterIDs[2],Weights[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],ActionProfileIDs[8],Async[9] cgrates.org,TH1,*string:~*req.Account:1001;*string:~*req.RunID:*default,;10,12,10,1s,true,ACT_PRF1,true cgrates.org,TH1,,,,,,,, cgrates.org,TH2,,,,,,,, cgrates.org,TH2,*string:~*req.Account:1002,,,,,true,,true cgrates.org,TH2,,;5,10,8,1s,true,ACT_PRF2,true `); err != nil { t.Fatal(err) } } func testLoadersLoad(t *testing.T) { var reply string if err := ldrRPC.Call(context.Background(), utils.LoaderSv1Run, &loaders.ArgsProcessFolder{ APIOpts: map[string]interface{}{ utils.MetaCache: utils.MetaReload, utils.MetaStopOnError: true, }, }, &reply); err != nil { t.Error(err) } else if reply != utils.OK { t.Error("Unexpected reply returned:", reply) } } func testLoadersGetAccounts(t *testing.T) { expAccs := []*utils.Account{ { Tenant: "cgrates.org", ID: "1001", Weights: utils.DynamicWeights{ { Weight: 20, }, }, Blockers: utils.DynamicBlockers{ { Blocker: false, }, }, Opts: make(map[string]interface{}), Balances: map[string]*utils.Balance{ "MonetaryBalance": { ID: "MonetaryBalance", Weights: utils.DynamicWeights{ { Weight: 10, }, }, Blockers: utils.DynamicBlockers{ { FilterIDs: []string{"*string:~*req.Account:1002"}, Blocker: true, }, { Blocker: false, }, }, Type: utils.MetaMonetary, Units: utils.NewDecimal(14, 0), UnitFactors: []*utils.UnitFactor{ { FilterIDs: []string{"fltr1", "fltr2"}, Factor: utils.NewDecimal(100, 0), }, { FilterIDs: []string{"fltr3"}, Factor: utils.NewDecimal(200, 0), }, }, Opts: map[string]interface{}{}, CostIncrements: []*utils.CostIncrement{ { FilterIDs: []string{"fltr1", "fltr2"}, Increment: utils.NewDecimal(13, 1), FixedFee: utils.NewDecimal(23, 1), RecurrentFee: utils.NewDecimal(33, 1), }, }, AttributeIDs: []string{"attr1", "attr2"}, }, "VoiceBalance": { ID: "VoiceBalance", Weights: utils.DynamicWeights{ { Weight: 10, }, }, Type: utils.MetaVoice, Units: utils.NewDecimal(int64(time.Hour), 0), Opts: make(map[string]interface{}), }, }, ThresholdIDs: []string{utils.MetaNone}, }, { Tenant: "cgrates.org", ID: "1002", Weights: utils.DynamicWeights{ { Weight: 30, }, }, Blockers: utils.DynamicBlockers{ { Blocker: false, }, }, Opts: make(map[string]interface{}), Balances: map[string]*utils.Balance{ "MonetaryBalance": { ID: "MonetaryBalance", Weights: utils.DynamicWeights{ { Weight: 20, }, }, Type: utils.MetaMonetary, Units: utils.NewDecimal(int64(time.Hour), 0), Opts: map[string]interface{}{}, }, "VoiceBalance": { ID: "VoiceBalance", Weights: utils.DynamicWeights{ { Weight: 10, }, }, Type: utils.MetaVoice, Units: utils.NewDecimal(14, 0), Opts: make(map[string]interface{}), UnitFactors: []*utils.UnitFactor{ { FilterIDs: []string{"fltr3", "fltr4"}, Factor: utils.NewDecimal(150, 0), }, { FilterIDs: []string{"fltr5"}, Factor: utils.NewDecimal(250, 0), }, }, CostIncrements: []*utils.CostIncrement{ { FilterIDs: []string{"fltr3", "fltr4"}, Increment: utils.NewDecimal(13, 1), FixedFee: utils.NewDecimal(23, 1), RecurrentFee: utils.NewDecimal(33, 1), }, }, AttributeIDs: []string{"attr3", "attr4"}, }, }, ThresholdIDs: []string{utils.MetaNone}, }, } var accs []*utils.Account if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetAccounts, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &accs); err != nil { t.Error(err) } else { sort.Slice(accs, func(i, j int) bool { return accs[i].ID < accs[j].ID }) if !reflect.DeepEqual(accs, expAccs) { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expAccs), utils.ToJSON(accs)) } } } func testLoadersGetActionProfiles(t *testing.T) { expActs := []*engine.ActionProfile{ { Tenant: "cgrates.org", ID: "ONE_TIME_ACT", Weights: utils.DynamicWeights{ { Weight: 10, }, }, Blockers: utils.DynamicBlockers{ { Blocker: true, }, }, Schedule: utils.MetaASAP, Targets: map[string]utils.StringSet{ "*accounts": { "1001": {}, "1002": {}, }, }, Actions: []*engine.APAction{ { ID: "TOPUP", TTL: 0, Type: utils.MetaAddBalance, Opts: map[string]interface{}{}, Diktats: []*engine.APDiktat{ { Path: "*balance.TestBalance.Value", Value: "10", }, }, }, { ID: "SET_BALANCE_TEST_DATA", TTL: 0, Type: utils.MetaSetBalance, Opts: map[string]interface{}{}, Diktats: []*engine.APDiktat{ { Path: "*balance.TestDataBalance.Type", Value: utils.MetaData, }, }, }, { ID: "TOPUP_TEST_DATA", TTL: 0, Type: utils.MetaAddBalance, Opts: map[string]interface{}{}, Diktats: []*engine.APDiktat{ { Path: "*balance.TestDataBalance.Value", Value: "1024", }, }, }, { ID: "SET_BALANCE_TEST_VOICE", TTL: 0, Type: utils.MetaSetBalance, Opts: map[string]interface{}{}, Diktats: []*engine.APDiktat{ { Path: "*balance.TestVoiceBalance.Type", Value: utils.MetaVoice, }, }, }, { ID: "TOPUP_TEST_VOICE", TTL: 0, Type: utils.MetaAddBalance, Opts: map[string]interface{}{}, Diktats: []*engine.APDiktat{ { Path: "*balance.TestVoiceBalance.Value", Value: "15m15s", }, { Path: "*balance.TestVoiceBalance2.Value", Value: "15m15s", }, }, }, }, }, } var acts []*engine.ActionProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetActionProfiles, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &acts); err != nil { t.Error(err) } else { sort.Slice(acts, func(i, j int) bool { return acts[i].ID < acts[j].ID }) if !reflect.DeepEqual(acts, expActs) { t.Errorf("expected: <%+v>, \nreceived: <%+v>", expActs, acts) } } } func testLoadersGetAttributeProfiles(t *testing.T) { expAttrs := []*engine.APIAttributeProfile{ { Tenant: "cgrates.org", ID: "ALS1", FilterIDs: []string{"*string:~*req.Account:1001", "*string:~*opts.*context:con1", "*string:~*opts.*context:con2|con3"}, Attributes: []*engine.ExternalAttribute{ { FilterIDs: []string{"*string:~*req.Field1:Initial"}, Path: utils.MetaReq + utils.NestingSep + "Field1", Type: utils.MetaVariable, Value: "Sub1", }, { Path: utils.MetaReq + utils.NestingSep + "Field2", Type: utils.MetaVariable, Value: "Sub2", }, }, Blockers: utils.DynamicBlockers{ { Blocker: true, }, }, Weights: utils.DynamicWeights{ { Weight: 20, }, }, }, { Tenant: "cgrates.org", ID: "ALS2", FilterIDs: []string{"*string:~*opts.*context:con2|con3", "*string:~*req.Account:1002", "*string:~*opts.*context:con1"}, Attributes: []*engine.ExternalAttribute{ { Path: utils.MetaReq + utils.NestingSep + "Field2", Type: utils.MetaVariable, Value: "Sub2", }, { FilterIDs: []string{"*string:~*req.Field1:Initial"}, Path: utils.MetaReq + utils.NestingSep + "Field1", Type: utils.MetaVariable, Value: "Sub1", }, }, Blockers: utils.DynamicBlockers{ { Blocker: false, }, }, Weights: utils.DynamicWeights{ { Weight: 20, }, }, }, } var attrs []*engine.APIAttributeProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetAttributeProfiles, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &attrs); err != nil { t.Error(err) } else { sort.Slice(attrs, func(i, j int) bool { return attrs[i].ID < attrs[j].ID }) if !reflect.DeepEqual(attrs, expAttrs) { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expAttrs), utils.ToJSON(attrs)) } } } func testLoadersGetChargerProfiles(t *testing.T) { expChrgs := []*engine.ChargerProfile{ { Tenant: "cgrates.org", ID: "Charger1", FilterIDs: []string{"*string:~*req.Account:1001"}, RunID: "*rated", AttributeIDs: []string{"ATTR_1001_SIMPLEAUTH"}, Weights: utils.DynamicWeights{ { Weight: 20, }, }, Blockers: utils.DynamicBlockers{ { Blocker: true, }, }, }, { Tenant: "cgrates.org", ID: "Charger2", FilterIDs: []string{"*string:~*req.Account:1002"}, RunID: "*rated", AttributeIDs: []string{"ATTR_1002_SIMPLEAUTH"}, Weights: utils.DynamicWeights{ { Weight: 15, }, }, Blockers: utils.DynamicBlockers{ { Blocker: false, }, }, }, } var chrgs []*engine.ChargerProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetChargerProfiles, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &chrgs); err != nil { t.Error(err) } else { sort.Slice(chrgs, func(i, j int) bool { return chrgs[i].ID < chrgs[j].ID }) if !reflect.DeepEqual(chrgs, expChrgs) { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expChrgs), utils.ToJSON(chrgs)) } } } func testLoadersGetDispatcherProfiles(t *testing.T) { expDspPrfs := []*engine.DispatcherProfile{ { Tenant: "cgrates.org", ID: "D1", FilterIDs: []string{"*string:~*req.Account:1001"}, Strategy: utils.MetaFirst, StrategyParams: map[string]interface{}{}, Weight: 20, Hosts: engine.DispatcherHostProfiles{ { ID: "C1", FilterIDs: []string{"fltr1", "fltr2", "fltr4"}, Weight: 10, Params: map[string]interface{}{ utils.MetaRatio: "1", "param1": "value1", "param2": "value2", }, Blocker: true, }, }, }, { Tenant: "cgrates.org", ID: "D2", FilterIDs: []string{"*string:~*req.Account:1002"}, Strategy: utils.MetaFirst, StrategyParams: map[string]interface{}{}, Weight: 20, Hosts: engine.DispatcherHostProfiles{ { ID: "C3", FilterIDs: []string{"fltr2"}, Weight: 20, Params: map[string]interface{}{}, Blocker: true, }, { ID: "C2", FilterIDs: []string{"fltr3"}, Weight: 10, Params: map[string]interface{}{ "param3": "value3", }, Blocker: false, }, }, }, } var dspPrfs []*engine.DispatcherProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetDispatcherProfiles, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &dspPrfs); err != nil { t.Error(err) } else { sort.Slice(dspPrfs, func(i, j int) bool { return dspPrfs[i].ID < dspPrfs[j].ID }) if !reflect.DeepEqual(dspPrfs, expDspPrfs) { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expDspPrfs), utils.ToJSON(dspPrfs)) } } } func testLoadersGetDispatcherHosts(t *testing.T) { expDspHosts := []*engine.DispatcherHost{ { Tenant: "cgrates.org", RemoteHost: &config.RemoteHost{ ID: "ALL", Address: "127.0.0.1:6012", Transport: utils.MetaJSON, ConnectAttempts: 1, Reconnects: 3, MaxReconnectInterval: 5 * time.Minute, ConnectTimeout: time.Minute, ReplyTimeout: 2 * time.Minute, TLS: true, }, }, } var dspHosts []*engine.DispatcherHost if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetDispatcherHosts, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &dspHosts); err != nil { t.Error(err) } else if !reflect.DeepEqual(dspHosts, expDspHosts) { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expDspHosts), utils.ToJSON(dspHosts)) } } func testLoadersGetFilters(t *testing.T) { expFltrs := []*engine.Filter{ { Tenant: "cgrates.org", ID: "FLTR_ACCOUNT_1001", Rules: []*engine.FilterRule{ { Element: utils.DynamicDataPrefix + utils.MetaReq + utils.NestingSep + utils.AccountField, Type: utils.MetaString, Values: []string{"1001", "1002"}, }, { Element: "~*req.Destination", Type: utils.MetaPrefix, Values: []string{"10", "20"}, }, { Element: "~*req.Subject", Type: utils.MetaRSR, Values: []string{"~^1.*1$"}, }, { Element: "~*req.Destination", Type: utils.MetaRSR, Values: []string{"1002"}, }, }, }, { Tenant: "cgrates.org", ID: "FLTR_ACNT_dan", Rules: []*engine.FilterRule{ { Element: utils.DynamicDataPrefix + utils.MetaReq + utils.NestingSep + utils.AccountField, Type: utils.MetaString, Values: []string{"dan"}, }, }, }, } var fltrs []*engine.Filter if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetFilters, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &fltrs); err != nil { t.Error(err) } else { sort.Slice(fltrs, func(i, j int) bool { return fltrs[i].ID < fltrs[j].ID }) if !reflect.DeepEqual(fltrs, expFltrs) { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expFltrs), utils.ToJSON(fltrs)) } } } func testLoadersGetRateProfiles(t *testing.T) { expRatePrfs := []*utils.RateProfile{ { Tenant: "cgrates.org", ID: "RP1", FilterIDs: []string{"*string:~*req.Subject:1001"}, Weights: utils.DynamicWeights{ { Weight: 0, }, }, MinCost: utils.NewDecimal(1, 1), MaxCost: utils.NewDecimal(6, 1), MaxCostStrategy: "*free", Rates: map[string]*utils.Rate{ "RT_WEEK": { ID: "RT_WEEK", Weights: utils.DynamicWeights{ { Weight: 0, }, }, ActivationTimes: "* * * * 1-5", IntervalRates: []*utils.IntervalRate{ { IntervalStart: utils.NewDecimal(int64(0*time.Second), 0), FixedFee: utils.NewDecimal(0, 0), RecurrentFee: utils.NewDecimal(12, 2), Unit: utils.NewDecimal(int64(time.Minute), 0), Increment: utils.NewDecimal(int64(time.Minute), 0), }, { IntervalStart: utils.NewDecimal(int64(time.Minute), 0), FixedFee: utils.NewDecimal(1234, 3), RecurrentFee: utils.NewDecimal(6, 2), Unit: utils.NewDecimal(int64(time.Minute), 0), Increment: utils.NewDecimal(int64(time.Second), 0), }, }, }, "RT_WEEKEND": { ID: "RT_WEEKEND", Weights: utils.DynamicWeights{ { Weight: 10, }, }, ActivationTimes: "* * * * 0,6", Blocker: true, IntervalRates: []*utils.IntervalRate{ { IntervalStart: utils.NewDecimal(int64(0*time.Second), 0), FixedFee: utils.NewDecimal(89, 3), RecurrentFee: utils.NewDecimal(6, 2), Unit: utils.NewDecimal(int64(time.Minute), 0), Increment: utils.NewDecimal(int64(time.Second), 0), }, }, }, "RT_CHRISTMAS": { ID: "RT_CHRISTMAS", Weights: utils.DynamicWeights{ { Weight: 30, }, }, Blocker: true, ActivationTimes: "* * 24 12 *", IntervalRates: []*utils.IntervalRate{ { IntervalStart: utils.NewDecimal(int64(0*time.Second), 0), FixedFee: utils.NewDecimal(564, 4), RecurrentFee: utils.NewDecimal(6, 2), Unit: utils.NewDecimal(int64(time.Minute), 0), Increment: utils.NewDecimal(int64(time.Second), 0), }, }, }, }, }, { Tenant: "cgrates.org", ID: "RP2", FilterIDs: []string{"*string:~*req.Subject:1002"}, Weights: utils.DynamicWeights{ { Weight: 10, }, }, MinCost: utils.NewDecimal(2, 1), MaxCost: utils.NewDecimal(4, 1), MaxCostStrategy: "*free", Rates: map[string]*utils.Rate{ "RT_WEEK": { ID: "RT_WEEK", Weights: utils.DynamicWeights{ { FilterIDs: []string{"fltr1"}, Weight: 20, }, }, ActivationTimes: "* * * * 1-5", IntervalRates: []*utils.IntervalRate{ { IntervalStart: utils.NewDecimal(int64(0*time.Second), 0), FixedFee: utils.NewDecimal(0, 0), RecurrentFee: utils.NewDecimal(24, 2), Unit: utils.NewDecimal(int64(2*time.Minute), 0), Increment: utils.NewDecimal(int64(30*time.Second), 0), }, { IntervalStart: utils.NewDecimal(int64(time.Minute), 0), FixedFee: utils.NewDecimal(1234, 3), RecurrentFee: utils.NewDecimal(6, 2), Unit: utils.NewDecimal(int64(time.Minute), 0), Increment: utils.NewDecimal(int64(time.Second), 0), }, }, }, }, }, } var ratePrfs []*utils.RateProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetRateProfiles, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &ratePrfs); err != nil { t.Error(err) } else { sort.Slice(ratePrfs, func(i, j int) bool { return ratePrfs[i].ID < ratePrfs[j].ID }) if !reflect.DeepEqual(ratePrfs, expRatePrfs) { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expRatePrfs), utils.ToJSON(ratePrfs)) } } } func testLoadersGetResourceProfiles(t *testing.T) { expRsPrfs := []*engine.ResourceProfile{ { Tenant: "cgrates.org", ID: "ResGroup21", FilterIDs: []string{"*string:~*req.Account:1001"}, UsageTTL: time.Second, AllocationMessage: "call", Weights: utils.DynamicWeights{ { Weight: 10, }}, Limit: 2, Blocker: true, Stored: true, }, { Tenant: "cgrates.org", ID: "ResGroup22", FilterIDs: []string{"*string:~*req.Account:dan"}, UsageTTL: time.Hour, AllocationMessage: "premium_call", Blocker: true, Stored: true, Weights: utils.DynamicWeights{ { Weight: 10, }}, Limit: 2, }, } var rsPrfs []*engine.ResourceProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetResourceProfiles, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &rsPrfs); err != nil { t.Error(err) } else { sort.Slice(rsPrfs, func(i, j int) bool { return rsPrfs[i].ID < rsPrfs[j].ID }) if !reflect.DeepEqual(rsPrfs, expRsPrfs) { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expRsPrfs), utils.ToJSON(rsPrfs)) } } } func testLoadersGetRouteProfiles(t *testing.T) { expRouPrfs := []*engine.RouteProfile{ { Tenant: "cgrates.org", ID: "RoutePrf1", FilterIDs: []string{"*string:~*req.Account:1001"}, Sorting: utils.MetaLC, Blockers: utils.DynamicBlockers{ { Blocker: true, }, }, Routes: []*engine.Route{ { ID: "route1", FilterIDs: []string{"fltr1", "fltr2"}, AccountIDs: []string{"Account1", "Account2"}, RateProfileIDs: []string{"RPL_1", "RPL_2", "RPL_3"}, ResourceIDs: []string{"ResGroup1", "ResGroup2", "ResGroup3", "ResGroup4"}, StatIDs: []string{"Stat1", "Stat2", "Stat3"}, Weights: utils.DynamicWeights{ { Weight: 10, }, }, Blockers: utils.DynamicBlockers{ { Blocker: true, }, }, RouteParameters: "param2", }, { ID: "route2", FilterIDs: []string{"fltr5"}, AccountIDs: []string{"Account1"}, RateProfileIDs: []string{"RPL_1"}, ResourceIDs: []string{"ResGroup1"}, StatIDs: []string{"Stat1"}, Weights: utils.DynamicWeights{ { FilterIDs: []string{"fltr1"}, Weight: 10, }, }, Blockers: utils.DynamicBlockers{ { Blocker: true, }, }, RouteParameters: "param1", }, }, Weights: utils.DynamicWeights{ { Weight: 20, }, }, }, { Tenant: "cgrates.org", ID: "RoutePrf2", FilterIDs: []string{"*string:~*req.Account:1002"}, Sorting: utils.MetaLC, Routes: []*engine.Route{ { ID: "route1", FilterIDs: []string{"fltr3"}, AccountIDs: []string{"Account3", "Account4"}, RateProfileIDs: []string{"RPL_2"}, ResourceIDs: []string{"ResGroup2"}, StatIDs: []string{"Stat2"}, Weights: utils.DynamicWeights{ { Weight: 10, }, }, Blockers: utils.DynamicBlockers{ { Blocker: true, }, }, RouteParameters: "param1", }, }, Weights: utils.DynamicWeights{ { Weight: 20, }, }, }, } var rouPrfs []*engine.RouteProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetRouteProfiles, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &rouPrfs); err != nil { t.Error(err) } else { sort.Slice(rouPrfs, func(i, j int) bool { return rouPrfs[i].ID < rouPrfs[j].ID }) if !reflect.DeepEqual(rouPrfs, expRouPrfs) { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expRouPrfs), utils.ToJSON(rouPrfs)) } } } func testLoadersGetStatQueueProfiles(t *testing.T) { expSqPrfs := []*engine.StatQueueProfile{ { Tenant: "cgrates.org", ID: "TestStats", FilterIDs: []string{"*string:~*req.Account:1001"}, QueueLength: 100, TTL: time.Second, Metrics: []*engine.MetricWithFilters{ { MetricID: "*sum#~*req.Value", }, { FilterIDs: []string{"fltr1", "fltr2"}, MetricID: "*average#~*req.Value", }, { MetricID: "*sum#~*req.Usage", Blockers: utils.DynamicBlockers{ { FilterIDs: []string{"*string:~*req.Account:1003", "fltr2"}, Blocker: true, }, { Blocker: false, }, }, }, }, ThresholdIDs: []string{"Th1", "Th2"}, Blockers: utils.DynamicBlockers{{Blocker: true}}, Stored: true, Weights: utils.DynamicWeights{ { Weight: 20, }, }, MinItems: 2, }, { Tenant: "cgrates.org", ID: "TestStats2", FilterIDs: []string{"*string:~*req.Account:1002"}, QueueLength: 100, TTL: time.Second, Metrics: []*engine.MetricWithFilters{ { MetricID: "*sum#~*req.Value", }, { MetricID: "*sum#~*req.Usage", }, { MetricID: "*average#~*req.Value", }, { MetricID: "*average#~*req.Usage", }, { MetricID: "*sum#~*req.Cost", }, { MetricID: "*average#~*req.Cost", Blockers: utils.DynamicBlockers{{Blocker: false}}, }, }, ThresholdIDs: []string{"Th"}, Blockers: utils.DynamicBlockers{{Blocker: true}}, Stored: true, Weights: utils.DynamicWeights{ { Weight: 20, }, }, MinItems: 2, }, { Tenant: "cgrates.org", ID: "TestStats3", FilterIDs: []string{"*string:~*req.Account:1003"}, QueueLength: 100, TTL: time.Second, Metrics: []*engine.MetricWithFilters{ { MetricID: "*sum#~*req.Value", }, { MetricID: "*average#~*req.Value", Blockers: utils.DynamicBlockers{ { FilterIDs: []string{"fltr_for_stats"}, Blocker: false, }, }, }, }, ThresholdIDs: []string{"Th1", "Th2"}, Blockers: utils.DynamicBlockers{{Blocker: true}}, Stored: true, Weights: utils.DynamicWeights{ { Weight: 20, }, }, MinItems: 2, }, } var sqPrfs []*engine.StatQueueProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetStatQueueProfiles, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &sqPrfs); err != nil { t.Error(err) } else { sort.Slice(sqPrfs, func(i, j int) bool { return sqPrfs[i].ID < sqPrfs[j].ID }) if !reflect.DeepEqual(sqPrfs, expSqPrfs) { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expSqPrfs), utils.ToJSON(sqPrfs)) } } } func testLoadersGetThresholdProfiles(t *testing.T) { expThPrfs := []*engine.ThresholdProfile{ { Tenant: "cgrates.org", ID: "TH1", FilterIDs: []string{"*string:~*req.Account:1001", "*string:~*req.RunID:*default"}, MaxHits: 12, MinHits: 10, MinSleep: time.Second, Blocker: true, Weights: utils.DynamicWeights{ { Weight: 10, }, }, ActionProfileIDs: []string{"ACT_PRF1"}, Async: true, }, { Tenant: "cgrates.org", ID: "TH2", FilterIDs: []string{"*string:~*req.Account:1002"}, MaxHits: 10, MinHits: 8, MinSleep: time.Second, Blocker: true, Weights: utils.DynamicWeights{ { Weight: 5, }, }, ActionProfileIDs: []string{"ACT_PRF2"}, Async: true, }, } var thPrfs []*engine.ThresholdProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetThresholdProfiles, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &thPrfs); err != nil { t.Error(err) } else { sort.Slice(thPrfs, func(i, j int) bool { return thPrfs[i].ID < thPrfs[j].ID }) if !reflect.DeepEqual(thPrfs, expThPrfs) { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ToJSON(expThPrfs), utils.ToJSON(thPrfs)) } } } func testLoadersRemove(t *testing.T) { var reply string if err := ldrRPC.Call(context.Background(), utils.LoaderSv1Run, //Remove, &loaders.ArgsProcessFolder{ LoaderID: "remove", APIOpts: map[string]interface{}{ utils.MetaCache: utils.MetaReload, utils.MetaStopOnError: true, }, }, &reply); err != nil { t.Error(err) } else if reply != utils.OK { t.Error("Unexpected reply returned:", reply) } } func testLoadersGetAccountAfterRemove(t *testing.T) { var accIDs []string if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetAccountIDs, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &accIDs); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } var rplyAccPrf utils.Account if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetAccount, utils.TenantID{ Tenant: "cgrates.org", ID: "ACC_PRF", }, &rplyAccPrf); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } } func testLoadersGetActionProfileAfterRemove(t *testing.T) { var actIDs []string if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetActionProfileIDs, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &actIDs); err == nil || utils.ErrNotFound.Error() != err.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } var rplyActPrf engine.ActionProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetActionProfile, utils.TenantID{ Tenant: "cgrates.org", ID: "ACT_PRF", }, &rplyActPrf); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } } func testLoadersGetAttributeProfileAfterRemove(t *testing.T) { var attrIDs []string if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetAttributeProfileIDs, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &attrIDs); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } var rplyAttrPrf engine.AttributeProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetAttributeProfile, utils.TenantID{ Tenant: "cgrates.org", ID: "ATTR_ACNT_1001", }, &rplyAttrPrf); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } } func testLoadersGetChargerProfileAfterRemove(t *testing.T) { var chgIDs []string if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetChargerProfileIDs, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &chgIDs); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } var rplyChgPrf engine.ChargerProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetChargerProfile, utils.TenantID{ Tenant: "cgrates.org", ID: "Raw", }, &rplyChgPrf); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } } func testLoadersGetDispatcherProfileAfterRemove(t *testing.T) { var dspPrfIDs []string if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetDispatcherProfileIDs, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &dspPrfIDs); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } var rplyDspPrf engine.ChargerProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetDispatcherProfile, utils.TenantID{ Tenant: "cgrates.org", ID: "DSP1", }, &rplyDspPrf); err == nil || err.Error() != utils.ErrDSPProfileNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrDSPProfileNotFound, err) } } func testLoadersGetDispatcherHostAfterRemove(t *testing.T) { var dspHostIDs []string if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetDispatcherHostIDs, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &dspHostIDs); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } var rplyDspHost engine.DispatcherHost if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetDispatcherHost, utils.TenantID{ Tenant: "cgrates.org", ID: "DSPHOST1", }, &rplyDspHost); err == nil || err.Error() != utils.ErrDSPHostNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrDSPHostNotFound, err) } } func testLoadersGetFilterAfterRemove(t *testing.T) { var fltrIDs []string if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetFilterIDs, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &fltrIDs); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } var rplyFltrPrf engine.Filter if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetFilter, utils.TenantID{ Tenant: "cgrates.org", ID: "FLTR_ACCOUNT_1001", }, &rplyFltrPrf); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } } func testLoadersGetRateProfileAfterRemove(t *testing.T) { var rateIDs []string if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetRateProfileIDs, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &rateIDs); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } var rplyRatePrf utils.RateProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetRateProfile, utils.TenantID{ Tenant: "cgrates.org", ID: "RP1", }, &rplyRatePrf); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } } func testLoadersGetResourceProfileAfterRemove(t *testing.T) { var rsIDs []string if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetResourceProfileIDs, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &rsIDs); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } var rplyRsPrf engine.ResourceProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetResourceProfile, utils.TenantID{ Tenant: "cgrates.org", ID: "RES_ACNT_1001", }, &rplyRsPrf); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } } func testLoadersGetRouteProfileAfterRemove(t *testing.T) { var rtIDs []string if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetRouteProfileIDs, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &rtIDs); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } var rplyRtPrf engine.RouteProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetRouteProfile, utils.TenantID{ Tenant: "cgrates.org", ID: "ROUTE_ACNT_1001", }, &rplyRtPrf); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } } func testLoadersGetStatQueueProfileAfterRemove(t *testing.T) { var sqIDs []string if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetStatQueueProfileIDs, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &sqIDs); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } var rplySqPrf engine.StatQueueProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetStatQueueProfile, utils.TenantID{ Tenant: "cgrates.org", ID: "Stat_1", }, &rplySqPrf); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } } func testLoadersGetThresholdProfileAfterRemove(t *testing.T) { var thIDs []string if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetThresholdProfileIDs, &utils.ArgsItemIDs{ Tenant: "cgrates.org", }, &thIDs); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } var rplyThPrf engine.ThresholdProfile if err := ldrRPC.Call(context.Background(), utils.AdminSv1GetThresholdProfile, utils.TenantID{ Tenant: "cgrates.org", ID: "THD_ACNT_1001", }, &rplyThPrf); err == nil || err.Error() != utils.ErrNotFound.Error() { t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err) } } func TestLoadersLoad(t *testing.T) { dirPath := "/tmp/TestLoadersLoad" err := os.Mkdir(dirPath, 0755) if err != nil { t.Error(err) } defer os.RemoveAll(dirPath) dirPathIn := "/tmp/TestLoadersLoad/in" err = os.Mkdir(dirPathIn, 0755) if err != nil { t.Error(err) } defer os.RemoveAll(dirPathIn) f1, err := os.Create(dirPathIn + "/emptyfile.txt") if err != nil { t.Error(err) } defer f1.Close() dirPathOut := "/tmp/TestLoadersLoad/out" err = os.Mkdir(dirPathOut, 0755) if err != nil { t.Error(err) } defer os.RemoveAll(dirPathOut) f2, err := os.Create(dirPathOut + "/emptyfile.txt") if err != nil { t.Error(err) } defer f2.Close() cfg := config.NewDefaultCGRConfig() loaderCfg := &config.LoaderSCfg{ ID: "LoaderID", Enabled: true, Tenant: "cgrates.org", RunDelay: 1 * time.Millisecond, LockFilePath: "lockFileName", FieldSeparator: ";", TpInDir: dirPathIn, TpOutDir: dirPathOut, Opts: &config.LoaderSOptsCfg{}, } cfg.LoaderCfg()[0] = loaderCfg data := engine.NewInternalDB(nil, nil, cfg.DataDbCfg().Items) dm := engine.NewDataManager(data, cfg.CacheCfg(), nil) fltrs := engine.NewFilterS(cfg, nil, dm) ldrS := loaders.NewLoaderS(cfg, dm, fltrs, nil) lSv1 := NewLoaderSv1(ldrS) args := &loaders.ArgsProcessFolder{ LoaderID: "LoaderID", } var reply string if err := lSv1.Run(context.Background(), args, &reply); err != nil { t.Error(err) } }