From 0cffb15262e3c4bdb63aadaedeebc10e910f96b6 Mon Sep 17 00:00:00 2001 From: DanB Date: Fri, 31 Aug 2018 21:48:11 +0200 Subject: [PATCH] SessionS.v1ForkSessions improvements, GetSessionRuns returning all sessions, SMGenericV1.InitiateSession doing authorization also - fixes #1150 --- agents/dmtagent_it_test.go | 2 +- agents/httpagent_it_test.go | 2 +- apier/v1/auth.go | 6 +- console/maxduration.go | 10 ++- data/conf/samples/dmtagent/cgrates.json | 3 + data/conf/samples/httpagent/httpagent.json | 2 +- engine/responder.go | 22 +++-- engine/responder_test.go | 4 +- general_tests/auth_test.go | 12 +-- sessions/sessions.go | 94 +++++++++++++++------- sessions/smgbirpc_it_test.go | 15 +++- 11 files changed, 110 insertions(+), 62 deletions(-) diff --git a/agents/dmtagent_it_test.go b/agents/dmtagent_it_test.go index 3d10e81d0..a6ffbf6a5 100644 --- a/agents/dmtagent_it_test.go +++ b/agents/dmtagent_it_test.go @@ -485,7 +485,7 @@ func TestDmtAgentSendCCRSMS(t *testing.T) { } else if len(cdrs) != 1 { t.Error("Unexpected number of CDRs returned: ", len(cdrs)) } else { - if cdrs[0].Usage != "60000000000" { // should be 1 but maxUsage returns rounded version + if cdrs[0].Usage != "1" { // should be 1 but maxUsage returns rounded version t.Errorf("Unexpected CDR Usage received, cdr: %+v ", cdrs[0]) } if cdrs[0].Cost != 0.6 { diff --git a/agents/httpagent_it_test.go b/agents/httpagent_it_test.go index 8142583be..296829072 100644 --- a/agents/httpagent_it_test.go +++ b/agents/httpagent_it_test.go @@ -123,7 +123,7 @@ func TestHAitAuth1001(t *testing.T) { eXml := []byte(` 1 - 6042 + 10800 `) if body, err := ioutil.ReadAll(rply.Body); err != nil { t.Error(err) diff --git a/apier/v1/auth.go b/apier/v1/auth.go index 80a3556f4..91048c644 100644 --- a/apier/v1/auth.go +++ b/apier/v1/auth.go @@ -57,14 +57,14 @@ func (self *ApierV1) GetMaxUsage(usageRecord engine.UsageRecord, maxUsage *float if err != nil { return utils.NewErrServerError(err) } - var maxDur float64 + var maxDur time.Duration if err := self.Responder.GetDerivedMaxSessionTime(storedCdr, &maxDur); err != nil { return err } - if maxDur == -1.0 { + if maxDur == time.Duration(-1) { *maxUsage = -1.0 return nil } - *maxUsage = time.Duration(maxDur).Seconds() + *maxUsage = maxDur.Seconds() return nil } diff --git a/console/maxduration.go b/console/maxduration.go index a4acfa0fb..ef22c7ac8 100644 --- a/console/maxduration.go +++ b/console/maxduration.go @@ -18,7 +18,11 @@ along with this program. If not, see package console -import "github.com/cgrates/cgrates/engine" +import ( + "time" + + "github.com/cgrates/cgrates/engine" +) func init() { c := &CmdGetMaxDuration{ @@ -59,8 +63,8 @@ func (self *CmdGetMaxDuration) PostprocessRpcParams() error { } func (self *CmdGetMaxDuration) RpcResult() interface{} { - var f float64 - return &f + var d time.Duration + return &d } func (self *CmdGetMaxDuration) ClientArgs() []string { diff --git a/data/conf/samples/dmtagent/cgrates.json b/data/conf/samples/dmtagent/cgrates.json index 9624cac60..3e4c4ae09 100644 --- a/data/conf/samples/dmtagent/cgrates.json +++ b/data/conf/samples/dmtagent/cgrates.json @@ -93,6 +93,9 @@ "pubsubs_conns": [ {"address": "*internal"} ], + "sessions_conns": [ + {"address": "127.0.0.1:2012","transport":"*json"} + ], }, } diff --git a/data/conf/samples/httpagent/httpagent.json b/data/conf/samples/httpagent/httpagent.json index 7cfd6be3d..bc684a1bd 100644 --- a/data/conf/samples/httpagent/httpagent.json +++ b/data/conf/samples/httpagent/httpagent.json @@ -56,7 +56,7 @@ { "id": "mtcall_cdr", "filters": ["*string:*req.request_type:MTCALL_CDR"], - "flags": ["*dryrun", "*cdrs"], + "flags": ["*cdrs"], "continue_on_success": false, "request_fields":[ {"id": "RequestType", "field_id": "RequestType", "type": "*constant", diff --git a/engine/responder.go b/engine/responder.go index 6a7a9ac3e..eeb467b7c 100644 --- a/engine/responder.go +++ b/engine/responder.go @@ -32,6 +32,7 @@ import ( // Individual session run type SessionRun struct { + RequestType string DerivedCharger *utils.DerivedCharger // Needed in reply CallDescriptor *CallDescriptor CallCosts []*CallCost @@ -290,7 +291,7 @@ func (rs *Responder) RefundRounding(arg *CallDescriptor, reply *float64) (err er return } -func (rs *Responder) GetMaxSessionTime(arg *CallDescriptor, reply *float64) (err error) { +func (rs *Responder) GetMaxSessionTime(arg *CallDescriptor, reply *time.Duration) (err error) { if arg.Subject == "" { arg.Subject = arg.Account } @@ -315,16 +316,16 @@ func (rs *Responder) GetMaxSessionTime(arg *CallDescriptor, reply *float64) (err return utils.ErrMaxUsageExceeded } r, e := arg.GetMaxSessionDuration() - *reply, err = float64(r), e + *reply, err = r, e return } // Returns MaxSessionTime for an event received in sessions, considering DerivedCharging for it -func (rs *Responder) GetDerivedMaxSessionTime(ev *CDR, reply *float64) (err error) { +func (rs *Responder) GetDerivedMaxSessionTime(ev *CDR, reply *time.Duration) (err error) { cacheKey := utils.GET_DERIV_MAX_SESS_TIME + ev.CGRID + ev.RunID if item, err := rs.getCache().Get(cacheKey); err == nil && item != nil { if item.Value != nil { - *reply = *(item.Value.(*float64)) + *reply = *(item.Value.(*time.Duration)) } return item.Err } @@ -353,7 +354,7 @@ func (rs *Responder) GetDerivedMaxSessionTime(ev *CDR, reply *float64) (err erro if !rs.usageAllowed(ev.ToR, ev.Usage) { return utils.ErrMaxUsageExceeded } - maxCallDuration := -1.0 + maxCallDuration := time.Duration(-1.0) attrsDC := &utils.AttrDerivedChargers{Tenant: ev.Tenant, Category: ev.Category, Direction: utils.OUT, Account: ev.Account, Subject: ev.Subject} @@ -410,15 +411,15 @@ func (rs *Responder) GetDerivedMaxSessionTime(ev *CDR, reply *float64) (err erro TimeStart: setupTime, TimeEnd: setupTime.Add(forkedCDR.Usage), } - var remainingDuration float64 + var remainingDuration time.Duration err = rs.GetMaxSessionTime(cd, &remainingDuration) if err != nil { - *reply = 0 + *reply = time.Duration(0) rs.getCache().Cache(cacheKey, &utils.ResponseCacheItem{Err: err}) return err } // Set maxCallDuration, smallest out of all forked sessions - if maxCallDuration == -1.0 { // first time we set it /not initialized yet + if maxCallDuration == time.Duration(-1) { // first time we set it /not initialized yet maxCallDuration = remainingDuration } else if maxCallDuration > remainingDuration { maxCallDuration = remainingDuration @@ -487,9 +488,6 @@ func (rs *Responder) GetSessionRuns(ev *CDR, sRuns *[]*SessionRun) (err error) { if err != nil { return err } - if !utils.IsSliceMember([]string{utils.META_PREPAID, utils.PREPAID}, forkedCDR.RequestType) { - continue // We only consider prepaid sessions - } startTime := forkedCDR.AnswerTime if startTime.IsZero() { // AnswerTime not parsable, try SetupTime startTime = forkedCDR.SetupTime @@ -513,7 +511,7 @@ func (rs *Responder) GetSessionRuns(ev *CDR, sRuns *[]*SessionRun) (err error) { cd.ForceDuration = true } } - sesRuns = append(sesRuns, &SessionRun{DerivedCharger: dc, CallDescriptor: cd}) + sesRuns = append(sesRuns, &SessionRun{RequestType: forkedCDR.RequestType, DerivedCharger: dc, CallDescriptor: cd}) } //utils.Logger.Info(fmt.Sprintf("RUNS: %v", len(sesRuns))) *sRuns = sesRuns diff --git a/engine/responder_test.go b/engine/responder_test.go index 719870d2e..dda163a3b 100644 --- a/engine/responder_test.go +++ b/engine/responder_test.go @@ -63,10 +63,10 @@ func TestResponderGetDerivedMaxSessionTime(t *testing.T) { RunID: utils.DEFAULT_RUNID, Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01} - var maxSessionTime float64 + var maxSessionTime time.Duration if err := rsponder.GetDerivedMaxSessionTime(cdr, &maxSessionTime); err != nil { t.Error(err) - } else if maxSessionTime != -1 { + } else if maxSessionTime != time.Duration(-1) { t.Error("Unexpected maxSessionTime received: ", maxSessionTime) } deTMobile := &Destination{Id: "DE_TMOBILE", diff --git a/general_tests/auth_test.go b/general_tests/auth_test.go index b8ec8f994..80b9133a2 100644 --- a/general_tests/auth_test.go +++ b/general_tests/auth_test.go @@ -102,7 +102,7 @@ func TestAuthPostpaidNoAcnt(t *testing.T) { cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_PREPAID, Tenant: "cgrates.org", Category: "call", Account: "nonexistent", Subject: "testauthpostpaid1", Destination: "4986517174963", SetupTime: time.Date(2015, 8, 27, 11, 26, 0, 0, time.UTC)} - var maxSessionTime float64 + var maxSessionTime time.Duration if err := rsponder.GetDerivedMaxSessionTime(cdr, &maxSessionTime); err != utils.ErrAccountNotFound { t.Error(err) } @@ -113,7 +113,7 @@ func TestAuthPostpaidNoDestination(t *testing.T) { cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_PREPAID, Tenant: "cgrates.org", Category: "call", Account: "testauthpostpaid1", Subject: "testauthpostpaid1", Destination: "441231234", SetupTime: time.Date(2015, 8, 27, 11, 26, 0, 0, time.UTC)} - var maxSessionTime float64 + var maxSessionTime time.Duration if err := rsponder.GetDerivedMaxSessionTime(cdr, &maxSessionTime); err == nil { t.Error("Expecting error for destination not allowed to subject") } @@ -124,10 +124,10 @@ func TestAuthPostpaidFallbackDest(t *testing.T) { cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_POSTPAID, Tenant: "cgrates.org", Category: "call", Account: "testauthpostpaid1", Subject: "testauthpostpaid2", Destination: "441231234", SetupTime: time.Date(2015, 8, 27, 11, 26, 0, 0, time.UTC)} - var maxSessionTime float64 + var maxSessionTime time.Duration if err := rsponder.GetDerivedMaxSessionTime(cdr, &maxSessionTime); err != nil { t.Error(err) - } else if maxSessionTime != -1 { + } else if maxSessionTime != time.Duration(-1) { t.Error("Unexpected maxSessionTime received: ", maxSessionTime) } } @@ -137,10 +137,10 @@ func TestAuthPostpaidWithDestination(t *testing.T) { cdr := &engine.CDR{ToR: utils.VOICE, RequestType: utils.META_POSTPAID, Tenant: "cgrates.org", Category: "call", Account: "testauthpostpaid1", Subject: "testauthpostpaid1", Destination: "4986517174963", SetupTime: time.Date(2015, 8, 27, 11, 26, 0, 0, time.UTC)} - var maxSessionTime float64 + var maxSessionTime time.Duration if err := rsponder.GetDerivedMaxSessionTime(cdr, &maxSessionTime); err != nil { t.Error(err) - } else if maxSessionTime != -1 { + } else if maxSessionTime != time.Duration(-1) { t.Error("Unexpected maxSessionTime received: ", maxSessionTime) } } diff --git a/sessions/sessions.go b/sessions/sessions.go index db8e1f9d7..af9c6f483 100644 --- a/sessions/sessions.go +++ b/sessions/sessions.go @@ -474,7 +474,8 @@ func (smg *SMGeneric) getSessionIDsForPrefix(prefix string, // v1ForkSessions is using DerivedChargers for session forking func (smg *SMGeneric) v1ForkSessions(tnt string, evStart *engine.SafEvent, - clntConn rpcclient.RpcClientConnection, cgrID, resourceID string) (ss []*SMGSession, err error) { + clntConn rpcclient.RpcClientConnection, cgrID, resourceID string, + handlePseudo bool) (ss []*SMGSession, err error) { cdr, err := evStart.AsCDR(smg.cgrCfg, smg.Timezone) if err != nil { utils.Logger.Warning(fmt.Sprintf("<%s> could not convert event: %s to CDR, err: %s", @@ -486,14 +487,19 @@ func (smg *SMGeneric) v1ForkSessions(tnt string, evStart *engine.SafEvent, cdr, &sessionRuns); err != nil { return nil, err } - if len(sessionRuns) == 0 { - return []*SMGSession{ - &SMGSession{CGRID: cgrID, ResourceID: resourceID, EventStart: evStart, - RunID: utils.META_NONE, Timezone: smg.Timezone, - rals: smg.rals, cdrsrv: smg.cdrsrv, - clntConn: clntConn}}, nil + noneSession := []*SMGSession{ + &SMGSession{CGRID: cgrID, ResourceID: resourceID, EventStart: evStart, + RunID: utils.META_NONE, Timezone: smg.Timezone, + rals: smg.rals, cdrsrv: smg.cdrsrv, + clntConn: clntConn}} + handledSessions := []string{utils.META_PREPAID} + if handlePseudo { + handledSessions = append(handledSessions, utils.META_PSEUDOPREPAID) } for _, sessionRun := range sessionRuns { + if !utils.IsSliceMember(handledSessions, sessionRun.RequestType) { + continue // not forking non-prepaid session + } ss = append(ss, &SMGSession{CGRID: cgrID, Tenant: tnt, ResourceID: resourceID, EventStart: evStart, @@ -502,13 +508,16 @@ func (smg *SMGeneric) v1ForkSessions(tnt string, evStart *engine.SafEvent, CD: sessionRun.CallDescriptor, clntConn: clntConn, clientProto: smg.cgrCfg.SessionSCfg().ClientProtocol}) } + if len(ss) == 0 { // we have no *prepaid session to work with + return noneSession, nil + } return } // v2ForkSessions is using ChargerS for session forking func (smg *SMGeneric) v2ForkSessions(tnt string, evStart *engine.SafEvent, clntConn rpcclient.RpcClientConnection, - cgrID, resourceID string) (ss []*SMGSession, err error) { + cgrID, resourceID string, handlePseudo bool) (ss []*SMGSession, err error) { cgrEv := &utils.CGREvent{ Tenant: tnt, ID: utils.UUIDSha1Prefix(), @@ -519,14 +528,18 @@ func (smg *SMGeneric) v2ForkSessions(tnt string, evStart *engine.SafEvent, err.Error() != utils.ErrNotFound.Error() { return nil, err } - noPrepaidSs := []*SMGSession{ + noneSession := []*SMGSession{ &SMGSession{CGRID: cgrID, ResourceID: resourceID, EventStart: evStart, RunID: utils.META_NONE, Timezone: smg.Timezone, rals: smg.rals, cdrsrv: smg.cdrsrv, clntConn: clntConn}} + handledSessions := []string{utils.META_PREPAID} + if handlePseudo { + handledSessions = append(handledSessions, utils.META_PSEUDOPREPAID) + } for _, chrgr := range chrgrs { evStart := engine.NewSafEvent(chrgr.CGREvent.Event) - if evStart.GetStringIgnoreErrors(utils.RequestType) != utils.META_PREPAID { + if !utils.IsSliceMember(handledSessions, evStart.GetStringIgnoreErrors(utils.RequestType)) { continue // not forking non-prepaid session } startTime := evStart.GetTimeIgnoreErrors(utils.AnswerTime, smg.Timezone) @@ -558,7 +571,7 @@ func (smg *SMGeneric) v2ForkSessions(tnt string, evStart *engine.SafEvent, clientProto: smg.cgrCfg.SessionSCfg().ClientProtocol}) } if len(ss) == 0 { // we have no *prepaid session to work with - return noPrepaidSs, nil + return noneSession, nil } return } @@ -574,9 +587,9 @@ func (smg *SMGeneric) sessionStart(tnt string, evStart *engine.SafEvent, } var ss []*SMGSession if smg.chargerS == nil { // old way of session forking - ss, err = smg.v1ForkSessions(tnt, evStart, clntConn, cgrID, resourceID) + ss, err = smg.v1ForkSessions(tnt, evStart, clntConn, cgrID, resourceID, false) } else { - ss, err = smg.v2ForkSessions(tnt, evStart, clntConn, cgrID, resourceID) + ss, err = smg.v2ForkSessions(tnt, evStart, clntConn, cgrID, resourceID, false) } if err != nil { return nil, err @@ -861,18 +874,34 @@ func (smg *SMGeneric) GetMaxUsage(tnt string, gev *engine.SafEvent) (maxUsage ti return (item.Value.(time.Duration)), item.Err } defer smg.responseCache.Cache(cacheKey, &utils.ResponseCacheItem{Value: maxUsage, Err: err}) - storedCdr, err := gev.AsCDR(config.CgrConfig(), smg.Timezone) - if err != nil { - return maxUsage, err - } if has := gev.HasField(utils.Usage); !has { // make sure we have a minimum duration configured - storedCdr.Usage = smg.cgrCfg.SessionSCfg().MaxCallDuration + gev.Set(utils.Usage, smg.cgrCfg.SessionSCfg().MaxCallDuration) } - var maxDur float64 - if err = smg.rals.Call("Responder.GetDerivedMaxSessionTime", storedCdr, &maxDur); err != nil { + // fork sessions + var ss []*SMGSession + if smg.chargerS == nil { // old way of session forking + ss, err = smg.v1ForkSessions(tnt, gev, nil, cgrID, "", true) + } else { + ss, err = smg.v2ForkSessions(tnt, gev, nil, cgrID, "", true) + } + if err != nil { return } - maxUsage = time.Duration(maxDur) + var minUsage *time.Duration // find out the minimum usage + for _, s := range ss { + if s.RunID == utils.META_NONE { + minUsage = utils.DurationPointer(-1) + break + } + var maxDur time.Duration + if err = smg.rals.Call("Responder.GetMaxSessionTime", s.CD, &maxDur); err != nil { + return + } + if minUsage == nil || maxDur < *minUsage { + minUsage = &maxDur + } + } + maxUsage = *minUsage if maxUsage != time.Duration(-1) && maxUsage < smg.cgrCfg.SessionSCfg().MinCallDuration { return 0, errors.New("UNAUTHORIZED_MIN_DURATION") @@ -1073,9 +1102,9 @@ func (smg *SMGeneric) ChargeEvent(tnt string, gev *engine.SafEvent) (maxUsage ti // fork sessions var ss []*SMGSession if smg.chargerS == nil { // old way of session forking - ss, err = smg.v1ForkSessions(tnt, gev, nil, cgrID, "") + ss, err = smg.v1ForkSessions(tnt, gev, nil, cgrID, "", false) } else { - ss, err = smg.v2ForkSessions(tnt, gev, nil, cgrID, "") + ss, err = smg.v2ForkSessions(tnt, gev, nil, cgrID, "", false) } if err != nil { return @@ -1083,8 +1112,8 @@ func (smg *SMGeneric) ChargeEvent(tnt string, gev *engine.SafEvent) (maxUsage ti // debit each forked session var maxDur *time.Duration // Avoid differences between default 0 and received 0 for _, s := range ss { - durDebit, err := s.debit(s.CD.GetDuration(), nil) - if err != nil { + var durDebit time.Duration + if durDebit, err = s.debit(s.CD.GetDuration(), nil); err != nil { utils.Logger.Err(fmt.Sprintf("<%s> Could not Debit CD: %+v, RunID: %s, error: %s", utils.SessionS, s.CD, s.RunID, err.Error())) break @@ -1240,9 +1269,9 @@ func (smg *SMGeneric) BiRPCV2GetMaxUsage(clnt rpcclient.RpcClientConnection, func (smg *SMGeneric) BiRPCV1InitiateSession(clnt rpcclient.RpcClientConnection, ev engine.MapEvent, maxUsage *float64) (err error) { var minMaxUsage time.Duration - if minMaxUsage, err = smg.InitiateSession( - utils.FirstNonEmpty(ev.GetStringIgnoreErrors(utils.Tenant), - smg.cgrCfg.DefaultTenant), + tnt := utils.FirstNonEmpty(ev.GetStringIgnoreErrors(utils.Tenant), + smg.cgrCfg.DefaultTenant) + if minMaxUsage, err = smg.InitiateSession(tnt, engine.NewSafEvent(ev), clnt, ""); err != nil { if err != rpcclient.ErrSessionNotFound { err = utils.NewErrServerError(err) @@ -1250,7 +1279,14 @@ func (smg *SMGeneric) BiRPCV1InitiateSession(clnt rpcclient.RpcClientConnection, return } if minMaxUsage == time.Duration(-1) { - *maxUsage = -1.0 + // handle auth for OpenSIPS 2.1 + var authUsage time.Duration + if authUsage, err = smg.GetMaxUsage(tnt, engine.NewSafEvent(ev)); err != nil { + return + } + if authUsage != time.Duration(-1) { + *maxUsage = authUsage.Seconds() + } } else { *maxUsage = minMaxUsage.Seconds() } diff --git a/sessions/smgbirpc_it_test.go b/sessions/smgbirpc_it_test.go index bf670852c..a4d42629e 100644 --- a/sessions/smgbirpc_it_test.go +++ b/sessions/smgbirpc_it_test.go @@ -145,13 +145,14 @@ func TestSMGBiRPCSessionAutomaticDisconnects(t *testing.T) { utils.RequestType: utils.META_PREPAID, utils.SetupTime: "2016-01-05 18:30:49", utils.AnswerTime: "2016-01-05 18:31:05", + utils.Usage: time.Duration(200 * time.Millisecond), }) var maxUsage float64 if err := smgBiRPC.Call(utils.SMGenericV1InitiateSession, smgEv, &maxUsage); err != nil { t.Error(err) } - if maxUsage != -1 { + if maxUsage != 0.01 { t.Error("Bad max usage: ", maxUsage) } // Make sure we are receiving a disconnect event @@ -194,11 +195,16 @@ func TestSMGBiRPCSessionAutomaticDisconnects(t *testing.T) { t.Errorf("Unexpected CDR CostSource received, cdr: %v %+v ", cdrs[0].CostSource, cdrs[0]) } } + } func TestSMGBiRPCSessionOriginatorTerminate(t *testing.T) { - attrSetBalance := utils.AttrSetBalance{Tenant: "cgrates.org", Account: "TestSMGBiRPCSessionOriginatorTerminate", BalanceType: utils.VOICE, BalanceID: utils.StringPointer("TestSMGBiRPCSessionOriginatorTerminate"), - Value: utils.Float64Pointer(1 * float64(time.Second)), RatingSubject: utils.StringPointer("*zero1ms")} + attrSetBalance := utils.AttrSetBalance{Tenant: "cgrates.org", + Account: "TestSMGBiRPCSessionOriginatorTerminate", + BalanceType: utils.VOICE, + BalanceID: utils.StringPointer("TestSMGBiRPCSessionOriginatorTerminate"), + Value: utils.Float64Pointer(1 * float64(time.Second)), + RatingSubject: utils.StringPointer("*zero1ms")} var reply string if err := smgRPC.Call("ApierV2.SetBalance", attrSetBalance, &reply); err != nil { t.Error(err) @@ -226,13 +232,14 @@ func TestSMGBiRPCSessionOriginatorTerminate(t *testing.T) { utils.RequestType: utils.META_PREPAID, utils.SetupTime: "2016-01-05 18:30:49", utils.AnswerTime: "2016-01-05 18:31:05", + utils.Usage: time.Duration(200 * time.Millisecond), }) var maxUsage float64 if err := smgBiRPC.Call(utils.SMGenericV1InitiateSession, smgEv, &maxUsage); err != nil { t.Error(err) } - if maxUsage != -1 { + if maxUsage != 0.2 { t.Error("Bad max usage: ", maxUsage) } time.Sleep(time.Duration(10 * time.Millisecond)) // Give time for debits to occur