From eb2e8f6876252d95e4d5fd7def9ef5fbee9778b8 Mon Sep 17 00:00:00 2001 From: DanB Date: Sun, 13 Dec 2015 17:28:55 +0100 Subject: [PATCH] Unified storage SetCdr and SetRatedCdr into SetCDR, engine/storage_cdrs_it_test should automate testing for the supported StoredDb drivers --- apier/v2/cdrs_mongo_local_test.go | 2 +- apier/v2/cdrs_mysql_local_test.go | 14 +- apier/v2/cdrs_psql_local_test.go | 2 +- data/conf/samples/storage/mysql/cgrates.json | 13 + .../samples/storage/postgres/cgrates.json | 13 + data/storage/mysql/create_cdrs_tables.sql | 7 +- data/storage/postgres/create_cdrs_tables.sql | 8 +- engine/action.go | 5 +- engine/actions_local_test.go | 7 +- engine/cdr.go | 35 +- engine/cdr_test.go | 2 +- engine/cdrs.go | 4 +- engine/models.go | 2 +- engine/storage_cdrs_it_test.go | 177 ++++ engine/storage_interface.go | 3 +- engine/storage_mongo_local_test.go | 967 ----------------- engine/storage_mongo_tp.go | 7 +- engine/storage_mysql_local_test.go | 976 ------------------ engine/storage_psql_local_test.go | 971 ----------------- engine/storage_sql.go | 118 +-- .../cdrs_replication_it_test.go | 32 +- local_test.sh | 12 +- utils/consts.go | 1 + 23 files changed, 324 insertions(+), 3054 deletions(-) create mode 100644 data/conf/samples/storage/mysql/cgrates.json create mode 100644 data/conf/samples/storage/postgres/cgrates.json create mode 100644 engine/storage_cdrs_it_test.go delete mode 100644 engine/storage_mongo_local_test.go delete mode 100644 engine/storage_mysql_local_test.go delete mode 100644 engine/storage_psql_local_test.go rename engine/cdrs_local_test.go => general_tests/cdrs_replication_it_test.go (84%) diff --git a/apier/v2/cdrs_mongo_local_test.go b/apier/v2/cdrs_mongo_local_test.go index 18576f84d..fee37b538 100644 --- a/apier/v2/cdrs_mongo_local_test.go +++ b/apier/v2/cdrs_mongo_local_test.go @@ -79,7 +79,7 @@ func TestV2CdrsMongoInjectUnratedCdr(t *testing.T) { SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, RunID: utils.DEFAULT_RUNID, Cost: 1.201} - if err := mysqlDb.SetCdr(strCdr1); err != nil { + if err := mysqlDb.SetCDR(strCdr1, false); err != nil { t.Error(err.Error()) } } diff --git a/apier/v2/cdrs_mysql_local_test.go b/apier/v2/cdrs_mysql_local_test.go index c895ab4a1..f087a8318 100644 --- a/apier/v2/cdrs_mysql_local_test.go +++ b/apier/v2/cdrs_mysql_local_test.go @@ -39,7 +39,7 @@ var cdrsCfgPath string var cdrsCfg *config.CGRConfig var cdrsRpc *rpc.Client -func TestV2CdrsMysqlInitConfig(t *testing.T) { +func TestV2CdrsMysqlAInitConfig(t *testing.T) { if !*testLocal { return } @@ -50,7 +50,7 @@ func TestV2CdrsMysqlInitConfig(t *testing.T) { } } -func TestV2CdrsMysqlInitDataDb(t *testing.T) { +func TestV2CdrsMysqAlInitDataDb(t *testing.T) { if !*testLocal { return } @@ -60,7 +60,7 @@ func TestV2CdrsMysqlInitDataDb(t *testing.T) { } // InitDb so we can rely on count -func TestV2CdrsMysqlInitCdrDb(t *testing.T) { +func TestV2CdrsMysqlAInitCdrDb(t *testing.T) { if !*testLocal { return } @@ -69,7 +69,7 @@ func TestV2CdrsMysqlInitCdrDb(t *testing.T) { } } -func TestV2CdrsMysqlInjectUnratedCdr(t *testing.T) { +func TestV2CdrsMysqlAInjectUnratedCdr(t *testing.T) { if !*testLocal { return } @@ -79,13 +79,13 @@ func TestV2CdrsMysqlInjectUnratedCdr(t *testing.T) { t.Error("Error on opening database connection: ", err) return } - strCdr1 := &engine.CDR{CGRID: utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String()), + strCdr1 := &engine.CDR{CGRID: utils.Sha1("bbb1", time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC).String()), RunID: utils.MetaRaw, TOR: utils.VOICE, OriginID: "bbb1", OriginHost: "192.168.1.1", Source: "UNKNOWN", RequestType: utils.META_RATED, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC), AnswerTime: time.Date(2015, 11, 21, 10, 47, 26, 0, time.UTC), Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 1.201} - if err := mysqlDb.SetCdr(strCdr1); err != nil { + Cost: 1.201} + if err := mysqlDb.SetCDR(strCdr1, false); err != nil { t.Error(err.Error()) } } diff --git a/apier/v2/cdrs_psql_local_test.go b/apier/v2/cdrs_psql_local_test.go index a916d3528..7e6c1d66c 100644 --- a/apier/v2/cdrs_psql_local_test.go +++ b/apier/v2/cdrs_psql_local_test.go @@ -82,7 +82,7 @@ func TestV2CdrsPsqlInjectUnratedCdr(t *testing.T) { SetupTime: time.Date(2015, 11, 21, 10, 47, 24, 0, time.UTC), AnswerTime: time.Date(2015, 11, 21, 10, 47, 26, 0, time.UTC), Usage: time.Duration(10) * time.Second, ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, RunID: utils.DEFAULT_RUNID, Cost: 1.201} - if err := psqlDb.SetCdr(strCdr1); err != nil { + if err := psqlDb.SetCDR(strCdr1, false); err != nil { t.Error(err.Error()) } } diff --git a/data/conf/samples/storage/mysql/cgrates.json b/data/conf/samples/storage/mysql/cgrates.json new file mode 100644 index 000000000..fd8b92330 --- /dev/null +++ b/data/conf/samples/storage/mysql/cgrates.json @@ -0,0 +1,13 @@ +{ +// CGRateS Configuration file used for testing mysql implementation + +"stor_db": { // database used to store offline tariff plans and CDRs + "db_type": "mysql", // stor database type to use: + "db_host": "127.0.0.1", // the host to connect to + "db_port": 3306, // the port to reach the stordb + "db_name": "cgrates", // stor database name + "db_user": "cgrates", // username to use when connecting to stordb + "db_passwd": "CGRateS.org", // password to use when connecting to stordb +}, + +} diff --git a/data/conf/samples/storage/postgres/cgrates.json b/data/conf/samples/storage/postgres/cgrates.json new file mode 100644 index 000000000..d1d700a9d --- /dev/null +++ b/data/conf/samples/storage/postgres/cgrates.json @@ -0,0 +1,13 @@ +{ +// CGRateS Configuration file used for testing mysql implementation + +"stor_db": { // database used to store offline tariff plans and CDRs + "db_type": "postgres", // stor database type to use: + "db_host": "127.0.0.1", // the host to connect to + "db_port": 5432, // the port to reach the stordb + "db_name": "cgrates", // stor database name + "db_user": "cgrates", // username to use when connecting to stordb + "db_passwd": "CGRateS.org", // password to use when connecting to stordb +}, + +} diff --git a/data/storage/mysql/create_cdrs_tables.sql b/data/storage/mysql/create_cdrs_tables.sql index bb2fe13d0..799d05edf 100644 --- a/data/storage/mysql/create_cdrs_tables.sql +++ b/data/storage/mysql/create_cdrs_tables.sql @@ -1,4 +1,3 @@ - -- -- Table structure for table `cdrs` -- @@ -28,13 +27,11 @@ CREATE TABLE cdrs ( extra_fields text NOT NULL, cost_source varchar(64) NOT NULL, cost DECIMAL(20,4) NOT NULL, - timespans text, + cost_details text, extra_info text, created_at TIMESTAMP, updated_at TIMESTAMP, deleted_at TIMESTAMP, PRIMARY KEY (id), - UNIQUE KEY cgrid (cgrid), - KEY answer_time_idx (answer_time), - KEY deleted_at_idx (deleted_at) + UNIQUE KEY cdrrun (cgrid, run_id) ); diff --git a/data/storage/postgres/create_cdrs_tables.sql b/data/storage/postgres/create_cdrs_tables.sql index b8ee5dd93..d76ab282b 100644 --- a/data/storage/postgres/create_cdrs_tables.sql +++ b/data/storage/postgres/create_cdrs_tables.sql @@ -24,15 +24,15 @@ CREATE TABLE cdrs ( usage NUMERIC(30,9) NOT NULL, supplier VARCHAR(128) NOT NULL, disconnect_cause VARCHAR(64) NOT NULL, - extra_fields jsonb NOT NULL, - cost NUMERIC(20,4) DEFAULT NULL, - timespans jsonb, + extra_fields jsonb, cost_source VARCHAR(64) NOT NULL, + cost NUMERIC(20,4) DEFAULT NULL, + cost_details jsonb, extra_info text, created_at TIMESTAMP, updated_at TIMESTAMP, deleted_at TIMESTAMP, - UNIQUE (cgrid) + UNIQUE (cgrid, run_id) ); ; DROP INDEX IF EXISTS deleted_at_cp_idx; diff --git a/engine/action.go b/engine/action.go index 11ee21af2..65c60f79f 100644 --- a/engine/action.go +++ b/engine/action.go @@ -253,10 +253,7 @@ func cdrLogAction(acc *Account, sq *StatsQueueTriggered, a *Action, acs Actions) if cdrStorage == nil { // Only save if the cdrStorage is defined continue } - if err := cdrStorage.SetCdr(cdr); err != nil { - return err - } - if err := cdrStorage.SetRatedCdr(cdr); err != nil { + if err := cdrStorage.SetCDR(cdr, true); err != nil { return err } // FixMe diff --git a/engine/actions_local_test.go b/engine/actions_local_test.go index 3d66f9717..936cc4e0a 100644 --- a/engine/actions_local_test.go +++ b/engine/actions_local_test.go @@ -19,6 +19,7 @@ along with this program. If not, see package engine import ( + "flag" "net/rpc" "net/rpc/jsonrpc" "path" @@ -33,6 +34,8 @@ var actsLclCfg *config.CGRConfig var actsLclRpc *rpc.Client var actsLclCfgPath = path.Join(*dataDir, "conf", "samples", "actions") +var waitRater = flag.Int("wait_rater", 100, "Number of miliseconds to wait for rater to start and cache") + func TestActionsLocalInitCfg(t *testing.T) { if !*testLocal { return @@ -61,7 +64,7 @@ func TestActionsLocalStartEngine(t *testing.T) { if !*testLocal { return } - if _, err := StartEngine(actsLclCfgPath, waitRater); err != nil { + if _, err := StartEngine(actsLclCfgPath, *waitRater); err != nil { t.Fatal(err) } } @@ -129,7 +132,7 @@ func TestActionsLocalStopCgrEngine(t *testing.T) { if !*testLocal { return } - if err := KillEngine(waitRater); err != nil { + if err := KillEngine(*waitRater); err != nil { t.Error(err) } } diff --git a/engine/cdr.go b/engine/cdr.go index cf9d32fa1..5fdd28d8d 100644 --- a/engine/cdr.go +++ b/engine/cdr.go @@ -33,10 +33,10 @@ import ( func NewCDRFromExternalCDR(extCdr *ExternalCDR, timezone string) (*CDR, error) { var err error - cdr := &CDR{CGRID: extCdr.CGRID, OrderID: extCdr.OrderID, TOR: extCdr.TOR, OriginID: extCdr.OriginID, OriginHost: extCdr.OriginHost, Source: extCdr.Source, - RequestType: extCdr.RequestType, Direction: extCdr.Direction, Tenant: extCdr.Tenant, Category: extCdr.Category, Account: extCdr.Account, Subject: extCdr.Subject, - Destination: extCdr.Destination, Supplier: extCdr.Supplier, DisconnectCause: extCdr.DisconnectCause, - RunID: extCdr.RunID, Cost: extCdr.Cost, Rated: extCdr.Rated} + cdr := &CDR{CGRID: extCdr.CGRID, RunID: extCdr.RunID, OrderID: extCdr.OrderID, TOR: extCdr.TOR, OriginID: extCdr.OriginID, OriginHost: extCdr.OriginHost, + Source: extCdr.Source, RequestType: extCdr.RequestType, Direction: extCdr.Direction, Tenant: extCdr.Tenant, Category: extCdr.Category, + Account: extCdr.Account, Subject: extCdr.Subject, Destination: extCdr.Destination, Supplier: extCdr.Supplier, + DisconnectCause: extCdr.DisconnectCause, CostSource: extCdr.CostSource, Cost: extCdr.Cost, Rated: extCdr.Rated} if cdr.SetupTime, err = utils.ParseTimeDetectLayout(extCdr.SetupTime, timezone); err != nil { return nil, err } @@ -93,16 +93,14 @@ type CDR struct { Supplier string // Supplier information when available DisconnectCause string // Disconnect cause of the event ExtraFields map[string]string // Extra fields to be stored in CDR + CostSource string // The source of this cost Cost float64 - ExtraInfo string // Container for extra information related to this CDR, eg: populated with error reason in case of error on calculation CostDetails *CallCost // Attach the cost details to CDR when possible + ExtraInfo string // Container for extra information related to this CDR, eg: populated with error reason in case of error on calculation Rated bool // Mark the CDR as rated so we do not process it during rating } func (cdr *CDR) CostDetailsJson() string { - if cdr.CostDetails == nil { - return "" - } mrshled, _ := json.Marshal(cdr.CostDetails) return string(mrshled) } @@ -494,11 +492,12 @@ func (cdr *CDR) ForkCdr(runId string, RequestTypeFld, directionFld, tenantFld, c func (cdr *CDR) AsExternalCDR() *ExternalCDR { return &ExternalCDR{CGRID: cdr.CGRID, + RunID: cdr.RunID, OrderID: cdr.OrderID, - TOR: cdr.TOR, - OriginID: cdr.OriginID, OriginHost: cdr.OriginHost, Source: cdr.Source, + OriginID: cdr.OriginID, + TOR: cdr.TOR, RequestType: cdr.RequestType, Direction: cdr.Direction, Tenant: cdr.Tenant, @@ -507,15 +506,17 @@ func (cdr *CDR) AsExternalCDR() *ExternalCDR { Subject: cdr.Subject, Destination: cdr.Destination, SetupTime: cdr.SetupTime.Format(time.RFC3339), + PDD: cdr.FieldAsString(&utils.RSRField{Id: utils.PDD}), AnswerTime: cdr.AnswerTime.Format(time.RFC3339), Usage: cdr.FormatUsage(utils.SECONDS), - PDD: cdr.FieldAsString(&utils.RSRField{Id: utils.PDD}), Supplier: cdr.Supplier, DisconnectCause: cdr.DisconnectCause, ExtraFields: cdr.ExtraFields, - RunID: cdr.RunID, + CostSource: cdr.CostSource, Cost: cdr.Cost, CostDetails: cdr.CostDetailsJson(), + ExtraInfo: cdr.ExtraInfo, + Rated: cdr.Rated, } } @@ -699,11 +700,12 @@ func (cdr *CDR) String() string { type ExternalCDR struct { CGRID string + RunID string OrderID int64 - TOR string - OriginID string OriginHost string Source string + OriginID string + TOR string RequestType string Direction string Tenant string @@ -712,15 +714,16 @@ type ExternalCDR struct { Subject string Destination string SetupTime string + PDD string AnswerTime string Usage string - PDD string Supplier string DisconnectCause string ExtraFields map[string]string - RunID string + CostSource string Cost float64 CostDetails string + ExtraInfo string Rated bool // Mark the CDR as rated so we do not process it during mediation } diff --git a/engine/cdr_test.go b/engine/cdr_test.go index 52766bc0c..3c92ae000 100644 --- a/engine/cdr_test.go +++ b/engine/cdr_test.go @@ -474,7 +474,7 @@ func TestCDRAsExternalCDR(t *testing.T) { Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: "2013-11-07T08:42:20Z", AnswerTime: "2013-11-07T08:42:26Z", RunID: utils.DEFAULT_RUNID, Usage: "0.00000001", PDD: "7", Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01} + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, Cost: 1.01, CostDetails: "null"} if cdrOut := storCdr.AsExternalCDR(); !reflect.DeepEqual(expectOutCdr, cdrOut) { t.Errorf("Expected: %+v, received: %+v", expectOutCdr, cdrOut) } diff --git a/engine/cdrs.go b/engine/cdrs.go index 1f0cf9d8f..f14a0e178 100644 --- a/engine/cdrs.go +++ b/engine/cdrs.go @@ -201,7 +201,7 @@ func (self *CdrServer) processCdr(cdr *CDR) (err error) { return err } if self.cgrCfg.CDRSStoreCdrs { // Store RawCDRs, this we do sync so we can reply with the status - if err := self.cdrDb.SetCdr(cdr); err != nil { // Only original CDR stored in primary table, no derived + if err := self.cdrDb.SetCDR(cdr, false); err != nil { // Only original CDR stored in primary table, no derived utils.Logger.Err(fmt.Sprintf(" Storing primary CDR %+v, got error: %s", cdr, err.Error())) return err // Error is propagated back and we don't continue processing the CDR if we cannot store it } @@ -257,7 +257,7 @@ func (self *CdrServer) rateStoreStatsReplicate(cdr *CDR) error { } if self.cgrCfg.CDRSStoreCdrs { // Store CDRs // Store RatedCDR - if err := self.cdrDb.SetRatedCdr(cdr); err != nil { + if err := self.cdrDb.SetCDR(cdr, true); err != nil { utils.Logger.Err(fmt.Sprintf(" Storing rated CDR %+v, got error: %s", cdr, err.Error())) } // Store CostDetails diff --git a/engine/models.go b/engine/models.go index f992d7b36..8235ab0e3 100644 --- a/engine/models.go +++ b/engine/models.go @@ -415,7 +415,7 @@ type TBLCDRs struct { DisconnectCause string ExtraFields string Cost float64 - Timespans string + CostDetails string CostSource string ExtraInfo string CreatedAt time.Time diff --git a/engine/storage_cdrs_it_test.go b/engine/storage_cdrs_it_test.go new file mode 100644 index 000000000..466ea2812 --- /dev/null +++ b/engine/storage_cdrs_it_test.go @@ -0,0 +1,177 @@ +/* +Rating system designed to be used in VoIP Carriers World +Copyright (C) 2012-2015 ITsysCOM + +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 engine + +import ( + "flag" + "fmt" + "path" + //"reflect" + "testing" + "time" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/utils" +) + +var testIntegration = flag.Bool("integration", false, "Perform the tests in integration mode, not by default.") // This flag will be passed here via "go test -local" args + +func TestITCDRsMySQL(t *testing.T) { + if !*testIntegration { + return + } + cfg, err := config.NewCGRConfigFromFolder(path.Join(*dataDir, "conf", "samples", "storage", "mysql")) + if err != nil { + t.Error(err) + } + if err := InitStorDb(cfg); err != nil { + t.Error(err) + } + mysqlDb, err := NewMySQLStorage(cfg.StorDBHost, cfg.StorDBPort, cfg.StorDBName, cfg.StorDBUser, cfg.StorDBPass, + cfg.StorDBMaxOpenConns, cfg.StorDBMaxIdleConns) + if err != nil { + t.Error("Error on opening database connection: ", err) + } + if err := testSetCDR(mysqlDb); err != nil { + t.Error(err) + } +} + +func TestITCDRsPSQL(t *testing.T) { + if !*testIntegration { + return + } + cfg, err := config.NewCGRConfigFromFolder(path.Join(*dataDir, "conf", "samples", "storage", "postgres")) + if err != nil { + t.Error(err) + } + if err := InitStorDb(cfg); err != nil { + t.Error(err) + } + psqlDb, err := NewPostgresStorage(cfg.StorDBHost, cfg.StorDBPort, cfg.StorDBName, cfg.StorDBUser, cfg.StorDBPass, + cfg.StorDBMaxOpenConns, cfg.StorDBMaxIdleConns) + if err != nil { + t.Error("Error on opening database connection: ", err) + } + if err := testSetCDR(psqlDb); err != nil { + t.Error(err) + } +} + +// helper function to populate CDRs and check if they were stored in storDb +func testSetCDR(cdrStorage CdrStorage) error { + rawCDR := &CDR{ + CGRID: utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()), + RunID: utils.MetaRaw, + OriginHost: "127.0.0.1", + Source: "testSetCDRs", + OriginID: "testevent1", + TOR: utils.VOICE, + RequestType: utils.META_PREPAID, + Direction: utils.OUT, + Tenant: "cgrates.org", + Category: "call", + Account: "1004", + Subject: "1004", + Destination: "1007", + SetupTime: time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC), + PDD: time.Duration(20) * time.Millisecond, + AnswerTime: time.Date(2015, 12, 12, 14, 52, 20, 0, time.UTC), + Usage: time.Duration(35) * time.Second, + Supplier: "SUPPLIER1", + DisconnectCause: "NORMAL_DISCONNECT", + ExtraFields: map[string]string{"ExtraHeader1": "ExtraVal1", "ExtraHeader2": "ExtraVal2"}, + Cost: -1, + } + if err := cdrStorage.SetCDR(rawCDR, false); err != nil { + return fmt.Errorf("rawCDR: %+v, SetCDR err: %s", rawCDR, err.Error()) + } + if cdrs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{rawCDR.CGRID}, RunIDs: []string{utils.MetaRaw}}); err != nil { + return fmt.Errorf("rawCDR: %+v, GetCDRs err: %s", rawCDR, err.Error()) + } else if len(cdrs) != 1 { + return fmt.Errorf("rawCDR %+v, Unexpected number of CDRs returned: %d", rawCDR, len(cdrs)) + } + ratedCDR := &CDR{ + CGRID: utils.Sha1("testevent1", time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC).String()), + RunID: utils.META_DEFAULT, + OriginHost: "127.0.0.1", + Source: "testSetCDRs", + OriginID: "testevent1", + TOR: utils.VOICE, + RequestType: utils.META_PREPAID, + Direction: utils.OUT, + Tenant: "cgrates.org", + Category: "call", + Account: "1004", + Subject: "1004", + Destination: "1007", + SetupTime: time.Date(2015, 12, 12, 14, 52, 0, 0, time.UTC), + PDD: time.Duration(20) * time.Millisecond, + AnswerTime: time.Date(2015, 12, 12, 14, 52, 20, 0, time.UTC), + Usage: time.Duration(35) * time.Second, + Supplier: "SUPPLIER1", + DisconnectCause: "NORMAL_DISCONNECT", + ExtraFields: map[string]string{"ExtraHeader1": "ExtraVal1", "ExtraHeader2": "ExtraVal2"}, + CostSource: "testSetCDRs", + Cost: 0.17, + } + if err := cdrStorage.SetCDR(ratedCDR, false); err != nil { + return fmt.Errorf("ratedCDR: %+v, SetCDR err: %s", ratedCDR, err.Error()) + } + if cdrs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{ratedCDR.CGRID}, RunIDs: []string{ratedCDR.RunID}}); err != nil { + return fmt.Errorf("ratedCDR: %+v, GetCDRs err: %s", ratedCDR, err.Error()) + } else if len(cdrs) != 1 { + return fmt.Errorf("ratedCDR %+v, Unexpected number of CDRs returned: %d", ratedCDR, len(cdrs)) + } else { + if cdrs[0].RunID != ratedCDR.RunID { + return fmt.Errorf("Unexpected ratedCDR received: %+v", cdrs[0]) + } + if cdrs[0].RequestType != ratedCDR.RequestType { + return fmt.Errorf("Unexpected ratedCDR received: %+v", cdrs[0]) + } + if cdrs[0].Cost != ratedCDR.Cost { + return fmt.Errorf("Unexpected ratedCDR received: %+v", cdrs[0]) + } + } + // Make sure duplicating does not work + if err := cdrStorage.SetCDR(ratedCDR, false); err == nil { + return fmt.Errorf("Duplicating ratedCDR: %+v works", ratedCDR) + } + ratedCDR.RequestType = utils.META_RATED + ratedCDR.Cost = 0.34 + if err := cdrStorage.SetCDR(ratedCDR, true); err != nil { + return fmt.Errorf("Rerating ratedCDR: %+v, SetCDR err: %s", ratedCDR, err.Error()) + } + if cdrs, _, err := cdrStorage.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{ratedCDR.CGRID}, RunIDs: []string{ratedCDR.RunID}}); err != nil { + return fmt.Errorf("Rerating ratedCDR: %+v, GetCDRs err: %s", ratedCDR, err.Error()) + } else if len(cdrs) != 1 { + return fmt.Errorf("Rerating ratedCDR %+v, Unexpected number of CDRs returned: %d", ratedCDR, len(cdrs)) + } else { + if cdrs[0].RunID != ratedCDR.RunID { + return fmt.Errorf("Unexpected ratedCDR received after rerating: %+v", cdrs[0]) + } + if cdrs[0].RequestType != ratedCDR.RequestType { + return fmt.Errorf("Unexpected ratedCDR received after rerating: %+v", cdrs[0]) + } + if cdrs[0].Cost != ratedCDR.Cost { + return fmt.Errorf("Unexpected ratedCDR received after rerating: %+v", cdrs[0]) + } + } + return nil +} diff --git a/engine/storage_interface.go b/engine/storage_interface.go index a2120c438..73bf2e988 100644 --- a/engine/storage_interface.go +++ b/engine/storage_interface.go @@ -94,8 +94,7 @@ type AccountingStorage interface { type CdrStorage interface { Storage - SetCdr(*CDR) error - SetRatedCdr(*CDR) error + SetCDR(*CDR, bool) error LogCallCost(cgrid, source, runid string, cc *CallCost) error GetCallCostLog(cgrid, source, runid string) (*CallCost, error) GetCDRs(*utils.CDRsFilter) ([]*CDR, int64, error) diff --git a/engine/storage_mongo_local_test.go b/engine/storage_mongo_local_test.go deleted file mode 100644 index 06bc1c543..000000000 --- a/engine/storage_mongo_local_test.go +++ /dev/null @@ -1,967 +0,0 @@ -/* -Rating system designed to be used in VoIP Carriers World -Copyright (C) 2012-2015 ITsysCOM - -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 engine - -import ( - "reflect" - "testing" - "time" - - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/utils" -) - -var mongoDb *MongoStorage - -func TestMongoCreateTables(t *testing.T) { - if !*testLocal { - return - } - cgrConfig, _ := config.NewDefaultCGRConfig() - var err error - if mongoDb, err = NewMongoStorage("localhost", "27017", cgrConfig.StorDBName, cgrConfig.StorDBUser, cgrConfig.StorDBPass); err != nil { - t.Error("Error on opening database connection: ", err) - } -} - -func TestMongoSetGetTPTiming(t *testing.T) { - if !*testLocal { - return - } - tm := TpTiming{Tpid: utils.TEST_SQL, Tag: "ALWAYS", Time: "00:00:00"} - if err := mongoDb.SetTpTimings([]TpTiming{tm}); err != nil { - t.Error(err.Error()) - } - if tmgs, err := mongoDb.GetTpTimings(utils.TEST_SQL, tm.Tag); err != nil { - t.Error(err.Error()) - } else if !modelEqual(tm, tmgs[0]) { - t.Errorf("Expecting: %+v, received: %+v", tm, tmgs[0]) - } - // Update - tm.Time = "00:00:01" - if err := mongoDb.SetTpTimings([]TpTiming{tm}); err != nil { - t.Error(err.Error()) - } - if tmgs, err := mongoDb.GetTpTimings(utils.TEST_SQL, tm.Tag); err != nil { - t.Error(err.Error()) - } else if !modelEqual(tm, tmgs[0]) { - t.Errorf("Expecting: %+v, received: %+v", tm, tmgs[0]) - } -} - -func TestMongoSetGetTPDestination(t *testing.T) { - if !*testLocal { - return - } - dst := []TpDestination{ - TpDestination{Tpid: utils.TEST_SQL, Tag: utils.TEST_SQL, Prefix: "+49"}, - TpDestination{Tpid: utils.TEST_SQL, Tag: utils.TEST_SQL, Prefix: "+49151"}, - TpDestination{Tpid: utils.TEST_SQL, Tag: utils.TEST_SQL, Prefix: "+49176"}, - } - if err := mongoDb.SetTpDestinations(dst); err != nil { - t.Error(err.Error()) - } - storData, err := mongoDb.GetTpDestinations(utils.TEST_SQL, utils.TEST_SQL) - dsts, err := TpDestinations(storData).GetDestinations() - expected := &Destination{Id: utils.TEST_SQL, Prefixes: []string{"+49", "+49151", "+49176"}} - if err != nil { - t.Error(err.Error()) - } else if !modelEqual(*expected, *dsts[utils.TEST_SQL]) { - t.Errorf("Expecting: %+v, received: %+v", expected, dsts[utils.TEST_SQL]) - } -} - -func TestMongoSetGetTPRates(t *testing.T) { - if !*testLocal { - return - } - RT_ID := "RT_1" - rtSlots := []*utils.RateSlot{ - &utils.RateSlot{ConnectFee: 0.02, Rate: 0.01, RateUnit: "60s", RateIncrement: "60s", GroupIntervalStart: "0s"}, - &utils.RateSlot{ConnectFee: 0.00, Rate: 0.005, RateUnit: "60s", RateIncrement: "1s", GroupIntervalStart: "60s"}, - } - for _, rs := range rtSlots { - rs.SetDurations() - } - rates := &utils.TPRate{ - TPid: utils.TEST_SQL, - RateId: RT_ID, - RateSlots: rtSlots, - } - mRates := APItoModelRate(rates) - if err := mongoDb.SetTpRates(mRates); err != nil { - t.Error(err.Error()) - } - if rts, err := mongoDb.GetTpRates(utils.TEST_SQL, RT_ID); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mRates[0], rts[0]) { - t.Errorf("Expecting: %+v, received: %+v", mRates, rts) - } -} - -func TestMongoSetGetTPDestinationRates(t *testing.T) { - if !*testLocal { - return - } - DR_ID := "DR_1" - dr := &utils.DestinationRate{DestinationId: "DST_1", RateId: "RT_1", RoundingMethod: "*up", RoundingDecimals: 4} - - eDrs := &utils.TPDestinationRate{TPid: utils.TEST_SQL, DestinationRateId: DR_ID, DestinationRates: []*utils.DestinationRate{dr}} - mdrs := APItoModelDestinationRate(eDrs) - if err := mongoDb.SetTpDestinationRates(mdrs); err != nil { - t.Error(err.Error()) - } - if drs, err := mongoDb.GetTpDestinationRates(utils.TEST_SQL, DR_ID, nil); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mdrs[0], drs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mdrs, drs) - } -} - -func TestMongoSetGetTPRatingPlans(t *testing.T) { - if !*testLocal { - return - } - RP_ID := "RP_1" - rbBinding := &utils.TPRatingPlanBinding{DestinationRatesId: "DR_1", TimingId: "TM_1", Weight: 10.0} - rp := &utils.TPRatingPlan{ - TPid: utils.TEST_SQL, - RatingPlanId: RP_ID, - RatingPlanBindings: []*utils.TPRatingPlanBinding{rbBinding}, - } - mrp := APItoModelRatingPlan(rp) - if err := mongoDb.SetTpRatingPlans(mrp); err != nil { - t.Error(err.Error()) - } - if drps, err := mongoDb.GetTpRatingPlans(utils.TEST_SQL, RP_ID, nil); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mrp[0], drps[0]) { - t.Errorf("Expecting: %+v, received: %+v", mrp, drps) - } -} - -func TestMongoSetGetTPRatingProfiles(t *testing.T) { - if !*testLocal { - return - } - ras := []*utils.TPRatingActivation{&utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId: "RP_1"}} - rp := &utils.TPRatingProfile{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Category: "call", Direction: "*out", Subject: "*any", RatingPlanActivations: ras} - mrp := APItoModelRatingProfile(rp) - if err := mongoDb.SetTpRatingProfiles(mrp); err != nil { - t.Error(err.Error()) - } - if rps, err := mongoDb.GetTpRatingProfiles(&mrp[0]); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mrp[0], rps[0]) { - t.Errorf("Expecting: %+v, received: %+v", mrp, rps) - } - -} - -func TestMongoSetGetTPSharedGroups(t *testing.T) { - if !*testLocal { - return - } - SG_ID := "SG_1" - tpSgs := &utils.TPSharedGroups{ - TPid: utils.TEST_SQL, - SharedGroupsId: SG_ID, - SharedGroups: []*utils.TPSharedGroup{ - &utils.TPSharedGroup{Account: "dan", Strategy: "*lowest_first", RatingSubject: "lowest_rates"}, - }, - } - mSgs := APItoModelSharedGroup(tpSgs) - if err := mongoDb.SetTpSharedGroups(mSgs); err != nil { - t.Error(err.Error()) - } - if sgs, err := mongoDb.GetTpSharedGroups(utils.TEST_SQL, SG_ID); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mSgs[0], sgs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mSgs, sgs) - } -} - -func TestMongoSetGetTPcdrstats(t *testing.T) { - if !*testLocal { - return - } - CS_ID := "cdrsTATS_1" - setCS := &utils.TPCdrStats{ - TPid: utils.TEST_SQL, - CdrStatsId: CS_ID, - CdrStats: []*utils.TPCdrStat{ - &utils.TPCdrStat{QueueLength: "10", TimeWindow: "10m", Metrics: "ASR", Tenants: "cgrates.org", Categories: "call"}, - }, - } - mcs := APItoModelCdrStat(setCS) - if err := mongoDb.SetTpCdrStats(mcs); err != nil { - t.Error(err.Error()) - } - if cs, err := mongoDb.GetTpCdrStats(utils.TEST_SQL, CS_ID); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mcs[0], cs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mcs, cs) - } -} - -func TestMongoSetGetTPDerivedChargers(t *testing.T) { - if !*testLocal { - return - } - dc := &utils.TPDerivedCharger{RunId: utils.DEFAULT_RUNID, ReqTypeField: "^" + utils.META_PREPAID, AccountField: "^rif", SubjectField: "^rif", - UsageField: "cgr_duration", SupplierField: "^supplier1"} - dcs := &utils.TPDerivedChargers{TPid: utils.TEST_SQL, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dan", DerivedChargers: []*utils.TPDerivedCharger{dc}} - - mdcs := APItoModelDerivedCharger(dcs) - if err := mongoDb.SetTpDerivedChargers(mdcs); err != nil { - t.Error(err.Error()) - } - if rDCs, err := mongoDb.GetTpDerivedChargers(&mdcs[0]); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mdcs[0], rDCs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mdcs, rDCs) - } -} - -func TestMongoSetGetTPActions(t *testing.T) { - if !*testLocal { - return - } - ACTS_ID := "PREPAID_10" - acts := []*utils.TPAction{ - &utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Directions: "*out", Units: 10, ExpiryTime: "*unlimited", - DestinationIds: "*any", BalanceWeight: 10, Weight: 10}} - tpActions := &utils.TPActions{TPid: utils.TEST_SQL, ActionsId: ACTS_ID, Actions: acts} - mas := APItoModelAction(tpActions) - if err := mongoDb.SetTpActions(mas); err != nil { - t.Error(err.Error()) - } - if rTpActs, err := mongoDb.GetTpActions(utils.TEST_SQL, ACTS_ID); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mas[0], rTpActs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mas, rTpActs) - } -} - -func TestMongoTPActionTimings(t *testing.T) { - if !*testLocal { - return - } - AP_ID := "AP_1" - ap := &utils.TPActionPlan{ - TPid: utils.TEST_SQL, - ActionPlanId: AP_ID, - ActionPlan: []*utils.TPActionTiming{&utils.TPActionTiming{ActionsId: "ACTS_1", TimingId: "TM_1", Weight: 10.0}}, - } - maps := APItoModelActionPlan(ap) - if err := mongoDb.SetTpActionPlans(maps); err != nil { - t.Error(err.Error()) - } - if rAP, err := mongoDb.GetTpActionPlans(utils.TEST_SQL, AP_ID); err != nil { - t.Error(err.Error()) - } else if !modelEqual(maps[0], rAP[0]) { - t.Errorf("Expecting: %+v, received: %+v", maps, rAP) - } -} - -func TestMongoSetGetTPActionTriggers(t *testing.T) { - if !*testLocal { - return - } - atrg := &utils.TPActionTrigger{ - Id: "MY_FIRST_ATGR", - BalanceType: "*monetary", - BalanceDirections: "*out", - ThresholdType: "*min_balance", - ThresholdValue: 2.0, - Recurrent: true, - BalanceDestinationIds: "*any", - Weight: 10.0, - ActionsId: "LOG_BALANCE", - } - atrgs := &utils.TPActionTriggers{ - TPid: utils.TEST_SQL, - ActionTriggersId: utils.TEST_SQL, - ActionTriggers: []*utils.TPActionTrigger{atrg}, - } - matrg := APItoModelActionTrigger(atrgs) - if err := mongoDb.SetTpActionTriggers(matrg); err != nil { - t.Error("Unexpected error: ", err.Error()) - } - if rcvMpAtrgs, err := mongoDb.GetTpActionTriggers(utils.TEST_SQL, utils.TEST_SQL); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if !modelEqual(matrg[0], rcvMpAtrgs[0]) { - t.Errorf("Expecting: %v, received: %v", matrg, rcvMpAtrgs) - } -} - -func TestMongoSetGetTpAccountActions(t *testing.T) { - if !*testLocal { - return - } - aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"} - maa := APItoModelAccountAction(aa) - if err := mongoDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil { - t.Error(err.Error()) - } - if aas, err := mongoDb.GetTpAccountActions(maa); err != nil { - t.Error(err.Error()) - } else if !modelEqual(*maa, aas[0]) { - t.Errorf("Expecting: %+v, received: %+v", maa, aas) - } -} - -func TestMongoGetTPIds(t *testing.T) { - if !*testLocal { - return - } - eTPIds := []string{utils.TEST_SQL} - if tpIds, err := mongoDb.GetTpIds(); err != nil { - t.Error(err.Error()) - } else if !reflect.DeepEqual(eTPIds, tpIds) { - t.Errorf("Expecting: %+v, received: %+v", eTPIds, tpIds) - } -} - -func TestMongoRemoveTPData(t *testing.T) { - if !*testLocal { - return - } - // Create Timings - tm := &utils.ApierTPTiming{TPid: utils.TEST_SQL, TimingId: "ALWAYS", Time: "00:00:00"} - tms := APItoModelTiming(tm) - if err := mongoDb.SetTpTimings([]TpTiming{*tms}); err != nil { - t.Error(err.Error()) - } - if tmgs, err := mongoDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil { - t.Error(err.Error()) - } else if len(tmgs) == 0 { - t.Error("Could not store TPTiming") - } - // Remove Timings - if err := mongoDb.RemTpData(utils.TBL_TP_TIMINGS, utils.TEST_SQL, map[string]string{"tag": tm.TimingId}); err != nil { - t.Error(err.Error()) - } - if tmgs, err := mongoDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil { - t.Error(err) - } else if len(tmgs) != 0 { - t.Errorf("Timings should be empty, got instead: %+v", tmgs) - } - // Create RatingProfile - ras := []*utils.TPRatingActivation{&utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId: "RETAIL1"}} - rp := &utils.TPRatingProfile{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Category: "call", Direction: "*out", Subject: "*any", RatingPlanActivations: ras} - mrp := APItoModelRatingProfile(rp) - if err := mongoDb.SetTpRatingProfiles(mrp); err != nil { - t.Error(err.Error()) - } - if rps, err := mongoDb.GetTpRatingProfiles(&mrp[0]); err != nil { - t.Error(err.Error()) - } else if len(rps) == 0 { - t.Error("Could not store TPRatingProfile") - } - // Remove RatingProfile - if err := mongoDb.RemTpData(utils.TBL_TP_RATE_PROFILES, rp.TPid, map[string]string{"loadid": rp.LoadId, "direction": rp.Direction, "tenant": rp.Tenant, "category": rp.Category, "subject": rp.Subject}); err != nil { - t.Error(err.Error()) - } - if rps, err := mongoDb.GetTpRatingProfiles(&mrp[0]); err != nil { - t.Error(err) - } else if len(rps) != 0 { - t.Errorf("RatingProfiles different than 0: %+v", rps) - } - // Create AccountActions - aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001", ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"} - maa := APItoModelAccountAction(aa) - if err := mongoDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil { - t.Error(err.Error()) - } - if aas, err := mongoDb.GetTpAccountActions(maa); err != nil { - t.Error(err.Error()) - } else if len(aas) == 0 { - t.Error("Could not create TPAccountActions") - } - // Remove AccountActions - if err := mongoDb.RemTpData(utils.TBL_TP_ACCOUNT_ACTIONS, aa.TPid, map[string]string{"loadid": aa.LoadId, "tenant": aa.Tenant, "account": aa.Account}); err != nil { - t.Error(err.Error()) - } - if aas, err := mongoDb.GetTpAccountActions(maa); err != nil { - t.Error(err) - } else if len(aas) != 0 { - t.Errorf("Non empty account actions: %+v", aas) - } - // Create again so we can test complete TP removal - if err := mongoDb.SetTpTimings([]TpTiming{*tms}); err != nil { - t.Error(err.Error()) - } - if tmgs, err := mongoDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil { - t.Error(err.Error()) - } else if len(tmgs) == 0 { - t.Error("Could not store TPTiming") - } - // Create RatingProfile - if err := mongoDb.SetTpRatingProfiles(mrp); err != nil { - t.Error(err.Error()) - } - if rps, err := mongoDb.GetTpRatingProfiles(&mrp[0]); err != nil { - t.Error(err.Error()) - } else if len(rps) == 0 { - t.Error("Could not store TPRatingProfile") - } - // Create AccountActions - if err := mongoDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil { - t.Error(err.Error()) - } - if aas, err := mongoDb.GetTpAccountActions(maa); err != nil { - t.Error(err.Error()) - } else if len(aas) == 0 { - t.Error("Could not create TPAccountActions") - } - // Remove TariffPlan completely - if err := mongoDb.RemTpData("", utils.TEST_SQL, nil); err != nil { - t.Error(err.Error()) - } - // Make sure we have removed it - if tms, err := mongoDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil { - t.Error(err) - } else if len(tms) != 0 { - t.Errorf("Non empty timings: %+v", tms) - } - if rpfs, err := mongoDb.GetTpRatingProfiles(&mrp[0]); err != nil { - t.Error(err) - } else if len(rpfs) != 0 { - t.Errorf("Non empty rpfs: %+v", rpfs) - } - if aas, err := mongoDb.GetTpAccountActions(maa); err != nil { - t.Error(err) - } else if len(aas) != 0 { - t.Errorf("Non empty account actions: %+v", aas) - } -} - -func TestMongoSetCdr(t *testing.T) { - if !*testLocal { - return - } - cgrCdr1 := &CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa1", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_RATED, - utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", - utils.CATEGORY: "call", utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "1002", utils.SETUP_TIME: "2013-11-08T08:42:20Z", - utils.ANSWER_TIME: "2013-11-08T08:42:26Z", utils.USAGE: "10s", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", - "field_extr1": "val_extr1", "fieldextr2": "valextr2", utils.CDRSOURCE: utils.TEST_SQL} - - cgrCdr2 := &CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa2", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_PREPAID, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", - utils.CATEGORY: "call", utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "1002", utils.SETUP_TIME: "2013-11-08T08:42:22Z", - utils.ANSWER_TIME: "2013-11-08T08:42:26Z", utils.USAGE: "20", utils.PDD: "7s", utils.SUPPLIER: "SUPPL1", - "field_extr1": "val_extr1", "fieldextr2": "valextr2", "Source": utils.TEST_SQL} - - cgrCdr3 := &CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa3", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_RATED, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", - utils.CATEGORY: "premium_call", utils.ACCOUNT: "1002", utils.SUBJECT: "1002", utils.DESTINATION: "1001", utils.SETUP_TIME: "2013-11-07T08:42:24Z", - utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "60s", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", - "field_extr1": "val_extr1", "fieldextr2": "valextr2", "Source": utils.TEST_SQL} - - cgrCdr4 := &CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa4", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: utils.META_PSEUDOPREPAID, utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", - utils.CATEGORY: "call", utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "+4986517174964", utils.SETUP_TIME: "2013-11-07T08:42:21Z", - utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "1m2s", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", - "field_extr1": "val_extr1", "fieldextr2": "valextr2", "Source": utils.TEST_SQL} - - cgrCdr5 := &CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa5", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: utils.META_POSTPAID, utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", - utils.CATEGORY: "call", utils.ACCOUNT: "1002", utils.SUBJECT: "1002", utils.DESTINATION: "+4986517174963", utils.SETUP_TIME: "2013-11-07T08:42:25Z", - utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "15s", utils.PDD: "7s", utils.SUPPLIER: "SUPPL1", - "field_extr1": "val_extr1", "fieldextr2": "valextr2", "Source": utils.TEST_SQL} - - for _, cdr := range []*CgrCdr{cgrCdr1, cgrCdr2, cgrCdr3, cgrCdr4, cgrCdr5} { - if err := mongoDb.SetCdr(cdr.AsStoredCdr("")); err != nil { - t.Error(err.Error()) - } - } - strCdr1 := &CDR{TOR: utils.VOICE, OriginID: "bbb1", OriginHost: "192.168.1.1", Source: "UNKNOWN", RequestType: utils.META_RATED, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(3) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 1.201} - strCdr1.CGRID = utils.Sha1(strCdr1.OriginID, strCdr1.SetupTime.String()) - strCdr2 := &CDR{TOR: utils.VOICE, OriginID: "bbb2", OriginHost: "192.168.1.2", Source: "UNKNOWN2", RequestType: utils.META_PREPAID, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(12) * time.Second, PDD: time.Duration(4) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 0.201} - strCdr2.CGRID = utils.Sha1(strCdr2.OriginID, strCdr2.SetupTime.String()) - strCdr3 := &CDR{TOR: utils.VOICE, OriginID: "bbb3", OriginHost: "192.168.1.1", Source: utils.TEST_SQL, RequestType: utils.META_RATED, - Direction: "*out", Tenant: "itsyscom.com", Category: "call", Account: "1002", Subject: "1000", Destination: "+4986517174963", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(2) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 1.201} - strCdr3.CGRID = utils.Sha1(strCdr3.OriginID, strCdr3.SetupTime.String()) - - for _, cdr := range []*CDR{strCdr1, strCdr2, strCdr3} { - if err := mongoDb.SetCdr(cdr); err != nil { - t.Error(err.Error()) - } - } -} - -func TestMongoSetRatedCdr(t *testing.T) { - if !*testLocal { - return - } - strCdr1 := &CDR{TOR: utils.VOICE, OriginID: "bbb1", OriginHost: "192.168.1.1", Source: "UNKNOWN", RequestType: utils.META_RATED, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(3) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 1.201} - strCdr1.CGRID = utils.Sha1(strCdr1.OriginID, strCdr1.SetupTime.String()) - strCdr2 := &CDR{TOR: utils.VOICE, OriginID: "bbb2", OriginHost: "192.168.1.2", Source: "UNKNOWN", RequestType: utils.META_PREPAID, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(12) * time.Second, PDD: time.Duration(7) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 0.201} - strCdr2.CGRID = utils.Sha1(strCdr2.OriginID, strCdr2.SetupTime.String()) - strCdr3 := &CDR{TOR: utils.VOICE, OriginID: "bbb3", OriginHost: "192.168.1.1", Source: utils.TEST_SQL, RequestType: utils.META_RATED, - Direction: "*out", Tenant: "itsyscom.com", Category: "call", Account: "1002", Subject: "1002", Destination: "+4986517174964", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(2) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: "wholesale_run", Cost: 1.201} - strCdr3.CGRID = utils.Sha1(strCdr3.OriginID, strCdr3.SetupTime.String()) - - for _, cdr := range []*CDR{strCdr1, strCdr2, strCdr3} { - if err := mongoDb.SetRatedCdr(cdr); err != nil { - t.Error(err.Error()) - } - } -} - -func TestMongoCallCost(t *testing.T) { - if !*testLocal { - return - } - CGRID := utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()) - cc := &CallCost{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "91001", - Account: "8001", - Destination: "1002", - TOR: utils.VOICE, - Timespans: []*TimeSpan{ - &TimeSpan{ - TimeStart: time.Date(2013, 9, 10, 13, 40, 0, 0, time.UTC), - TimeEnd: time.Date(2013, 9, 10, 13, 41, 0, 0, time.UTC), - }, - &TimeSpan{ - TimeStart: time.Date(2013, 9, 10, 13, 41, 0, 0, time.UTC), - TimeEnd: time.Date(2013, 9, 10, 13, 41, 30, 0, time.UTC), - }, - }, - } - if err := mongoDb.LogCallCost(CGRID, utils.TEST_SQL, utils.DEFAULT_RUNID, cc); err != nil { - t.Error(err.Error()) - } - if ccRcv, err := mongoDb.GetCallCostLog(CGRID, utils.TEST_SQL, utils.DEFAULT_RUNID); err != nil { - t.Error(err.Error()) - } else if cc.Cost != ccRcv.Cost { - t.Errorf("Expecting call cost:\n%+v,\nreceived:\n%+v", cc.Timespans[0], ccRcv.Timespans[0]) - } - // UPDATE test here - cc.Category = "premium_call" - if err := mongoDb.LogCallCost(CGRID, utils.TEST_SQL, utils.DEFAULT_RUNID, cc); err != nil { - t.Error(err.Error()) - } - if ccRcv, err := mongoDb.GetCallCostLog(CGRID, utils.TEST_SQL, utils.DEFAULT_RUNID); err != nil { - t.Error(err.Error()) - } else if cc.Cost != ccRcv.Cost { - t.Errorf("Expecting call cost: %v, received: %v", cc, ccRcv) - } -} - -func TestMongoGetcdrs(t *testing.T) { - if !*testLocal { - return - } - var timeStart, timeEnd time.Time - // All cdrs, no filter - if cdrs, _, err := mongoDb.GetCDRs(new(utils.CDRsFilter)); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 20 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Count ALL - if cdrs, count, err := mongoDb.GetCDRs(&utils.CDRsFilter{Count: true}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 0 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } else if count != 20 { - t.Error("Unexpected count of cdrs returned: ", count) - } - // Limit 5 - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 5 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Offset 5 - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 5 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Offset with limit 2 - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(2), Offset: utils.IntPointer(5)}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 2 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on CGRIDs - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 3 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Count on CGRIDS - if _, count, err := mongoDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, Count: true}); err != nil { - t.Error(err.Error()) - } else if count != 3 { - t.Error("Unexpected count of cdrs returned: ", count) - } - // Filter on CGRIDs plus RequestType - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, RequestTypes: []string{utils.META_PREPAID}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 1 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Count on multiple filter - if _, count, err := mongoDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, RequestTypes: []string{utils.META_PREPAID}, Count: true}); err != nil { - t.Error(err.Error()) - } else if count != 1 { - t.Error("Unexpected count of cdrs returned: ", count) - } - // Filter on runId - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{RunIDs: []string{utils.DEFAULT_RUNID}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 14 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on TOR - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{TORs: []string{utils.SMS}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 0 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on multiple TOR - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{TORs: []string{utils.SMS, utils.VOICE}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 15 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on OriginHost - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{OriginHosts: []string{"192.168.1.2"}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 3 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on multiple OriginHost - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{OriginHosts: []string{"192.168.1.1", "192.168.1.2"}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 15 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on Source - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{Sources: []string{"UNKNOWN"}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 2 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on multiple Source - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{Sources: []string{"UNKNOWN", "UNKNOWN2"}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 2 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on RequestType - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_PREPAID}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 5 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on multiple RequestType - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_PREPAID, utils.META_PSEUDOPREPAID}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 6 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on direction - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{Directions: []string{"*out"}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 15 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on tenant - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{Tenants: []string{"itsyscom.com"}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 4 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on multiple tenants - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{Tenants: []string{"itsyscom.com", "cgrates.org"}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 15 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on category - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{Categories: []string{"premium_call"}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 1 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on multiple categories - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{Categories: []string{"premium_call", "call"}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 15 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on account - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{Accounts: []string{"1002"}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 6 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on multiple account - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{Accounts: []string{"1001", "1002"}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 13 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on subject - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{Subjects: []string{"1000"}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 1 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on multiple subject - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{Subjects: []string{"1000", "1002"}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 6 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on destPrefix - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{DestinationPrefixes: []string{"+498651"}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 4 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on multiple DestinationPrefixes - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{DestinationPrefixes: []string{"1001", "+498651"}}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 5 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on ignoreRated - var OrderIDStart, OrderIDEnd int64 // Capture also OrderIDs for the next test - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{MaxCost: utils.Float64Pointer(0.0)}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 7 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } else { - for _, cdr := range cdrs { - if cdr.OrderID < OrderIDStart { - OrderIDStart = cdr.OrderID - } - if cdr.OrderID > OrderIDEnd { - OrderIDEnd = cdr.OrderID - } - } - } - // Filter on OrderIDStart - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{OrderIDStart: OrderIDStart}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 20 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on OrderIDStart and OrderIDEnd - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{OrderIDStart: OrderIDStart, OrderIDEnd: OrderIDEnd}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 20 { // TODO: find mongo equivalent - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on timeStart - timeStart = time.Date(2013, 11, 8, 8, 0, 0, 0, time.UTC) - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{AnswerTimeStart: &timeStart}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 6 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on timeStart and timeEnd - timeEnd = time.Date(2013, 12, 1, 8, 0, 0, 0, time.UTC) - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 2 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on minPDD - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{MinPDD: utils.Float64Pointer(float64(3 * time.Second))}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 7 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on maxPDD - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{MaxPDD: utils.Float64Pointer(float64(3 * time.Second))}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 13 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on minPDD, maxPDD - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{MinPDD: utils.Float64Pointer(float64(3 * time.Second)), MaxPDD: utils.Float64Pointer(float64(5 * time.Second))}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 4 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Combined filter - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_RATED}, AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 1 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - // Filter on ignoreDerived - if cdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd, FilterOnRated: true}); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 2 { // ToDo: Recheck this value - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } -} - -func TestMongoRemCDRs(t *testing.T) { - if !*testLocal { - return - } - CGRIDB1 := utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()) - if err := mongoDb.RemCDRs([]string{CGRIDB1}); err != nil { - t.Error(err.Error()) - } - if cdrs, _, err := mongoDb.GetCDRs(new(utils.CDRsFilter)); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 20 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } - tm, _ := utils.ParseTimeDetectLayout("2013-11-08T08:42:20Z", "") - CGRIDA1 := utils.Sha1("aaa1", tm.String()) - tm, _ = utils.ParseTimeDetectLayout("2013-11-08T08:42:22Z", "") - CGRIDA2 := utils.Sha1("aaa2", tm.String()) - tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:24Z", "") - CGRIDA3 := utils.Sha1("aaa3", tm.String()) - tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:21Z", "") - CGRIDA4 := utils.Sha1("aaa4", tm.String()) - tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:25Z", "") - CGRIDA5 := utils.Sha1("aaa5", tm.String()) - CGRIDB2 := utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()) - CGRIDB3 := utils.Sha1("bbb3", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()) - if err := mongoDb.RemCDRs([]string{CGRIDA1, CGRIDA2, CGRIDA3, CGRIDA4, CGRIDA5, - CGRIDB2, CGRIDB3}); err != nil { - t.Error(err.Error()) - } - if cdrs, _, err := mongoDb.GetCDRs(new(utils.CDRsFilter)); err != nil { - t.Error(err.Error()) - } else if len(cdrs) != 20 { - t.Error("Unexpected number of cdrs returned: ", len(cdrs)) - } -} - -// Make sure that what we get is what we set -func TestMongoStoreRestoreCdr(t *testing.T) { - if !*testLocal { - return - } - strCdr := &CDR{TOR: utils.VOICE, OriginID: "ccc1", OriginHost: "192.168.1.1", Source: "TEST_CDR", RequestType: utils.META_RATED, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(3) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 1.201} - strCdr.CGRID = utils.Sha1(strCdr.OriginID, strCdr.SetupTime.String()) - if err := mongoDb.SetCdr(strCdr); err != nil { - t.Error(err.Error()) - } - if err := mongoDb.SetRatedCdr(strCdr); err != nil { - t.Error(err.Error()) - } - // Check RawCdr - if rcvcdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{strCdr.CGRID}}); err != nil { - t.Error(err.Error()) - } else if len(rcvcdrs) != 1 { - t.Errorf("Unexpected cdrs returned: %+v", rcvcdrs) - } else { - rcvCdr := rcvcdrs[0] - if strCdr.CGRID != rcvCdr.CGRID || - strCdr.TOR != rcvCdr.TOR || - strCdr.OriginID != rcvCdr.OriginID || - strCdr.OriginHost != rcvCdr.OriginHost || - strCdr.RequestType != rcvCdr.RequestType || - strCdr.Direction != rcvCdr.Direction || - strCdr.Tenant != rcvCdr.Tenant || - strCdr.Category != rcvCdr.Category || - strCdr.Account != rcvCdr.Account || - strCdr.Subject != rcvCdr.Subject || - strCdr.Destination != rcvCdr.Destination || - !strCdr.SetupTime.Equal(rcvCdr.SetupTime) || - !strCdr.AnswerTime.Equal(rcvCdr.AnswerTime) || - strCdr.Usage != rcvCdr.Usage || - strCdr.PDD != rcvCdr.PDD || - strCdr.Supplier != rcvCdr.Supplier || - strCdr.DisconnectCause != rcvCdr.DisconnectCause || - !reflect.DeepEqual(strCdr.ExtraFields, rcvCdr.ExtraFields) { - t.Errorf("Expecting: %+v, received: %+v", strCdr, rcvcdrs[0]) - } - } - // Check RatedCdr - if rcvcdrs, _, err := mongoDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{strCdr.CGRID}, FilterOnRated: true}); err != nil { - t.Error(err.Error()) - } else if len(rcvcdrs) != 1 { - t.Errorf("Unexpected cdrs returned: %+v", rcvcdrs) - } else { - rcvCdr := rcvcdrs[0] - if strCdr.CGRID != rcvCdr.CGRID || - strCdr.TOR != rcvCdr.TOR || - strCdr.OriginID != rcvCdr.OriginID || - strCdr.OriginHost != rcvCdr.OriginHost || - strCdr.RequestType != rcvCdr.RequestType || - strCdr.Direction != rcvCdr.Direction || - strCdr.Tenant != rcvCdr.Tenant || - strCdr.Category != rcvCdr.Category || - strCdr.Account != rcvCdr.Account || - strCdr.Subject != rcvCdr.Subject || - strCdr.Destination != rcvCdr.Destination || - //!strCdr.SetupTime.Equal(rcvCdr.SetupTime) || // FixMe - //!strCdr.AnswerTime.Equal(rcvCdr.AnswerTime) || // FixMe - strCdr.Usage != rcvCdr.Usage || - strCdr.PDD != rcvCdr.PDD || - strCdr.Supplier != rcvCdr.Supplier || - strCdr.DisconnectCause != rcvCdr.DisconnectCause || - strCdr.Cost != rcvCdr.Cost || - !reflect.DeepEqual(strCdr.ExtraFields, rcvCdr.ExtraFields) { - t.Errorf("Expecting: %+v, received: %+v", strCdr, rcvcdrs[0]) - } - } -} diff --git a/engine/storage_mongo_tp.go b/engine/storage_mongo_tp.go index 553a934cc..87800376c 100644 --- a/engine/storage_mongo_tp.go +++ b/engine/storage_mongo_tp.go @@ -716,12 +716,7 @@ func (ms *MongoStorage) GetCallCostLog(cgrid, source, runid string) (cc *CallCos return } -func (ms *MongoStorage) SetCdr(cdr *CDR) error { - _, err := ms.db.C(colCdrs).Upsert(bson.M{"cgrid": cdr.CGRID, "mediationrunid": cdr.RunID}, cdr) - return err -} - -func (ms *MongoStorage) SetRatedCdr(cdr *CDR) error { +func (ms *MongoStorage) SetCDR(cdr *CDR, allowUpdate bool) error { _, err := ms.db.C(colCdrs).Upsert(bson.M{"cgrid": cdr.CGRID, "mediationrunid": cdr.RunID}, cdr) return err } diff --git a/engine/storage_mysql_local_test.go b/engine/storage_mysql_local_test.go deleted file mode 100644 index f4a1aa39f..000000000 --- a/engine/storage_mysql_local_test.go +++ /dev/null @@ -1,976 +0,0 @@ -/* -Rating system designed to be used in VoIP Carriers World -Copyright (C) 2012-2015 ITsysCOM - -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 engine - -import ( - "fmt" - "path" - "reflect" - "testing" - "time" - - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/utils" -) - -var mysqlDb *MySQLStorage - -func TestMySQLCreateTables(t *testing.T) { - if !*testLocal { - return - } - cgrConfig, _ := config.NewDefaultCGRConfig() - var err error - if mysqlDb, err = NewMySQLStorage(cgrConfig.StorDBHost, cgrConfig.StorDBPort, cgrConfig.StorDBName, cgrConfig.StorDBUser, cgrConfig.StorDBPass, - cgrConfig.StorDBMaxOpenConns, cgrConfig.StorDBMaxIdleConns); err != nil { - t.Error("Error on opening database connection: ", err) - return - } - for _, scriptName := range []string{utils.CREATE_CDRS_TABLES_SQL, utils.CREATE_TARIFFPLAN_TABLES_SQL} { - if err := mysqlDb.CreateTablesFromScript(path.Join(*dataDir, "storage", utils.MYSQL, scriptName)); err != nil { - t.Error("Error on mysqlDb creation: ", err.Error()) - return // No point in going further - } - } - if _, err := mysqlDb.Db.Query(fmt.Sprintf("SELECT 1 from %s", utils.TBL_CDRS)); err != nil { - t.Error(err.Error()) - } -} - -func TestMySQLSetGetTPTiming(t *testing.T) { - if !*testLocal { - return - } - tm := TpTiming{Tpid: utils.TEST_SQL, Tag: "ALWAYS", Time: "00:00:00"} - if err := mysqlDb.SetTpTimings([]TpTiming{tm}); err != nil { - t.Error(err.Error()) - } - if tmgs, err := mysqlDb.GetTpTimings(utils.TEST_SQL, tm.Tag); err != nil { - t.Error(err.Error()) - } else if !modelEqual(tm, tmgs[0]) { - t.Errorf("Expecting: %+v, received: %+v", tm, tmgs[0]) - } - // Update - tm.Time = "00:00:01" - if err := mysqlDb.SetTpTimings([]TpTiming{tm}); err != nil { - t.Error(err.Error()) - } - if tmgs, err := mysqlDb.GetTpTimings(utils.TEST_SQL, tm.Tag); err != nil { - t.Error(err.Error()) - } else if !modelEqual(tm, tmgs[0]) { - t.Errorf("Expecting: %+v, received: %+v", tm, tmgs[0]) - } -} - -func TestMySQLSetGetTPDestination(t *testing.T) { - if !*testLocal { - return - } - dst := []TpDestination{ - TpDestination{Tpid: utils.TEST_SQL, Tag: utils.TEST_SQL, Prefix: "+49"}, - TpDestination{Tpid: utils.TEST_SQL, Tag: utils.TEST_SQL, Prefix: "+49151"}, - TpDestination{Tpid: utils.TEST_SQL, Tag: utils.TEST_SQL, Prefix: "+49176"}, - } - if err := mysqlDb.SetTpDestinations(dst); err != nil { - t.Error(err.Error()) - } - storData, err := mysqlDb.GetTpDestinations(utils.TEST_SQL, utils.TEST_SQL) - dsts, err := TpDestinations(storData).GetDestinations() - expected := &Destination{Id: utils.TEST_SQL, Prefixes: []string{"+49", "+49151", "+49176"}} - if err != nil { - t.Error(err.Error()) - } else if !modelEqual(*expected, *dsts[utils.TEST_SQL]) { - t.Errorf("Expecting: %+v, received: %+v", expected, dsts[utils.TEST_SQL]) - } -} - -func TestMySQLSetGetTPRates(t *testing.T) { - if !*testLocal { - return - } - RT_ID := "RT_1" - rtSlots := []*utils.RateSlot{ - &utils.RateSlot{ConnectFee: 0.02, Rate: 0.01, RateUnit: "60s", RateIncrement: "60s", GroupIntervalStart: "0s"}, - &utils.RateSlot{ConnectFee: 0.00, Rate: 0.005, RateUnit: "60s", RateIncrement: "1s", GroupIntervalStart: "60s"}, - } - for _, rs := range rtSlots { - rs.SetDurations() - } - rates := &utils.TPRate{ - TPid: utils.TEST_SQL, - RateId: RT_ID, - RateSlots: rtSlots, - } - mRates := APItoModelRate(rates) - if err := mysqlDb.SetTpRates(mRates); err != nil { - t.Error(err.Error()) - } - if rts, err := mysqlDb.GetTpRates(utils.TEST_SQL, RT_ID); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mRates[0], rts[0]) { - t.Errorf("Expecting: %+v, received: %+v", mRates, rts) - } -} - -func TestMySQLSetGetTPDestinationRates(t *testing.T) { - if !*testLocal { - return - } - DR_ID := "DR_1" - dr := &utils.DestinationRate{DestinationId: "DST_1", RateId: "RT_1", RoundingMethod: "*up", RoundingDecimals: 4} - - eDrs := &utils.TPDestinationRate{TPid: utils.TEST_SQL, DestinationRateId: DR_ID, DestinationRates: []*utils.DestinationRate{dr}} - mdrs := APItoModelDestinationRate(eDrs) - if err := mysqlDb.SetTpDestinationRates(mdrs); err != nil { - t.Error(err.Error()) - } - if drs, err := mysqlDb.GetTpDestinationRates(utils.TEST_SQL, DR_ID, nil); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mdrs[0], drs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mdrs, drs) - } -} - -func TestMySQLSetGetTPRatingPlans(t *testing.T) { - if !*testLocal { - return - } - RP_ID := "RP_1" - rbBinding := &utils.TPRatingPlanBinding{DestinationRatesId: "DR_1", TimingId: "TM_1", Weight: 10.0} - rp := &utils.TPRatingPlan{ - TPid: utils.TEST_SQL, - RatingPlanId: RP_ID, - RatingPlanBindings: []*utils.TPRatingPlanBinding{rbBinding}, - } - mrp := APItoModelRatingPlan(rp) - if err := mysqlDb.SetTpRatingPlans(mrp); err != nil { - t.Error(err.Error()) - } - if drps, err := mysqlDb.GetTpRatingPlans(utils.TEST_SQL, RP_ID, nil); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mrp[0], drps[0]) { - t.Errorf("Expecting: %+v, received: %+v", mrp, drps) - } -} - -func TestMySQLSetGetTPRatingProfiles(t *testing.T) { - if !*testLocal { - return - } - ras := []*utils.TPRatingActivation{&utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId: "RP_1"}} - rp := &utils.TPRatingProfile{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Category: "call", Direction: "*out", Subject: "*any", RatingPlanActivations: ras} - mrp := APItoModelRatingProfile(rp) - if err := mysqlDb.SetTpRatingProfiles(mrp); err != nil { - t.Error(err.Error()) - } - if rps, err := mysqlDb.GetTpRatingProfiles(&mrp[0]); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mrp[0], rps[0]) { - t.Errorf("Expecting: %+v, received: %+v", mrp, rps) - } - -} - -func TestMySQLSetGetTPSharedGroups(t *testing.T) { - if !*testLocal { - return - } - SG_ID := "SG_1" - tpSgs := &utils.TPSharedGroups{ - TPid: utils.TEST_SQL, - SharedGroupsId: SG_ID, - SharedGroups: []*utils.TPSharedGroup{ - &utils.TPSharedGroup{Account: "dan", Strategy: "*lowest_first", RatingSubject: "lowest_rates"}, - }, - } - mSgs := APItoModelSharedGroup(tpSgs) - if err := mysqlDb.SetTpSharedGroups(mSgs); err != nil { - t.Error(err.Error()) - } - if sgs, err := mysqlDb.GetTpSharedGroups(utils.TEST_SQL, SG_ID); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mSgs[0], sgs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mSgs, sgs) - } -} - -func TestMySQLSetGetTPCdrStats(t *testing.T) { - if !*testLocal { - return - } - CS_ID := "CDRSTATS_1" - setCS := &utils.TPCdrStats{ - TPid: utils.TEST_SQL, - CdrStatsId: CS_ID, - CdrStats: []*utils.TPCdrStat{ - &utils.TPCdrStat{QueueLength: "10", TimeWindow: "10m", Metrics: "ASR", Tenants: "cgrates.org", Categories: "call"}, - }, - } - mcs := APItoModelCdrStat(setCS) - if err := mysqlDb.SetTpCdrStats(mcs); err != nil { - t.Error(err.Error()) - } - if cs, err := mysqlDb.GetTpCdrStats(utils.TEST_SQL, CS_ID); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mcs[0], cs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mcs, cs) - } -} - -func TestMySQLSetGetTPDerivedChargers(t *testing.T) { - if !*testLocal { - return - } - dc := &utils.TPDerivedCharger{RunId: utils.DEFAULT_RUNID, ReqTypeField: "^" + utils.META_PREPAID, AccountField: "^rif", SubjectField: "^rif", - UsageField: "cgr_duration", SupplierField: "^supplier1"} - dcs := &utils.TPDerivedChargers{TPid: utils.TEST_SQL, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dan", DerivedChargers: []*utils.TPDerivedCharger{dc}} - - mdcs := APItoModelDerivedCharger(dcs) - if err := mysqlDb.SetTpDerivedChargers(mdcs); err != nil { - t.Error(err.Error()) - } - if rDCs, err := mysqlDb.GetTpDerivedChargers(&mdcs[0]); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mdcs[0], rDCs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mdcs, rDCs) - } -} - -func TestMySQLSetGetTPActions(t *testing.T) { - if !*testLocal { - return - } - ACTS_ID := "PREPAID_10" - acts := []*utils.TPAction{ - &utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Directions: "*out", Units: 10, ExpiryTime: "*unlimited", - DestinationIds: "*any", BalanceWeight: 10, Weight: 10}} - tpActions := &utils.TPActions{TPid: utils.TEST_SQL, ActionsId: ACTS_ID, Actions: acts} - mas := APItoModelAction(tpActions) - if err := mysqlDb.SetTpActions(mas); err != nil { - t.Error(err.Error()) - } - if rTpActs, err := mysqlDb.GetTpActions(utils.TEST_SQL, ACTS_ID); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mas[0], rTpActs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mas, rTpActs) - } -} - -func TestMySQLTPActionTimings(t *testing.T) { - if !*testLocal { - return - } - AP_ID := "AP_1" - ap := &utils.TPActionPlan{ - TPid: utils.TEST_SQL, - ActionPlanId: AP_ID, - ActionPlan: []*utils.TPActionTiming{&utils.TPActionTiming{ActionsId: "ACTS_1", TimingId: "TM_1", Weight: 10.0}}, - } - maps := APItoModelActionPlan(ap) - if err := mysqlDb.SetTpActionPlans(maps); err != nil { - t.Error(err.Error()) - } - if rAP, err := mysqlDb.GetTpActionPlans(utils.TEST_SQL, AP_ID); err != nil { - t.Error(err.Error()) - } else if !modelEqual(maps[0], rAP[0]) { - t.Errorf("Expecting: %+v, received: %+v", maps, rAP) - } -} - -func TestMySQLSetGetTPActionTriggers(t *testing.T) { - if !*testLocal { - return - } - atrg := &utils.TPActionTrigger{ - Id: "MY_FIRST_ATGR", - BalanceType: "*monetary", - BalanceDirections: "*out", - ThresholdType: "*min_balance", - ThresholdValue: 2.0, - Recurrent: true, - BalanceDestinationIds: "*any", - Weight: 10.0, - ActionsId: "LOG_BALANCE", - } - atrgs := &utils.TPActionTriggers{ - TPid: utils.TEST_SQL, - ActionTriggersId: utils.TEST_SQL, - ActionTriggers: []*utils.TPActionTrigger{atrg}, - } - matrg := APItoModelActionTrigger(atrgs) - if err := mysqlDb.SetTpActionTriggers(matrg); err != nil { - t.Error("Unexpected error: ", err.Error()) - } - if rcvMpAtrgs, err := mysqlDb.GetTpActionTriggers(utils.TEST_SQL, utils.TEST_SQL); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if !modelEqual(matrg[0], rcvMpAtrgs[0]) { - t.Errorf("Expecting: %v, received: %v", matrg, rcvMpAtrgs) - } -} - -func TestMySQLSetGetTpAccountActions(t *testing.T) { - if !*testLocal { - return - } - aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001", - ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"} - maa := APItoModelAccountAction(aa) - if err := mysqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil { - t.Error(err.Error()) - } - if aas, err := mysqlDb.GetTpAccountActions(maa); err != nil { - t.Error(err.Error()) - } else if !modelEqual(*maa, aas[0]) { - t.Errorf("Expecting: %+v, received: %+v", maa, aas) - } -} - -func TestMySQLGetTPIds(t *testing.T) { - if !*testLocal { - return - } - eTPIds := []string{utils.TEST_SQL} - if tpIds, err := mysqlDb.GetTpIds(); err != nil { - t.Error(err.Error()) - } else if !reflect.DeepEqual(eTPIds, tpIds) { - t.Errorf("Expecting: %+v, received: %+v", eTPIds, tpIds) - } -} - -func TestMySQLRemoveTPData(t *testing.T) { - if !*testLocal { - return - } - // Create Timings - tm := &utils.ApierTPTiming{TPid: utils.TEST_SQL, TimingId: "ALWAYS", Time: "00:00:00"} - tms := APItoModelTiming(tm) - if err := mysqlDb.SetTpTimings([]TpTiming{*tms}); err != nil { - t.Error(err.Error()) - } - if tmgs, err := mysqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil { - t.Error(err.Error()) - } else if len(tmgs) == 0 { - t.Error("Could not store TPTiming") - } - // Remove Timings - if err := mysqlDb.RemTpData(utils.TBL_TP_TIMINGS, utils.TEST_SQL, map[string]string{"tag": tm.TimingId}); err != nil { - t.Error(err.Error()) - } - if tmgs, err := mysqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil { - t.Error(err) - } else if len(tmgs) != 0 { - t.Errorf("Timings should be empty, got instead: %+v", tmgs) - } - // Create RatingProfile - ras := []*utils.TPRatingActivation{&utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId: "RETAIL1"}} - rp := &utils.TPRatingProfile{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Category: "call", Direction: "*out", Subject: "*any", RatingPlanActivations: ras} - mrp := APItoModelRatingProfile(rp) - if err := mysqlDb.SetTpRatingProfiles(mrp); err != nil { - t.Error(err.Error()) - } - if rps, err := mysqlDb.GetTpRatingProfiles(&mrp[0]); err != nil { - t.Error(err.Error()) - } else if len(rps) == 0 { - t.Error("Could not store TPRatingProfile") - } - // Remove RatingProfile - if err := mysqlDb.RemTpData(utils.TBL_TP_RATE_PROFILES, rp.TPid, map[string]string{"loadid": rp.LoadId, "direction": rp.Direction, "tenant": rp.Tenant, "category": rp.Category, "subject": rp.Subject}); err != nil { - t.Error(err.Error()) - } - if rps, err := mysqlDb.GetTpRatingProfiles(&mrp[0]); err != nil { - t.Error(err) - } else if len(rps) != 0 { - t.Errorf("RatingProfiles different than 0: %+v", rps) - } - // Create AccountActions - aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001", - ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"} - maa := APItoModelAccountAction(aa) - if err := mysqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil { - t.Error(err.Error()) - } - if aas, err := mysqlDb.GetTpAccountActions(maa); err != nil { - t.Error(err.Error()) - } else if len(aas) == 0 { - t.Error("Could not create TPAccountActions") - } - // Remove AccountActions - if err := mysqlDb.RemTpData(utils.TBL_TP_ACCOUNT_ACTIONS, aa.TPid, map[string]string{"loadid": aa.LoadId, "tenant": aa.Tenant, "account": aa.Account}); err != nil { - t.Error(err.Error()) - } - if aas, err := mysqlDb.GetTpAccountActions(maa); err != nil { - t.Error(err) - } else if len(aas) != 0 { - t.Errorf("Non empty account actions: %+v", aas) - } - // Create again so we can test complete TP removal - if err := mysqlDb.SetTpTimings([]TpTiming{*tms}); err != nil { - t.Error(err.Error()) - } - if tmgs, err := mysqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil { - t.Error(err.Error()) - } else if len(tmgs) == 0 { - t.Error("Could not store TPTiming") - } - // Create RatingProfile - if err := mysqlDb.SetTpRatingProfiles(mrp); err != nil { - t.Error(err.Error()) - } - if rps, err := mysqlDb.GetTpRatingProfiles(&mrp[0]); err != nil { - t.Error(err.Error()) - } else if len(rps) == 0 { - t.Error("Could not store TPRatingProfile") - } - // Create AccountActions - if err := mysqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil { - t.Error(err.Error()) - } - if aas, err := mysqlDb.GetTpAccountActions(maa); err != nil { - t.Error(err.Error()) - } else if len(aas) == 0 { - t.Error("Could not create TPAccountActions") - } - // Remove TariffPlan completely - if err := mysqlDb.RemTpData("", utils.TEST_SQL, nil); err != nil { - t.Error(err.Error()) - } - // Make sure we have removed it - if tms, err := mysqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil { - t.Error(err) - } else if len(tms) != 0 { - t.Errorf("Non empty timings: %+v", tms) - } - if rpfs, err := mysqlDb.GetTpRatingProfiles(&mrp[0]); err != nil { - t.Error(err) - } else if len(rpfs) != 0 { - t.Errorf("Non empty rpfs: %+v", rpfs) - } - if aas, err := mysqlDb.GetTpAccountActions(maa); err != nil { - t.Error(err) - } else if len(aas) != 0 { - t.Errorf("Non empty account actions: %+v", aas) - } -} - -func TestMySQLSetCdr(t *testing.T) { - if !*testLocal { - return - } - cgrCdr1 := &CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa1", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_RATED, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", - utils.CATEGORY: "call", utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "1002", utils.SETUP_TIME: "2013-11-08T08:42:20Z", - utils.ANSWER_TIME: "2013-11-08T08:42:26Z", utils.USAGE: "10s", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", utils.CDRSOURCE: utils.TEST_SQL} - - cgrCdr2 := &CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa2", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_PREPAID, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", - utils.CATEGORY: "call", utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "1002", utils.SETUP_TIME: "2013-11-08T08:42:22Z", - utils.ANSWER_TIME: "2013-11-08T08:42:26Z", utils.USAGE: "20", utils.PDD: "7s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL} - - cgrCdr3 := &CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa3", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_RATED, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", - utils.CATEGORY: "premium_call", utils.ACCOUNT: "1002", utils.SUBJECT: "1002", utils.DESTINATION: "1001", utils.SETUP_TIME: "2013-11-07T08:42:24Z", - utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "60s", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL} - - cgrCdr4 := &CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa4", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: utils.META_PSEUDOPREPAID, utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", - utils.CATEGORY: "call", utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "+4986517174964", utils.SETUP_TIME: "2013-11-07T08:42:21Z", - utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "1m2s", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL} - - cgrCdr5 := &CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa5", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: utils.META_POSTPAID, utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", - utils.CATEGORY: "call", utils.ACCOUNT: "1002", utils.SUBJECT: "1002", utils.DESTINATION: "+4986517174963", utils.SETUP_TIME: "2013-11-07T08:42:25Z", - utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "15s", utils.PDD: "7s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL} - - for _, cdr := range []*CgrCdr{cgrCdr1, cgrCdr2, cgrCdr3, cgrCdr4, cgrCdr5} { - if err := mysqlDb.SetCdr(cdr.AsStoredCdr("")); err != nil { - t.Error(err.Error()) - } - } - strCdr1 := &CDR{TOR: utils.VOICE, OriginID: "bbb1", OriginHost: "192.168.1.1", Source: "UNKNOWN", RequestType: utils.META_RATED, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(3) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 1.201} - strCdr1.CGRID = utils.Sha1(strCdr1.OriginID, strCdr1.SetupTime.String()) - strCdr2 := &CDR{TOR: utils.VOICE, OriginID: "bbb2", OriginHost: "192.168.1.2", Source: "UNKNOWN2", RequestType: utils.META_PREPAID, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(12) * time.Second, PDD: time.Duration(4) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 0.201} - strCdr2.CGRID = utils.Sha1(strCdr2.OriginID, strCdr2.SetupTime.String()) - strCdr3 := &CDR{TOR: utils.VOICE, OriginID: "bbb3", OriginHost: "192.168.1.1", Source: utils.TEST_SQL, RequestType: utils.META_RATED, - Direction: "*out", Tenant: "itsyscom.com", Category: "call", Account: "1002", Subject: "1000", Destination: "+4986517174963", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(2) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 1.201} - strCdr3.CGRID = utils.Sha1(strCdr3.OriginID, strCdr3.SetupTime.String()) - - for _, cdr := range []*CDR{strCdr1, strCdr2, strCdr3} { - if err := mysqlDb.SetCdr(cdr); err != nil { - t.Error(err.Error()) - } - } -} - -func TestMySQLSetRatedCdr(t *testing.T) { - if !*testLocal { - return - } - strCdr1 := &CDR{TOR: utils.VOICE, OriginID: "bbb1", OriginHost: "192.168.1.1", Source: "UNKNOWN", RequestType: utils.META_RATED, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(3) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 1.201} - strCdr1.CGRID = utils.Sha1(strCdr1.OriginID, strCdr1.SetupTime.String()) - strCdr2 := &CDR{TOR: utils.VOICE, OriginID: "bbb2", OriginHost: "192.168.1.2", Source: "UNKNOWN", RequestType: utils.META_PREPAID, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(12) * time.Second, PDD: time.Duration(7) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 0.201} - strCdr2.CGRID = utils.Sha1(strCdr2.OriginID, strCdr2.SetupTime.String()) - strCdr3 := &CDR{TOR: utils.VOICE, OriginID: "bbb3", OriginHost: "192.168.1.1", Source: utils.TEST_SQL, RequestType: utils.META_RATED, - Direction: "*out", Tenant: "itsyscom.com", Category: "call", Account: "1002", Subject: "1002", Destination: "+4986517174964", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(2) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: "wholesale_run", Cost: 1.201} - strCdr3.CGRID = utils.Sha1(strCdr3.OriginID, strCdr3.SetupTime.String()) - - for _, cdr := range []*CDR{strCdr1, strCdr2, strCdr3} { - if err := mysqlDb.SetRatedCdr(cdr); err != nil { - t.Error(err.Error()) - } - } -} - -func TestMySQLCallCost(t *testing.T) { - if !*testLocal { - return - } - CGRID := utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()) - cc := &CallCost{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "91001", - Account: "8001", - Destination: "1002", - TOR: utils.VOICE, - Timespans: []*TimeSpan{ - &TimeSpan{ - TimeStart: time.Date(2013, 9, 10, 13, 40, 0, 0, time.UTC), - TimeEnd: time.Date(2013, 9, 10, 13, 41, 0, 0, time.UTC), - }, - &TimeSpan{ - TimeStart: time.Date(2013, 9, 10, 13, 41, 0, 0, time.UTC), - TimeEnd: time.Date(2013, 9, 10, 13, 41, 30, 0, time.UTC), - }, - }, - } - if err := mysqlDb.LogCallCost(CGRID, utils.TEST_SQL, utils.DEFAULT_RUNID, cc); err != nil { - t.Error(err.Error()) - } - if ccRcv, err := mysqlDb.GetCallCostLog(CGRID, utils.TEST_SQL, utils.DEFAULT_RUNID); err != nil { - t.Error(err.Error()) - } else if !reflect.DeepEqual(cc, ccRcv) { - t.Errorf("Expecting call cost: %v, received: %v", cc, ccRcv) - } - // UPDATE test here - cc.Category = "premium_call" - if err := mysqlDb.LogCallCost(CGRID, utils.TEST_SQL, utils.DEFAULT_RUNID, cc); err != nil { - t.Error(err.Error()) - } - if ccRcv, err := mysqlDb.GetCallCostLog(CGRID, utils.TEST_SQL, utils.DEFAULT_RUNID); err != nil { - t.Error(err.Error()) - } else if !reflect.DeepEqual(cc, ccRcv) { - t.Errorf("Expecting call cost: %v, received: %v", cc, ccRcv) - } -} - -func TestMySQLGetCDRs(t *testing.T) { - if !*testLocal { - return - } - var timeStart, timeEnd time.Time - // All CDRs, no filter - if storedCdrs, _, err := mysqlDb.GetCDRs(new(utils.CDRsFilter)); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Count ALL - if storedCdrs, count, err := mysqlDb.GetCDRs(&utils.CDRsFilter{Count: true}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 0 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } else if count != 8 { - t.Error("Unexpected count of StoredCdrs returned: ", count) - } - // Limit 5 - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 5 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Offset 5 - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 5 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Offset with limit 2 - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(2), Offset: utils.IntPointer(5)}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 2 { - t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs)) - } - // Filter on CGRIDs - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 2 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Count on CGRIDS - if _, count, err := mysqlDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, Count: true}); err != nil { - t.Error(err.Error()) - } else if count != 2 { - t.Error("Unexpected count of StoredCdrs returned: ", count) - } - // Filter on CGRIDs plus RequestType - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, RequestTypes: []string{utils.META_PREPAID}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 1 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Count on multiple filter - if _, count, err := mysqlDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, RequestTypes: []string{utils.META_PREPAID}, Count: true}); err != nil { - t.Error(err.Error()) - } else if count != 1 { - t.Error("Unexpected count of StoredCdrs returned: ", count) - } - // Filter on runId - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{RunIDs: []string{utils.DEFAULT_RUNID}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 2 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on TOR - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{TORs: []string{utils.SMS}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 0 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple TOR - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{TORs: []string{utils.SMS, utils.VOICE}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on OriginHost - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{OriginHosts: []string{"192.168.1.2"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 3 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple OriginHost - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{OriginHosts: []string{"192.168.1.1", "192.168.1.2"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on Source - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{Sources: []string{"UNKNOWN"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 1 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple Source - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{Sources: []string{"UNKNOWN", "UNKNOWN2"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 2 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on RequestType - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_PREPAID}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 2 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple RequestType - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_PREPAID, utils.META_PSEUDOPREPAID}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 3 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on direction - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{Directions: []string{"*out"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on tenant - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{Tenants: []string{"itsyscom.com"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 3 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple tenants - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{Tenants: []string{"itsyscom.com", "cgrates.org"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on category - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{Categories: []string{"premium_call"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 1 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple categories - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{Categories: []string{"premium_call", "call"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on account - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{Accounts: []string{"1002"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 3 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple account - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{Accounts: []string{"1001", "1002"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on subject - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{Subjects: []string{"1000"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 1 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple subject - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{Subjects: []string{"1000", "1002"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 3 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on destPrefix - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{DestinationPrefixes: []string{"+498651"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 3 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple DestinationPrefixes - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{DestinationPrefixes: []string{"1001", "+498651"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 4 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on ignoreRated - var OrderIDStart, OrderIDEnd int64 // Capture also orderIds for the next test - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{MaxCost: utils.Float64Pointer(0.0)}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 5 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } else { - for _, cdr := range storedCdrs { - if cdr.OrderID < OrderIDStart { - OrderIDStart = cdr.OrderID - } - if cdr.OrderID > OrderIDEnd { - OrderIDEnd = cdr.OrderID - } - } - } - // Filter on OrderIDStart - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{OrderIDStart: OrderIDStart}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on OrderIDStart and OrderIDEnd - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{OrderIDStart: OrderIDStart, OrderIDEnd: OrderIDEnd}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 4 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on timeStart - timeStart = time.Date(2013, 11, 8, 8, 0, 0, 0, time.UTC) - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{AnswerTimeStart: &timeStart}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 5 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on timeStart and timeEnd - timeEnd = time.Date(2013, 12, 1, 8, 0, 0, 0, time.UTC) - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 2 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on minPDD - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{MinPDD: utils.Float64Pointer(3)}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 7 { - t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs)) - } - // Filter on maxPDD - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{MaxPDD: utils.Float64Pointer(3)}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 1 { - t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs)) - } - // Filter on minPDD, maxPDD - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{MinPDD: utils.Float64Pointer(3), MaxPDD: utils.Float64Pointer(5)}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 5 { - t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs)) - } - // Combined filter - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_RATED}, AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 1 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on ignoreDerived - if storedCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd, FilterOnRated: true}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 0 { // ToDo: Recheck this value - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } -} - -func TestMySQLRemCDRs(t *testing.T) { - if !*testLocal { - return - } - CGRIDB1 := utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()) - if err := mysqlDb.RemCDRs([]string{CGRIDB1}); err != nil { - t.Error(err.Error()) - } - if storedCdrs, _, err := mysqlDb.GetCDRs(new(utils.CDRsFilter)); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 7 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - tm, _ := utils.ParseTimeDetectLayout("2013-11-08T08:42:20Z", "") - CGRIDA1 := utils.Sha1("aaa1", tm.String()) - tm, _ = utils.ParseTimeDetectLayout("2013-11-08T08:42:22Z", "") - CGRIDA2 := utils.Sha1("aaa2", tm.String()) - tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:24Z", "") - CGRIDA3 := utils.Sha1("aaa3", tm.String()) - tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:21Z", "") - CGRIDA4 := utils.Sha1("aaa4", tm.String()) - tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:25Z", "") - CGRIDA5 := utils.Sha1("aaa5", tm.String()) - CGRIDB2 := utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()) - CGRIDB3 := utils.Sha1("bbb3", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()) - if err := mysqlDb.RemCDRs([]string{CGRIDA1, CGRIDA2, CGRIDA3, CGRIDA4, CGRIDA5, - CGRIDB2, CGRIDB3}); err != nil { - t.Error(err.Error()) - } - if storedCdrs, _, err := mysqlDb.GetCDRs(new(utils.CDRsFilter)); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 0 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } -} - -// Make sure that what we get is what we set -func TestMySQLStoreRestoreCdr(t *testing.T) { - if !*testLocal { - return - } - strCdr := &CDR{TOR: utils.VOICE, OriginID: "ccc1", OriginHost: "192.168.1.1", Source: "TEST_CDR", RequestType: utils.META_RATED, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(3) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 1.201} - strCdr.CGRID = utils.Sha1(strCdr.OriginID, strCdr.SetupTime.String()) - if err := mysqlDb.SetCdr(strCdr); err != nil { - t.Error(err.Error()) - } - if err := mysqlDb.SetRatedCdr(strCdr); err != nil { - t.Error(err.Error()) - } - // Check RawCdr - if rcvCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{strCdr.CGRID}}); err != nil { - t.Error(err.Error()) - } else if len(rcvCdrs) != 1 { - t.Errorf("Unexpected cdrs returned: %+v", rcvCdrs) - } else { - rcvCdr := rcvCdrs[0] - if strCdr.CGRID != rcvCdr.CGRID || - strCdr.TOR != rcvCdr.TOR || - strCdr.OriginID != rcvCdr.OriginID || - strCdr.OriginHost != rcvCdr.OriginHost || - strCdr.RequestType != rcvCdr.RequestType || - strCdr.Direction != rcvCdr.Direction || - strCdr.Tenant != rcvCdr.Tenant || - strCdr.Category != rcvCdr.Category || - strCdr.Account != rcvCdr.Account || - strCdr.Subject != rcvCdr.Subject || - strCdr.Destination != rcvCdr.Destination || - !strCdr.SetupTime.Equal(rcvCdr.SetupTime) || - !strCdr.AnswerTime.Equal(rcvCdr.AnswerTime) || - strCdr.Usage != rcvCdr.Usage || - strCdr.PDD != rcvCdr.PDD || - strCdr.Supplier != rcvCdr.Supplier || - strCdr.DisconnectCause != rcvCdr.DisconnectCause || - !reflect.DeepEqual(strCdr.ExtraFields, rcvCdr.ExtraFields) { - t.Errorf("Expecting: %+v, received: %+v", strCdr, rcvCdrs[0]) - } - } - // Check RatedCdr - if rcvCdrs, _, err := mysqlDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{strCdr.CGRID}, FilterOnRated: true}); err != nil { - t.Error(err.Error()) - } else if len(rcvCdrs) != 1 { - t.Errorf("Unexpected cdrs returned: %+v", rcvCdrs) - } else { - rcvCdr := rcvCdrs[0] - if strCdr.CGRID != rcvCdr.CGRID || - strCdr.TOR != rcvCdr.TOR || - strCdr.OriginID != rcvCdr.OriginID || - strCdr.OriginHost != rcvCdr.OriginHost || - strCdr.RequestType != rcvCdr.RequestType || - strCdr.Direction != rcvCdr.Direction || - strCdr.Tenant != rcvCdr.Tenant || - strCdr.Category != rcvCdr.Category || - strCdr.Account != rcvCdr.Account || - strCdr.Subject != rcvCdr.Subject || - strCdr.Destination != rcvCdr.Destination || - //!strCdr.SetupTime.Equal(rcvCdr.SetupTime) || // FixMe - //!strCdr.AnswerTime.Equal(rcvCdr.AnswerTime) || // FixMe - strCdr.Usage != rcvCdr.Usage || - strCdr.PDD != rcvCdr.PDD || - strCdr.Supplier != rcvCdr.Supplier || - strCdr.DisconnectCause != rcvCdr.DisconnectCause || - strCdr.Cost != rcvCdr.Cost || - !reflect.DeepEqual(strCdr.ExtraFields, rcvCdr.ExtraFields) { - t.Errorf("Expecting: %+v, received: %+v", strCdr, rcvCdrs[0]) - } - } -} diff --git a/engine/storage_psql_local_test.go b/engine/storage_psql_local_test.go deleted file mode 100644 index a59c7fe36..000000000 --- a/engine/storage_psql_local_test.go +++ /dev/null @@ -1,971 +0,0 @@ -/* -Rating system designed to be used in VoIP Carriers World -Copyright (C) 2012-2015 ITsysCOM - -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 engine - -import ( - "fmt" - "path" - "reflect" - "testing" - "time" - - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/utils" -) - -var psqlDb *PostgresStorage - -func TestPSQLCreateTables(t *testing.T) { - if !*testLocal { - return - } - cgrConfig, _ := config.NewDefaultCGRConfig() - var err error - if psqlDb, err = NewPostgresStorage("localhost", "5432", cgrConfig.StorDBName, cgrConfig.StorDBUser, cgrConfig.StorDBPass, - cgrConfig.StorDBMaxOpenConns, cgrConfig.StorDBMaxIdleConns); err != nil { - t.Error("Error on opening database connection: ", err) - return - } - for _, scriptName := range []string{utils.CREATE_CDRS_TABLES_SQL, utils.CREATE_TARIFFPLAN_TABLES_SQL} { - if err := psqlDb.CreateTablesFromScript(path.Join(*dataDir, "storage", utils.POSTGRES, scriptName)); err != nil { - t.Error("Error on psqlDb creation: ", err.Error()) - return // No point in going further - } - } - if _, err := psqlDb.Db.Query(fmt.Sprintf("SELECT 1 from %s", utils.TBL_CDRS)); err != nil { - t.Error(err.Error()) - } -} - -func TestPSQLSetGetTPTiming(t *testing.T) { - if !*testLocal { - return - } - tm := &utils.ApierTPTiming{TPid: utils.TEST_SQL, TimingId: "ALWAYS", Time: "00:00:00"} - mtm := APItoModelTiming(tm) - mtms := []TpTiming{*mtm} - if err := psqlDb.SetTpTimings(mtms); err != nil { - t.Error(err.Error()) - } - if tmgs, err := psqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mtms[0], tmgs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mtms, tmgs) - } - // Update - tm.Time = "00:00:01" - if err := psqlDb.SetTpTimings(mtms); err != nil { - t.Error(err.Error()) - } - if tmgs, err := psqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mtms[0], tmgs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mtms, tmgs) - } -} - -func TestPSQLSetGetTPDestination(t *testing.T) { - if !*testLocal { - return - } - dst := &utils.TPDestination{TPid: utils.TEST_SQL, DestinationId: utils.TEST_SQL, Prefixes: []string{"+49", "+49151", "+49176"}} - dests := APItoModelDestination(dst) - if err := psqlDb.SetTpDestinations(dests); err != nil { - t.Error(err.Error()) - } - storData, err := psqlDb.GetTpDestinations(utils.TEST_SQL, utils.TEST_SQL) - dsts, err := TpDestinations(storData).GetDestinations() - if err != nil { - t.Error(err.Error()) - } else if len(dst.Prefixes) != len(dsts[utils.TEST_SQL].Prefixes) { - t.Errorf("Expecting: %+v, received: %+v", dst, dsts[utils.TEST_SQL]) - } -} - -func TestPSQLSetGetTPRates(t *testing.T) { - if !*testLocal { - return - } - RT_ID := "RT_1" - rtSlots := []*utils.RateSlot{ - &utils.RateSlot{ConnectFee: 0.02, Rate: 0.01, RateUnit: "60s", RateIncrement: "60s", GroupIntervalStart: "0s"}, - &utils.RateSlot{ConnectFee: 0.00, Rate: 0.005, RateUnit: "60s", RateIncrement: "1s", GroupIntervalStart: "60s"}, - } - for _, rs := range rtSlots { - rs.SetDurations() - } - expectedTPRate := &utils.TPRate{TPid: utils.TEST_SQL, RateId: RT_ID, RateSlots: rtSlots} - mRates := APItoModelRate(expectedTPRate) - if err := psqlDb.SetTpRates(mRates); err != nil { - t.Error(err.Error()) - } - rts, err := psqlDb.GetTpRates(utils.TEST_SQL, RT_ID) - trts, err := TpRates(rts).GetRates() - if err != nil { - t.Error(err.Error()) - } else if len(expectedTPRate.RateSlots) != len(trts[RT_ID].RateSlots) { - t.Errorf("Expecting: %+v, received: %+v", expectedTPRate, trts[RT_ID]) - } -} - -func TestPSQLSetGetTPDestinationRates(t *testing.T) { - if !*testLocal { - return - } - DR_ID := "DR_1" - dr := &utils.DestinationRate{DestinationId: "DST_1", RateId: "RT_1", RoundingMethod: "*up", RoundingDecimals: 4} - eDrs := &utils.TPDestinationRate{TPid: utils.TEST_SQL, DestinationRateId: DR_ID, DestinationRates: []*utils.DestinationRate{dr}} - mdrs := APItoModelDestinationRate(eDrs) - if err := psqlDb.SetTpDestinationRates(mdrs); err != nil { - t.Error(err.Error()) - } - if drs, err := psqlDb.GetTpDestinationRates(utils.TEST_SQL, DR_ID, nil); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mdrs[0], drs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mdrs, drs) - } -} - -func TestPSQLSetGetTPRatingPlans(t *testing.T) { - if !*testLocal { - return - } - RP_ID := "RP_1" - rbBinding := &utils.TPRatingPlanBinding{DestinationRatesId: "DR_1", TimingId: "TM_1", Weight: 10.0} - rp := &utils.TPRatingPlan{ - TPid: utils.TEST_SQL, - RatingPlanId: RP_ID, - RatingPlanBindings: []*utils.TPRatingPlanBinding{rbBinding}, - } - mrp := APItoModelRatingPlan(rp) - - if err := psqlDb.SetTpRatingPlans(mrp); err != nil { - t.Error(err.Error()) - } - if drps, err := psqlDb.GetTpRatingPlans(utils.TEST_SQL, RP_ID, nil); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mrp[0], drps[0]) { - t.Errorf("Expecting: %+v, received: %+v", mrp, drps) - } -} - -func TestPSQLSetGetTPRatingProfiles(t *testing.T) { - if !*testLocal { - return - } - ras := []*utils.TPRatingActivation{&utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId: "RP_1"}} - rp := &utils.TPRatingProfile{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Category: "call", Direction: "*out", Subject: "*any", RatingPlanActivations: ras} - - mrp := APItoModelRatingProfile(rp) - if err := psqlDb.SetTpRatingProfiles(mrp); err != nil { - t.Error(err.Error()) - } - if rps, err := psqlDb.GetTpRatingProfiles(&mrp[0]); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mrp[0], rps[0]) { - t.Errorf("Expecting: %+v, received: %+v", mrp, rps) - } -} - -func TestPSQLSetGetTPSharedGroups(t *testing.T) { - if !*testLocal { - return - } - SG_ID := "SG_1" - tpSgs := &utils.TPSharedGroups{ - TPid: utils.TEST_SQL, - SharedGroupsId: SG_ID, - SharedGroups: []*utils.TPSharedGroup{ - &utils.TPSharedGroup{Account: "dan", Strategy: "*lowest_first", RatingSubject: "lowest_rates"}, - }, - } - mSgs := APItoModelSharedGroup(tpSgs) - if err := psqlDb.SetTpSharedGroups(mSgs); err != nil { - t.Error(err.Error()) - } - if sgs, err := psqlDb.GetTpSharedGroups(utils.TEST_SQL, SG_ID); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mSgs[0], sgs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mSgs, sgs) - } -} - -func TestPSQLSetGetTPCdrStats(t *testing.T) { - if !*testLocal { - return - } - CS_ID := "CDRSTATS_1" - setCS := &utils.TPCdrStats{ - TPid: utils.TEST_SQL, - CdrStatsId: CS_ID, - CdrStats: []*utils.TPCdrStat{ - &utils.TPCdrStat{QueueLength: "10", TimeWindow: "10m", Metrics: "ASR", Tenants: "cgrates.org", Categories: "call"}, - }, - } - mcs := APItoModelCdrStat(setCS) - if err := psqlDb.SetTpCdrStats(mcs); err != nil { - t.Error(err.Error()) - } - if cs, err := psqlDb.GetTpCdrStats(utils.TEST_SQL, CS_ID); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mcs[0], cs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mcs, cs) - } -} - -func TestPSQLSetGetTPDerivedChargers(t *testing.T) { - if !*testLocal { - return - } - dc := &utils.TPDerivedCharger{RunId: utils.DEFAULT_RUNID, ReqTypeField: "^" + utils.META_PREPAID, AccountField: "^rif", SubjectField: "^rif", - UsageField: "cgr_duration", SupplierField: "^supplier1"} - dcs := &utils.TPDerivedChargers{TPid: utils.TEST_SQL, Direction: utils.OUT, Tenant: "cgrates.org", Category: "call", Account: "dan", Subject: "dan", DerivedChargers: []*utils.TPDerivedCharger{dc}} - mdcs := APItoModelDerivedCharger(dcs) - if err := psqlDb.SetTpDerivedChargers(mdcs); err != nil { - t.Error(err.Error()) - } - if rDCs, err := psqlDb.GetTpDerivedChargers(&mdcs[0]); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mdcs[0], rDCs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mdcs, rDCs) - } -} - -func TestPSQLSetGetTPActions(t *testing.T) { - if !*testLocal { - return - } - ACTS_ID := "PREPAID_10" - acts := []*utils.TPAction{ - &utils.TPAction{Identifier: "*topup_reset", BalanceType: "*monetary", Directions: "*out", Units: 10, ExpiryTime: "*unlimited", - DestinationIds: "*any", BalanceWeight: 10, Weight: 10}} - tpActions := &utils.TPActions{TPid: utils.TEST_SQL, ActionsId: ACTS_ID, Actions: acts} - mas := APItoModelAction(tpActions) - if err := psqlDb.SetTpActions(mas); err != nil { - t.Error(err.Error()) - } - if rTpActs, err := psqlDb.GetTpActions(utils.TEST_SQL, ACTS_ID); err != nil { - t.Error(err.Error()) - } else if !modelEqual(mas[0], rTpActs[0]) { - t.Errorf("Expecting: %+v, received: %+v", mas, rTpActs) - } -} - -func TestPSQLTPActionTimings(t *testing.T) { - if !*testLocal { - return - } - AP_ID := "AP_1" - ap := &utils.TPActionPlan{ - TPid: utils.TEST_SQL, - ActionPlanId: AP_ID, - ActionPlan: []*utils.TPActionTiming{&utils.TPActionTiming{ActionsId: "ACTS_1", TimingId: "TM_1", Weight: 10.0}}, - } - maps := APItoModelActionPlan(ap) - if err := psqlDb.SetTpActionPlans(maps); err != nil { - t.Error(err.Error()) - } - if rAP, err := psqlDb.GetTpActionPlans(utils.TEST_SQL, AP_ID); err != nil { - t.Error(err.Error()) - } else if !modelEqual(maps[0], rAP[0]) { - t.Errorf("Expecting: %+v, received: %+v", maps, rAP) - } -} - -func TestPSQLSetGetTPActionTriggers(t *testing.T) { - if !*testLocal { - return - } - atrg := &utils.TPActionTrigger{ - Id: "MY_FIRST_ATGR", - BalanceType: "*monetary", - BalanceDirections: "*out", - ThresholdType: "*min_balance", - ThresholdValue: 2.0, - Recurrent: true, - BalanceDestinationIds: "*any", - Weight: 10.0, - ActionsId: "LOG_BALANCE", - } - atrgs := &utils.TPActionTriggers{ - TPid: utils.TEST_SQL, - ActionTriggersId: utils.TEST_SQL, - ActionTriggers: []*utils.TPActionTrigger{atrg}, - } - matrg := APItoModelActionTrigger(atrgs) - if err := psqlDb.SetTpActionTriggers(matrg); err != nil { - t.Error("Unexpected error: ", err.Error()) - } - if rcvMpAtrgs, err := psqlDb.GetTpActionTriggers(utils.TEST_SQL, utils.TEST_SQL); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if !modelEqual(matrg[0], rcvMpAtrgs[0]) { - t.Errorf("Expecting: %+v, received: %+v", matrg, rcvMpAtrgs) - } -} - -func TestPSQLSetGetTpAccountActions(t *testing.T) { - if !*testLocal { - return - } - aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001", - ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"} - maa := APItoModelAccountAction(aa) - if err := psqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil { - t.Error(err.Error()) - } - if aas, err := psqlDb.GetTpAccountActions(maa); err != nil { - t.Error(err.Error()) - } else if !modelEqual(*maa, aas[0]) { - t.Errorf("Expecting: %+v, received: %+v", maa, aas) - } -} - -func TestPSQLGetTPIds(t *testing.T) { - if !*testLocal { - return - } - eTPIds := []string{utils.TEST_SQL} - if tpIds, err := psqlDb.GetTpIds(); err != nil { - t.Error(err.Error()) - } else if !reflect.DeepEqual(eTPIds, tpIds) { - t.Errorf("Expecting: %+v, received: %+v", eTPIds, tpIds) - } -} - -func TestPSQLRemoveTPData(t *testing.T) { - if !*testLocal { - return - } - // Create Timings - tm := &utils.ApierTPTiming{TPid: utils.TEST_SQL, TimingId: "ALWAYS", Time: "00:00:00"} - tms := APItoModelTiming(tm) - if err := psqlDb.SetTpTimings([]TpTiming{*tms}); err != nil { - t.Error(err.Error()) - } - if tmgs, err := psqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil { - t.Error(err.Error()) - } else if len(tmgs) == 0 { - t.Error("Could not store TPTiming") - } - // Remove Timings - if err := psqlDb.RemTpData(utils.TBL_TP_TIMINGS, utils.TEST_SQL, map[string]string{"tag": tm.TimingId}); err != nil { - t.Error(err.Error()) - } - if tmgs, err := psqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil { - t.Error(err) - } else if len(tmgs) != 0 { - t.Errorf("Timings should be empty, got instead: %+v", tmgs) - } - // Create RatingProfile - ras := []*utils.TPRatingActivation{&utils.TPRatingActivation{ActivationTime: "2012-01-01T00:00:00Z", RatingPlanId: "RETAIL1"}} - rp := &utils.TPRatingProfile{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Category: "call", Direction: "*out", Subject: "*any", RatingPlanActivations: ras} - mrp := APItoModelRatingProfile(rp) - if err := psqlDb.SetTpRatingProfiles(mrp); err != nil { - t.Error(err.Error()) - } - if rps, err := psqlDb.GetTpRatingProfiles(&mrp[0]); err != nil { - t.Error(err.Error()) - } else if len(rps) == 0 { - t.Error("Could not store TPRatingProfile") - } - // Remove RatingProfile - if err := psqlDb.RemTpData(utils.TBL_TP_RATE_PROFILES, rp.TPid, map[string]string{"loadid": rp.LoadId, "direction": rp.Direction, "tenant": rp.Tenant, "category": rp.Category, "subject": rp.Subject}); err != nil { - t.Error(err.Error()) - } - if rps, err := psqlDb.GetTpRatingProfiles(&mrp[0]); err != nil { - t.Error(err) - } else if len(rps) != 0 { - t.Errorf("RatingProfiles different than 0: %+v", rps) - } - // Create AccountActions - aa := &utils.TPAccountActions{TPid: utils.TEST_SQL, LoadId: utils.TEST_SQL, Tenant: "cgrates.org", Account: "1001", - ActionPlanId: "PREPAID_10", ActionTriggersId: "STANDARD_TRIGGERS"} - maa := APItoModelAccountAction(aa) - if err := psqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil { - t.Error(err.Error()) - } - if aas, err := psqlDb.GetTpAccountActions(maa); err != nil { - t.Error(err.Error()) - } else if len(aas) == 0 { - t.Error("Could not create TPAccountActions") - } - // Remove AccountActions - if err := psqlDb.RemTpData(utils.TBL_TP_ACCOUNT_ACTIONS, aa.TPid, map[string]string{"loadid": aa.LoadId, "tenant": aa.Tenant, "account": aa.Account}); err != nil { - t.Error(err.Error()) - } - if aas, err := psqlDb.GetTpAccountActions(maa); err != nil { - t.Error(err) - } else if len(aas) != 0 { - t.Errorf("Non empty account actions: %+v", aas) - } - // Create again so we can test complete TP removal - if err := psqlDb.SetTpTimings([]TpTiming{*tms}); err != nil { - t.Error(err.Error()) - } - if tmgs, err := psqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil { - t.Error(err.Error()) - } else if len(tmgs) == 0 { - t.Error("Could not store TPTiming") - } - // Create RatingProfile - if err := psqlDb.SetTpRatingProfiles(mrp); err != nil { - t.Error(err.Error()) - } - if rps, err := psqlDb.GetTpRatingProfiles(&mrp[0]); err != nil { - t.Error(err.Error()) - } else if len(rps) == 0 { - t.Error("Could not store TPRatingProfile") - } - // Create AccountActions - if err := psqlDb.SetTpAccountActions([]TpAccountAction{*maa}); err != nil { - t.Error(err.Error()) - } - if aas, err := psqlDb.GetTpAccountActions(maa); err != nil { - t.Error(err.Error()) - } else if len(aas) == 0 { - t.Error("Could not create TPAccountActions") - } - // Remove TariffPlan completely - if err := psqlDb.RemTpData("", utils.TEST_SQL, nil); err != nil { - t.Error(err.Error()) - } - // Make sure we have removed it - if tms, err := psqlDb.GetTpTimings(utils.TEST_SQL, tm.TimingId); err != nil { - t.Error(err) - } else if len(tms) != 0 { - t.Errorf("Non empty timings: %+v", tms) - } - if rpfs, err := psqlDb.GetTpRatingProfiles(&mrp[0]); err != nil { - t.Error(err) - } else if len(rpfs) != 0 { - t.Errorf("Non empty rpfs: %+v", rpfs) - } - if aas, err := psqlDb.GetTpAccountActions(maa); err != nil { - t.Error(err) - } else if len(aas) != 0 { - t.Errorf("Non empty account actions: %+v", aas) - } -} - -func TestPSQLSetCdr(t *testing.T) { - if !*testLocal { - return - } - cgrCdr1 := &CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa1", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_RATED, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", - utils.CATEGORY: "call", utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "1002", utils.SETUP_TIME: "2013-11-08T08:42:20Z", - utils.ANSWER_TIME: "2013-11-08T08:42:26Z", utils.USAGE: "10s", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", utils.CDRSOURCE: utils.TEST_SQL} - - cgrCdr2 := &CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa2", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_PREPAID, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", - utils.CATEGORY: "call", utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "1002", utils.SETUP_TIME: "2013-11-08T08:42:22Z", - utils.ANSWER_TIME: "2013-11-08T08:42:26Z", utils.USAGE: "20", utils.PDD: "7s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL} - - cgrCdr3 := &CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa3", utils.CDRHOST: "192.168.1.1", utils.REQTYPE: utils.META_RATED, utils.DIRECTION: "*out", utils.TENANT: "cgrates.org", - utils.CATEGORY: "premium_call", utils.ACCOUNT: "1002", utils.SUBJECT: "1002", utils.DESTINATION: "1001", utils.SETUP_TIME: "2013-11-07T08:42:24Z", - utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "60s", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL} - - cgrCdr4 := &CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa4", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: utils.META_PSEUDOPREPAID, utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", - utils.CATEGORY: "call", utils.ACCOUNT: "1001", utils.SUBJECT: "1001", utils.DESTINATION: "+4986517174964", utils.SETUP_TIME: "2013-11-07T08:42:21Z", - utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "1m2s", utils.PDD: "4s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL} - - cgrCdr5 := &CgrCdr{utils.TOR: utils.VOICE, utils.ACCID: "aaa5", utils.CDRHOST: "192.168.1.2", utils.REQTYPE: utils.META_POSTPAID, utils.DIRECTION: "*out", utils.TENANT: "itsyscom.com", - utils.CATEGORY: "call", utils.ACCOUNT: "1002", utils.SUBJECT: "1002", utils.DESTINATION: "+4986517174963", utils.SETUP_TIME: "2013-11-07T08:42:25Z", - utils.ANSWER_TIME: "2013-11-07T08:42:26Z", utils.USAGE: "15s", utils.PDD: "7s", utils.SUPPLIER: "SUPPL1", "field_extr1": "val_extr1", "fieldextr2": "valextr2", "cdrsource": utils.TEST_SQL} - - for _, cdr := range []*CgrCdr{cgrCdr1, cgrCdr2, cgrCdr3, cgrCdr4, cgrCdr5} { - if err := psqlDb.SetCdr(cdr.AsStoredCdr("")); err != nil { - t.Error(err.Error()) - } - } - strCdr1 := &CDR{TOR: utils.VOICE, OriginID: "bbb1", OriginHost: "192.168.1.1", Source: "UNKNOWN", RequestType: utils.META_RATED, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(3) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 1.201} - strCdr1.CGRID = utils.Sha1(strCdr1.OriginID, strCdr1.SetupTime.String()) - strCdr2 := &CDR{TOR: utils.VOICE, OriginID: "bbb2", OriginHost: "192.168.1.2", Source: "UNKNOWN2", RequestType: utils.META_PREPAID, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(12) * time.Second, PDD: time.Duration(4) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 0.201} - strCdr2.CGRID = utils.Sha1(strCdr2.OriginID, strCdr2.SetupTime.String()) - strCdr3 := &CDR{TOR: utils.VOICE, OriginID: "bbb3", OriginHost: "192.168.1.1", Source: utils.TEST_SQL, RequestType: utils.META_RATED, - Direction: "*out", Tenant: "itsyscom.com", Category: "call", Account: "1002", Subject: "1000", Destination: "+4986517174963", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(2) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 1.201} - strCdr3.CGRID = utils.Sha1(strCdr3.OriginID, strCdr3.SetupTime.String()) - - for _, cdr := range []*CDR{strCdr1, strCdr2, strCdr3} { - if err := psqlDb.SetCdr(cdr); err != nil { - t.Error(err.Error()) - } - } -} - -func TestPSQLCallCost(t *testing.T) { - if !*testLocal { - return - } - CGRID := utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()) - cc := &CallCost{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "91001", - Account: "8001", - Destination: "1002", - TOR: utils.VOICE, - Timespans: []*TimeSpan{ - &TimeSpan{ - TimeStart: time.Date(2013, 9, 10, 13, 40, 0, 0, time.UTC), - TimeEnd: time.Date(2013, 9, 10, 13, 41, 0, 0, time.UTC), - }, - &TimeSpan{ - TimeStart: time.Date(2013, 9, 10, 13, 41, 0, 0, time.UTC), - TimeEnd: time.Date(2013, 9, 10, 13, 41, 30, 0, time.UTC), - }, - }, - } - if err := psqlDb.LogCallCost(CGRID, utils.TEST_SQL, utils.DEFAULT_RUNID, cc); err != nil { - t.Error(err.Error()) - } - if ccRcv, err := psqlDb.GetCallCostLog(CGRID, utils.TEST_SQL, utils.DEFAULT_RUNID); err != nil { - t.Error(err.Error()) - } else if !reflect.DeepEqual(cc, ccRcv) { - t.Errorf("Expecting call cost: %v, received: %v", cc, ccRcv) - } - // UPDATE test here - cc.Category = "premium_call" - if err := psqlDb.LogCallCost(CGRID, utils.TEST_SQL, utils.DEFAULT_RUNID, cc); err != nil { - t.Error(err.Error()) - } - if ccRcv, err := psqlDb.GetCallCostLog(CGRID, utils.TEST_SQL, utils.DEFAULT_RUNID); err != nil { - t.Error(err.Error()) - } else if !reflect.DeepEqual(cc, ccRcv) { - t.Errorf("Expecting call cost: %v, received: %v", cc, ccRcv) - } -} - -func TestPSQLSetRatedCdr(t *testing.T) { - if !*testLocal { - return - } - strCdr1 := &CDR{TOR: utils.VOICE, OriginID: "bbb1", OriginHost: "192.168.1.1", Source: "UNKNOWN", RequestType: utils.META_RATED, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(3) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 1.201} - strCdr1.CGRID = utils.Sha1(strCdr1.OriginID, strCdr1.SetupTime.String()) - strCdr2 := &CDR{TOR: utils.VOICE, OriginID: "bbb2", OriginHost: "192.168.1.2", Source: "UNKNOWN", RequestType: utils.META_PREPAID, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(12) * time.Second, PDD: time.Duration(7) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 0.201} - strCdr2.CGRID = utils.Sha1(strCdr2.OriginID, strCdr2.SetupTime.String()) - strCdr3 := &CDR{TOR: utils.VOICE, OriginID: "bbb3", OriginHost: "192.168.1.1", Source: utils.TEST_SQL, RequestType: utils.META_RATED, - Direction: "*out", Tenant: "itsyscom.com", Category: "call", Account: "1002", Subject: "1002", Destination: "+4986517174964", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(2) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: "wholesale_run", Cost: 1.201} - strCdr3.CGRID = utils.Sha1(strCdr3.OriginID, strCdr3.SetupTime.String()) - - for _, cdr := range []*CDR{strCdr1, strCdr2, strCdr3} { - if err := psqlDb.SetRatedCdr(cdr); err != nil { - t.Error(err.Error()) - } - } -} - -func TestPSQLGetCDRs(t *testing.T) { - if !*testLocal { - return - } - var timeStart, timeEnd time.Time - // All CDRs, no filter - if storedCdrs, _, err := psqlDb.GetCDRs(new(utils.CDRsFilter)); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Count ALL - if storedCdrs, count, err := psqlDb.GetCDRs(&utils.CDRsFilter{Count: true}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 0 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } else if count != 8 { - t.Error("Unexpected count of StoredCdrs returned: ", count) - } - // Limit 5 - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 5 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Offset 5 - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(5), Offset: utils.IntPointer(0)}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 5 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Offset with limit 2 - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{Paginator: utils.Paginator{Limit: utils.IntPointer(2), Offset: utils.IntPointer(5)}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 2 { - t.Error("Unexpected number of StoredCdrs returned: ", len(storedCdrs)) - } - // Filter on CGRIDs - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 2 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Count on CGRIDS - if _, count, err := psqlDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, Count: true}); err != nil { - t.Error(err.Error()) - } else if count != 2 { - t.Error("Unexpected count of StoredCdrs returned: ", count) - } - // Filter on CGRIDs plus RequestType - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, RequestTypes: []string{utils.META_PREPAID}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 1 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Count on multiple filter - if _, count, err := psqlDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String())}, RequestTypes: []string{utils.META_PREPAID}, Count: true}); err != nil { - t.Error(err.Error()) - } else if count != 1 { - t.Error("Unexpected count of StoredCdrs returned: ", count) - } - // Filter on runId - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{RunIDs: []string{utils.DEFAULT_RUNID}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 2 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on TOR - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{TORs: []string{utils.SMS}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 0 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple TOR - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{TORs: []string{utils.SMS, utils.VOICE}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on OriginHost - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{OriginHosts: []string{"192.168.1.2"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 3 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple OriginHost - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{OriginHosts: []string{"192.168.1.1", "192.168.1.2"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on Source - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{Sources: []string{"UNKNOWN"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 1 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple Source - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{Sources: []string{"UNKNOWN", "UNKNOWN2"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 2 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on RequestType - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_PREPAID}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 2 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple RequestType - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_PREPAID, utils.META_PSEUDOPREPAID}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 3 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on direction - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{Directions: []string{"*out"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on tenant - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{Tenants: []string{"itsyscom.com"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 3 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple tenants - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{Tenants: []string{"itsyscom.com", "cgrates.org"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on category - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{Categories: []string{"premium_call"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 1 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple categories - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{Categories: []string{"premium_call", "call"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on account - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{Accounts: []string{"1002"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 3 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple account - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{Accounts: []string{"1001", "1002"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on subject - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{Subjects: []string{"1000"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 1 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple subject - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{Subjects: []string{"1000", "1002"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 3 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on destPrefix - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{DestinationPrefixes: []string{"+498651"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 3 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on multiple DestinationPrefixes - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{DestinationPrefixes: []string{"1001", "+498651"}}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 4 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on ignoreRated - var OrderIDStart, OrderIDEnd int64 // Capture also orderIds for the next test - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{MaxCost: utils.Float64Pointer(0.0)}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 5 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } else { - for _, cdr := range storedCdrs { - if cdr.OrderID < OrderIDStart { - OrderIDStart = cdr.OrderID - } - if cdr.OrderID > OrderIDEnd { - OrderIDEnd = cdr.OrderID - } - } - } - // Filter on OrderIDStart - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{OrderIDStart: OrderIDStart}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 8 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on OrderIDStart and OrderIDEnd - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{OrderIDStart: OrderIDStart, OrderIDEnd: OrderIDEnd}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 4 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on timeStart - timeStart = time.Date(2013, 11, 8, 8, 0, 0, 0, time.UTC) - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{AnswerTimeStart: &timeStart}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 5 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on timeStart and timeEnd - timeEnd = time.Date(2013, 12, 1, 8, 0, 0, 0, time.UTC) - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 2 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on minPDD - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{MinPDD: utils.Float64Pointer(3)}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 7 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on maxPDD - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{MaxPDD: utils.Float64Pointer(3)}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 1 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on minPDD, maxPDD - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{MinPDD: utils.Float64Pointer(3), MaxPDD: utils.Float64Pointer(5)}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 5 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Combined filter - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{RequestTypes: []string{utils.META_RATED}, AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 1 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - // Filter on ignoreDerived - if storedCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{AnswerTimeStart: &timeStart, AnswerTimeEnd: &timeEnd, FilterOnRated: true}); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 0 { // ToDo: Recheck this value - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } -} - -func TestPSQLRemCDRs(t *testing.T) { - if !*testLocal { - return - } - CGRIDB1 := utils.Sha1("bbb1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()) - if err := psqlDb.RemCDRs([]string{CGRIDB1}); err != nil { - t.Error(err.Error()) - } - if storedCdrs, _, err := psqlDb.GetCDRs(new(utils.CDRsFilter)); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 7 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } - tm, _ := utils.ParseTimeDetectLayout("2013-11-08T08:42:20Z", "") - CGRIDA1 := utils.Sha1("aaa1", tm.String()) - tm, _ = utils.ParseTimeDetectLayout("2013-11-08T08:42:22Z", "") - CGRIDA2 := utils.Sha1("aaa2", tm.String()) - tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:24Z", "") - CGRIDA3 := utils.Sha1("aaa3", tm.String()) - tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:21Z", "") - CGRIDA4 := utils.Sha1("aaa4", tm.String()) - tm, _ = utils.ParseTimeDetectLayout("2013-11-07T08:42:25Z", "") - CGRIDA5 := utils.Sha1("aaa5", tm.String()) - CGRIDB2 := utils.Sha1("bbb2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()) - CGRIDB3 := utils.Sha1("bbb3", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()) - if err := psqlDb.RemCDRs([]string{CGRIDA1, CGRIDA2, CGRIDA3, CGRIDA4, CGRIDA5, - CGRIDB2, CGRIDB3}); err != nil { - t.Error(err.Error()) - } - if storedCdrs, _, err := psqlDb.GetCDRs(new(utils.CDRsFilter)); err != nil { - t.Error(err.Error()) - } else if len(storedCdrs) != 0 { - t.Error("Unexpected number of StoredCdrs returned: ", storedCdrs) - } -} - -// Make sure that what we get is what we set -func TestPSQLStoreRestoreCdr(t *testing.T) { - if !*testLocal { - return - } - strCdr := &CDR{TOR: utils.VOICE, OriginID: "ccc1", OriginHost: "192.168.1.1", Source: "TEST_CDR", RequestType: utils.META_RATED, - Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", - SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(10) * time.Second, PDD: time.Duration(3) * time.Second, Supplier: "SUPPL1", - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - RunID: utils.DEFAULT_RUNID, Cost: 1.201} - strCdr.CGRID = utils.Sha1(strCdr.OriginID, strCdr.SetupTime.String()) - if err := psqlDb.SetCdr(strCdr); err != nil { - t.Error(err.Error()) - } - if err := psqlDb.SetRatedCdr(strCdr); err != nil { - t.Error(err.Error()) - } - // Check RawCdr - if rcvCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{strCdr.CGRID}}); err != nil { - t.Error(err.Error()) - } else if len(rcvCdrs) != 1 { - t.Errorf("Unexpected cdrs returned: %+v", rcvCdrs) - } else { - rcvCdr := rcvCdrs[0] - if strCdr.CGRID != rcvCdr.CGRID || - strCdr.TOR != rcvCdr.TOR || - strCdr.OriginID != rcvCdr.OriginID || - strCdr.OriginHost != rcvCdr.OriginHost || - strCdr.RequestType != rcvCdr.RequestType || - strCdr.Direction != rcvCdr.Direction || - strCdr.Tenant != rcvCdr.Tenant || - strCdr.Category != rcvCdr.Category || - strCdr.Account != rcvCdr.Account || - strCdr.Subject != rcvCdr.Subject || - strCdr.Destination != rcvCdr.Destination || - !strCdr.SetupTime.Equal(rcvCdr.SetupTime) || - !strCdr.AnswerTime.Equal(rcvCdr.AnswerTime) || - strCdr.Usage != rcvCdr.Usage || - strCdr.PDD != rcvCdr.PDD || - strCdr.Supplier != rcvCdr.Supplier || - strCdr.DisconnectCause != rcvCdr.DisconnectCause || - !reflect.DeepEqual(strCdr.ExtraFields, rcvCdr.ExtraFields) { - t.Errorf("Expecting: %+v, received: %+v", strCdr, rcvCdrs[0]) - } - } - // Check RatedCdr - if rcvCdrs, _, err := psqlDb.GetCDRs(&utils.CDRsFilter{CGRIDs: []string{strCdr.CGRID}, FilterOnRated: true}); err != nil { - t.Error(err.Error()) - } else if len(rcvCdrs) != 1 { - t.Errorf("Unexpected cdrs returned: %+v", rcvCdrs) - } else { - rcvCdr := rcvCdrs[0] - if strCdr.CGRID != rcvCdr.CGRID || - strCdr.TOR != rcvCdr.TOR || - strCdr.OriginID != rcvCdr.OriginID || - strCdr.OriginHost != rcvCdr.OriginHost || - strCdr.RequestType != rcvCdr.RequestType || - strCdr.Direction != rcvCdr.Direction || - strCdr.Tenant != rcvCdr.Tenant || - strCdr.Category != rcvCdr.Category || - strCdr.Account != rcvCdr.Account || - strCdr.Subject != rcvCdr.Subject || - strCdr.Destination != rcvCdr.Destination || - //!strCdr.SetupTime.Equal(rcvCdr.SetupTime) || // FixMe - //!strCdr.AnswerTime.Equal(rcvCdr.AnswerTime) || // FixMe - strCdr.Usage != rcvCdr.Usage || - strCdr.PDD != rcvCdr.PDD || - strCdr.Supplier != rcvCdr.Supplier || - strCdr.DisconnectCause != rcvCdr.DisconnectCause || - strCdr.Cost != rcvCdr.Cost || - !reflect.DeepEqual(strCdr.ExtraFields, rcvCdr.ExtraFields) { - t.Errorf("Expecting: %+v, received: %+v", strCdr, rcvCdrs[0]) - } - } -} diff --git a/engine/storage_sql.go b/engine/storage_sql.go index 3ec0bd0b3..f152cc890 100644 --- a/engine/storage_sql.go +++ b/engine/storage_sql.go @@ -590,7 +590,7 @@ func (self *SQLStorage) LogCallCost(cgrid, source, runid string, cc *CallCost) ( Subject: cc.Subject, Destination: cc.Destination, Cost: cc.Cost, - Timespans: string(tss), + CostDetails: string(tss), CostSource: source, CreatedAt: time.Now(), } @@ -599,7 +599,7 @@ func (self *SQLStorage) LogCallCost(cgrid, source, runid string, cc *CallCost) ( tx.Rollback() tx = self.db.Begin() updated := tx.Model(TBLCDRs{}).Where(&TBLCDRs{Cgrid: cgrid, RunID: runid}).Updates(&TBLCDRs{Tor: cc.TOR, Direction: cc.Direction, Tenant: cc.Tenant, Category: cc.Category, - Account: cc.Account, Subject: cc.Subject, Destination: cc.Destination, Cost: cc.Cost, Timespans: string(tss), CostSource: source, UpdatedAt: time.Now()}) + Account: cc.Account, Subject: cc.Subject, Destination: cc.Destination, Cost: cc.Cost, CostDetails: string(tss), CostSource: source, UpdatedAt: time.Now()}) if updated.Error != nil { tx.Rollback() return updated.Error @@ -614,7 +614,7 @@ func (self *SQLStorage) GetCallCostLog(cgrid, source, runid string) (*CallCost, if err := self.db.Where(&TBLCDRs{Cgrid: cgrid, RunID: runid, CostSource: source}).First(&tpCostDetail).Error; err != nil { return nil, err } - if len(tpCostDetail.Timespans) == 0 { + if len(tpCostDetail.CostDetails) == 0 { return nil, nil // No costs returned } cc := new(CallCost) @@ -626,7 +626,7 @@ func (self *SQLStorage) GetCallCostLog(cgrid, source, runid string) (*CallCost, cc.Subject = tpCostDetail.Subject cc.Destination = tpCostDetail.Destination cc.Cost = tpCostDetail.Cost - if err := json.Unmarshal([]byte(tpCostDetail.Timespans), &cc.Timespans); err != nil { + if err := json.Unmarshal([]byte(tpCostDetail.CostDetails), &cc.Timespans); err != nil { return nil, err } return cc, nil @@ -639,7 +639,7 @@ func (self *SQLStorage) LogActionPlan(source string, at *ActionPlan, as Actions) return } -func (self *SQLStorage) SetCdr(cdr *CDR) error { +func (self *SQLStorage) SetCDR(cdr *CDR, allowUpdate bool) error { extraFields, err := json.Marshal(cdr.ExtraFields) if err != nil { return err @@ -647,10 +647,11 @@ func (self *SQLStorage) SetCdr(cdr *CDR) error { tx := self.db.Begin() saved := tx.Save(&TBLCDRs{ Cgrid: cdr.CGRID, - Tor: cdr.TOR, - OriginID: cdr.OriginID, + RunID: cdr.RunID, OriginHost: cdr.OriginHost, Source: cdr.Source, + OriginID: cdr.OriginID, + Tor: cdr.TOR, RequestType: cdr.RequestType, Direction: cdr.Direction, Tenant: cdr.Tenant, @@ -659,51 +660,51 @@ func (self *SQLStorage) SetCdr(cdr *CDR) error { Subject: cdr.Subject, Destination: cdr.Destination, SetupTime: cdr.SetupTime, + Pdd: cdr.PDD.Seconds(), AnswerTime: cdr.AnswerTime, Usage: cdr.Usage.Seconds(), - Pdd: cdr.PDD.Seconds(), Supplier: cdr.Supplier, DisconnectCause: cdr.DisconnectCause, ExtraFields: string(extraFields), - CreatedAt: time.Now()}) - if saved.Error != nil { - tx.Rollback() - return saved.Error - } - tx.Commit() - return nil -} - -func (self *SQLStorage) SetRatedCdr(cdr *CDR) (err error) { - tx := self.db.Begin() - saved := tx.Save(&TBLCDRs{ - Cgrid: cdr.CGRID, - RunID: cdr.RunID, - RequestType: cdr.RequestType, - Direction: cdr.Direction, - Tenant: cdr.Tenant, - Category: cdr.Category, - Account: cdr.Account, - Subject: cdr.Subject, - Destination: cdr.Destination, - SetupTime: cdr.SetupTime, - AnswerTime: cdr.AnswerTime, - Usage: cdr.Usage.Seconds(), - Pdd: cdr.PDD.Seconds(), - Supplier: cdr.Supplier, - DisconnectCause: cdr.DisconnectCause, + CostSource: cdr.CostSource, Cost: cdr.Cost, + CostDetails: cdr.CostDetailsJson(), ExtraInfo: cdr.ExtraInfo, CreatedAt: time.Now(), }) if saved.Error != nil { tx.Rollback() + if !allowUpdate { + return saved.Error + } tx = self.db.Begin() - updated := tx.Model(TBLCDRs{}).Where(&TBLCDRs{Cgrid: cdr.CGRID, RunID: cdr.RunID}).Updates(&TBLCDRs{RequestType: cdr.RequestType, - Direction: cdr.Direction, Tenant: cdr.Tenant, Category: cdr.Category, Account: cdr.Account, Subject: cdr.Subject, Destination: cdr.Destination, - SetupTime: cdr.SetupTime, AnswerTime: cdr.AnswerTime, Usage: cdr.Usage.Seconds(), Pdd: cdr.PDD.Seconds(), Supplier: cdr.Supplier, DisconnectCause: cdr.DisconnectCause, - Cost: cdr.Cost, ExtraInfo: cdr.ExtraInfo, - UpdatedAt: time.Now()}) + updated := tx.Model(TBLCDRs{}).Where(&TBLCDRs{Cgrid: cdr.CGRID, RunID: cdr.RunID}).Updates( + &TBLCDRs{ + OriginHost: cdr.OriginHost, + Source: cdr.Source, + OriginID: cdr.OriginID, + Tor: cdr.TOR, + RequestType: cdr.RequestType, + Direction: cdr.Direction, + Tenant: cdr.Tenant, + Category: cdr.Category, + Account: cdr.Account, + Subject: cdr.Subject, + Destination: cdr.Destination, + SetupTime: cdr.SetupTime, + Pdd: cdr.PDD.Seconds(), + AnswerTime: cdr.AnswerTime, + Usage: cdr.Usage.Seconds(), + Supplier: cdr.Supplier, + DisconnectCause: cdr.DisconnectCause, + ExtraFields: string(extraFields), + CostSource: cdr.CostSource, + Cost: cdr.Cost, + CostDetails: cdr.CostDetailsJson(), + ExtraInfo: cdr.ExtraInfo, + UpdatedAt: time.Now(), + }, + ) if updated.Error != nil { tx.Rollback() return updated.Error @@ -711,7 +712,6 @@ func (self *SQLStorage) SetRatedCdr(cdr *CDR) (err error) { } tx.Commit() return nil - } func (self *SQLStorage) GetCDRs(qryFltr *utils.CDRsFilter) ([]*CDR, int64, error) { @@ -937,14 +937,12 @@ func (self *SQLStorage) GetCDRs(qryFltr *utils.CDRsFilter) ([]*CDR, int64, error for _, result := range results { var extraFieldsMp map[string]string - var ccTimespans TimeSpans - if len(result.ExtraFields) != 0 { - if err := json.Unmarshal([]byte(result.ExtraFields), &extraFieldsMp); err != nil { - return nil, 0, fmt.Errorf("JSON unmarshal error for cgrid: %s, runid: %v, error: %s", result.Cgrid, result.RunID, err.Error()) - } + if err := json.Unmarshal([]byte(result.ExtraFields), &extraFieldsMp); err != nil { + return nil, 0, fmt.Errorf("JSON unmarshal error for cgrid: %s, runid: %v, error: %s", result.Cgrid, result.RunID, err.Error()) } - if len(result.Timespans) != 0 { - if err := json.Unmarshal([]byte(result.Timespans), &ccTimespans); err != nil { + var callCost CallCost + if len(result.CostDetails) != 0 { + if err := json.Unmarshal([]byte(result.CostDetails), &callCost); err != nil { return nil, 0, fmt.Errorf("JSON unmarshal callcost error for cgrid: %s, runid: %v, error: %s", result.Cgrid, result.RunID, err.Error()) } } @@ -952,11 +950,12 @@ func (self *SQLStorage) GetCDRs(qryFltr *utils.CDRsFilter) ([]*CDR, int64, error pddDur, _ := time.ParseDuration(strconv.FormatFloat(result.Pdd, 'f', -1, 64) + "s") storCdr := &CDR{ CGRID: result.Cgrid, + RunID: result.RunID, OrderID: result.ID, - TOR: result.Tor, - OriginID: result.OriginID, OriginHost: result.OriginHost, Source: result.Source, + OriginID: result.OriginID, + TOR: result.Tor, RequestType: result.RequestType, Direction: result.Direction, Tenant: result.Tenant, @@ -971,26 +970,11 @@ func (self *SQLStorage) GetCDRs(qryFltr *utils.CDRsFilter) ([]*CDR, int64, error Supplier: result.Supplier, DisconnectCause: result.DisconnectCause, ExtraFields: extraFieldsMp, - RunID: result.RunID, + CostSource: result.CostSource, Cost: result.Cost, + CostDetails: &callCost, ExtraInfo: result.ExtraInfo, } - if ccTimespans != nil { - storCdr.CostDetails = &CallCost{ - Direction: result.Direction, - Category: result.Category, - Tenant: result.Tenant, - Subject: result.Subject, - Account: result.Account, - Destination: result.Destination, - TOR: result.Tor, - Cost: result.Cost, - Timespans: ccTimespans, - } - } - //if !result.Cost.Valid { //There was no cost provided, will fakely insert 0 if we do not handle it and reflect on re-rating - storCdr.Cost = -1 - //} cdrs = append(cdrs, storCdr) } return cdrs, 0, nil diff --git a/engine/cdrs_local_test.go b/general_tests/cdrs_replication_it_test.go similarity index 84% rename from engine/cdrs_local_test.go rename to general_tests/cdrs_replication_it_test.go index fe5181275..92a046679 100644 --- a/engine/cdrs_local_test.go +++ b/general_tests/cdrs_replication_it_test.go @@ -16,14 +16,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see */ -package engine +package general_tests import ( + "flag" "path" "testing" "time" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" "github.com/cgrates/rpcclient" ) @@ -31,12 +33,10 @@ import ( var cdrsMasterCfgPath, cdrsSlaveCfgPath string var cdrsMasterCfg, cdrsSlaveCfg *config.CGRConfig -//var cdrsHttpJsonRpc *rpcclient.RpcClient - -var waitRater = 500 +var testIntegration = flag.Bool("integration", false, "Perform the tests in integration mode, not by default.") // This flag will be passed here via "go test -local" args func TestCdrsInitConfig(t *testing.T) { - if !*testLocal { + if !*testIntegration { return } var err error @@ -52,45 +52,45 @@ func TestCdrsInitConfig(t *testing.T) { // InitDb so we can rely on count func TestCdrsInitCdrDb(t *testing.T) { - if !*testLocal { + if !*testIntegration { return } - if err := InitStorDb(cdrsMasterCfg); err != nil { + if err := engine.InitStorDb(cdrsMasterCfg); err != nil { t.Fatal(err) } - if err := InitStorDb(cdrsSlaveCfg); err != nil { + if err := engine.InitStorDb(cdrsSlaveCfg); err != nil { t.Fatal(err) } } func TestCdrsStartMasterEngine(t *testing.T) { - if !*testLocal { + if !*testIntegration { return } - if _, err := StopStartEngine(cdrsMasterCfgPath, waitRater); err != nil { + if _, err := engine.StopStartEngine(cdrsMasterCfgPath, *waitRater); err != nil { t.Fatal(err) } } func TestCdrsStartSlaveEngine(t *testing.T) { - if !*testLocal { + if !*testIntegration { return } - if _, err := StartEngine(cdrsSlaveCfgPath, waitRater); err != nil { + if _, err := engine.StartEngine(cdrsSlaveCfgPath, *waitRater); err != nil { t.Fatal(err) } } // Connect rpc client to rater func TestCdrsHttpCdrReplication(t *testing.T) { - if !*testLocal { + if !*testIntegration { return } cdrsMasterRpc, err := rpcclient.NewRpcClient("tcp", cdrsMasterCfg.RPCJSONListen, 1, 1, "json", nil) if err != nil { t.Fatal("Could not connect to rater: ", err.Error()) } - testCdr1 := &CDR{CGRID: utils.Sha1("httpjsonrpc1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), + testCdr1 := &engine.CDR{CGRID: utils.Sha1("httpjsonrpc1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), TOR: utils.VOICE, OriginID: "httpjsonrpc1", OriginHost: "192.168.1.1", Source: "UNKNOWN", RequestType: utils.META_PSEUDOPREPAID, Direction: "*out", Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1002", SetupTime: time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2013, 12, 7, 8, 42, 26, 0, time.UTC), @@ -102,13 +102,13 @@ func TestCdrsHttpCdrReplication(t *testing.T) { } else if reply != utils.OK { t.Error("Unexpected reply received: ", reply) } - time.Sleep(time.Duration(waitRater) * time.Millisecond) + time.Sleep(time.Duration(*waitRater) * time.Millisecond) cdrsSlaveRpc, err := rpcclient.NewRpcClient("tcp", "127.0.0.1:12012", 1, 1, "json", nil) if err != nil { t.Fatal("Could not connect to rater: ", err.Error()) } // ToDo: Fix cdr_http to be compatible with rest of processCdr methods - var rcvedCdrs []*ExternalCDR + var rcvedCdrs []*engine.ExternalCDR if err := cdrsSlaveRpc.Call("ApierV2.GetCdrs", utils.RPCCDRsFilter{CGRIDs: []string{testCdr1.CGRID}, RunIDs: []string{utils.META_DEFAULT}}, &rcvedCdrs); err != nil { t.Error("Unexpected error: ", err.Error()) } else if len(rcvedCdrs) != 1 { diff --git a/local_test.sh b/local_test.sh index b2089608c..b35a4e809 100755 --- a/local_test.sh +++ b/local_test.sh @@ -8,8 +8,8 @@ ap1=$? echo 'go test github.com/cgrates/cgrates/apier/v2 -local' go test github.com/cgrates/cgrates/apier/v2 -local ap2=$? -echo 'go test github.com/cgrates/cgrates/engine -local' -go test github.com/cgrates/cgrates/engine -local +echo 'go test github.com/cgrates/cgrates/engine -local -integration' +go test github.com/cgrates/cgrates/engine -local -integration en=$? echo 'go test github.com/cgrates/cgrates/cdrc -local' go test github.com/cgrates/cgrates/cdrc -local @@ -18,8 +18,10 @@ echo 'go test github.com/cgrates/cgrates/config -local' go test github.com/cgrates/cgrates/config -local cfg=$? echo 'go test github.com/cgrates/cgrates/utils -local' -echo 'go test github.com/cgrates/cgrates/general_tests -local' -go test github.com/cgrates/cgrates/general_tests -local +go test github.com/cgrates/cgrates/utils -local +utl=$? +echo 'go test github.com/cgrates/cgrates/general_tests -local -integration' +go test github.com/cgrates/cgrates/general_tests -local -integration gnr=$? echo 'go test github.com/cgrates/cgrates/agents -integration' go test github.com/cgrates/cgrates/agents -integration @@ -29,4 +31,4 @@ agts=$? -exit $gen && $ap1 && $ap2 && $en && $cdrc && $cfg && $gnr && $agts +exit $gen && $ap1 && $ap2 && $en && $cdrc && $cfg && $utl && $gnr && $agts diff --git a/utils/consts.go b/utils/consts.go index 9e04d2102..0cdeb6b59 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -262,6 +262,7 @@ const ( MatchEndPrefix = "$" SMG = "SMG" MetaGrouped = "*grouped" + MetaRaw = "*raw" ) var (