diff --git a/data/tariffplans/testData/Chargers.csv b/data/tariffplans/testData/Chargers.csv new file mode 100644 index 000000000..c270b5867 --- /dev/null +++ b/data/tariffplans/testData/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/engine/account.go b/engine/account.go index 412e2eb12..33e21fcf0 100644 --- a/engine/account.go +++ b/engine/account.go @@ -533,18 +533,18 @@ func (ub *Account) debitCreditBalance(cd *CallDescriptor, count bool, dryRun boo defaultBalance := ub.GetDefaultMoneyBalance() defaultBalance.SubstractValue(cost) //send default balance to thresholdS to be processed - acntTnt := utils.NewTenantID(ub.ID) - thEv := &ArgsProcessEvent{ - CGREvent: &utils.CGREvent{ - Tenant: acntTnt.Tenant, - ID: utils.GenUUID(), - Event: map[string]interface{}{ - utils.EventType: utils.BalanceUpdate, - utils.EventSource: utils.AccountService, - utils.Account: acntTnt.ID, - utils.BalanceID: defaultBalance.ID, - utils.Units: defaultBalance.Value}}} if thresholdS != nil { + acntTnt := utils.NewTenantID(ub.ID) + thEv := &ArgsProcessEvent{ + CGREvent: &utils.CGREvent{ + Tenant: acntTnt.Tenant, + ID: utils.GenUUID(), + Event: map[string]interface{}{ + utils.EventType: utils.BalanceUpdate, + utils.EventSource: utils.AccountService, + utils.Account: acntTnt.ID, + utils.BalanceID: defaultBalance.ID, + utils.Units: defaultBalance.Value}}} var tIDs []string if err := thresholdS.Call(utils.ThresholdSv1ProcessEvent, thEv, &tIDs); err != nil && err.Error() != utils.ErrNotFound.Error() { diff --git a/engine/calldesc.go b/engine/calldesc.go index 1b896a8a0..cc11fa517 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -648,6 +648,8 @@ If the user has no credit then it will return 0. If the user has postpayed plan it returns -1. */ func (origCD *CallDescriptor) getMaxSessionDuration(origAcc *Account) (time.Duration, error) { + fmt.Println("===Teo==== Enter in CallDesc getMaxSessionDuration") + // clone the account for discarding chenges on debit dry run //log.Printf("ORIG CD: %+v", origCD) account := origAcc.Clone() @@ -663,15 +665,18 @@ func (origCD *CallDescriptor) getMaxSessionDuration(origAcc *Account) (time.Dura } cd := origCD.Clone() initialDuration := cd.TimeEnd.Sub(cd.TimeStart) + fmt.Println("initialDuration : ", initialDuration) defaultBalance := account.GetDefaultMoneyBalance() //use this to check what increment was payed with debt initialDefaultBalanceValue := defaultBalance.GetValue() + tStart := time.Now() cc, err := cd.debit(account, true, false) if err != nil { return 0, err } + fmt.Println("Duration for debit from getMaxSessionDuration: ", time.Now().Sub(tStart)) // not enough credit for connect fee if cc.negativeConnectFee == true { @@ -680,7 +685,9 @@ func (origCD *CallDescriptor) getMaxSessionDuration(origAcc *Account) (time.Dura var totalCost float64 var totalDuration time.Duration + decompressStart := time.Now() cc.Timespans.Decompress() + fmt.Println("Duration for dcc.Timespans.Decompress(): ", time.Now().Sub(decompressStart)) for _, ts := range cc.Timespans { if cd.MaxRate > 0 && cd.MaxRateUnit > 0 { rate, _, rateUnit := ts.RateInterval.GetRateParameters(ts.GetGroupStart()) @@ -710,6 +717,8 @@ func (origCD *CallDescriptor) getMaxSessionDuration(origAcc *Account) (time.Dura } } } + fmt.Println("totalDuration : ", totalDuration) + fmt.Println("===Teo==== Exit CallDesc getMaxSessionDuration") return utils.MinDuration(initialDuration, totalDuration), nil } @@ -821,8 +830,13 @@ func (cd *CallDescriptor) Debit() (cc *CallCost, err error) { // by the GetMaxSessionDuration method. The amount filed has to be filled in call descriptor. func (cd *CallDescriptor) MaxDebit() (cc *CallCost, err error) { cd.account = nil // make sure it's not cached + fmt.Println("===Teo=== ") + fmt.Println("===Teo=== Enter in CallDescriptor MaxDebit") + tSt := time.Now() + //fmt.Println("===Teo=== cc : ", utils.ToJSON(cd)) _, err = guardian.Guardian.Guard(func() (iface interface{}, err error) { account, err := cd.getAccount() + //fmt.Println("Account: ", utils.ToJSON(account)) if err != nil { return nil, err } @@ -838,10 +852,16 @@ func (cd *CallDescriptor) MaxDebit() (cc *CallCost, err error) { } } _, err = guardian.Guardian.Guard(func() (iface interface{}, err error) { + tStart := time.Now() + fmt.Println("CD before getMaxSessionDuration: ", cd) remainingDuration, err := cd.getMaxSessionDuration(account) if err != nil && cd.GetDuration() > 0 { return nil, err } + // fmt.Println("Account after cd.getMaxSessionDuration: ", utils.ToJSON(account)) + fmt.Println("Total time spend in cd.getMaxSessionDuration(account) : ", time.Now().Sub(tStart)) + fmt.Println("CD after getMaxSessionDuration: ", cd) + fmt.Println("remainingDuration after exit getMaxSessionDuration: ", remainingDuration) // check ForceDuartion if cd.ForceDuration && !account.AllowNegative && remainingDuration < cd.GetDuration() { return nil, utils.ErrInsufficientCredit @@ -871,16 +891,20 @@ func (cd *CallDescriptor) MaxDebit() (cc *CallCost, err error) { cd.TimeEnd = cd.TimeStart.Add(remainingDuration) cd.DurationIndex -= initialDuration - remainingDuration } + fmt.Println("CD after if remainingDuration > 0 {: ", cd) //log.Print("Remaining duration: ", remainingDuration) + tStart3 := time.Now() cc, err = cd.debit(account, cd.DryRun, !cd.DenyNegativeAccount) if err == nil { cc.AccountSummary = cd.AccountSummary() } + fmt.Println("Duration from CallDesc debit : ", time.Now().Sub(tStart3)) //log.Print(balanceMap[0].Value, balanceMap[1].Value) return }, config.CgrConfig().GeneralCfg().LockingTimeout, lkIDs...) return }, config.CgrConfig().GeneralCfg().LockingTimeout, utils.ACCOUNT_PREFIX+cd.GetAccountKey()) + fmt.Println("===Teo=== Exit callDest MaxDebit with a duration of :", time.Now().Sub(tSt)) return cc, err } diff --git a/engine/responder.go b/engine/responder.go index b17200da5..d7a4017a4 100644 --- a/engine/responder.go +++ b/engine/responder.go @@ -142,7 +142,6 @@ func (rs *Responder) MaxDebit(arg *CallDescriptorWithArgDispatcher, reply *CallC nil, true, utils.NonTransactional) } // end of RPC caching - if arg.Subject == "" { arg.Subject = arg.Account } diff --git a/general_tests/data_it_test.go b/general_tests/data_it_test.go index f861a8829..348ac50fe 100644 --- a/general_tests/data_it_test.go +++ b/general_tests/data_it_test.go @@ -20,6 +20,7 @@ along with this program. If not, see package general_tests import ( + "fmt" "net/rpc" "net/rpc/jsonrpc" "path" @@ -29,6 +30,7 @@ import ( v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/sessions" "github.com/cgrates/cgrates/utils" ) @@ -44,15 +46,18 @@ var sTestsData = []func(t *testing.T){ testV1DataLoadConfig, testV1DataInitDataDb, testV1DataResetStorDb, - testV1DataStartEngine, + //testV1DataStartEngine, testV1DataRpcConn, testV1DataLoadTarrifPlans, - testV1DataDataDebitUsageWith10Kilo, - testV1DataGetCostWith10Kilo, - testV1DataDebitBalanceWith10Kilo, - testV1DataDataDebitUsage1G0, - testV1DataGetCost1G0, - testV1DataDebitBalance1G0, + // testV1DataDataDebitUsageWith10Kilo, + // testV1DataGetCostWith10Kilo, + // testV1DataDebitBalanceWith10Kilo, + // testV1DataDataDebitUsage1G0, + // testV1DataGetCost1G0, + // testV1DataDebitBalance1G0, + testV1DataInitSession, + testV1DataUpdateWith1Mo, + testV1DataUpdateWith1Go, testV1DataStopEngine, } @@ -387,6 +392,165 @@ func testV1DataDebitBalance1G0(t *testing.T) { } } +func testV1DataInitSession(t *testing.T) { + attrSetBalance := utils.AttrSetBalance{ + Tenant: "cgrates.org", + Account: "testV1DataInitSession", + BalanceType: utils.DATA, + Categories: utils.StringPointer("data"), + BalanceID: utils.StringPointer("testV1DataInitSession"), + Value: utils.Float64Pointer(1100000000), + RatingSubject: utils.StringPointer("*zero10000ns"), + } + var reply string + if err := dataRpc.Call("ApierV2.SetBalance", attrSetBalance, &reply); err != nil { + t.Error(err) + } else if reply != utils.OK { + t.Errorf("Received: %s", reply) + } + + expected := 1100000000.0 + var acc *engine.Account + if err := dataRpc.Call("ApierV2.GetAccount", + &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "testV1DataInitSession"}, + &acc); err != nil { + t.Error(err) + } else if _, has := acc.BalanceMap[utils.DATA]; !has { + t.Error("Unexpected balance returned: ", utils.ToJSON(acc.BalanceMap[utils.DATA])) + } else if rply := acc.BalanceMap[utils.DATA].GetTotalValue(); rply != expected { + t.Errorf("Expecting: %v, received: %v", + expected, rply) + } + + initUsage := 10000 + args := &sessions.V1InitSessionArgs{ + InitSession: true, + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "testV1DataInitSession", + Event: map[string]interface{}{ + utils.Tenant: "cgrates.org", + utils.ToR: utils.DATA, + utils.Category: "data", + utils.OriginID: "781512335", + utils.RequestType: utils.META_PREPAID, + utils.Account: "testV1DataInitSession", + utils.Subject: "10kilo", + utils.Destination: "*any", + utils.SetupTime: time.Date(2018, time.January, 7, 16, 60, 0, 0, time.UTC), + utils.AnswerTime: time.Date(2018, time.January, 7, 16, 60, 0, 0, time.UTC), + utils.Usage: initUsage, + "SessionTTL": "300s", + "SessionTTLLastUsed": "0s", + "SessionTTLMaxDelay": "1800s", + "SessionTTLUsage": "0s", + }, + }, + } + var rply sessions.V1InitSessionReply + if err := dataRpc.Call(utils.SessionSv1InitiateSession, + args, &rply); err != nil { + t.Error(err) + } + + aSessions := make([]*sessions.ActiveSession, 0) + if err := dataRpc.Call(utils.SessionSv1GetActiveSessions, + &utils.SessionFilter{}, &aSessions); err != nil { + t.Error(err) + } else if len(aSessions) != 1 { + t.Errorf("wrong active sessions: %s \n , and len(aSessions) %+v", + utils.ToJSON(aSessions), len(aSessions)) + } + fmt.Println("Session : ", utils.ToJSON(aSessions)) +} + +func testV1DataUpdateWith1Mo(t *testing.T) { + reqUsage := 1000000 + args := &sessions.V1UpdateSessionArgs{ + UpdateSession: true, + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "testV1DataUpdateWith1Mo", + Event: map[string]interface{}{ + utils.Tenant: "cgrates.org", + utils.ToR: utils.DATA, + utils.Category: "data", + "InitialOriginID": "781512335", + "LastUsed": 0, + "OriginID": "781512335-11", + utils.RequestType: utils.META_PREPAID, + utils.Account: "testV1DataInitSession", + utils.Subject: "10kilo", + utils.Destination: "*any", + utils.SetupTime: time.Date(2018, time.January, 7, 16, 60, 0, 0, time.UTC), + utils.AnswerTime: time.Date(2018, time.January, 7, 16, 60, 0, 0, time.UTC), + utils.Usage: reqUsage, + "SessionTTL": "28807s", + "SessionTTLLastUsed": "0s", + "SessionTTLMaxDelay": "1800s", + "SessionTTLUsage": "0s", + }, + }, + } + var rply sessions.V1UpdateSessionReply + if err := dataRpc.Call(utils.SessionSv1UpdateSession, + args, &rply); err != nil { + t.Error(err) + } + aSessions := make([]*sessions.ActiveSession, 0) + if err := dataRpc.Call(utils.SessionSv1GetActiveSessions, + &utils.SessionFilter{}, &aSessions); err != nil { + t.Error(err) + } else if len(aSessions) != 1 { + t.Errorf("wrong active sessions: %s \n , and len(aSessions) %+v", + utils.ToJSON(aSessions), len(aSessions)) + } +} + +func testV1DataUpdateWith1Go(t *testing.T) { + reqUsage := 1000000000 + args := &sessions.V1UpdateSessionArgs{ + UpdateSession: true, + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "testV1DataUpdateWith1Go", + Event: map[string]interface{}{ + utils.Tenant: "cgrates.org", + utils.ToR: utils.DATA, + utils.Category: "data", + "InitialOriginID": "781512335", + "LastUsed": 946405, + "OriginID": "781512335-11", + utils.RequestType: utils.META_PREPAID, + utils.Account: "testV1DataInitSession", + utils.Subject: "10kilo", + utils.Destination: "*any", + utils.SetupTime: time.Date(2018, time.January, 7, 16, 60, 0, 0, time.UTC), + utils.AnswerTime: time.Date(2018, time.January, 7, 16, 60, 0, 0, time.UTC), + utils.Usage: reqUsage, + "SessionTTL": "28807s", + "SessionTTLLastUsed": "0s", + "SessionTTLMaxDelay": "1800s", + "SessionTTLUsage": "0s", + }, + }, + } + var rply sessions.V1UpdateSessionReply + if err := dataRpc.Call(utils.SessionSv1UpdateSession, + args, &rply); err != nil { + t.Error(err) + } + aSessions := make([]*sessions.ActiveSession, 0) + if err := dataRpc.Call(utils.SessionSv1GetActiveSessions, + &utils.SessionFilter{}, &aSessions); err != nil { + t.Error(err) + } else if len(aSessions) != 1 { + t.Errorf("wrong active sessions: %s \n , and len(aSessions) %+v", + utils.ToJSON(aSessions), len(aSessions)) + } + +} + func testV1DataStopEngine(t *testing.T) { if err := engine.KillEngine(dataDelay); err != nil { t.Error(err)