diff --git a/apier/v1/accountsv1_it_test.go b/apier/v1/accountsv1_it_test.go index 7d72502e2..f22c32418 100644 --- a/apier/v1/accountsv1_it_test.go +++ b/apier/v1/accountsv1_it_test.go @@ -58,6 +58,8 @@ func TestAccountSv1IT(t *testing.T) { testAccountSv1DebitMultipleAccLimited, testAccountSv1DebitWithAttributeSandRateS, testAccountSv1DebitWithRateS, + testAccountSv1DebitWithRateS2, + testAccountSv1KillEngine, } switch *dbType { case utils.MetaInternal: @@ -926,3 +928,114 @@ func testAccountSv1DebitWithRateS(t *testing.T) { t.Errorf("Expecting : %+v, received: %s", decimal.New(95, 0), reply2.Balances["Balance1"].Units) } } + +func testAccountSv1DebitWithRateS2(t *testing.T) { + accPrfAPI := &APIAccountProfileWithCache{ + APIAccountProfile: &utils.APIAccountProfile{ + Tenant: "cgrates.org", + ID: "ACC_WITH_RATES2", + FilterIDs: []string{"*string:~*req.Account:ACC_WITH_RATES2"}, + Weights: ";10", + Balances: map[string]*utils.APIBalance{ + "Balance1": &utils.APIBalance{ + ID: "Balance1", + Weights: ";10", + Type: utils.MetaAbstract, + Units: 100, + CostIncrements: []*utils.APICostIncrement{ + { + Increment: utils.Float64Pointer(1), + RecurrentFee: utils.Float64Pointer(-1), + }, + }, + RateProfileIDs: []string{"RP_Test22"}, + }, + "Balance2": &utils.APIBalance{ + ID: "Balance2", + Weights: ";10", + Type: utils.MetaConcrete, + Units: 100, + }, + }, + ThresholdIDs: []string{utils.MetaNone}, + }, + } + var reply string + if err := acntSRPC.Call(utils.APIerSv1SetAccountProfile, accPrfAPI, &reply); err != nil { + t.Error(err) + } else if reply != utils.OK { + t.Error("Unexpected reply returned", reply) + } + var err error + var convAcc *utils.AccountProfile + if convAcc, err = accPrfAPI.AsAccountProfile(); err != nil { + t.Error(err) + } + var reply2 *utils.AccountProfile + if err := acntSRPC.Call(utils.APIerSv1GetAccountProfile, &utils.TenantIDWithOpts{ + TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "ACC_WITH_RATES2"}}, &reply2); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(convAcc, reply2) { + t.Errorf("Expecting : %+v, received: %+v", convAcc, reply2) + } + + //set a rate profile to be used in case of debit + apiRPrf := &engine.APIRateProfile{ + Tenant: "cgrates.org", + ID: "RP_Test22", + FilterIDs: []string{"*string:~*req.Account:ACC_WITH_RATES2"}, + Weights: ";20", + Rates: map[string]*engine.APIRate{ + "RT_ALWAYS": { + ID: "RT_ALWAYS", + Weights: ";0", + ActivationTimes: "* * * * *", + IntervalRates: []*engine.APIIntervalRate{ + { + IntervalStart: "0", + RecurrentFee: utils.Float64Pointer(0.5), + Increment: utils.Float64Pointer(2), + Unit: utils.Float64Pointer(2), + }, + }, + }, + }, + } + + if err := acntSRPC.Call(utils.APIerSv1SetRateProfile, + &APIRateProfileWithCache{ + APIRateProfileWithOpts: &engine.APIRateProfileWithOpts{ + APIRateProfile: apiRPrf}, + }, &reply); err != nil { + t.Fatal(err) + } else if reply != utils.OK { + t.Errorf("Expecting: %+v, received: %+v", utils.OK, reply) + } + + var eEc *utils.ExtEventCharges + if err := acntSRPC.Call(utils.AccountSv1DebitUsage, + &utils.ArgsAccountsForEvent{CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "testAccountSv1DebitWithAttributeS", + Event: map[string]interface{}{ + utils.AccountField: "ACC_WITH_RATES2", + utils.Usage: "20", + }}}, &eEc); err != nil { + t.Error(err) + } else if eEc.Usage == nil || *eEc.Usage != 20.0 { + t.Fatalf("received usage: %v", *eEc.Usage) + } + + if err := acntSRPC.Call(utils.APIerSv1GetAccountProfile, &utils.TenantIDWithOpts{ + TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "ACC_WITH_RATES2"}}, &reply2); err != nil { + t.Error(err) + } else if reply2.Balances["Balance1"].Units.Cmp(decimal.New(80, 0)) != 0 { + t.Errorf("Expecting : %+v, received: %s", decimal.New(80, 0), reply2.Balances["Balance1"].Units) + } +} + +func testAccountSv1KillEngine(t *testing.T) { + if err := engine.KillEngine(100); err != nil { + t.Error(err) + } +} diff --git a/cmd/cgr-tester/combined_max_usage/combined_max_usage.go b/cmd/cgr-tester/combined_max_usage/combined_max_usage.go new file mode 100644 index 000000000..ae21fb688 --- /dev/null +++ b/cmd/cgr-tester/combined_max_usage/combined_max_usage.go @@ -0,0 +1,145 @@ +/* +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 main + +import ( + "flag" + "fmt" + "log" + "math/rand" + "net/rpc" + "net/rpc/jsonrpc" + "path" + "sync" + "time" + + "github.com/cgrates/cgrates/engine" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/utils" +) + +var ( + dataDir = flag.String("data_dir", "/usr/share/cgrates", "CGR data dir path here") + requests = flag.Int("requests", 10000, "Number of requests") + gorutines = flag.Int("goroutines", 5, "Number of simultaneous goroutines") +) + +// How to run: +// 1) Start the engine with the following configuration < cgr-engine -config_path=/usr/share/cgrates/conf/samples/accounts_mysql > +// 2) Load the data with < cgr-loader -config_path=/usr/share/cgrates/conf/samples/accounts_mysql -verbose -path=/usr/share/cgrates/tariffplans/oldaccvsnew > +// 3) Run the program with < go run combined_max_usage.go -requests=10000 -goroutines=5 > + +func main() { + flag.Parse() + var err error + var rpc *rpc.Client + var cfgPath string + var cfg *config.CGRConfig + cfgPath = path.Join(*dataDir, "conf", "samples", "accounts_mysql") + if cfg, err = config.NewCGRConfigFromPath(cfgPath); err != nil { + log.Fatal("Got config error: ", err.Error()) + } + if rpc, err = jsonrpc.Dial(utils.TCP, cfg.ListenCfg().RPCJSONListen); err != nil { + return + } + + s1 := rand.NewSource(time.Now().UnixNano()) + r1 := rand.New(s1) + + var wgAccountS sync.WaitGroup + var accountSTime time.Duration + var sumAccountS float64 + + var wgRALs sync.WaitGroup + var ralsTime time.Duration + var sumRALs float64 + + for i := 0; i < *requests; i++ { + wgAccountS.Add(1) + wgRALs.Add(1) + usage := fmt.Sprintf("%+vm", 1+r1.Intn(59)) + go func() { + var eEc *utils.ExtEventCharges + arg := &utils.ArgsAccountsForEvent{CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: utils.UUIDSha1Prefix(), + Event: map[string]interface{}{ + utils.AccountField: "1002", + utils.ToR: utils.MetaVoice, + utils.Usage: usage, + }}} + tNow := time.Now() + if err := rpc.Call(utils.AccountSv1MaxUsage, + arg, &eEc); err != nil { + return + } + accountSTime += time.Now().Sub(tNow) + sumAccountS += *eEc.Usage + wgAccountS.Done() + }() + + go func() { + tStart := time.Date(2016, 3, 31, 0, 0, 0, 0, time.UTC) + usageDur, _ := utils.ParseDurationWithNanosecs(usage) + cd := &engine.CallDescriptorWithOpts{ + CallDescriptor: &engine.CallDescriptor{ + Category: "call", + Tenant: "cgrates.org", + Subject: "1002", + Account: "1002", + Destination: "1003", + TimeStart: tStart, + TimeEnd: tStart.Add(usageDur), + }, + } + var rply time.Duration + tNow := time.Now() + if err := rpc.Call(utils.ResponderGetMaxSessionTime, cd, &rply); err != nil { + return + } + ralsTime += time.Now().Sub(tNow) + sumRALs += rply.Seconds() + wgRALs.Done() + }() + + if i%*gorutines == 0 { + wgAccountS.Wait() + wgRALs.Wait() + } + + } + wgAccountS.Wait() + wgRALs.Wait() + + fmt.Println("Sum AccountS MaxUsage") + fmt.Println(sumAccountS) + fmt.Println("Average AccountS MaxUsage") + fmt.Println(accountSTime / time.Duration(*requests)) + fmt.Println("Total AccountS MaxUsage Time") + fmt.Println(accountSTime) + + fmt.Println("Sum RALs GetMaxSessionTime") + fmt.Println(sumRALs) + fmt.Println("Average RALs GetMaxSessionTime") + fmt.Println(ralsTime / time.Duration(*requests)) + fmt.Println("Total RALs GetMaxSessionTime Time") + fmt.Println(ralsTime) + +} diff --git a/data/tariffplans/oldaccvsnew/AccountActions.csv b/data/tariffplans/oldaccvsnew/AccountActions.csv index 44fa1907f..d4eaddc97 100644 --- a/data/tariffplans/oldaccvsnew/AccountActions.csv +++ b/data/tariffplans/oldaccvsnew/AccountActions.csv @@ -1,2 +1,3 @@ #Tenant,Account,ActionPlanId,ActionTriggersId,AllowNegative,Disabled -cgrates.org,1001,AP_PACKAGE_10,,, \ No newline at end of file +cgrates.org,1001,AP_PACKAGE_10,,, +cgrates.org,1002,AP_PACKAGE_11,,, \ No newline at end of file diff --git a/data/tariffplans/oldaccvsnew/AccountProfiles.csv b/data/tariffplans/oldaccvsnew/AccountProfiles.csv index 347e400b8..4ae31802d 100644 --- a/data/tariffplans/oldaccvsnew/AccountProfiles.csv +++ b/data/tariffplans/oldaccvsnew/AccountProfiles.csv @@ -1,3 +1,4 @@ #Tenant,ID,FilterIDs,ActivationInterval,Weights,Opts,BalanceID,BalanceFilterIDs,BalanceWeights,BalanceType,BalanceUnits,BalanceUnitFactors,BalanceOpts,BalanceCostIncrements,BalanceAttributeIDs,BalanceRateProfileIDs,ThresholdIDs cgrates.org,1001,*string:~*req.Account:1001,,,,VoiceBalance,,;10,*abstract,3600000000000,,,*string:~*req.ToR:*voice;1000000000;0;0,,, - +cgrates.org,1002,*string:~*req.Account:1002,,,,VoiceBalance,,;10,*abstract,3600000000000,,,*string:~*req.ToR:*voice;1000000000;0;-1,,RP_ANY, +cgrates.org,1002,,,,,MonetaryBalance,,;10,*concrete,100,,,,,, diff --git a/data/tariffplans/oldaccvsnew/ActionPlans.csv b/data/tariffplans/oldaccvsnew/ActionPlans.csv index b10e827b5..1dfd09f7a 100644 --- a/data/tariffplans/oldaccvsnew/ActionPlans.csv +++ b/data/tariffplans/oldaccvsnew/ActionPlans.csv @@ -1,2 +1,3 @@ #Id,ActionsId,TimingId,Weight -AP_PACKAGE_10,ACT_TOPUP_RST_10,*asap,10 \ No newline at end of file +AP_PACKAGE_10,ACT_TOPUP_RST_10,*asap,10 +AP_PACKAGE_11,ACT_TOPUP_RST_11,*asap,10 \ No newline at end of file diff --git a/data/tariffplans/oldaccvsnew/Actions.csv b/data/tariffplans/oldaccvsnew/Actions.csv index f505ed4c2..48ab4c657 100644 --- a/data/tariffplans/oldaccvsnew/Actions.csv +++ b/data/tariffplans/oldaccvsnew/Actions.csv @@ -1,2 +1,4 @@ #ActionsId[0],Action[1],ExtraParameters[2],Filter[3],BalanceId[4],BalanceType[5],Categories[6],DestinationIds[7],RatingSubject[8],SharedGroup[9],ExpiryTime[10],TimingIds[11],Units[12],BalanceWeight[13],BalanceBlocker[14],BalanceDisabled[15],Weight[16] ACT_TOPUP_RST_10,*topup_reset,,,test,*voice,,*any,,,*unlimited,,3600000000000,10,false,false,10 +ACT_TOPUP_RST_11,*topup_reset,,,,*voice,,*any,RP_ANY,,*unlimited,,3600000000000,10,false,false,10 +ACT_TOPUP_RST_11,*topup_reset,,,,*monetary,,*any,,,*unlimited,,100,10,false,false,10 diff --git a/data/tariffplans/oldaccvsnew/Chargers.csv b/data/tariffplans/oldaccvsnew/Chargers.csv new file mode 100644 index 000000000..c270b5867 --- /dev/null +++ b/data/tariffplans/oldaccvsnew/Chargers.csv @@ -0,0 +1,2 @@ +#Tenant,ID,FilterIDs,ActivationInterval,RunID,AttributeIDs,Weight +cgrates.org,DEFAULT,,,*default,*none,0 \ No newline at end of file diff --git a/data/tariffplans/oldaccvsnew/DestinationRates.csv b/data/tariffplans/oldaccvsnew/DestinationRates.csv new file mode 100644 index 000000000..1978117eb --- /dev/null +++ b/data/tariffplans/oldaccvsnew/DestinationRates.csv @@ -0,0 +1,2 @@ +#Id,DestinationId,RatesTag,RoundingMethod,RoundingDecimals,MaxCost,MaxCostStrategy +DR_ANY,*any,RT_ANY,*up,20,0, \ No newline at end of file diff --git a/data/tariffplans/oldaccvsnew/RateProfiles.csv b/data/tariffplans/oldaccvsnew/RateProfiles.csv new file mode 100644 index 000000000..48b90d455 --- /dev/null +++ b/data/tariffplans/oldaccvsnew/RateProfiles.csv @@ -0,0 +1,3 @@ +#Tenant,ID,FilterIDs,ActivationInterval,Weight,MinCost,MaxCost,MaxCostStrategy,RateID,RateFilterIDs,RateActivationStart,RateWeight,RateBlocker,RateIntervalStart,RateFixedFee,RateRecurrentFee,RateUnit,RateIncrement +cgrates.org,RP_ANY,,,,,,,RT_ANY,,,,,0s,0,0.2,60s,60s +cgrates.org,RP_ANY,,,,,,,RT_ANY,,,,,60s,0,0.1,60s,1s \ No newline at end of file diff --git a/data/tariffplans/oldaccvsnew/Rates.csv b/data/tariffplans/oldaccvsnew/Rates.csv new file mode 100644 index 000000000..f0637c8cc --- /dev/null +++ b/data/tariffplans/oldaccvsnew/Rates.csv @@ -0,0 +1,3 @@ +#Id,ConnectFee,Rate,RateUnit,RateIncrement,GroupIntervalStart +RT_ANY,0,0.2,60s,60s,0s +RT_ANY,0,0.1,60s,1s,60s \ No newline at end of file diff --git a/data/tariffplans/oldaccvsnew/RatingPlans.csv b/data/tariffplans/oldaccvsnew/RatingPlans.csv new file mode 100644 index 000000000..4749de4d3 --- /dev/null +++ b/data/tariffplans/oldaccvsnew/RatingPlans.csv @@ -0,0 +1,2 @@ +#Id,DestinationRatesId,TimingTag,Weight +RP_ANY,DR_ANY,*any,10 \ No newline at end of file diff --git a/data/tariffplans/oldaccvsnew/RatingProfiles.csv b/data/tariffplans/oldaccvsnew/RatingProfiles.csv new file mode 100644 index 000000000..924509fd8 --- /dev/null +++ b/data/tariffplans/oldaccvsnew/RatingProfiles.csv @@ -0,0 +1,3 @@ +#Tenant,Category,Subject,ActivationTime,RatingPlanId,RatesFallbackSubject +cgrates.org,call,*any,2014-01-14T00:00:00Z,RP_ANY, +