From 71e4563ecd268bb8e9adbee68935f4d9a69842ff Mon Sep 17 00:00:00 2001 From: gezimbll Date: Mon, 14 Jul 2025 12:55:59 +0200 Subject: [PATCH] benchmarks for ips functionality && rewriting actionTypes constants --- apis/loaders_it_test.go | 12 +- apis/preload_it_test.go | 12 +- apis/tpes_it_test.go | 10 +- data/tariffplans/loadRateTest/Actions.csv | 14 +- data/tariffplans/testit/Actions.csv | 14 +- data/tariffplans/tutactions/Actions.csv | 14 +- data/tariffplans/tutroutes/Actions.csv | 4 +- general_tests/ips_load_test.go | 324 ++++++++++++++++++++++ ips/ips_it_test.go | 151 ++++++++++ utils/consts.go | 18 +- 10 files changed, 524 insertions(+), 49 deletions(-) create mode 100644 general_tests/ips_load_test.go diff --git a/apis/loaders_it_test.go b/apis/loaders_it_test.go index 429087820..830b289a7 100644 --- a/apis/loaders_it_test.go +++ b/apis/loaders_it_test.go @@ -199,14 +199,14 @@ cgrates.org,1002,,;30,;false,,VoiceBalance,,;10,,*voice,14,fltr3&fltr4;150;fltr5 #Tenant,ID,FilterIDs,Weights,Blockers,Schedule,TargetType,TargetIDs,ActionID,ActionFilterIDs,ActionTTL,ActionType,ActionOpts,ActionWeights,ActionBlockers,ActionDiktatsID,ActionDiktatsFilterIDs,ActionDiktatsOpts,ActionDiktatsWeights,ActionDiktatsBlockers 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,,,,ADDBALVALUE,,,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP,,0s,*addBalance,,,,ADDBALVALUE,,,, cgrates.org,ONE_TIME_ACT,,,,*asap,*accounts,1001;1002,,,,,,,,,,,, cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP,,,,,,,ADDBALVALUE,,*balancePath:*balance.TestBalance.Value;*balanceValue:10,, -cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_DATA,,0s,*set_balance,,,,SETBALTYPE,,*balancePath:*balance.TestDataBalance.Type;*balanceValue:*data,, -cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_DATA,,0s,*add_balance,,,,ADDBALVALUE,,*balancePath:*balance.TestDataBalance.Value;*balanceValue:1024,, -cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_VOICE,,0s,*set_balance,,,,SETBALTYPE,,*balancePath:*balance.TestVoiceBalance.Type;*balanceValue:*voice,, -cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*add_balance,,,,ADDBALVALUE1,,*balancePath:*balance.TestVoiceBalance.Value;*balanceValue:15m15s,, -cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*add_balance,,,,ADDBALVALUE2,,*balancePath:*balance.TestVoiceBalance2.Value;*balanceValue:15m15s,, +cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_DATA,,0s,*setBalance,,,,SETBALTYPE,,*balancePath:*balance.TestDataBalance.Type;*balanceValue:*data,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_DATA,,0s,*addBalance,,,,ADDBALVALUE,,*balancePath:*balance.TestDataBalance.Value;*balanceValue:1024,, +cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_VOICE,,0s,*setBalance,,,,SETBALTYPE,,*balancePath:*balance.TestVoiceBalance.Type;*balanceValue:*voice,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*addBalance,,,,ADDBALVALUE1,,*balancePath:*balance.TestVoiceBalance.Value;*balanceValue:15m15s,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*addBalance,,,,ADDBALVALUE2,,*balancePath:*balance.TestVoiceBalance2.Value;*balanceValue:15m15s,, `); err != nil { t.Fatal(err) } diff --git a/apis/preload_it_test.go b/apis/preload_it_test.go index 81b30e1d6..e3ce7d85f 100644 --- a/apis/preload_it_test.go +++ b/apis/preload_it_test.go @@ -104,12 +104,12 @@ cgrates.org,1001,,,,,VoiceBalance,,;10,*string:~*req.Destination:1002;true;;fals // writing in files the csv containing the profile for ActionProfile if err := os.WriteFile(path.Join("/tmp/ActionsIn", utils.ActionsCsv), []byte(` #Tenant,ID,FilterIDs,Weights,Blockers,Schedule,TargetType,TargetIDs,ActionID,ActionFilterIDs,ActionTTL,ActionType,ActionOpts,ActionWeights,ActionBlockers,ActionDiktatsID,ActionDiktatsFilterIDs,ActionDiktatsOpts,ActionDiktatsWeights,ActionDiktatsBlockers -cgrates.org,ONE_TIME_ACT,,;10,,*asap,*accounts,1001;1002,TOPUP,,0s,*add_balance,,,,ADDBALVALUE,,*balancePath:*balance.TestBalance.Value;*balanceValue:10,, -cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_DATA,,0s,*set_balance,,,,SETBALTYPE,,*balancePath:*balance.TestDataBalance.Type;*balanceValue:*data,, -cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_DATA,,0s,*add_balance,,,,ADDBALVALUE,,*balancePath:*balance.TestDataBalance.Value;*balanceValue:1024,, -cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_VOICE,,0s,*set_balance,,,,SETBALTYPE,,*balancePath:*balance.TestVoiceBalance.Type;*balanceValue:*voice,, -cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*add_balance,,,,ADDBALVALUE1,,*balancePath:*balance.TestVoiceBalance.Value;*balanceValue:15m15s,, -cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*add_balance,,,,ADDBALVALUE2,,*balancePath:*balance.TestVoiceBalance2.Value;*balanceValue:15m15s,, +cgrates.org,ONE_TIME_ACT,,;10,,*asap,*accounts,1001;1002,TOPUP,,0s,*addBalance,,,,ADDBALVALUE,,*balancePath:*balance.TestBalance.Value;*balanceValue:10,, +cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_DATA,,0s,*setBalance,,,,SETBALTYPE,,*balancePath:*balance.TestDataBalance.Type;*balanceValue:*data,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_DATA,,0s,*addBalance,,,,ADDBALVALUE,,*balancePath:*balance.TestDataBalance.Value;*balanceValue:1024,, +cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_VOICE,,0s,*setBalance,,,,SETBALTYPE,,*balancePath:*balance.TestVoiceBalance.Type;*balanceValue:*voice,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*addBalance,,,,ADDBALVALUE1,,*balancePath:*balance.TestVoiceBalance.Value;*balanceValue:15m15s,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*addBalance,,,,ADDBALVALUE2,,*balancePath:*balance.TestVoiceBalance2.Value;*balanceValue:15m15s,, `), 0644); err != nil { t.Fatalf("Err %v when writing in file %s", err, utils.ActionsCsv) } diff --git a/apis/tpes_it_test.go b/apis/tpes_it_test.go index 081c64304..6ee9a00bd 100644 --- a/apis/tpes_it_test.go +++ b/apis/tpes_it_test.go @@ -1077,7 +1077,7 @@ func testTPeSExportTariffPlanHalfTariffPlan(t *testing.T) { utils.ActionType, utils.ActionOpts, utils.ActionWeights, utils.ActionBlockers, utils.ActionDiktatsID, utils.ActionDiktatsFilterIDs, utils.ActionDiktatsOpts, utils.ActionDiktatsWeights, utils.ActionDiktatsBlockers}, - {"cgrates.org", "Execute_thd", "", ";20", "", "", "*thresholds", "THD_1", "actID", "", "0s", "*reset_threshold", "", "", "", "", "", "", "", ""}, + {"cgrates.org", "Execute_thd", "", ";20", "", "", "*thresholds", "THD_1", "actID", "", "0s", "*resetThreshold", "", "", "", "", "", "", "", ""}, }, utils.ThresholdsCsv: { {"#Tenant", "ID", "FilterIDs", "Weights", "MaxHits", "MinHits", "MinSleep", "Blocker", "ActionProfileIDs", "Async", "EeIDs"}, @@ -1210,8 +1210,8 @@ func testTPeSExportTariffPlanAllTariffPlan(t *testing.T) { utils.ActionType, utils.ActionOpts, utils.ActionWeights, utils.ActionBlockers, utils.ActionDiktatsID, utils.ActionDiktatsFilterIDs, utils.ActionDiktatsOpts, utils.ActionDiktatsWeights, utils.ActionDiktatsBlockers}, - {"cgrates.org", "Execute_thd", "", ";20", "", "", "*thresholds", "THD_1", "actID", "", "0s", "*reset_threshold", "", "", "", "", "", "", "", ""}, - {"cgrates.org", "SET_BAL", "*string:~*req.Account:1001", ";10", "", "*asap", "*accounts", "1001", "SET_BAL", "", "0s", "*set_balance", "", "", "", "SetBalMonetary10", "", "*balancePath:MONETARY;*balanceValue:10", "", ""}, + {"cgrates.org", "Execute_thd", "", ";20", "", "", "*thresholds", "THD_1", "actID", "", "0s", "*resetThreshold", "", "", "", "", "", "", "", ""}, + {"cgrates.org", "SET_BAL", "*string:~*req.Account:1001", ";10", "", "*asap", "*accounts", "1001", "SET_BAL", "", "0s", "*setBalance", "", "", "", "SetBalMonetary10", "", "*balancePath:MONETARY;*balanceValue:10", "", ""}, }, utils.ThresholdsCsv: { {"#Tenant", "ID", "FilterIDs", "Weights", "MaxHits", "MinHits", "MinSleep", "Blocker", "ActionProfileIDs", "Async", "EeIDs"}, @@ -1225,7 +1225,7 @@ func testTPeSExportTariffPlanAllTariffPlan(t *testing.T) { expected[utils.AccountsCsv] = csvRply[utils.AccountsCsv] if !reflect.DeepEqual(expected, csvRply) { - if !reflect.DeepEqual(csvRply[utils.ActionsCsv][2], []string{"cgrates.org", "SET_BAL", "*string:~*req.Account:1001", ";10", "", "*asap", "*accounts", "1001", "SET_BAL", "", "0s", "*set_balance", "", "", "", "SetBalMonetary10", "", "*balanceValue:10;*balancePath:MONETARY", "", ""}) { + if !reflect.DeepEqual(csvRply[utils.ActionsCsv][2], []string{"cgrates.org", "SET_BAL", "*string:~*req.Account:1001", ";10", "", "*asap", "*accounts", "1001", "SET_BAL", "", "0s", "*setBalance", "", "", "", "SetBalMonetary10", "", "*balanceValue:10;*balancePath:MONETARY", "", ""}) { t.Errorf("Expected %+v \n received %+v", utils.ToJSON(expected), utils.ToJSON(csvRply)) } else { newCsvReply := csvRply[utils.ActionsCsv][:1] @@ -1266,7 +1266,7 @@ func testTPeSExportTariffPlanAllTariffPlan(t *testing.T) { } // expected will remain the same if !reflect.DeepEqual(expected, csvRply) { - if !reflect.DeepEqual(csvRply[utils.ActionsCsv][2], []string{"cgrates.org", "SET_BAL", "*string:~*req.Account:1001", ";10", "", "*asap", "*accounts", "1001", "SET_BAL", "", "0s", "*set_balance", "", "", "", "SetBalMonetary10", "", "*balanceValue:10;*balancePath:MONETARY", "", ""}) { + if !reflect.DeepEqual(csvRply[utils.ActionsCsv][2], []string{"cgrates.org", "SET_BAL", "*string:~*req.Account:1001", ";10", "", "*asap", "*accounts", "1001", "SET_BAL", "", "0s", "*setBalance", "", "", "", "SetBalMonetary10", "", "*balanceValue:10;*balancePath:MONETARY", "", ""}) { t.Errorf("Expected %+v \n received %+v", utils.ToJSON(expected), utils.ToJSON(csvRply)) } else { csvRply[utils.ActionsCsv][2] = nil diff --git a/data/tariffplans/loadRateTest/Actions.csv b/data/tariffplans/loadRateTest/Actions.csv index fad28f733..e4684b178 100644 --- a/data/tariffplans/loadRateTest/Actions.csv +++ b/data/tariffplans/loadRateTest/Actions.csv @@ -1,8 +1,8 @@ #Tenant,ID,FilterIDs,Weights,Blockers,Schedule,TargetType,TargetIDs,ActionID,ActionFilterIDs,ActionTTL,ActionType,ActionOpts,ActionWeights,ActionBlockers,ActionDiktatsID,ActionDiktatsFilterIDs,ActionDiktatsOpts,ActionDiktatsWeights,ActionDiktatsBlockers -cgrates.org,ONE_TIME_ACT,,;10,,*asap,*accounts,1001;1002,TOPUP,,0s,*add_balance,,,,ADDBALUNITS,,*balancePath:*balance.TestBalance.Units:*balanceValue:10,, -cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_DATA,,0s,*set_balance,,,,SETBALTYPE,,*balancePath:*balance.TestDataBalance.Type;*balanceValue:*data,, -cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_DATA,,0s,*add_balance,,,,ADDBALUNITS,,*balancePath:*balance.TestDataBalance.Units;*balanceValue:1024,, -cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_VOICE,,0s,*set_balance,,,,SETBALTYPE,,*balancePath:*balance.TestVoiceBalance.Type;*balanceValue:*voice,, -cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*add_balance,,,,ADDBALUNITS,,*balancePath:*balance.TestVoiceBalance.Units;*balanceValue:15m15s,, -cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_FILTERS,,0s,*set_balance,,,,SETBALFILTER,,*balancePath:*balance.TestVoiceBalance.Filters;*balanceValue:*string:~*req.CustomField:500,, -cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_REM_VOICE,,0s,*rem_balance,,,,REMBAL,,*balancePath:TestVoiceBalance2,, \ No newline at end of file +cgrates.org,ONE_TIME_ACT,,;10,,*asap,*accounts,1001;1002,TOPUP,,0s,*addBalance,,,,ADDBALUNITS,,*balancePath:*balance.TestBalance.Units:*balanceValue:10,, +cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_DATA,,0s,*setBalance,,,,SETBALTYPE,,*balancePath:*balance.TestDataBalance.Type;*balanceValue:*data,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_DATA,,0s,*addBalance,,,,ADDBALUNITS,,*balancePath:*balance.TestDataBalance.Units;*balanceValue:1024,, +cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_VOICE,,0s,*setBalance,,,,SETBALTYPE,,*balancePath:*balance.TestVoiceBalance.Type;*balanceValue:*voice,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*addBalance,,,,ADDBALUNITS,,*balancePath:*balance.TestVoiceBalance.Units;*balanceValue:15m15s,, +cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_FILTERS,,0s,*setBalance,,,,SETBALFILTER,,*balancePath:*balance.TestVoiceBalance.Filters;*balanceValue:*string:~*req.CustomField:500,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_REM_VOICE,,0s,*remBalance,,,,REMBAL,,*balancePath:TestVoiceBalance2,, diff --git a/data/tariffplans/testit/Actions.csv b/data/tariffplans/testit/Actions.csv index 150dcb4b0..d973b482d 100644 --- a/data/tariffplans/testit/Actions.csv +++ b/data/tariffplans/testit/Actions.csv @@ -1,8 +1,8 @@ #Tenant,ID,FilterIDs,Weights,Blockers,Schedule,TargetType,TargetIDs,ActionID,ActionFilterIDs,ActionTTL,ActionType,ActionOpts,ActionWeights,ActionBlockers,ActionDiktatsID,ActionDiktatsFilterIDs,ActionDiktatsOpts,ActionDiktatsWeights,ActionDiktatsBlockers -cgrates.org,ONE_TIME_ACT,,;10,,*asap,*accounts,1001;1002,TOPUP,,0s,*add_balance,,,,ADDBALUNITS,,*balancePath:*balance.TestBalance.Units;*balanceValue:10,, -cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_DATA,,0s,*set_balance,,,,SETBALTYPE,,*balancePath:*balance.TestDataBalance.Type;*balanceValue:*data,, -cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_DATA,,0s,*add_balance,,,,ADDBALUNITS,,*balancePath:*balance.TestDataBalance.Units;*balanceValue:1024,, -cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_VOICE,,0s,*set_balance,,,,SETBALTYPE,,*balancePath:*balance.TestVoiceBalance.Type;*balanceValue:*voice,, -cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*add_balance,,,,ADDBALUNITS,,*balancePath:*balance.TestVoiceBalance.Units;*balanceValue:15m15s,, -cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_FILTERS,,0s,*set_balance,,,,SETBALFILTER,,*balancePath:*balance.TestVoiceBalance.Filters;*balanceValue:*string:~*req.CustomField:500,, -cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_REM_VOICE,,0s,*rem_balance,,,,REMBAL,,*balancePath:TestVoiceBalance2,, \ No newline at end of file +cgrates.org,ONE_TIME_ACT,,;10,,*asap,*accounts,1001;1002,TOPUP,,0s,*addBalance,,,,ADDBALUNITS,,*balancePath:*balance.TestBalance.Units;*balanceValue:10,, +cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_DATA,,0s,*setBalance,,,,SETBALTYPE,,*balancePath:*balance.TestDataBalance.Type;*balanceValue:*data,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_DATA,,0s,*addBalance,,,,ADDBALUNITS,,*balancePath:*balance.TestDataBalance.Units;*balanceValue:1024,, +cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_VOICE,,0s,*setBalance,,,,SETBALTYPE,,*balancePath:*balance.TestVoiceBalance.Type;*balanceValue:*voice,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*addBalance,,,,ADDBALUNITS,,*balancePath:*balance.TestVoiceBalance.Units;*balanceValue:15m15s,, +cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_FILTERS,,0s,*setBalance,,,,SETBALFILTER,,*balancePath:*balance.TestVoiceBalance.Filters;*balanceValue:*string:~*req.CustomField:500,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_REM_VOICE,,0s,*remBalance,,,,REMBAL,,*balancePath:TestVoiceBalance2,, diff --git a/data/tariffplans/tutactions/Actions.csv b/data/tariffplans/tutactions/Actions.csv index c9e30a9eb..e4684b178 100644 --- a/data/tariffplans/tutactions/Actions.csv +++ b/data/tariffplans/tutactions/Actions.csv @@ -1,8 +1,8 @@ #Tenant,ID,FilterIDs,Weights,Blockers,Schedule,TargetType,TargetIDs,ActionID,ActionFilterIDs,ActionTTL,ActionType,ActionOpts,ActionWeights,ActionBlockers,ActionDiktatsID,ActionDiktatsFilterIDs,ActionDiktatsOpts,ActionDiktatsWeights,ActionDiktatsBlockers -cgrates.org,ONE_TIME_ACT,,;10,,*asap,*accounts,1001;1002,TOPUP,,0s,*add_balance,,,,ADDBALUNITS,,*balancePath:*balance.TestBalance.Units:*balanceValue:10,, -cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_DATA,,0s,*set_balance,,,,SETBALTYPE,,*balancePath:*balance.TestDataBalance.Type;*balanceValue:*data,, -cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_DATA,,0s,*add_balance,,,,ADDBALUNITS,,*balancePath:*balance.TestDataBalance.Units;*balanceValue:1024,, -cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_VOICE,,0s,*set_balance,,,,SETBALTYPE,,*balancePath:*balance.TestVoiceBalance.Type;*balanceValue:*voice,, -cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*add_balance,,,,ADDBALUNITS,,*balancePath:*balance.TestVoiceBalance.Units;*balanceValue:15m15s,, -cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_FILTERS,,0s,*set_balance,,,,SETBALFILTER,,*balancePath:*balance.TestVoiceBalance.Filters;*balanceValue:*string:~*req.CustomField:500,, -cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_REM_VOICE,,0s,*rem_balance,,,,REMBAL,,*balancePath:TestVoiceBalance2,, +cgrates.org,ONE_TIME_ACT,,;10,,*asap,*accounts,1001;1002,TOPUP,,0s,*addBalance,,,,ADDBALUNITS,,*balancePath:*balance.TestBalance.Units:*balanceValue:10,, +cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_DATA,,0s,*setBalance,,,,SETBALTYPE,,*balancePath:*balance.TestDataBalance.Type;*balanceValue:*data,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_DATA,,0s,*addBalance,,,,ADDBALUNITS,,*balancePath:*balance.TestDataBalance.Units;*balanceValue:1024,, +cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_VOICE,,0s,*setBalance,,,,SETBALTYPE,,*balancePath:*balance.TestVoiceBalance.Type;*balanceValue:*voice,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_TEST_VOICE,,0s,*addBalance,,,,ADDBALUNITS,,*balancePath:*balance.TestVoiceBalance.Units;*balanceValue:15m15s,, +cgrates.org,ONE_TIME_ACT,,,,,,,SET_BALANCE_TEST_FILTERS,,0s,*setBalance,,,,SETBALFILTER,,*balancePath:*balance.TestVoiceBalance.Filters;*balanceValue:*string:~*req.CustomField:500,, +cgrates.org,ONE_TIME_ACT,,,,,,,TOPUP_REM_VOICE,,0s,*remBalance,,,,REMBAL,,*balancePath:TestVoiceBalance2,, diff --git a/data/tariffplans/tutroutes/Actions.csv b/data/tariffplans/tutroutes/Actions.csv index 70c982932..d391ac99a 100644 --- a/data/tariffplans/tutroutes/Actions.csv +++ b/data/tariffplans/tutroutes/Actions.csv @@ -2,6 +2,6 @@ # TOPUP_RST_MONETARY_10 resets the <*default> <*monetary> balance to 10 units -#cgrates.org,TOPUP_RST_MONETARY_10,,;10,,*asap,*accounts,1001,TOPUP,,0s,*add_balance,,;10,;false,*asap,,,,,,10,10,,,,ADDBAL,,*balanceValue:10,, +#cgrates.org,TOPUP_RST_MONETARY_10,,;10,,*asap,*accounts,1001,TOPUP,,0s,*addBalance,,;10,;false,*asap,,,,,,10,10,,,,ADDBAL,,*balanceValue:10,, -cgrates.org,TOPUP_RST_MONETARY_10,,;10,,*asap,*accounts,1001,TOPUP,,0s,*add_balance,,,,ADDBALUNITS,,*balancePath:*balance.Concrete1.Units;*balanceValue:10,, +cgrates.org,TOPUP_RST_MONETARY_10,,;10,,*asap,*accounts,1001,TOPUP,,0s,*addBalance,,,,ADDBALUNITS,,*balancePath:*balance.Concrete1.Units;*balanceValue:10,, diff --git a/general_tests/ips_load_test.go b/general_tests/ips_load_test.go new file mode 100644 index 000000000..3e750394f --- /dev/null +++ b/general_tests/ips_load_test.go @@ -0,0 +1,324 @@ +//go:build performance +// +build performance + +/* +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 ( + "bytes" + "flag" + "fmt" + "slices" + "sync" + "testing" + "time" + + "github.com/cgrates/birpc/context" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +var count = flag.Int("count", 1000, "Number of events to process in the load test") + +func TestStressIPsAllocateIP(t *testing.T) { + var dbConfig engine.DBCfg + switch *utils.DBType { + case utils.MetaInternal: + dbConfig = engine.DBCfg{ + DataDB: &engine.DBParams{ + Type: utils.StringPointer(utils.MetaInternal), + }, + StorDB: &engine.DBParams{ + Type: utils.StringPointer(utils.MetaInternal), + }, + } + case utils.MetaMySQL: + case utils.MetaMongo, utils.MetaPostgres: + t.SkipNow() + default: + t.Fatal("unsupported dbtype value") + } + + content := `{ + "general": { + "log_level": 7 + }, + "stor_db": { + "db_password": "CGRateS.org" + }, + + "admins": { + "enabled": true, + }, + "ips": { + "enabled": true, + "indexed_selects":false, + }, + }` + + ng := engine.TestEngine{ + ConfigJSON: content, + DBCfg: dbConfig, + LogBuffer: bytes.NewBuffer(nil), + Encoding: utils.MetaJSON, + } + client, _ := ng.Run(t) + + t.Run("SetIPProfile", func(t *testing.T) { + var reply string + for i := 1; i <= 10; i++ { + ipProfile := &utils.IPProfileWithAPIOpts{ + IPProfile: &utils.IPProfile{ + Tenant: "cgrates.org", + ID: fmt.Sprintf("IP_PROF_%d", i), + FilterIDs: []string{fmt.Sprintf("*string:~*req.Account:%d", i)}, + TTL: 10 * time.Minute, + Pools: []*utils.IPPool{ + { + ID: "POOL_A", + Range: fmt.Sprintf("10.%d.0.0/16", i), + Message: "Allocated by test", + }, + }, + }, + } + if err := client.Call(context.Background(), utils.AdminSv1SetIPProfile, ipProfile, &reply); err != nil { + t.Fatalf("Failed to set IP profile: %v", err) + } + } + }) + + t.Run("IPsAllocateEvent", func(t *testing.T) { + ticker := time.NewTicker(time.Second / time.Duration(*count)) + defer ticker.Stop() + jobs := make(chan int, *count) + for i := 1; i <= *count; i++ { + jobs <- i + } + close(jobs) + + numWrk := 50 + var wg sync.WaitGroup + latencies := make(chan time.Duration, *count) + + totalCall := time.Now() + for range numWrk { + wg.Add(1) + go func() { + defer wg.Done() + for i := range jobs { + <-ticker.C + + callStart := time.Now() + + args := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: utils.GenUUID(), + Event: map[string]any{ + utils.AccountField: fmt.Sprintf("%d", ((i-1)%10)+1), + utils.AnswerTime: utils.TimePointer(time.Now()), + utils.Usage: 10, + utils.Tenant: "cgrates.org", + }, + APIOpts: map[string]any{ + utils.OptsIPsAllocationID: utils.GenUUID(), + }, + } + var reply utils.AllocatedIP + if err := client.Call(context.Background(), utils.IPsV1AllocateIP, args, &reply); err != nil { + t.Errorf("Error processing event %d: %v", i, err) + continue + } + latencies <- time.Since(callStart) + } + }() + } + + wg.Wait() + totalDuration := time.Since(totalCall) + close(latencies) + latencySlice := make([]time.Duration, 0, *count) + for latency := range latencies { + latencySlice = append(latencySlice, latency) + } + + successfulCalls := len(latencySlice) + if successfulCalls == 0 { + t.Fatal("No calls succeeded, cannot calculate performance.") + } + + actualThroughput := float64(successfulCalls) / totalDuration.Seconds() + slices.Sort(latencySlice) + + t.Logf("--- IP Allocation Performance Load Test Results ---") + t.Logf("Target Rate: %d events/sec", *count) + t.Logf("Successful Calls: %d", successfulCalls) + t.Logf("Actual Throughput: %.2f events/sec", actualThroughput) + t.Logf("Total Duration: %v", totalDuration) + + // Calculate percentiles + p50Index := int(float64(successfulCalls) * 0.50) + p90Index := int(float64(successfulCalls) * 0.90) + p99Index := int(float64(successfulCalls) * 0.99) + + t.Logf("p50 Latency: %v", latencySlice[p50Index]) + t.Logf("p90 Latency: %v", latencySlice[p90Index]) + t.Logf("p99 Latency: %v", latencySlice[p99Index]) + }) +} + +func TestStressIPsAuthorize(t *testing.T) { + var dbConfig engine.DBCfg + switch *utils.DBType { + case utils.MetaInternal: + dbConfig = engine.DBCfg{ + DataDB: &engine.DBParams{ + Type: utils.StringPointer(utils.MetaInternal), + }, + StorDB: &engine.DBParams{ + Type: utils.StringPointer(utils.MetaInternal), + }, + } + case utils.MetaMySQL: + case utils.MetaMongo, utils.MetaPostgres: + t.SkipNow() + default: + t.Fatal("unsupported dbtype value") + } + + content := `{ + "general": { + "log_level": 7 + }, + "stor_db": { + "db_password": "CGRateS.org" + }, + + "admins": { + "enabled": true, + }, + "ips": { + "enabled": true, + "indexed_selects":false, + }, + }` + + ng := engine.TestEngine{ + ConfigJSON: content, + DBCfg: dbConfig, + LogBuffer: bytes.NewBuffer(nil), + Encoding: utils.MetaGOB, + } + client, _ := ng.Run(t) + + t.Run("SetIPProfile", func(t *testing.T) { + var reply string + for i := 1; i <= 10; i++ { + ipProfile := &utils.IPProfileWithAPIOpts{ + IPProfile: &utils.IPProfile{ + Tenant: "cgrates.org", + ID: fmt.Sprintf("IP_PROF_%d", i), + FilterIDs: []string{fmt.Sprintf("*string:~*req.Account:%d", i)}, + TTL: 10 * time.Minute, + Pools: []*utils.IPPool{ + { + ID: "POOL_A", + Range: fmt.Sprintf("10.0.0.%d/32", i), + Message: "Allocated by test", + }, + }, + }, + } + if err := client.Call(context.Background(), utils.AdminSv1SetIPProfile, ipProfile, &reply); err != nil { + t.Fatalf("Failed to set IP profile: %v", err) + } + } + }) + + t.Run("IPsAuthorizeEvent", func(t *testing.T) { + ticker := time.NewTicker(time.Second / time.Duration(*count)) + defer ticker.Stop() + jobs := make(chan int, *count) + for i := 1; i <= *count; i++ { + jobs <- i + } + close(jobs) + numWrk := 50 + var wg sync.WaitGroup + latencies := make(chan time.Duration, *count) + totalCall := time.Now() + for range numWrk { + wg.Add(1) + go func() { + defer wg.Done() + for i := range jobs { + <-ticker.C + callStart := time.Now() + args := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: utils.GenUUID(), + Event: map[string]any{ + utils.AccountField: fmt.Sprintf("%d", ((i-1)%10)+1), + }, + APIOpts: map[string]any{ + utils.OptsIPsAllocationID: utils.GenUUID(), + }, + } + var reply utils.AllocatedIP + if err := client.Call(context.Background(), utils.IPsV1AuthorizeIP, args, &reply); err != nil { + t.Errorf("Error processing event %d: %v", i, err) + continue + } + latencies <- time.Since(callStart) + } + }() + } + wg.Wait() + totalDuration := time.Since(totalCall) + close(latencies) + latencySlice := make([]time.Duration, 0, *count) + for latency := range latencies { + latencySlice = append(latencySlice, latency) + } + + successfulCalls := len(latencySlice) + if successfulCalls == 0 { + t.Fatal("No calls succeeded, cannot calculate performance.") + } + + actualThroughput := float64(successfulCalls) / totalDuration.Seconds() + slices.Sort(latencySlice) + + t.Logf("--- IP Allocation Performance Load Test Results ---") + t.Logf("Target Rate: %d events/sec", *count) + t.Logf("Successful Calls: %d", successfulCalls) + t.Logf("Actual Throughput: %.2f events/sec", actualThroughput) + t.Logf("Total Duration: %v", totalDuration) + + // Calculate percentiles + p50Index := int(float64(successfulCalls) * 0.50) + p90Index := int(float64(successfulCalls) * 0.90) + p99Index := int(float64(successfulCalls) * 0.99) + + t.Logf("p50 Latency: %v", latencySlice[p50Index]) + t.Logf("p90 Latency: %v", latencySlice[p90Index]) + t.Logf("p99 Latency: %v", latencySlice[p99Index]) + }) + +} diff --git a/ips/ips_it_test.go b/ips/ips_it_test.go index 599a7e202..99ea2463f 100644 --- a/ips/ips_it_test.go +++ b/ips/ips_it_test.go @@ -24,8 +24,10 @@ import ( "bytes" "fmt" "testing" + "time" "github.com/cgrates/birpc/context" + "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" ) @@ -319,3 +321,152 @@ cgrates.org,IPs2,*string:~*req.Account:1002,;20,2s,false,POOL1,*string:~*req.Des } }) } +func BenchmarkIPsAuthorize(b *testing.B) { + cfg := config.NewDefaultCGRConfig() + dataDB, _ := engine.NewInternalDB(nil, nil, nil, cfg.DataDbCfg().Items) + dm := engine.NewDataManager(dataDB, cfg, nil) + fltrs := engine.NewFilterS(cfg, nil, dm) + cm := engine.NewConnManager(cfg) + ipService := NewIPService(dm, cfg, fltrs, cm) + + ctx := context.Background() + profile := &utils.IPProfile{ + Tenant: "cgrates.org", + ID: "IP1", + FilterIDs: []string{"*string:~*req.Account:1001"}, + Weights: utils.DynamicWeights{{Weight: 10}}, + TTL: time.Second, + Stored: false, + Pools: []*utils.IPPool{{ + ID: "POOL1", + FilterIDs: []string{}, + Type: "*ipv4", + Range: "192.168.122.1/32", + Strategy: "*ascending", + Message: "bench pool", + Weights: utils.DynamicWeights{{Weight: 10}}, + Blockers: utils.DynamicBlockers{{Blocker: false}}, + }}, + } + if err := dm.SetIPProfile(ctx, profile, true); err != nil { + b.Fatalf("Failed to set IPProfile: %v", err) + } + + for b.Loop() { + b.StopTimer() + args := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: utils.UUIDSha1Prefix(), + Event: map[string]any{ + utils.AccountField: "1001", + }, + APIOpts: map[string]any{ + utils.OptsIPsAllocationID: "alloc1", + }, + } + var allocIP utils.AllocatedIP + b.StartTimer() + if err := ipService.V1AuthorizeIP(ctx, args, &allocIP); err != nil { + b.Error("AuthorizeIP failed:", err) + } + } +} + +func BenchmarkIPsAllocate(b *testing.B) { + cfg := config.NewDefaultCGRConfig() + dataDB, _ := engine.NewInternalDB(nil, nil, nil, cfg.DataDbCfg().Items) + dm := engine.NewDataManager(dataDB, cfg, nil) + fltrs := engine.NewFilterS(cfg, nil, dm) + cm := engine.NewConnManager(cfg) + ipService := NewIPService(dm, cfg, fltrs, cm) + + ctx := context.Background() + profile := &utils.IPProfile{ + Tenant: "cgrates.org", + ID: "IP2", + FilterIDs: []string{"*string:~*req.Account:1001"}, + Weights: utils.DynamicWeights{{Weight: 10}}, + TTL: time.Second, + Stored: false, + Pools: []*utils.IPPool{{ + ID: "POOL1", + FilterIDs: []string{}, + Type: "*ipv4", + Range: "192.168.122.1/32", + Strategy: "*ascending", + Message: "bench pool", + Weights: utils.DynamicWeights{{Weight: 10}}, + Blockers: utils.DynamicBlockers{{Blocker: false}}, + }}, + } + if err := dm.SetIPProfile(ctx, profile, true); err != nil { + b.Fatalf("Failed to set IPProfile: %v", err) + } + for b.Loop() { + b.StopTimer() + args := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: utils.UUIDSha1Prefix(), + Event: map[string]any{ + utils.AccountField: "1001", + }, + APIOpts: map[string]any{ + utils.OptsIPsAllocationID: "alloc1", + }, + } + var allocIP utils.AllocatedIP + b.StartTimer() + if err := ipService.V1AllocateIP(ctx, args, &allocIP); err != nil { + b.Error("AuthorizeIP failed:", err) + } + } +} +func BenchmarkIPsRelease(b *testing.B) { + cfg := config.NewDefaultCGRConfig() + data, _ := engine.NewInternalDB(nil, nil, nil, cfg.DataDbCfg().Items) + dm := engine.NewDataManager(data, cfg, nil) + fltrs := engine.NewFilterS(cfg, nil, dm) + cm := engine.NewConnManager(cfg) + ipService := NewIPService(dm, cfg, fltrs, cm) + ctx := context.Background() + profile := &utils.IPProfile{ + Tenant: "cgrates.org", + ID: "IP3", + FilterIDs: []string{"*string:~*req.Account:1001"}, + Weights: utils.DynamicWeights{{Weight: 10}}, + TTL: time.Second, + Stored: false, + Pools: []*utils.IPPool{{ + ID: "POOL1", + FilterIDs: []string{}, + Type: "*ipv4", + Range: "192.168.122.1/32", + Strategy: "*ascending", + Message: "bench pool", + Weights: utils.DynamicWeights{{Weight: 10}}, + Blockers: utils.DynamicBlockers{{Blocker: false}}, + }}, + } + if err := dm.SetIPProfile(ctx, profile, true); err != nil { + b.Fatalf("Failed to set IPProfile: %v", err) + } + + for b.Loop() { + b.StopTimer() + args := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: utils.UUIDSha1Prefix(), + Event: map[string]any{ + utils.AccountField: "1001", + }, + APIOpts: map[string]any{ + utils.OptsIPsAllocationID: "alloc1", + }, + } + var reply string + b.StartTimer() + if err := ipService.V1ReleaseIP(ctx, args, &reply); err != nil { + b.Error("AuthorizeIP failed:", err) + } + } +} diff --git a/utils/consts.go b/utils/consts.go index 8601af440..d148d625e 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -1133,8 +1133,8 @@ const ( MetaRemoveSessionCosts = "*remove_session_costs" MetaPostEvent = "*post_event" MetaCDRAccount = "*reset_account_cdr" - MetaResetThreshold = "*reset_threshold" - MetaResetStatQueue = "*reset_stat_queue" + MetaResetThreshold = "*resetThreshold" + MetaResetStatQueue = "*resetStatQueue" MetaRemoteSetAccount = "*remote_set_account" ActionID = "ActionID" ActionType = "ActionType" @@ -1143,14 +1143,14 @@ const ( BalanceUnitFactors = "BalanceUnitFactors" ExtraParameters = "ExtraParameters" - MetaAddBalance = "*add_balance" - MetaSetBalance = "*set_balance" - MetaRemBalance = "*rem_balance" + MetaAddBalance = "*addBalance" + MetaSetBalance = "*setBalance" + MetaRemBalance = "*remBalance" DynaprepaidActionplansCfg = "dynaprepaid_actionprofile" - MetaDynamicThreshold = "*dynamic_threshold" - MetaDynamicStats = "*dynamic_stats" - MetaDynamicAttribute = "*dynamic_attribute" - MetaDynamicResource = "*dynamic_resource" + MetaDynamicThreshold = "*dynamicThreshold" + MetaDynamicStats = "*dynamicStats" + MetaDynamicAttribute = "*dynamicAttribute" + MetaDynamicResource = "*dynamicResource" MetaDynamicTrend = "*dynamicTrend" MetaDynamicRanking = "*dynamicRanking" MetaDynamicFilter = "*dynamicFilter"