From 1ad4068d73cb4c0107d696ea5f0ebfbdacfe2be9 Mon Sep 17 00:00:00 2001 From: DanB Date: Mon, 19 May 2014 17:50:31 +0200 Subject: [PATCH] Fixup CdrServer receiving nanoseconds as usage, more tests --- apier/apier.go | 8 +-- console/account.go | 8 +-- data/conf/samples/mediator_test1.cfg | 3 + ...atachrg1_test.go => datachrg1_test_tmp.go} | 58 +++++++++++++++++-- mediator/mediator_local_test.go | 37 +++++++++++- utils/apitpdata.go | 6 ++ utils/cgrcdr.go | 2 +- utils/cgrcdr_test.go | 2 +- 8 files changed, 105 insertions(+), 19 deletions(-) rename general_tests/{datachrg1_test.go => datachrg1_test_tmp.go} (62%) diff --git a/apier/apier.go b/apier/apier.go index 95dc54670..83ddd25b9 100644 --- a/apier/apier.go +++ b/apier/apier.go @@ -64,14 +64,8 @@ func (self *ApierV1) GetRatingPlan(rplnId string, reply *engine.RatingPlan) erro return nil } -type AttrGetAccount struct { - Tenant string - Account string - Direction string -} - // Get balance -func (self *ApierV1) GetAccount(attr *AttrGetAccount, reply *engine.Account) error { +func (self *ApierV1) GetAccount(attr *utils.AttrGetAccount, reply *engine.Account) error { tag := fmt.Sprintf("%s:%s:%s", attr.Direction, attr.Tenant, attr.Account) userBalance, err := self.AccountDb.GetAccount(tag) if err != nil { diff --git a/console/account.go b/console/account.go index ae7ee87ff..d874dba38 100644 --- a/console/account.go +++ b/console/account.go @@ -19,15 +19,15 @@ along with this program. If not, see package console import ( - "github.com/cgrates/cgrates/apier" "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" ) func init() { c := &CmdGetAccount{ name: "account", rpcMethod: "ApierV1.GetAccount", - rpcParams: &apier.AttrGetAccount{Direction: "*out"}, + rpcParams: &utils.AttrGetAccount{Direction: "*out"}, } commands[c.Name()] = c c.CommandExecuter = &CommandExecuter{c} @@ -37,7 +37,7 @@ func init() { type CmdGetAccount struct { name string rpcMethod string - rpcParams *apier.AttrGetAccount + rpcParams *utils.AttrGetAccount *CommandExecuter } @@ -51,7 +51,7 @@ func (self *CmdGetAccount) RpcMethod() string { func (self *CmdGetAccount) RpcParams() interface{} { if self.rpcParams == nil { - self.rpcParams = &apier.AttrGetAccount{Direction: "*out"} + self.rpcParams = &utils.AttrGetAccount{Direction: "*out"} } return self.rpcParams } diff --git a/data/conf/samples/mediator_test1.cfg b/data/conf/samples/mediator_test1.cfg index c0a33e969..ef7266402 100644 --- a/data/conf/samples/mediator_test1.cfg +++ b/data/conf/samples/mediator_test1.cfg @@ -6,6 +6,9 @@ [rater] enabled = true # Enable RaterCDRSExportPath service: . +[scheduler] +enabled = true # Starts Scheduler service: . + [cdrs] enabled = true # Start the CDR Server service: . mediator = internal # Address where to reach the Mediator. Empty for disabling mediation. <""|internal> diff --git a/general_tests/datachrg1_test.go b/general_tests/datachrg1_test_tmp.go similarity index 62% rename from general_tests/datachrg1_test.go rename to general_tests/datachrg1_test_tmp.go index 32a3ce912..8e292a299 100644 --- a/general_tests/datachrg1_test.go +++ b/general_tests/datachrg1_test_tmp.go @@ -35,10 +35,14 @@ func TestSetStorageDtChrg1(t *testing.T) { } func TestLoadCsvTpDtChrg1(t *testing.T) { - timings := `ALWAYS,*any,*any,*any,*any,00:00:00` - rates := `RT_DATA_2c,0,0.002,10,10,0` - destinationRates := `DR_DATA_1,*any,RT_DATA_2c,*up,4` - ratingPlans := `RP_DATA1,DR_DATA_1,ALWAYS,10` + timings := `TM1,*any,*any,*any,*any,00:00:00 +TM2,*any,*any,*any,*any,01:00:00` + rates := `RT_DATA_2c,0,0.002,10,10,0 +RT_DATA_1c,0,0.001,10,10,0` + destinationRates := `DR_DATA_1,*any,RT_DATA_2c,*up,4 +DR_DATA_2,*any,RT_DATA_1c,*up,4` + ratingPlans := `RP_DATA1,DR_DATA_1,TM1,10 +RP_DATA1,DR_DATA_2,TM2,10` ratingProfiles := `*out,cgrates.org,data,*any,2012-01-01T00:00:00Z,RP_DATA1,` csvr := engine.NewStringCSVReader(ratingDb, acntDb, ',', "", timings, rates, destinationRates, ratingPlans, ratingProfiles, "", "", "", "", "", "", "") @@ -71,7 +75,51 @@ func TestLoadCsvTpDtChrg1(t *testing.T) { func TestGetDataCostDtChrg1(t *testing.T) { usedData := 20 usageDur := time.Duration(usedData) * time.Second - timeStart := time.Date(2014, 3, 4, 6, 0, 0, 0, time.UTC) + timeStart := time.Date(2014, 3, 4, 0, 0, 0, 0, time.Local) + cd := &engine.CallDescriptor{ + Direction: "*out", + Category: "data", + Tenant: "cgrates.org", + Subject: "12345", + Account: "12345", + TimeStart: timeStart, + TimeEnd: timeStart.Add(usageDur), + DurationIndex: usageDur, + TOR: utils.DATA, + } + if cc, err := cd.GetCost(); err != nil { + t.Error(err) + } else if cc.Cost != 0.004 { + t.Error("Wrong cost returned: ", cc.Cost) + } +} + +func TestGetDataCostSecondIntDtChrg1(t *testing.T) { + usedData := 20 + usageDur := time.Duration(usedData) * time.Second + timeStart := time.Date(2014, 3, 4, 1, 0, 0, 0, time.Local) + cd := &engine.CallDescriptor{ + Direction: "*out", + Category: "data", + Tenant: "cgrates.org", + Subject: "12345", + Account: "12345", + TimeStart: timeStart, + TimeEnd: timeStart.Add(usageDur), + DurationIndex: usageDur, + TOR: utils.DATA, + } + if cc, err := cd.GetCost(); err != nil { + t.Error(err) + } else if cc.Cost != 0.002 { + t.Error("Wrong cost returned: ", cc.Cost) + } +} + +func TestGetBetweenCostDtChrg1(t *testing.T) { + usedData := 20 + usageDur := time.Duration(usedData) * time.Second + timeStart := time.Date(2014, 3, 4, 0, 59, 50, 0, time.Local) cd := &engine.CallDescriptor{ Direction: "*out", Category: "data", diff --git a/mediator/mediator_local_test.go b/mediator/mediator_local_test.go index 0747c5002..e3776f4ef 100644 --- a/mediator/mediator_local_test.go +++ b/mediator/mediator_local_test.go @@ -51,6 +51,7 @@ README: var cfg *config.CGRConfig var cgrRpc *rpc.Client var cdrStor engine.CdrStorage +var httpClient *http.Client var testLocal = flag.Bool("local", false, "Perform the tests only on local test environment, not by default.") // This flag will be passed here via "go test -local" args var dataDir = flag.String("data_dir", "/usr/share/cgrates", "CGR data dir path here") @@ -117,6 +118,7 @@ func TestStartEngine(t *testing.T) { t.Fatal("Cannot start cgr-engine: ", err.Error()) } time.Sleep(time.Duration(*startDelay) * time.Millisecond) // Give time to rater to fire up + httpClient = new(http.Client) } // Connect rpc client @@ -135,7 +137,6 @@ func TestPostCdrs(t *testing.T) { if !*testLocal { return } - httpClient := new(http.Client) cdrForm1 := url.Values{utils.TOR: []string{utils.VOICE}, utils.ACCID: []string{"dsafdsaf"}, utils.CDRHOST: []string{"192.168.1.1"}, utils.REQTYPE: []string{"rated"}, utils.DIRECTION: []string{"*out"}, utils.TENANT: []string{"cgrates.org"}, utils.CATEGORY: []string{"call"}, utils.ACCOUNT: []string{"1001"}, utils.SUBJECT: []string{"1001"}, utils.DESTINATION: []string{"+4986517174963"}, @@ -241,6 +242,40 @@ func TestRateCdrs(t *testing.T) { } } +func TestMediatePseudoprepaid(t *testing.T) { + if !*testLocal { + return + } + var reply *engine.Account + attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1003", Direction: "*out"} + if err := cgrRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil { + t.Error("Got error on ApierV1.GetAccount: ", err.Error()) + } else if reply.BalanceMap[engine.CREDIT+attrs.Direction].GetTotalValue() != 11 { + t.Errorf("Calling ApierV1.GetBalance expected: 10.0, received: %f", reply.BalanceMap[engine.CREDIT+attrs.Direction].GetTotalValue()) + } + voiceCdr := &utils.StoredCdr{TOR: utils.VOICE, AccId: "dsafdsaf", CdrHost: "192.168.1.1", CdrSource: "test", ReqType: utils.PSEUDOPREPAID, Direction: utils.OUT, + Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "+4986517174963", + SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(5) * time.Second} + dataCdr := &utils.StoredCdr{TOR: utils.DATA, AccId: "6163508432", CdrHost: "192.168.1.1", CdrSource: "test", ReqType: utils.PSEUDOPREPAID, Direction: utils.OUT, + Tenant: "cgrates.org", Category: "data", Account: "1003", Subject: "1003", + SetupTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), AnswerTime: time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(10) * time.Second} + for _, cdrForm := range []url.Values{voiceCdr.AsHttpForm(), dataCdr.AsHttpForm()} { + cdrForm.Set(utils.CDRSOURCE, engine.TEST_SQL) + if _, err := httpClient.PostForm(fmt.Sprintf("http://%s/cgr", cfg.HTTPListen), cdrForm); err != nil { + t.Error(err.Error()) + } + } + time.Sleep(time.Duration(*startDelay) * time.Millisecond) // Give time for debits to happen + expectBalance := 5.998 + if err := cgrRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil { + t.Error("Got error on ApierV1.GetAccount: ", err.Error()) + } else if reply.BalanceMap[engine.CREDIT+attrs.Direction].GetTotalValue() != expectBalance { // 5 from voice, 0.002 from DATA + t.Errorf("Calling ApierV1.GetBalance expected: %f, received: %f", expectBalance, reply.BalanceMap[engine.CREDIT+attrs.Direction].GetTotalValue()) + } +} + // Simply kill the engine after we are done with tests within this file func TestStopEngine(t *testing.T) { if !*testLocal { diff --git a/utils/apitpdata.go b/utils/apitpdata.go index 4424b9e58..9e9108bbb 100644 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -277,6 +277,12 @@ func (self *TPAccountActions) KeyId() string { return fmt.Sprintf("%s:%s:%s", self.Direction, self.Tenant, self.Account) } +type AttrGetAccount struct { + Tenant string + Account string + Direction string +} + // Data used to do remote cache reloads via api type ApiReloadCache struct { DestinationIds []string diff --git a/utils/cgrcdr.go b/utils/cgrcdr.go index 72b69eca3..5007f599f 100644 --- a/utils/cgrcdr.go +++ b/utils/cgrcdr.go @@ -69,7 +69,7 @@ func (cgrCdr CgrCdr) AsStoredCdr() *StoredCdr { storCdr.Destination = cgrCdr[DESTINATION] storCdr.SetupTime, _ = ParseTimeDetectLayout(cgrCdr[SETUP_TIME]) // Not interested to process errors, should do them if necessary in a previous step storCdr.AnswerTime, _ = ParseTimeDetectLayout(cgrCdr[ANSWER_TIME]) - storCdr.Usage, _ = ParseDurationWithSecs(cgrCdr[USAGE]) + storCdr.Usage, _ = ParseDurationWithNanosecs(cgrCdr[USAGE]) storCdr.ExtraFields = cgrCdr.getExtraFields() storCdr.Cost = -1 return storCdr diff --git a/utils/cgrcdr_test.go b/utils/cgrcdr_test.go index 178a4262e..e50e6f31d 100644 --- a/utils/cgrcdr_test.go +++ b/utils/cgrcdr_test.go @@ -34,7 +34,7 @@ func TestCgrCdrInterfaces(t *testing.T) { func TestCgrCdrAsStoredCdr(t *testing.T) { cgrCdr := CgrCdr{TOR: VOICE, ACCID: "dsafdsaf", CDRHOST: "192.168.1.1", CDRSOURCE: "internal_test", REQTYPE: "rated", DIRECTION: "*out", TENANT: "cgrates.org", CATEGORY: "call", - ACCOUNT: "1001", SUBJECT: "1001", DESTINATION: "1002", SETUP_TIME: "2013-11-07T08:42:20Z", ANSWER_TIME: "2013-11-07T08:42:26Z", USAGE: "10", + ACCOUNT: "1001", SUBJECT: "1001", DESTINATION: "1002", SETUP_TIME: "2013-11-07T08:42:20Z", ANSWER_TIME: "2013-11-07T08:42:26Z", USAGE: "10000000000", "field_extr1": "val_extr1", "fieldextr2": "valextr2"} setupTime, _ := ParseTimeDetectLayout(cgrCdr["setup_time"]) expctRtCdr := &StoredCdr{CgrId: Sha1(cgrCdr["accid"], setupTime.String()), TOR: VOICE, AccId: cgrCdr["accid"], CdrHost: cgrCdr["cdrhost"], CdrSource: cgrCdr["cdrsource"], ReqType: cgrCdr["reqtype"],