From 337a1bab785cd4ff4f46f99f0cb7f8e1a21dd598 Mon Sep 17 00:00:00 2001 From: TeoV Date: Mon, 9 Jul 2018 08:45:48 -0400 Subject: [PATCH] Rename tutorial_it_test => oldtutorial_it_test and add example config (mongo_atlas) --- data/conf/samples/mongo_atlas/cgrates.json | 183 +++ engine/storage_mongo_datadb.go | 1 + general_tests/oldtutorial_it_test.go | 1488 ++++++++++++++++++ general_tests/tutorial_it_test.go | 1617 ++------------------ 4 files changed, 1801 insertions(+), 1488 deletions(-) create mode 100755 data/conf/samples/mongo_atlas/cgrates.json create mode 100644 general_tests/oldtutorial_it_test.go diff --git a/data/conf/samples/mongo_atlas/cgrates.json b/data/conf/samples/mongo_atlas/cgrates.json new file mode 100755 index 000000000..c1a212fa2 --- /dev/null +++ b/data/conf/samples/mongo_atlas/cgrates.json @@ -0,0 +1,183 @@ +{ +// CGRateS Configuration file + + +"general": { + "log_level": 7, + "reply_timeout": "30s", +}, + + +"listen": { + "rpc_json": ":2012", + "rpc_gob": ":2013", + "http": ":2080", +}, + + +"data_db": { + "db_type": "mongo", + "db_host": "cgrates-shard-00-00-dbhlm.mongodb.net:27017,cgrates-shard-00-01-dbhlm.mongodb.net:27017,cgrates-shard-00-02-dbhlm.mongodb.net", // data_db host address + "db_port": 27017, + "db_name": "OnlineTarrifPlans?replicaSet=CGRateS-shard-0&authSource=admin&ssl=true", + "db_user": "CGRateS", + "db_password": "123456y", +}, + + +"stor_db": { + "db_type": "mongo", + "db_host": "cgrates-shard-00-00-dbhlm.mongodb.net:27017,cgrates-shard-00-01-dbhlm.mongodb.net:27017,cgrates-shard-00-02-dbhlm.mongodb.net", // data_db host address + "db_port": 27017, + "db_name": "OfflineTarrifPlans?replicaSet=CGRateS-shard-0&authSource=admin&ssl=true", + "db_user": "CGRateS", + "db_password": "123456y", +}, + + +"cache":{ + "destinations": {"limit": 10000, "ttl":"0s", "precache": true}, + "reverse_destinations": {"limit": 10000, "ttl":"0s", "precache": true}, + "rating_plans": {"limit": 10000, "ttl":"0s","precache": true}, + "rating_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "lcr_rules": {"limit": 10000, "ttl":"0s", "precache": true}, + "cdr_stats": {"limit": 10000, "ttl":"0s", "precache": true}, + "actions": {"limit": 10000, "ttl":"0s", "precache": true}, + "action_plans": {"limit": 10000, "ttl":"0s", "precache": true}, + "account_action_plans": {"limit": 10000, "ttl":"0s", "precache": true}, + "action_triggers": {"limit": 10000, "ttl":"0s", "precache": true}, + "shared_groups": {"limit": 10000, "ttl":"0s", "precache": true}, + "aliases": {"limit": 10000, "ttl":"0s", "precache": true}, + "reverse_aliases": {"limit": 10000, "ttl":"0s", "precache": true}, + "derived_chargers": {"limit": 10000, "ttl":"0s", "precache": true}, + "resource_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "resources": {"limit": 10000, "ttl":"0s", "precache": true}, + "statqueues": {"limit": 10000, "ttl":"0s", "precache": true}, + "statqueue_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "thresholds": {"limit": 10000, "ttl":"0s", "precache": true}, + "threshold_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "filters": {"limit": 10000, "ttl":"0s", "precache": true}, + "supplier_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "attribute_profiles": {"limit": 10000, "ttl":"0s", "precache": true}, + "resource_filter_indexes" :{"limit": 10000, "ttl":"0s"}, + "resource_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, + "stat_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "stat_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, + "threshold_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "threshold_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, + "supplier_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "supplier_filter_revindexes" :{"limit": 10000, "ttl":"0s"}, + "attribute_filter_indexes" : {"limit": 10000, "ttl":"0s"}, + "attribute_filter_revindexes" : {"limit": 10000, "ttl":"0s"}, +}, + + +"rals": { + "enabled": true, + "thresholds_conns": [ + {"address": "*internal"} + ], + "cdrstats_conns": [ + {"address": "*internal"} + ], + "pubsubs_conns": [ + {"address": "*internal"} + ], + "users_conns": [ + {"address": "*internal"} + ], + "aliases_conns": [ + {"address": "*internal"} + ], +}, + + +"scheduler": { + "enabled": true, +}, + + +"cdrs": { + "enabled": true, + "cdrstats_conns": [ + {"address": "*internal"} + ], +}, + + +"cdre": { + "TestTutITExportCDR": { + "content_fields": [ + {"tag": "CGRID", "type": "*composed", "value": "CGRID"}, + {"tag": "RunID", "type": "*composed", "value": "RunID"}, + {"tag":"OriginID", "type": "*composed", "value": "OriginID"}, + {"tag":"RequestType", "type": "*composed", "value": "RequestType"}, + {"tag":"Tenant", "type": "*composed", "value": "Tenant"}, + {"tag":"Category", "type": "*composed", "value": "Category"}, + {"tag":"Account", "type": "*composed", "value": "Account"}, + {"tag":"Destination", "type": "*composed", "value": "Destination"}, + {"tag":"AnswerTime", "type": "*composed", "value": "AnswerTime", "layout": "2006-01-02T15:04:05Z07:00"}, + {"tag":"Usage", "type": "*composed", "value": "Usage"}, + {"tag":"Cost", "type": "*composed", "value": "Cost", "rounding_decimals": 4}, + {"tag":"MatchedDestinationID", "type": "*composed", "value": "~CostDetails:s/\"MatchedDestId\":.*_(\\w{4})/${1}/:s/\"MatchedDestId\":\"INTERNAL\"/ON010/"}, + ], + }, +}, + + +"resources": { + "enabled": true, + "store_interval": "1s", + "thresholds_conns": [ + {"address": "*internal"} + ], +}, + + +"stats": { + "enabled": true, + "store_interval": "1s", + "thresholds_conns": [ + {"address": "*internal"} + ], +}, + + +"thresholds": { + "enabled": true, + "store_interval": "1s", +}, + + +"suppliers": { + "enabled": true, +}, + + +"attributes": { + "enabled": true, +}, + + +"sessions": { + "enabled": true, +}, + + +"migrator": { + "out_datadb_type": "mongo", + "out_datadb_host": "cgrates-shard-00-00-dbhlm.mongodb.net:27017,cgrates-shard-00-01-dbhlm.mongodb.net:27017,cgrates-shard-00-02-dbhlm.mongodb.net", + "out_datadb_port": "27017", + "out_datadb_name": "OnlineTarrifPlans?replicaSet=CGRateS-shard-0&authSource=admin&ssl=true", + "out_datadb_user": "CGRateS", + "out_datadb_password":"123456y", + "out_stordb_type": "mongo", + "out_stordb_host": "cgrates-shard-00-00-dbhlm.mongodb.net:27017,cgrates-shard-00-01-dbhlm.mongodb.net:27017,cgrates-shard-00-02-dbhlm.mongodb.net", + "out_stordb_port": "27017", + "out_stordb_name": "OfflineTarrifPlans?replicaSet=CGRateS-shard-0&authSource=admin&ssl=true", + "out_stordb_user": "CGRateS", + "out_stordb_password": "123456y", +}, + + +} diff --git a/engine/storage_mongo_datadb.go b/engine/storage_mongo_datadb.go index e4a305d72..aae29bc3b 100644 --- a/engine/storage_mongo_datadb.go +++ b/engine/storage_mongo_datadb.go @@ -112,6 +112,7 @@ func NewMongoStorage(host, port, db, user, pass, storageType string, url += "/" + db dbName = strings.Split(db, "?")[0] // remove extra info after ? } + fmt.Printf("URL : %+v \n", url) session, err := mgo.Dial(url) if err != nil { return nil, err diff --git a/general_tests/oldtutorial_it_test.go b/general_tests/oldtutorial_it_test.go new file mode 100644 index 000000000..b7faee6ed --- /dev/null +++ b/general_tests/oldtutorial_it_test.go @@ -0,0 +1,1488 @@ +// +build integration + +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package general_tests + +import ( + "io/ioutil" + "net/rpc" + "net/rpc/jsonrpc" + "os" + "path" + "reflect" + "testing" + "time" + + "github.com/cgrates/cgrates/apier/v1" + "github.com/cgrates/cgrates/apier/v2" + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +var tutLocalCfgPath string +var tutFsLocalCfg *config.CGRConfig +var tutLocalRpc *rpc.Client +var loadInst utils.LoadInstance // Share load information between tests + +func TestTutITInitCfg(t *testing.T) { + tutLocalCfgPath = path.Join(*dataDir, "conf", "samples", "tutmysql") + // Init config first + var err error + tutFsLocalCfg, err = config.NewCGRConfigFromFolder(tutLocalCfgPath) + if err != nil { + t.Error(err) + } + tutFsLocalCfg.DataFolderPath = *dataDir // Share DataFolderPath through config towards StoreDb for Flush() + config.SetCgrConfig(tutFsLocalCfg) +} + +// Remove data in dataDB +func TestTutITResetDataDb(t *testing.T) { + if err := engine.InitDataDb(tutFsLocalCfg); err != nil { + t.Fatal(err) + } +} + +// Wipe out the cdr database +func TestTutITResetStorDb(t *testing.T) { + if err := engine.InitStorDb(tutFsLocalCfg); err != nil { + t.Fatal(err) + } +} + +// Start CGR Engine +func TestTutITStartEngine(t *testing.T) { + if _, err := engine.StopStartEngine(tutLocalCfgPath, *waitRater); err != nil { + t.Fatal(err) + } +} + +// Connect rpc client to rater +func TestTutITRpcConn(t *testing.T) { + var err error + tutLocalRpc, err = jsonrpc.Dial("tcp", tutFsLocalCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed + if err != nil { + t.Fatal(err) + } +} + +// Load the tariff plan, creating accounts and their balances +func TestTutITLoadTariffPlanFromFolder(t *testing.T) { + attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "oldtutorial")} + if err := tutLocalRpc.Call("ApierV2.LoadTariffPlanFromFolder", attrs, &loadInst); err != nil { + t.Error(err) + } + time.Sleep(100*time.Millisecond + time.Duration(*waitRater)*time.Millisecond) // Give time for scheduler to execute topups +} + +// Check loaded stats +func TestTutITCacheStats(t *testing.T) { + var reply string + if err := tutLocalRpc.Call("ApierV1.LoadCache", utils.AttrReloadCache{}, &reply); err != nil { + t.Error(err) + } else if reply != "OK" { + t.Error(reply) + } + var rcvStats *utils.CacheStats + expectedStats := &utils.CacheStats{Destinations: 5, ReverseDestinations: 7, RatingPlans: 4, RatingProfiles: 10, + Actions: 9, ActionPlans: 4, AccountActionPlans: 5, SharedGroups: 1, DerivedChargers: 1, LcrProfiles: 5, + CdrStats: 6, Users: 3, Aliases: 1, ReverseAliases: 2, ResourceProfiles: 3, Resources: 3, StatQueues: 1, + StatQueueProfiles: 1, Thresholds: 7, ThresholdProfiles: 7, Filters: 16, SupplierProfiles: 3, AttributeProfiles: 1} + var args utils.AttrCacheStats + if err := tutLocalRpc.Call("ApierV1.GetCacheStats", args, &rcvStats); err != nil { + t.Error("Got error on ApierV1.GetCacheStats: ", err.Error()) + } else if !reflect.DeepEqual(expectedStats, rcvStats) { + t.Errorf("Calling ApierV1.GetCacheStats expected: %+v, received: %+v", expectedStats, rcvStats) + } + expKeys := utils.ArgsCache{ + DestinationIDs: &[]string{"DST_1003", "DST_1002", "DST_DE_MOBILE", "DST_1007", "DST_FS"}, + RatingPlanIDs: &[]string{"RP_RETAIL1", "RP_GENERIC"}, + } + var rcvKeys utils.ArgsCache + argsAPI := utils.ArgsCacheKeys{ArgsCache: utils.ArgsCache{ + DestinationIDs: &[]string{}, RatingPlanIDs: &[]string{"RP_RETAIL1", "RP_GENERIC", "NONEXISTENT"}}} + if err := tutLocalRpc.Call("ApierV1.GetCacheKeys", argsAPI, &rcvKeys); err != nil { + t.Error("Got error on ApierV1.GetCacheStats: ", err.Error()) + } else { + if len(*expKeys.DestinationIDs) != len(*rcvKeys.DestinationIDs) { + t.Errorf("Expected: %+v, received: %+v", expKeys.DestinationIDs, rcvKeys.DestinationIDs) + } + if !reflect.DeepEqual(*expKeys.RatingPlanIDs, *rcvKeys.RatingPlanIDs) { + t.Errorf("Expected: %+v, received: %+v", expKeys.RatingPlanIDs, rcvKeys.RatingPlanIDs) + } + } + if _, err := engine.StopStartEngine(tutLocalCfgPath, 1500); err != nil { + t.Fatal(err) + } + var err error + tutLocalRpc, err = jsonrpc.Dial("tcp", tutFsLocalCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed + if err != nil { + t.Fatal(err) + } + if err := tutLocalRpc.Call("ApierV1.GetCacheStats", args, &rcvStats); err != nil { + t.Error("Got error on ApierV1.GetCacheStats: ", err.Error()) + } else if !reflect.DeepEqual(expectedStats, rcvStats) { + t.Errorf("Calling ApierV1.GetCacheStats expected: %+v, received: %+v", expectedStats, rcvStats) + } +} + +func TestTutITGetUsers(t *testing.T) { + var users engine.UserProfiles + if err := tutLocalRpc.Call("UsersV1.GetUsers", engine.UserProfile{}, &users); err != nil { + t.Error("Got error on UsersV1.GetUsers: ", err.Error()) + } else if len(users) != 3 { + t.Error("Calling UsersV1.GetUsers got users:", len(users)) + } +} + +func TestTutITGetMatchingAlias(t *testing.T) { + args := engine.AttrMatchingAlias{ + Destination: "1005", + Direction: "*out", + Tenant: "cgrates.org", + Category: "call", + Account: "1006", + Subject: "1006", + Context: utils.MetaRating, + Target: "Account", + Original: "1006", + } + eMatchingAlias := "1002" + var matchingAlias string + if err := tutLocalRpc.Call("AliasesV1.GetMatchingAlias", args, &matchingAlias); err != nil { + t.Error(err) + } else if matchingAlias != eMatchingAlias { + t.Errorf("Expecting: %s, received: %+v", eMatchingAlias, matchingAlias) + } +} + +// Check call costs +func TestTutITGetCosts(t *testing.T) { + tStart, _ := utils.ParseDate("2014-08-04T13:00:00Z") + tEnd, _ := utils.ParseDate("2014-08-04T13:00:20Z") + cd := engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1002", + DurationIndex: 0, + TimeStart: tStart, + TimeEnd: tEnd, + } + var cc engine.CallCost + if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.Cost != 0.6 { + t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) + } + // Make sure that the same cost is returned via users aliasing + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: utils.USERS, + Subject: utils.USERS, + Account: utils.USERS, + Destination: "1002", + DurationIndex: 0, + TimeStart: tStart, + TimeEnd: tEnd, + ExtraFields: map[string]string{"Uuid": "388539dfd4f5cefee8f488b78c6c244b9e19138e"}, + } + if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.Cost != 0.6 { + t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) + } + tStart, _ = utils.ParseDate("2014-08-04T13:00:00Z") + tEnd, _ = utils.ParseDate("2014-08-04T13:01:25Z") + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1002", + DurationIndex: 0, + TimeStart: tStart, + TimeEnd: tEnd, + } + if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.Cost != 0.6418 { // 0.01 first minute, 0.04 25 seconds with RT_20CNT + t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) + } + tStart, _ = utils.ParseDate("2014-08-04T13:00:00Z") + tEnd, _ = utils.ParseDate("2014-08-04T13:00:20Z") + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1003", + DurationIndex: 0, + TimeStart: tStart, + TimeEnd: tEnd, + } + if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.Cost != 1 { + t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) + } + tStart, _ = utils.ParseDate("2014-08-04T13:00:00Z") + tEnd, _ = utils.ParseDate("2014-08-04T13:01:25Z") + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1003", + DurationIndex: 0, + TimeStart: tStart, + TimeEnd: tEnd, + } + if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.Cost != 1.3 { + t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) + } + tStart, _ = utils.ParseDate("2014-08-04T13:00:00Z") + tEnd, _ = utils.ParseDate("2014-08-04T13:00:20Z") + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1004", + DurationIndex: 0, + TimeStart: tStart, + TimeEnd: tEnd, + } + if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.Cost != 1 { + t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) + } + tStart, _ = utils.ParseDate("2014-08-04T13:00:00Z") + tEnd, _ = utils.ParseDate("2014-08-04T13:01:25Z") + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1004", + DurationIndex: 0, + TimeStart: tStart, + TimeEnd: tEnd, + } + if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.Cost != 1.3 { + t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) + } + tStart = time.Date(2014, 8, 4, 13, 0, 0, 0, time.UTC) + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1007", + TimeStart: tStart, + TimeEnd: tStart.Add(time.Duration(50) * time.Second), + } + if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.Cost != 0.5 { + t.Errorf("Calling Responder.GetCost got callcost: %s", cc.AsJSON()) + } + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1007", + TimeStart: tStart, + TimeEnd: tStart.Add(time.Duration(70) * time.Second), + } + if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.Cost != 0.62 { + t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) + } + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1002", + Account: "1002", + Destination: "1007", + TimeStart: tStart, + TimeEnd: tStart.Add(time.Duration(50) * time.Second), + } + if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.Cost != 0.5 { + t.Errorf("Calling Responder.GetCost got callcost: %s", cc.AsJSON()) + } + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1002", + Account: "1002", + Destination: "1007", + TimeStart: tStart, + TimeEnd: tStart.Add(time.Duration(70) * time.Second), + } + if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.Cost != 0.7 { // In case of *disconnect strategy, it will not be applied so we can go on negative costs + t.Errorf("Calling Responder.GetCost got callcost: %s", cc.AsJSON()) + } + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1004", + TimeStart: time.Date(2016, 1, 6, 19, 0, 0, 0, time.UTC), + TimeEnd: time.Date(2016, 1, 6, 19, 1, 30, 0, time.UTC), + } + if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.Cost != 0.3249 { // + t.Errorf("Calling Responder.GetCost got callcost: %s", cc.AsJSON()) + } + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1004", + TimeStart: time.Date(2016, 1, 6, 18, 31, 5, 0, time.UTC), + TimeEnd: time.Date(2016, 1, 6, 18, 32, 35, 0, time.UTC), + } + if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.Cost != 1.3 { // + t.Errorf("Calling Responder.GetCost got callcost: %s", cc.AsJSON()) + } + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1002", + TimeStart: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC), + TimeEnd: time.Date(2014, 12, 7, 8, 44, 26, 0, time.UTC), + } + if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.Cost != 0.3498 { // + t.Errorf("Calling Responder.GetCost got callcost: %s", cc.AsJSON()) + } +} + +// Check call costs +func TestTutITMaxDebit(t *testing.T) { + tStart := time.Date(2014, 8, 4, 13, 0, 0, 0, time.UTC) + cd := engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1002", + DurationIndex: 0, + TimeStart: tStart, + TimeEnd: tStart.Add(time.Duration(20) * time.Second), + } + var cc engine.CallCost + if err := tutLocalRpc.Call("Responder.MaxDebit", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.GetDuration() == 20 { + t.Errorf("Calling Responder.MaxDebit got callcost: %v", cc.GetDuration()) + } + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1003", + DurationIndex: 0, + TimeStart: tStart, + TimeEnd: tStart.Add(time.Duration(200) * time.Second), + } + if err := tutLocalRpc.Call("Responder.MaxDebit", cd, &cc); err != nil { + t.Error("Got error on Responder.MaxDebit: ", err.Error()) + } else if cc.GetDuration() == 200 { + t.Errorf("Calling Responder.MaxDebit got duration: %v", cc.GetDuration()) + } + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1007", + DurationIndex: 0, + TimeStart: tStart, + TimeEnd: tStart.Add(time.Duration(120) * time.Second), + } + cd.CgrID = "1" + if err := tutLocalRpc.Call("Responder.MaxDebit", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.GetDuration() == 120 { + t.Errorf("Calling Responder.MaxDebit got callcost: %v", cc.GetDuration()) + } + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1004", + Account: "1004", + Destination: "1007", + DurationIndex: 0, + TimeStart: tStart, + TimeEnd: tStart.Add(time.Duration(120) * time.Second), + } + cd.CgrID = "2" + if err := tutLocalRpc.Call("Responder.MaxDebit", cd, &cc); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if cc.GetDuration() != time.Duration(62)*time.Second { // We have as strategy *dsconnect + t.Errorf("Calling Responder.MaxDebit got callcost: %v", cc.GetDuration()) + } + var maxTime float64 + if err := tutLocalRpc.Call("Responder.GetMaxSessionTime", cd, &maxTime); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if maxTime != 62000000000 { // We have as strategy *dsconnect + t.Errorf("Calling Responder.GetMaxSessionTime got maxTime: %f", maxTime) + } +} + +// Check call costs +func TestTutITDerivedMaxSessionTime(t *testing.T) { + tStart := time.Date(2014, 8, 4, 13, 0, 0, 0, time.UTC) + ev := engine.CDR{ + CGRID: utils.Sha1("testevent1", tStart.String()), + ToR: utils.VOICE, + OriginID: "testevent1", + OriginHost: "127.0.0.1", + RequestType: utils.META_PREPAID, + Tenant: "cgrates.org", + Category: "call", + Account: "1004", + Subject: "1004", + Destination: "1007", + SetupTime: tStart, + AnswerTime: tStart, + Usage: time.Duration(120) * time.Second, + Cost: -1, + } + var maxTime float64 + if err := tutLocalRpc.Call("Responder.GetDerivedMaxSessionTime", ev, &maxTime); err != nil { + t.Error("Got error on Responder.GetCost: ", err.Error()) + } else if maxTime != 62000000000 { // We have as strategy *dsconnect + t.Errorf("Calling Responder.GetMaxSessionTime got maxTime: %f", maxTime) + } +} + +// Check MaxUsage +func TestTutITMaxUsage(t *testing.T) { + setupReq := &engine.UsageRecord{ToR: utils.VOICE, + RequestType: utils.META_PREPAID, Tenant: "cgrates.org", Category: "call", + Account: "1003", Subject: "1003", Destination: "1001", + SetupTime: "2014-08-04T13:00:00Z", Usage: "1s", + } + var maxTime float64 + if err := tutLocalRpc.Call("ApierV2.GetMaxUsage", setupReq, &maxTime); err != nil { + t.Error(err) + } else if maxTime != 1 { + t.Errorf("Calling ApierV2.MaxUsage got maxTime: %f", maxTime) + } + setupReq = &engine.UsageRecord{ToR: utils.VOICE, RequestType: utils.META_RATED, Tenant: "cgrates.org", Category: "call", + Account: "test_max_usage", Destination: "1001", + SetupTime: "2014-08-04T13:00:00Z", + } + if err := tutLocalRpc.Call("ApierV2.GetMaxUsage", setupReq, &maxTime); err != nil { + t.Error(err) + } else if maxTime != -1 { + t.Errorf("Calling ApierV2.MaxUsage got maxTime: %f", maxTime) + } +} + +// Check DebitUsage +func TestTutITDebitUsage(t *testing.T) { + setupReq := &engine.UsageRecord{ToR: utils.VOICE, RequestType: utils.META_PREPAID, Tenant: "cgrates.org", Category: "call", + Account: "1003", Subject: "1003", Destination: "1001", + AnswerTime: "2014-08-04T13:00:00Z", Usage: "1", + } + var reply string + if err := tutLocalRpc.Call("ApierV2.DebitUsage", setupReq, &reply); err != nil { + t.Error(err) + } else if reply != utils.OK { + t.Error("Calling ApierV2.DebitUsage reply: ", reply) + } +} + +// Test CDR from external sources +func TestTutITProcessExternalCdr(t *testing.T) { + cdr := &engine.ExternalCDR{ToR: utils.VOICE, + OriginID: "testextcdr1", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1001", + SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z", + Usage: "1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, + } + var reply string + if err := tutLocalRpc.Call("CdrsV1.ProcessExternalCdr", cdr, &reply); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if reply != utils.OK { + t.Error("Unexpected reply received: ", reply) + } +} + +// Test CDR involving UserProfile +func TestTutITProcessExternalCdrUP(t *testing.T) { + cdr := &engine.ExternalCDR{ToR: utils.VOICE, + OriginID: "testextcdr2", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, + RequestType: utils.USERS, Tenant: utils.USERS, Account: utils.USERS, Destination: "1001", + SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z", Usage: "2s", + ExtraFields: map[string]string{"Cli": "+4986517174964", "fieldextr2": "valextr2", "SysUserName": utils.USERS}, + } + var reply string + if err := tutLocalRpc.Call("CdrsV1.ProcessExternalCdr", cdr, &reply); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if reply != utils.OK { + t.Error("Unexpected reply received: ", reply) + } + time.Sleep(time.Duration(*waitRater) * time.Millisecond) + eCdr := &engine.ExternalCDR{CGRID: "63a8d2bfeca2cfb790826c3ec461696d6574cfde", OrderID: 2, + ToR: utils.VOICE, + OriginID: "testextcdr2", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1004", Subject: "1004", Destination: "1001", + SetupTime: time.Date(2014, 8, 4, 13, 0, 0, 0, time.UTC).Local().Format(time.RFC3339), + AnswerTime: time.Date(2014, 8, 4, 13, 0, 7, 0, time.UTC).Local().Format(time.RFC3339), Usage: "2s", + ExtraFields: map[string]string{"Cli": "+4986517174964", "fieldextr2": "valextr2", "SysUserName": "danb4"}, + RunID: utils.DEFAULT_RUNID, Cost: 1} + var cdrs []*engine.ExternalCDR + req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, + Accounts: []string{"1004"}, DestinationPrefixes: []string{"1001"}} + if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if len(cdrs) != 1 { + t.Error("Unexpected number of CDRs returned: ", len(cdrs)) + } else { + if cdrs[0].CGRID != eCdr.CGRID { + t.Errorf("Unexpected CGRID for CDR: %+v", cdrs[0]) + } + if cdrs[0].ToR != eCdr.ToR { + t.Errorf("Unexpected TOR for CDR: %+v", cdrs[0]) + } + if cdrs[0].Source != eCdr.Source { + t.Errorf("Unexpected Source for CDR: %+v", cdrs[0]) + } + if cdrs[0].RequestType != eCdr.RequestType { + t.Errorf("Unexpected RequestType for CDR: %+v", cdrs[0]) + } + if cdrs[0].Tenant != eCdr.Tenant { + t.Errorf("Unexpected Tenant for CDR: %+v", cdrs[0]) + } + if cdrs[0].Category != eCdr.Category { + t.Errorf("Unexpected Category for CDR: %+v", cdrs[0]) + } + if cdrs[0].Account != eCdr.Account { + t.Errorf("Unexpected Account for CDR: %+v", cdrs[0]) + } + if cdrs[0].Subject != eCdr.Subject { + t.Errorf("Unexpected Subject for CDR: %+v", cdrs[0]) + } + if cdrs[0].Destination != eCdr.Destination { + t.Errorf("Unexpected Destination for CDR: %+v", cdrs[0]) + } + if cdrs[0].SetupTime != eCdr.SetupTime { + t.Errorf("Unexpected SetupTime for CDR: %+v", cdrs[0]) + } + if cdrs[0].AnswerTime != eCdr.AnswerTime { + t.Errorf("Unexpected AnswerTime for CDR: %+v", cdrs[0]) + } + if cdrs[0].Usage != eCdr.Usage { + t.Errorf("Unexpected Usage for CDR: %+v", cdrs[0]) + } + } +} + +func TestTutITCostErrors(t *testing.T) { + cdr := &engine.ExternalCDR{ToR: utils.VOICE, + OriginID: "TestTutIT_1", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "fake", Account: "2001", Subject: "2001", Destination: "1001", + SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z", + Usage: "1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, + } + var reply string + if err := tutLocalRpc.Call("CdrsV1.ProcessExternalCdr", cdr, &reply); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if reply != utils.OK { + t.Error("Unexpected reply received: ", reply) + } + time.Sleep(time.Duration(*waitRater) * time.Millisecond) + var cdrs []*engine.ExternalCDR + req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{cdr.Account}, DestinationPrefixes: []string{cdr.Destination}} + if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if len(cdrs) != 1 { + t.Error("Unexpected number of CDRs returned: ", len(cdrs)) + } else { + if cdrs[0].OriginID != cdr.OriginID { + t.Errorf("Unexpected OriginID for Cdr received: %+v", cdrs[0]) + } + if cdrs[0].Cost != -1 { + t.Errorf("Unexpected Cost for Cdr received: %+v", cdrs[0]) + } + } + cdr2 := &engine.ExternalCDR{ToR: utils.VOICE, + OriginID: "TestTutIT_2", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_POSTPAID, + Tenant: "cgrates.org", Category: "fake", Account: "2002", Subject: "2002", Destination: "1001", + SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z", + Usage: "1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, + } + if err := tutLocalRpc.Call("CdrsV1.ProcessExternalCdr", cdr2, &reply); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if reply != utils.OK { + t.Error("Unexpected reply received: ", reply) + } + time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for CDR to be processed + req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{cdr2.Account}, DestinationPrefixes: []string{cdr2.Destination}} + if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if len(cdrs) != 1 { + t.Error("Unexpected number of CDRs returned: ", len(cdrs)) + } else { + if cdrs[0].OriginID != cdr2.OriginID { + t.Errorf("Unexpected OriginID for Cdr received: %+v", cdrs[0]) + } + if cdrs[0].Cost != -1 { + t.Errorf("Unexpected Cost for Cdr received: %+v", cdrs[0]) + } + } + cdr3 := &engine.ExternalCDR{ToR: utils.VOICE, + OriginID: "TestTutIT_3", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_POSTPAID, + Tenant: "cgrates.org", Category: "fake", Account: "1001", Subject: "1001", Destination: "2002", + SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z", + Usage: "1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, + } + if err := tutLocalRpc.Call("CdrsV1.ProcessExternalCdr", cdr3, &reply); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if reply != utils.OK { + t.Error("Unexpected reply received: ", reply) + } + time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for CDR to be processed + req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{cdr3.Account}, DestinationPrefixes: []string{cdr3.Destination}} + if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if len(cdrs) != 1 { + t.Error("Unexpected number of CDRs returned: ", len(cdrs)) + } else { + if cdrs[0].OriginID != cdr3.OriginID { + t.Errorf("Unexpected OriginID for Cdr received: %+v", cdrs[0]) + } + if cdrs[0].Cost != -1 { + t.Errorf("Unexpected Cost for Cdr received: %+v", cdrs[0]) + } + } +} + +// Make sure queueids were created +func TestTutITCdrStats(t *testing.T) { + var queueIds []string + eQueueIds := []string{"CDRST1", "CDRST_1001", "CDRST_1002", "CDRST_1003", "STATS_SUPPL1", "STATS_SUPPL2"} + if err := tutLocalRpc.Call("CDRStatsV1.GetQueueIds", "", &queueIds); err != nil { + t.Error("Calling CDRStatsV1.GetQueueIds, got error: ", err.Error()) + } else if len(eQueueIds) != len(queueIds) { + t.Errorf("Expecting: %v, received: %v", eQueueIds, queueIds) + } +} + +func TestTutITLeastCost(t *testing.T) { + tStart, _ := utils.ParseDate("2014-08-04T13:00:00Z") + tEnd, _ := utils.ParseDate("2014-08-04T13:01:00Z") + cd := engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1005", + Account: "1005", + Destination: "1002", + TimeStart: tStart, + TimeEnd: tEnd, + } + eStLcr := &engine.LCRCost{ + Entry: &engine.LCREntry{DestinationId: "DST_1002", RPCategory: "lcr_profile2", Strategy: engine.LCR_STRATEGY_LOWEST, StrategyParams: "", Weight: 10.0}, + SupplierCosts: []*engine.LCRSupplierCost{ + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile2:suppl3", Cost: 0.01, Duration: 60 * time.Second}, + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile2:suppl1", Cost: 0.6, Duration: 60 * time.Second}, + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile2:suppl2", Cost: 1.2, Duration: 60 * time.Second}, + }, + } + var lcr engine.LCRCost + cd.CgrID = "10" + cd.RunID = "10" + if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) + } else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.SupplierCosts, lcr.SupplierCosts) + } + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1005", + Account: "1005", + Destination: "1003", + TimeStart: tStart, + TimeEnd: tEnd, + } + eStLcr = &engine.LCRCost{ + Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_LOWEST, StrategyParams: "", Weight: 10.0}, + SupplierCosts: []*engine.LCRSupplierCost{ + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second}, + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 1.2, Duration: 60 * time.Second}, + }, + } + eStLcr2 := &engine.LCRCost{ + Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_LOWEST, StrategyParams: "", Weight: 10.0}, + SupplierCosts: []*engine.LCRSupplierCost{ + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 1.2, Duration: 60 * time.Second}, + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second}, + }, + } + cd.CgrID = "11" + cd.RunID = "11" + if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) + } else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) && !reflect.DeepEqual(eStLcr2.SupplierCosts, lcr.SupplierCosts) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.SupplierCosts[0], lcr.SupplierCosts[0]) + } +} + +// Check LCR +func TestTutITLcrStatic(t *testing.T) { + tStart, _ := utils.ParseDate("2014-08-04T13:00:00Z") + tEnd, _ := utils.ParseDate("2014-08-04T13:01:00Z") + cd := engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1002", + TimeStart: tStart, + TimeEnd: tEnd, + } + eStLcr := &engine.LCRCost{ + Entry: &engine.LCREntry{DestinationId: "DST_1002", RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_STATIC, StrategyParams: "suppl2;suppl1", Weight: 10.0}, + SupplierCosts: []*engine.LCRSupplierCost{ + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 0.6, Duration: 60 * time.Second}, + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second}, + }, + } + var lcr engine.LCRCost + cd.CgrID = "1" + cd.RunID = "1" + if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) + } else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.SupplierCosts[0], lcr.SupplierCosts[0]) + } + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1001", + Account: "1001", + Destination: "1003", + TimeStart: tStart, + TimeEnd: tEnd, + } + eStLcr = &engine.LCRCost{ + Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_STATIC, StrategyParams: "suppl1;suppl2", Weight: 10.0}, + SupplierCosts: []*engine.LCRSupplierCost{ + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second}, + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 1.2, Duration: 60 * time.Second}, + }, + } + cd.CgrID = "2" + cd.RunID = "2" + if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) + } else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.SupplierCosts[0], lcr.SupplierCosts[0]) + } +} + +func TestTutITLcrHighestCost(t *testing.T) { + tStart, _ := utils.ParseDate("2014-08-04T13:00:00Z") + tEnd, _ := utils.ParseDate("2014-08-04T13:01:00Z") + cd := engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1002", + Account: "1002", + Destination: "1002", + TimeStart: tStart, + TimeEnd: tEnd, + } + eStLcr := &engine.LCRCost{ + Entry: &engine.LCREntry{DestinationId: "DST_1002", RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_HIGHEST, StrategyParams: "", Weight: 10.0}, + SupplierCosts: []*engine.LCRSupplierCost{ + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second}, + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 0.6, Duration: 60 * time.Second}, + }, + } + var lcr engine.LCRCost + if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) + } else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.SupplierCosts[0], lcr.SupplierCosts[0]) + } + // LCR with Alias + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1006", + Account: "1006", + Destination: "1002", + TimeStart: tStart, + TimeEnd: tEnd, + } + if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) + } else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.SupplierCosts[0], lcr.SupplierCosts[0]) + } +} + +func TestTutITLcrQos(t *testing.T) { + tStart, _ := utils.ParseDate("2014-08-04T13:00:00Z") + tEnd, _ := utils.ParseDate("2014-08-04T13:01:00Z") + cd := engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1002", + Account: "1002", + Destination: "1003", + TimeStart: tStart, + TimeEnd: tEnd, + } + eStLcr := &engine.LCRCost{ + Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", + Strategy: engine.LCR_STRATEGY_QOS, StrategyParams: "", Weight: 10.0}, + SupplierCosts: []*engine.LCRSupplierCost{ + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", + Cost: 1.2, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: -1, engine.ACC: -1, engine.TCC: -1, + engine.ASR: -1, engine.ACD: -1, engine.DDC: -1}}, + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", + Cost: 1.2, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: -1, engine.ACC: -1, engine.TCC: -1, + engine.ASR: -1, engine.ACD: -1, engine.DDC: -1}}, + }, + } + /* + eStLcr2 := &engine.LCRCost{ + Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", + Strategy: engine.LCR_STRATEGY_QOS, StrategyParams: "", Weight: 10.0}, + SupplierCosts: []*engine.LCRSupplierCost{ + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", + Cost: 1.2, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: -1, engine.ACC: -1, engine.TCC: -1, + engine.ASR: -1, engine.ACD: -1, engine.DDC: -1}}, + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", + Cost: 1.2, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: -1, engine.ACC: -1, engine.TCC: -1, + engine.ASR: -1, engine.ACD: -1, engine.DDC: -1}}, + }, + } + */ + var lcr engine.LCRCost + // Since there is no real quality difference, the suppliers will come in random order here + cd.CgrID = "3" + cd.RunID = "3" + /* + if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) + } else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) && + !reflect.DeepEqual(eStLcr2.SupplierCosts, lcr.SupplierCosts) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.SupplierCosts[0], lcr.SupplierCosts[0]) + } + */ + // Post some CDRs to influence stats + testCdr1 := &engine.CDR{CGRID: utils.Sha1("testcdr1", + time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), + ToR: utils.VOICE, OriginID: "testcdr1", OriginHost: "192.168.1.1", + Source: "TEST_QOS_LCR", RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1001", + Subject: "1001", Destination: "1002", + SetupTime: time.Date(2014, 12, 7, 8, 42, 24, 0, time.UTC), + AnswerTime: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(2) * time.Minute, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} + testCdr2 := &engine.CDR{CGRID: utils.Sha1("testcdr2", + time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), + ToR: utils.VOICE, OriginID: "testcdr2", OriginHost: "192.168.1.1", + Source: "TEST_QOS_LCR", RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1002", + Subject: "1002", Destination: "1003", + SetupTime: time.Date(2014, 12, 7, 8, 42, 24, 0, time.UTC), + AnswerTime: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(90) * time.Second, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} + var reply string + for _, cdr := range []*engine.CDR{testCdr1, testCdr2} { + if err := tutLocalRpc.Call("CdrsV1.ProcessCdr", cdr, &reply); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if reply != utils.OK { + t.Error("Unexpected reply received: ", reply) + } + } + // Based on stats, supplier1 should always be better since he has a higer ACD + eStLcr = &engine.LCRCost{ + Entry: &engine.LCREntry{DestinationId: utils.ANY, + RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_QOS, + StrategyParams: "", Weight: 10.0}, + SupplierCosts: []*engine.LCRSupplierCost{ + &engine.LCRSupplierCost{ + Supplier: "*out:cgrates.org:lcr_profile1:suppl1", + Cost: 1.2, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: 240, engine.ACC: 0.35, + engine.TCC: 0.7, engine.ASR: 100, engine.ACD: 120}}, + &engine.LCRSupplierCost{ + Supplier: "*out:cgrates.org:lcr_profile1:suppl2", + Cost: 1.2, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: 90, engine.ACC: 0.325, + engine.TCC: 0.325, engine.ASR: 100, engine.ACD: 90}}, + }, + } + cd.CgrID = "4" + cd.RunID = "4" + if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) + //} else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) && !reflect.DeepEqual(eStLcr2.SupplierCosts, lcr.SupplierCosts) { + // t.Errorf("Expecting: %+v, %+v, received: %+v, %+v", eStLcr.SupplierCosts[0], eStLcr.SupplierCosts[1], lcr.SupplierCosts[0], lcr.SupplierCosts[1]) + } + testCdr3 := &engine.CDR{CGRID: utils.Sha1("testcdr3", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), + ToR: utils.VOICE, OriginID: "testcdr3", OriginHost: "192.168.1.1", Source: "TEST_QOS_LCR", RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1004", + SetupTime: time.Date(2014, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(180) * time.Second} + if err := tutLocalRpc.Call("CdrsV1.ProcessCdr", testCdr3, &reply); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if reply != utils.OK { + t.Error("Unexpected reply received: ", reply) + } + // Since ACD has considerably increased for supplier2, we should have it as first prio now + eStLcr = &engine.LCRCost{ + Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_QOS, StrategyParams: "", Weight: 10.0}, + SupplierCosts: []*engine.LCRSupplierCost{ + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 1.2, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: 270, engine.ACC: 0.3625, engine.TCC: 0.725, engine.ASR: 100, engine.ACD: 135}}, + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: 240, engine.ACC: 0.35, engine.TCC: 0.7, engine.ASR: 100, engine.ACD: 120}}, + }, + } + cd.CgrID = "5" + cd.RunID = "5" + if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) + //} else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) && !reflect.DeepEqual(eStLcr2.SupplierCosts, lcr.SupplierCosts) { + // t.Errorf("Expecting: %+v, %+v, received: %+v, %+v", eStLcr.SupplierCosts[0], eStLcr.SupplierCosts[1], lcr.SupplierCosts[0], lcr.SupplierCosts[1]) + } +} + +func TestTutITLcrQosThreshold(t *testing.T) { + tStart, _ := utils.ParseDate("2014-08-04T13:00:00Z") + tEnd, _ := utils.ParseDate("2014-08-04T13:01:00Z") + cd := engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1003", + Account: "1003", + Destination: "1002", + TimeStart: tStart, + TimeEnd: tEnd, + } + eLcr := &engine.LCRCost{ + Entry: &engine.LCREntry{DestinationId: "DST_1002", RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_QOS_THRESHOLD, StrategyParams: "20;;;;2m;;;;;;;", Weight: 10.0}, + SupplierCosts: []*engine.LCRSupplierCost{ + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 0.6, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: 270, engine.ACC: 0.3625, engine.TCC: 0.725, engine.ASR: 100, engine.ACD: 135}}, + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: 240, engine.ACC: 0.35, engine.TCC: 0.7, engine.ASR: 100, engine.ACD: 120}}, + }, + } + var lcr engine.LCRCost + cd.CgrID = "6" + cd.RunID = "6" + if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eLcr.Entry, lcr.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eLcr.Entry, lcr.Entry) + //} else if !reflect.DeepEqual(eLcr.SupplierCosts, lcr.SupplierCosts) { + // t.Errorf("Expecting: %+v, %+v received: %+v, %+v", eLcr.SupplierCosts[0], eLcr.SupplierCosts[1], lcr.SupplierCosts[0], lcr.SupplierCosts[1]) + } + testCdr4 := &engine.CDR{CGRID: utils.Sha1("testcdr4", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), + ToR: utils.VOICE, OriginID: "testcdr4", OriginHost: "192.168.1.1", Source: "TEST_QOS_LCR", RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1004", + SetupTime: time.Date(2014, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(60) * time.Second} + var reply string + if err := tutLocalRpc.Call("CdrsV1.ProcessCdr", testCdr4, &reply); err != nil { // Should drop ACD under the 2m required by threshold, removing suppl2 from lcr + t.Error("Unexpected error: ", err.Error()) + } else if reply != utils.OK { + t.Error("Unexpected reply received: ", reply) + } + eLcr = &engine.LCRCost{ + Entry: &engine.LCREntry{DestinationId: "DST_1002", RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_QOS_THRESHOLD, StrategyParams: "20;;;;2m;;;;;;;", Weight: 10.0}, + SupplierCosts: []*engine.LCRSupplierCost{ + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: 240, engine.ACC: 0.35, engine.TCC: 0.7, engine.ASR: 100, engine.ACD: 120}}, + }, + } + cd.CgrID = "7" + cd.RunID = "7" + if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eLcr.Entry, lcr.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eLcr.Entry, lcr.Entry) + //} else if !reflect.DeepEqual(eLcr.SupplierCosts, lcr.SupplierCosts) { + // t.Errorf("Expecting: %+v, received: %+v", eLcr.SupplierCosts[0], lcr.SupplierCosts[0]) + } + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1003", + Account: "1003", + Destination: "1004", + TimeStart: tStart, + TimeEnd: tEnd, + } + eLcr = &engine.LCRCost{ + Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_QOS_THRESHOLD, StrategyParams: "40;;;;90s;;;;;;;", Weight: 10.0}, + SupplierCosts: []*engine.LCRSupplierCost{ + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: 240, engine.ACC: 0.35, engine.TCC: 0.7, engine.ASR: 100, engine.ACD: 120}}, + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 1.2, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: 330, engine.ACC: 0.3416666667, engine.TCC: 1.025, engine.ASR: 100, engine.ACD: 110}}, + }, + } + /*eLcr2 := &engine.LCRCost{ + Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_QOS_THRESHOLD, StrategyParams: "40;;90s;;;;;;;", Weight: 10.0}, + SupplierCosts: []*engine.LCRSupplierCost{ + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 1.2, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: 330, engine.ACC: 0.3416666667, engine.TCC: 1.025, engine.ASR: 100, engine.ACD: 110}}, + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: 240, engine.ACC: 0.35, engine.TCC: 0.7, engine.ASR: 100, engine.ACD: 120}}, + }, + } + */ + cd.CgrID = "8" + cd.RunID = "8" + if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eLcr.Entry, lcr.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eLcr.Entry, lcr.Entry) + //} else if !reflect.DeepEqual(eLcr.SupplierCosts, lcr.SupplierCosts) && !reflect.DeepEqual(eLcr2.SupplierCosts, lcr.SupplierCosts) { + // t.Errorf("Expecting: %+v, received: %+v", eLcr.SupplierCosts[1], lcr.SupplierCosts[1]) + } + testCdr5 := &engine.CDR{CGRID: utils.Sha1("testcdr5", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), + ToR: utils.VOICE, OriginID: "testcdr5", OriginHost: "192.168.1.1", Source: "TEST_QOS_LCR", RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1004", + SetupTime: time.Date(2014, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC), + Usage: time.Duration(1) * time.Second} + if err := tutLocalRpc.Call("CdrsV1.ProcessCdr", testCdr5, &reply); err != nil { // Should drop ACD under the 1m required by threshold, removing suppl2 from lcr + t.Error("Unexpected error: ", err.Error()) + } else if reply != utils.OK { + t.Error("Unexpected reply received: ", reply) + } + eLcr = &engine.LCRCost{ + Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_QOS_THRESHOLD, StrategyParams: "40;;;;90s;;;;;;;", Weight: 10.0}, + SupplierCosts: []*engine.LCRSupplierCost{ + &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second, + QOS: map[string]float64{engine.TCD: 240, engine.ACC: 0.35, engine.TCC: 0.7, engine.ASR: 100, engine.ACD: 120}}, + }, + } + cd.CgrID = "9" + cd.RunID = "9" + if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eLcr.Entry, lcr.Entry) { + t.Errorf("Expecting: %+v, received: %+v", eLcr.Entry, lcr.Entry) + //} else if !reflect.DeepEqual(eLcr.SupplierCosts, lcr.SupplierCosts) { + // t.Errorf("Expecting: %+v, received: %+v", eLcr.SupplierCosts[0], lcr.SupplierCosts[0]) + } +} + +// Test adding the account via API, using the data previously devined in .csv +func TestTutITSetAccount(t *testing.T) { + var reply string + attrs := &v2.AttrSetAccount{Tenant: "cgrates.org", Account: "tutacnt1", ActionPlanIDs: &[]string{"PACKAGE_10"}, ActionTriggerIDs: &[]string{"STANDARD_TRIGGERS"}, ReloadScheduler: true} + if err := tutLocalRpc.Call("ApierV2.SetAccount", attrs, &reply); err != nil { + t.Error("Got error on ApierV2.SetAccount: ", err.Error()) + } else if reply != "OK" { + t.Errorf("Calling ApierV2.SetAccount received: %s", reply) + } + type AttrGetAccounts struct { + Tenant string + Direction string + AccountIds []string + Offset int // Set the item offset + Limit int // Limit number of items retrieved + } + time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups + var acnts []*engine.Account + if err := tutLocalRpc.Call("ApierV2.GetAccounts", utils.AttrGetAccounts{Tenant: attrs.Tenant, AccountIds: []string{attrs.Account}}, &acnts); err != nil { + t.Error(err) + } else if len(acnts) != 1 { + t.Errorf("Accounts received: %+v", acnts) + } else { + acnt := acnts[0] + dta, _ := utils.NewTAFromAccountKey(acnt.ID) + if dta.Tenant != attrs.Tenant || dta.Account != attrs.Account { + t.Error("Unexpected account id received: ", acnt.ID) + } + if balances := acnt.BalanceMap["*monetary"]; len(balances) != 1 { + t.Errorf("Unexpected balances found: %+v", balances) + } + if len(acnt.ActionTriggers) != 4 { + t.Errorf("Unexpected action triggers for account: %+v", acnt.ActionTriggers) + } + if acnt.AllowNegative { + t.Error("AllowNegative should not be set") + } + if acnt.Disabled { + t.Error("Disabled should not be set") + } + } + attrs = &v2.AttrSetAccount{Tenant: "cgrates.org", Account: "tutacnt1", ActionPlanIDs: &[]string{"PACKAGE_10"}, ActionTriggerIDs: &[]string{"STANDARD_TRIGGERS"}, AllowNegative: utils.BoolPointer(true), Disabled: utils.BoolPointer(true), ReloadScheduler: true} + + if err := tutLocalRpc.Call("ApierV2.SetAccount", attrs, &reply); err != nil { + t.Error("Got error on ApierV2.SetAccount: ", err.Error()) + } else if reply != "OK" { + t.Errorf("Calling ApierV2.SetAccount received: %s", reply) + } + if err := tutLocalRpc.Call("ApierV2.GetAccounts", utils.AttrGetAccounts{Tenant: attrs.Tenant, AccountIds: []string{attrs.Account}}, &acnts); err != nil { + t.Error(err) + } else if len(acnts) != 1 { + t.Errorf("Accounts received: %+v", acnts) + } else { + acnt := acnts[0] + dta, _ := utils.NewTAFromAccountKey(acnt.ID) + if dta.Tenant != attrs.Tenant || dta.Account != attrs.Account { + t.Error("Unexpected account id received: ", acnt.ID) + } + if balances := acnt.BalanceMap["*monetary"]; len(balances) != 1 { + t.Errorf("Unexpected balances found: %+v", balances) + } + if len(acnt.ActionTriggers) != 4 { + t.Errorf("Unexpected action triggers for account: %+v", acnt.ActionTriggers) + } + if !acnt.AllowNegative { + t.Error("AllowNegative should be set") + } + if !acnt.Disabled { + t.Error("Disabled should be set") + } + } + attrs = &v2.AttrSetAccount{Tenant: "cgrates.org", Account: "tutacnt1", ActionPlanIDs: &[]string{"PACKAGE_1001"}, ActionTriggerIDs: &[]string{"CDRST1_WARN"}, AllowNegative: utils.BoolPointer(true), Disabled: utils.BoolPointer(true), ReloadScheduler: true} + + if err := tutLocalRpc.Call("ApierV2.SetAccount", attrs, &reply); err != nil { + t.Error("Got error on ApierV2.SetAccount: ", err.Error()) + } else if reply != "OK" { + t.Errorf("Calling ApierV2.SetAccount received: %s", reply) + } + time.Sleep(100*time.Millisecond + time.Duration(*waitRater)*time.Millisecond) // Give time for scheduler to execute topups + if err := tutLocalRpc.Call("ApierV2.GetAccounts", utils.AttrGetAccounts{Tenant: attrs.Tenant, AccountIds: []string{attrs.Account}}, &acnts); err != nil { + t.Error(err) + } else if len(acnts) != 1 { + t.Errorf("Accounts received: %+v", acnts) + } else { + acnt := acnts[0] + dta, _ := utils.NewTAFromAccountKey(acnt.ID) + if dta.Tenant != attrs.Tenant || dta.Account != attrs.Account { + t.Error("Unexpected account id received: ", acnt.ID) + } + if balances := acnt.BalanceMap["*monetary"]; len(balances) != 3 { + t.Errorf("Unexpected balances found: %+v", balances) + } + if len(acnt.ActionTriggers) != 7 { + t.Errorf("Unexpected action triggers for account: %+v", acnt.ActionTriggers) + } + if !acnt.AllowNegative { + t.Error("AllowNegative should be set") + } + if !acnt.Disabled { + t.Error("Disabled should be set") + } + } +} + +/* +// Make sure all stats queues were updated +func TestTutITCdrStatsAfter(t *testing.T) { + var statMetrics map[string]float64 + eMetrics := map[string]float64{engine.ACD: 90.2, engine.ASR: 100, engine.TCC: 1.675, engine.TCD: 451, engine.ACC: 0.335} + if err := tutLocalRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST1"}, &statMetrics); err != nil { + t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) + } else if !reflect.DeepEqual(eMetrics, statMetrics) { + t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) + } + eMetrics = map[string]float64{engine.ACC: 0.35, engine.ACD: 120, engine.ASR: 100, engine.TCC: 1.675, engine.TCD: 451} + if err := tutLocalRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1001"}, &statMetrics); err != nil { + t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) + } else if !reflect.DeepEqual(eMetrics, statMetrics) { + t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) + } + eMetrics = map[string]float64{engine.TCD: 451, engine.ACC: 0.325, engine.ACD: 90, engine.ASR: 100, engine.TCC: 1.675} + if err := tutLocalRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1002"}, &statMetrics); err != nil { + t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) + } else if !reflect.DeepEqual(eMetrics, statMetrics) { + t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) + } + eMetrics = map[string]float64{engine.TCC: 1.675, engine.TCD: 451, engine.ACC: 0.325, engine.ACD: 90, engine.ASR: 100} + if err := tutLocalRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1003"}, &statMetrics); err != nil { + t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) + } else if !reflect.DeepEqual(eMetrics, statMetrics) { + t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) + } + eMetrics = map[string]float64{engine.TCC: 0.7, engine.TCD: 240, engine.ACC: 0.35, engine.ACD: 120, engine.ASR: 100} + if err := tutLocalRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL1"}, &statMetrics); err != nil { + t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) + //} else if !reflect.DeepEqual(eMetrics, statMetrics) { + // t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) + } + eMetrics = map[string]float64{engine.TCD: 331, engine.ACC: 0.33125, engine.ACD: 82.75, engine.ASR: 100, engine.TCC: 1.325} + if err := tutLocalRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL2"}, &statMetrics); err != nil { + t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) + } else if !reflect.DeepEqual(eMetrics, statMetrics) { + t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) + } +} +*/ + +/* FixMe : In CallCost (Timespans) Increments is not populated so does not convert properly CallCost to Event + +func TestTutITPrepaidCDRWithSMCost(t *testing.T) { + cdr := &engine.CDR{CGRID: utils.Sha1("testprepaid1", time.Date(2016, 4, 6, 13, 29, 24, 0, time.UTC).String()), + ToR: utils.VOICE, OriginID: "testprepaid1", OriginHost: "192.168.1.1", + Source: "TEST_PREPAID_CDR_SMCOST1", RequestType: utils.META_PREPAID, Tenant: "cgrates.org", + RunID: utils.META_DEFAULT, + Category: "call", Account: "1001", Subject: "1001", Destination: "1003", + SetupTime: time.Date(2016, 4, 6, 13, 29, 24, 0, time.UTC), + AnswerTime: time.Date(2016, 4, 6, 13, 30, 0, 0, time.UTC), + Usage: time.Duration(90) * time.Second, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} + + + cc := &engine.CallCost{ + Category: "call", + Account: "1001", + Subject: "1001", + Tenant: "cgrates.org", + Direction: utils.OUT, + Destination: "1003", + Timespans: []*engine.TimeSpan{ + &engine.TimeSpan{ + TimeStart: time.Date(2016, 4, 6, 13, 30, 0, 0, time.UTC), + TimeEnd: time.Date(2016, 4, 6, 13, 31, 30, 0, time.UTC), + DurationIndex: 0, + RateInterval: &engine.RateInterval{ + Rating: &engine.RIRate{ + Rates: engine.RateGroups{ + &engine.Rate{ + GroupIntervalStart: 0, + Value: 0.01, + RateIncrement: 10 * time.Second, + RateUnit: time.Second}}}}, + }, + }, + TOR: utils.VOICE} + smCost := &engine.SMCost{CGRID: cdr.CGRID, + RunID: utils.META_DEFAULT, + OriginHost: cdr.OriginHost, + OriginID: cdr.OriginID, + CostSource: "TestTutITPrepaidCDRWithSMCost", + Usage: cdr.Usage, + CostDetails: engine.NewEventCostFromCallCost(cc, cdr.CGRID, utils.META_DEFAULT), + } + var reply string + if err := tutLocalRpc.Call("CdrsV1.StoreSMCost", &engine.AttrCDRSStoreSMCost{Cost: smCost}, &reply); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if reply != utils.OK { + t.Error("Unexpected reply received: ", reply) + } + if err := tutLocalRpc.Call("CdrsV1.ProcessCdr", cdr, &reply); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if reply != utils.OK { + t.Error("Unexpected reply received: ", reply) + } + time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for CDR to be processed + var cdrs []*engine.ExternalCDR + req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, CGRIDs: []string{cdr.CGRID}} + if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if len(cdrs) != 1 { + t.Error("Unexpected number of CDRs returned: ", len(cdrs)) + } else { + if cdrs[0].OriginID != cdr.OriginID { + t.Errorf("Unexpected OriginID for Cdr received: %+v", cdrs[0].OriginID) + } + if cdrs[0].Cost != 0.9 { + t.Errorf("Unexpected Cost for Cdr received: %+v", utils.ToJSON(cdrs[0].Cost)) + } + } +} +*/ + +func TestTutITPrepaidCDRWithoutSMCost(t *testing.T) { + cdr := &engine.CDR{CGRID: utils.Sha1("testprepaid2", time.Date(2016, 4, 6, 13, 29, 24, 0, time.UTC).String()), + ToR: utils.VOICE, OriginID: "testprepaid2", OriginHost: "192.168.1.1", Source: "TEST_PREPAID_CDR_NO_SMCOST1", RequestType: utils.META_PREPAID, + Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1003", + SetupTime: time.Date(2016, 4, 6, 13, 29, 24, 0, time.UTC), AnswerTime: time.Date(2016, 4, 6, 13, 30, 0, 0, time.UTC), + Usage: time.Duration(90) * time.Second, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} + var reply string + if err := tutLocalRpc.Call("CdrsV1.ProcessCdr", cdr, &reply); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if reply != utils.OK { + t.Error("Unexpected reply received: ", reply) + } + /* + time.Sleep(time.Duration(7000) * time.Millisecond) // Give time for CDR to be processed + var cdrs []*engine.ExternalCDR + req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, CGRIDs: []string{cdr.CGRID}} + if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if len(cdrs) != 1 { + t.Error("Unexpected number of CDRs returned: ", len(cdrs)) + } else { + if cdrs[0].OriginID != cdr.OriginID { + t.Errorf("Unexpected OriginID for Cdr received: %+v", cdrs[0]) + } + if cdrs[0].Cost != 0.9 { + t.Errorf("Unexpected Cost for Cdr received: %+v", cdrs[0]) + } + } + */ +} + +func TestTutITExportCDR(t *testing.T) { + cdr := &engine.CDR{ToR: utils.VOICE, OriginID: "testexportcdr1", OriginHost: "192.168.1.1", Source: "TestTutITExportCDR", RequestType: utils.META_RATED, + Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1003", + SetupTime: time.Date(2016, 11, 30, 17, 5, 24, 0, time.UTC), AnswerTime: time.Date(2016, 11, 30, 17, 6, 4, 0, time.UTC), + Usage: time.Duration(98) * time.Second, + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} + cdr.ComputeCGRID() + var reply string + if err := tutLocalRpc.Call("CdrsV1.ProcessCdr", cdr, &reply); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if reply != utils.OK { + t.Error("Unexpected reply received: ", reply) + } + time.Sleep(time.Duration(50) * time.Millisecond) // Give time for CDR to be processed + var cdrs []*engine.ExternalCDR + req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, CGRIDs: []string{cdr.CGRID}} + if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil { + t.Error("Unexpected error: ", err.Error()) + } else if len(cdrs) != 1 { + t.Error("Unexpected number of CDRs returned: ", len(cdrs)) + } else { + if cdrs[0].OriginID != cdr.OriginID { + t.Errorf("Unexpected OriginID for Cdr received: %+v", cdrs[0]) + } + if cdrs[0].Cost != 1.3334 { + t.Errorf("Unexpected Cost for Cdr received: %+v", cdrs[0]) + } + } + var replyExport v1.RplExportedCDRs + exportArgs := v1.ArgExportCDRs{ + ExportPath: utils.StringPointer("/tmp"), + ExportFileName: utils.StringPointer("TestTutITExportCDR.csv"), + ExportTemplate: utils.StringPointer("TestTutITExportCDR"), + RPCCDRsFilter: utils.RPCCDRsFilter{CGRIDs: []string{cdr.CGRID}, NotRunIDs: []string{utils.MetaRaw}}} + if err := tutLocalRpc.Call("ApierV1.ExportCDRs", exportArgs, &replyExport); err != nil { + t.Error(err) + } + eExportContent := `f0a92222a7d21b4d9f72744aabe82daef52e20d8,*default,testexportcdr1,*rated,cgrates.org,call,1001,1003,2016-11-30T18:06:04+01:00,98,1.33340,RETA +f0a92222a7d21b4d9f72744aabe82daef52e20d8,derived_run1,testexportcdr1,*rated,cgrates.org,call,1001,1003,2016-11-30T18:06:04+01:00,98,1.33340,RETA +` + eExportContent2 := `f0a92222a7d21b4d9f72744aabe82daef52e20d8,derived_run1,testexportcdr1,*rated,cgrates.org,call,1001,1003,2016-11-30T18:06:04+01:00,98,1.33340,RETA +f0a92222a7d21b4d9f72744aabe82daef52e20d8,*default,testexportcdr1,*rated,cgrates.org,call,1001,1003,2016-11-30T18:06:04+01:00,98,1.33340,RETA +` + expFilePath := path.Join(*exportArgs.ExportPath, *exportArgs.ExportFileName) + if expContent, err := ioutil.ReadFile(expFilePath); err != nil { + t.Error(err) + } else if eExportContent != string(expContent) && eExportContent2 != string(expContent) { // CDRs are showing up randomly so we cannot predict order of export + t.Errorf("Expecting: <%q> or <%q> received: <%q>", eExportContent, eExportContent2, string(expContent)) + } + if err := os.Remove(expFilePath); err != nil { + t.Error(err) + } + +} + +func TestTutITStopCgrEngine(t *testing.T) { + if err := engine.KillEngine(1000); err != nil { + t.Error(err) + } +} diff --git a/general_tests/tutorial_it_test.go b/general_tests/tutorial_it_test.go index b7faee6ed..1d136598e 100644 --- a/general_tests/tutorial_it_test.go +++ b/general_tests/tutorial_it_test.go @@ -1,1488 +1,129 @@ -// +build integration - -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ - -package general_tests - -import ( - "io/ioutil" - "net/rpc" - "net/rpc/jsonrpc" - "os" - "path" - "reflect" - "testing" - "time" - - "github.com/cgrates/cgrates/apier/v1" - "github.com/cgrates/cgrates/apier/v2" - "github.com/cgrates/cgrates/config" - "github.com/cgrates/cgrates/engine" - "github.com/cgrates/cgrates/utils" -) - -var tutLocalCfgPath string -var tutFsLocalCfg *config.CGRConfig -var tutLocalRpc *rpc.Client -var loadInst utils.LoadInstance // Share load information between tests - -func TestTutITInitCfg(t *testing.T) { - tutLocalCfgPath = path.Join(*dataDir, "conf", "samples", "tutmysql") - // Init config first - var err error - tutFsLocalCfg, err = config.NewCGRConfigFromFolder(tutLocalCfgPath) - if err != nil { - t.Error(err) - } - tutFsLocalCfg.DataFolderPath = *dataDir // Share DataFolderPath through config towards StoreDb for Flush() - config.SetCgrConfig(tutFsLocalCfg) -} - -// Remove data in dataDB -func TestTutITResetDataDb(t *testing.T) { - if err := engine.InitDataDb(tutFsLocalCfg); err != nil { - t.Fatal(err) - } -} - -// Wipe out the cdr database -func TestTutITResetStorDb(t *testing.T) { - if err := engine.InitStorDb(tutFsLocalCfg); err != nil { - t.Fatal(err) - } -} - -// Start CGR Engine -func TestTutITStartEngine(t *testing.T) { - if _, err := engine.StopStartEngine(tutLocalCfgPath, *waitRater); err != nil { - t.Fatal(err) - } -} - -// Connect rpc client to rater -func TestTutITRpcConn(t *testing.T) { - var err error - tutLocalRpc, err = jsonrpc.Dial("tcp", tutFsLocalCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed - if err != nil { - t.Fatal(err) - } -} - -// Load the tariff plan, creating accounts and their balances -func TestTutITLoadTariffPlanFromFolder(t *testing.T) { - attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "oldtutorial")} - if err := tutLocalRpc.Call("ApierV2.LoadTariffPlanFromFolder", attrs, &loadInst); err != nil { - t.Error(err) - } - time.Sleep(100*time.Millisecond + time.Duration(*waitRater)*time.Millisecond) // Give time for scheduler to execute topups -} - -// Check loaded stats -func TestTutITCacheStats(t *testing.T) { - var reply string - if err := tutLocalRpc.Call("ApierV1.LoadCache", utils.AttrReloadCache{}, &reply); err != nil { - t.Error(err) - } else if reply != "OK" { - t.Error(reply) - } - var rcvStats *utils.CacheStats - expectedStats := &utils.CacheStats{Destinations: 5, ReverseDestinations: 7, RatingPlans: 4, RatingProfiles: 10, - Actions: 9, ActionPlans: 4, AccountActionPlans: 5, SharedGroups: 1, DerivedChargers: 1, LcrProfiles: 5, - CdrStats: 6, Users: 3, Aliases: 1, ReverseAliases: 2, ResourceProfiles: 3, Resources: 3, StatQueues: 1, - StatQueueProfiles: 1, Thresholds: 7, ThresholdProfiles: 7, Filters: 16, SupplierProfiles: 3, AttributeProfiles: 1} - var args utils.AttrCacheStats - if err := tutLocalRpc.Call("ApierV1.GetCacheStats", args, &rcvStats); err != nil { - t.Error("Got error on ApierV1.GetCacheStats: ", err.Error()) - } else if !reflect.DeepEqual(expectedStats, rcvStats) { - t.Errorf("Calling ApierV1.GetCacheStats expected: %+v, received: %+v", expectedStats, rcvStats) - } - expKeys := utils.ArgsCache{ - DestinationIDs: &[]string{"DST_1003", "DST_1002", "DST_DE_MOBILE", "DST_1007", "DST_FS"}, - RatingPlanIDs: &[]string{"RP_RETAIL1", "RP_GENERIC"}, - } - var rcvKeys utils.ArgsCache - argsAPI := utils.ArgsCacheKeys{ArgsCache: utils.ArgsCache{ - DestinationIDs: &[]string{}, RatingPlanIDs: &[]string{"RP_RETAIL1", "RP_GENERIC", "NONEXISTENT"}}} - if err := tutLocalRpc.Call("ApierV1.GetCacheKeys", argsAPI, &rcvKeys); err != nil { - t.Error("Got error on ApierV1.GetCacheStats: ", err.Error()) - } else { - if len(*expKeys.DestinationIDs) != len(*rcvKeys.DestinationIDs) { - t.Errorf("Expected: %+v, received: %+v", expKeys.DestinationIDs, rcvKeys.DestinationIDs) - } - if !reflect.DeepEqual(*expKeys.RatingPlanIDs, *rcvKeys.RatingPlanIDs) { - t.Errorf("Expected: %+v, received: %+v", expKeys.RatingPlanIDs, rcvKeys.RatingPlanIDs) - } - } - if _, err := engine.StopStartEngine(tutLocalCfgPath, 1500); err != nil { - t.Fatal(err) - } - var err error - tutLocalRpc, err = jsonrpc.Dial("tcp", tutFsLocalCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed - if err != nil { - t.Fatal(err) - } - if err := tutLocalRpc.Call("ApierV1.GetCacheStats", args, &rcvStats); err != nil { - t.Error("Got error on ApierV1.GetCacheStats: ", err.Error()) - } else if !reflect.DeepEqual(expectedStats, rcvStats) { - t.Errorf("Calling ApierV1.GetCacheStats expected: %+v, received: %+v", expectedStats, rcvStats) - } -} - -func TestTutITGetUsers(t *testing.T) { - var users engine.UserProfiles - if err := tutLocalRpc.Call("UsersV1.GetUsers", engine.UserProfile{}, &users); err != nil { - t.Error("Got error on UsersV1.GetUsers: ", err.Error()) - } else if len(users) != 3 { - t.Error("Calling UsersV1.GetUsers got users:", len(users)) - } -} - -func TestTutITGetMatchingAlias(t *testing.T) { - args := engine.AttrMatchingAlias{ - Destination: "1005", - Direction: "*out", - Tenant: "cgrates.org", - Category: "call", - Account: "1006", - Subject: "1006", - Context: utils.MetaRating, - Target: "Account", - Original: "1006", - } - eMatchingAlias := "1002" - var matchingAlias string - if err := tutLocalRpc.Call("AliasesV1.GetMatchingAlias", args, &matchingAlias); err != nil { - t.Error(err) - } else if matchingAlias != eMatchingAlias { - t.Errorf("Expecting: %s, received: %+v", eMatchingAlias, matchingAlias) - } -} - -// Check call costs -func TestTutITGetCosts(t *testing.T) { - tStart, _ := utils.ParseDate("2014-08-04T13:00:00Z") - tEnd, _ := utils.ParseDate("2014-08-04T13:00:20Z") - cd := engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1002", - DurationIndex: 0, - TimeStart: tStart, - TimeEnd: tEnd, - } - var cc engine.CallCost - if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.Cost != 0.6 { - t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) - } - // Make sure that the same cost is returned via users aliasing - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: utils.USERS, - Subject: utils.USERS, - Account: utils.USERS, - Destination: "1002", - DurationIndex: 0, - TimeStart: tStart, - TimeEnd: tEnd, - ExtraFields: map[string]string{"Uuid": "388539dfd4f5cefee8f488b78c6c244b9e19138e"}, - } - if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.Cost != 0.6 { - t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) - } - tStart, _ = utils.ParseDate("2014-08-04T13:00:00Z") - tEnd, _ = utils.ParseDate("2014-08-04T13:01:25Z") - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1002", - DurationIndex: 0, - TimeStart: tStart, - TimeEnd: tEnd, - } - if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.Cost != 0.6418 { // 0.01 first minute, 0.04 25 seconds with RT_20CNT - t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) - } - tStart, _ = utils.ParseDate("2014-08-04T13:00:00Z") - tEnd, _ = utils.ParseDate("2014-08-04T13:00:20Z") - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1003", - DurationIndex: 0, - TimeStart: tStart, - TimeEnd: tEnd, - } - if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.Cost != 1 { - t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) - } - tStart, _ = utils.ParseDate("2014-08-04T13:00:00Z") - tEnd, _ = utils.ParseDate("2014-08-04T13:01:25Z") - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1003", - DurationIndex: 0, - TimeStart: tStart, - TimeEnd: tEnd, - } - if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.Cost != 1.3 { - t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) - } - tStart, _ = utils.ParseDate("2014-08-04T13:00:00Z") - tEnd, _ = utils.ParseDate("2014-08-04T13:00:20Z") - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1004", - DurationIndex: 0, - TimeStart: tStart, - TimeEnd: tEnd, - } - if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.Cost != 1 { - t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) - } - tStart, _ = utils.ParseDate("2014-08-04T13:00:00Z") - tEnd, _ = utils.ParseDate("2014-08-04T13:01:25Z") - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1004", - DurationIndex: 0, - TimeStart: tStart, - TimeEnd: tEnd, - } - if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.Cost != 1.3 { - t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) - } - tStart = time.Date(2014, 8, 4, 13, 0, 0, 0, time.UTC) - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1007", - TimeStart: tStart, - TimeEnd: tStart.Add(time.Duration(50) * time.Second), - } - if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.Cost != 0.5 { - t.Errorf("Calling Responder.GetCost got callcost: %s", cc.AsJSON()) - } - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1007", - TimeStart: tStart, - TimeEnd: tStart.Add(time.Duration(70) * time.Second), - } - if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.Cost != 0.62 { - t.Errorf("Calling Responder.GetCost got callcost: %v", cc.Cost) - } - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1002", - Account: "1002", - Destination: "1007", - TimeStart: tStart, - TimeEnd: tStart.Add(time.Duration(50) * time.Second), - } - if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.Cost != 0.5 { - t.Errorf("Calling Responder.GetCost got callcost: %s", cc.AsJSON()) - } - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1002", - Account: "1002", - Destination: "1007", - TimeStart: tStart, - TimeEnd: tStart.Add(time.Duration(70) * time.Second), - } - if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.Cost != 0.7 { // In case of *disconnect strategy, it will not be applied so we can go on negative costs - t.Errorf("Calling Responder.GetCost got callcost: %s", cc.AsJSON()) - } - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1004", - TimeStart: time.Date(2016, 1, 6, 19, 0, 0, 0, time.UTC), - TimeEnd: time.Date(2016, 1, 6, 19, 1, 30, 0, time.UTC), - } - if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.Cost != 0.3249 { // - t.Errorf("Calling Responder.GetCost got callcost: %s", cc.AsJSON()) - } - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1004", - TimeStart: time.Date(2016, 1, 6, 18, 31, 5, 0, time.UTC), - TimeEnd: time.Date(2016, 1, 6, 18, 32, 35, 0, time.UTC), - } - if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.Cost != 1.3 { // - t.Errorf("Calling Responder.GetCost got callcost: %s", cc.AsJSON()) - } - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1002", - TimeStart: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC), - TimeEnd: time.Date(2014, 12, 7, 8, 44, 26, 0, time.UTC), - } - if err := tutLocalRpc.Call("Responder.GetCost", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.Cost != 0.3498 { // - t.Errorf("Calling Responder.GetCost got callcost: %s", cc.AsJSON()) - } -} - -// Check call costs -func TestTutITMaxDebit(t *testing.T) { - tStart := time.Date(2014, 8, 4, 13, 0, 0, 0, time.UTC) - cd := engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1002", - DurationIndex: 0, - TimeStart: tStart, - TimeEnd: tStart.Add(time.Duration(20) * time.Second), - } - var cc engine.CallCost - if err := tutLocalRpc.Call("Responder.MaxDebit", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.GetDuration() == 20 { - t.Errorf("Calling Responder.MaxDebit got callcost: %v", cc.GetDuration()) - } - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1003", - DurationIndex: 0, - TimeStart: tStart, - TimeEnd: tStart.Add(time.Duration(200) * time.Second), - } - if err := tutLocalRpc.Call("Responder.MaxDebit", cd, &cc); err != nil { - t.Error("Got error on Responder.MaxDebit: ", err.Error()) - } else if cc.GetDuration() == 200 { - t.Errorf("Calling Responder.MaxDebit got duration: %v", cc.GetDuration()) - } - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1007", - DurationIndex: 0, - TimeStart: tStart, - TimeEnd: tStart.Add(time.Duration(120) * time.Second), - } - cd.CgrID = "1" - if err := tutLocalRpc.Call("Responder.MaxDebit", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.GetDuration() == 120 { - t.Errorf("Calling Responder.MaxDebit got callcost: %v", cc.GetDuration()) - } - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1004", - Account: "1004", - Destination: "1007", - DurationIndex: 0, - TimeStart: tStart, - TimeEnd: tStart.Add(time.Duration(120) * time.Second), - } - cd.CgrID = "2" - if err := tutLocalRpc.Call("Responder.MaxDebit", cd, &cc); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if cc.GetDuration() != time.Duration(62)*time.Second { // We have as strategy *dsconnect - t.Errorf("Calling Responder.MaxDebit got callcost: %v", cc.GetDuration()) - } - var maxTime float64 - if err := tutLocalRpc.Call("Responder.GetMaxSessionTime", cd, &maxTime); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if maxTime != 62000000000 { // We have as strategy *dsconnect - t.Errorf("Calling Responder.GetMaxSessionTime got maxTime: %f", maxTime) - } -} - -// Check call costs -func TestTutITDerivedMaxSessionTime(t *testing.T) { - tStart := time.Date(2014, 8, 4, 13, 0, 0, 0, time.UTC) - ev := engine.CDR{ - CGRID: utils.Sha1("testevent1", tStart.String()), - ToR: utils.VOICE, - OriginID: "testevent1", - OriginHost: "127.0.0.1", - RequestType: utils.META_PREPAID, - Tenant: "cgrates.org", - Category: "call", - Account: "1004", - Subject: "1004", - Destination: "1007", - SetupTime: tStart, - AnswerTime: tStart, - Usage: time.Duration(120) * time.Second, - Cost: -1, - } - var maxTime float64 - if err := tutLocalRpc.Call("Responder.GetDerivedMaxSessionTime", ev, &maxTime); err != nil { - t.Error("Got error on Responder.GetCost: ", err.Error()) - } else if maxTime != 62000000000 { // We have as strategy *dsconnect - t.Errorf("Calling Responder.GetMaxSessionTime got maxTime: %f", maxTime) - } -} - -// Check MaxUsage -func TestTutITMaxUsage(t *testing.T) { - setupReq := &engine.UsageRecord{ToR: utils.VOICE, - RequestType: utils.META_PREPAID, Tenant: "cgrates.org", Category: "call", - Account: "1003", Subject: "1003", Destination: "1001", - SetupTime: "2014-08-04T13:00:00Z", Usage: "1s", - } - var maxTime float64 - if err := tutLocalRpc.Call("ApierV2.GetMaxUsage", setupReq, &maxTime); err != nil { - t.Error(err) - } else if maxTime != 1 { - t.Errorf("Calling ApierV2.MaxUsage got maxTime: %f", maxTime) - } - setupReq = &engine.UsageRecord{ToR: utils.VOICE, RequestType: utils.META_RATED, Tenant: "cgrates.org", Category: "call", - Account: "test_max_usage", Destination: "1001", - SetupTime: "2014-08-04T13:00:00Z", - } - if err := tutLocalRpc.Call("ApierV2.GetMaxUsage", setupReq, &maxTime); err != nil { - t.Error(err) - } else if maxTime != -1 { - t.Errorf("Calling ApierV2.MaxUsage got maxTime: %f", maxTime) - } -} - -// Check DebitUsage -func TestTutITDebitUsage(t *testing.T) { - setupReq := &engine.UsageRecord{ToR: utils.VOICE, RequestType: utils.META_PREPAID, Tenant: "cgrates.org", Category: "call", - Account: "1003", Subject: "1003", Destination: "1001", - AnswerTime: "2014-08-04T13:00:00Z", Usage: "1", - } - var reply string - if err := tutLocalRpc.Call("ApierV2.DebitUsage", setupReq, &reply); err != nil { - t.Error(err) - } else if reply != utils.OK { - t.Error("Calling ApierV2.DebitUsage reply: ", reply) - } -} - -// Test CDR from external sources -func TestTutITProcessExternalCdr(t *testing.T) { - cdr := &engine.ExternalCDR{ToR: utils.VOICE, - OriginID: "testextcdr1", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, - Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1001", - SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z", - Usage: "1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - } - var reply string - if err := tutLocalRpc.Call("CdrsV1.ProcessExternalCdr", cdr, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if reply != utils.OK { - t.Error("Unexpected reply received: ", reply) - } -} - -// Test CDR involving UserProfile -func TestTutITProcessExternalCdrUP(t *testing.T) { - cdr := &engine.ExternalCDR{ToR: utils.VOICE, - OriginID: "testextcdr2", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, - RequestType: utils.USERS, Tenant: utils.USERS, Account: utils.USERS, Destination: "1001", - SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z", Usage: "2s", - ExtraFields: map[string]string{"Cli": "+4986517174964", "fieldextr2": "valextr2", "SysUserName": utils.USERS}, - } - var reply string - if err := tutLocalRpc.Call("CdrsV1.ProcessExternalCdr", cdr, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if reply != utils.OK { - t.Error("Unexpected reply received: ", reply) - } - time.Sleep(time.Duration(*waitRater) * time.Millisecond) - eCdr := &engine.ExternalCDR{CGRID: "63a8d2bfeca2cfb790826c3ec461696d6574cfde", OrderID: 2, - ToR: utils.VOICE, - OriginID: "testextcdr2", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, - Tenant: "cgrates.org", Category: "call", Account: "1004", Subject: "1004", Destination: "1001", - SetupTime: time.Date(2014, 8, 4, 13, 0, 0, 0, time.UTC).Local().Format(time.RFC3339), - AnswerTime: time.Date(2014, 8, 4, 13, 0, 7, 0, time.UTC).Local().Format(time.RFC3339), Usage: "2s", - ExtraFields: map[string]string{"Cli": "+4986517174964", "fieldextr2": "valextr2", "SysUserName": "danb4"}, - RunID: utils.DEFAULT_RUNID, Cost: 1} - var cdrs []*engine.ExternalCDR - req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, - Accounts: []string{"1004"}, DestinationPrefixes: []string{"1001"}} - if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(cdrs) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(cdrs)) - } else { - if cdrs[0].CGRID != eCdr.CGRID { - t.Errorf("Unexpected CGRID for CDR: %+v", cdrs[0]) - } - if cdrs[0].ToR != eCdr.ToR { - t.Errorf("Unexpected TOR for CDR: %+v", cdrs[0]) - } - if cdrs[0].Source != eCdr.Source { - t.Errorf("Unexpected Source for CDR: %+v", cdrs[0]) - } - if cdrs[0].RequestType != eCdr.RequestType { - t.Errorf("Unexpected RequestType for CDR: %+v", cdrs[0]) - } - if cdrs[0].Tenant != eCdr.Tenant { - t.Errorf("Unexpected Tenant for CDR: %+v", cdrs[0]) - } - if cdrs[0].Category != eCdr.Category { - t.Errorf("Unexpected Category for CDR: %+v", cdrs[0]) - } - if cdrs[0].Account != eCdr.Account { - t.Errorf("Unexpected Account for CDR: %+v", cdrs[0]) - } - if cdrs[0].Subject != eCdr.Subject { - t.Errorf("Unexpected Subject for CDR: %+v", cdrs[0]) - } - if cdrs[0].Destination != eCdr.Destination { - t.Errorf("Unexpected Destination for CDR: %+v", cdrs[0]) - } - if cdrs[0].SetupTime != eCdr.SetupTime { - t.Errorf("Unexpected SetupTime for CDR: %+v", cdrs[0]) - } - if cdrs[0].AnswerTime != eCdr.AnswerTime { - t.Errorf("Unexpected AnswerTime for CDR: %+v", cdrs[0]) - } - if cdrs[0].Usage != eCdr.Usage { - t.Errorf("Unexpected Usage for CDR: %+v", cdrs[0]) - } - } -} - -func TestTutITCostErrors(t *testing.T) { - cdr := &engine.ExternalCDR{ToR: utils.VOICE, - OriginID: "TestTutIT_1", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_RATED, - Tenant: "cgrates.org", Category: "fake", Account: "2001", Subject: "2001", Destination: "1001", - SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z", - Usage: "1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - } - var reply string - if err := tutLocalRpc.Call("CdrsV1.ProcessExternalCdr", cdr, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if reply != utils.OK { - t.Error("Unexpected reply received: ", reply) - } - time.Sleep(time.Duration(*waitRater) * time.Millisecond) - var cdrs []*engine.ExternalCDR - req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{cdr.Account}, DestinationPrefixes: []string{cdr.Destination}} - if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(cdrs) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(cdrs)) - } else { - if cdrs[0].OriginID != cdr.OriginID { - t.Errorf("Unexpected OriginID for Cdr received: %+v", cdrs[0]) - } - if cdrs[0].Cost != -1 { - t.Errorf("Unexpected Cost for Cdr received: %+v", cdrs[0]) - } - } - cdr2 := &engine.ExternalCDR{ToR: utils.VOICE, - OriginID: "TestTutIT_2", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_POSTPAID, - Tenant: "cgrates.org", Category: "fake", Account: "2002", Subject: "2002", Destination: "1001", - SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z", - Usage: "1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - } - if err := tutLocalRpc.Call("CdrsV1.ProcessExternalCdr", cdr2, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if reply != utils.OK { - t.Error("Unexpected reply received: ", reply) - } - time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for CDR to be processed - req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{cdr2.Account}, DestinationPrefixes: []string{cdr2.Destination}} - if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(cdrs) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(cdrs)) - } else { - if cdrs[0].OriginID != cdr2.OriginID { - t.Errorf("Unexpected OriginID for Cdr received: %+v", cdrs[0]) - } - if cdrs[0].Cost != -1 { - t.Errorf("Unexpected Cost for Cdr received: %+v", cdrs[0]) - } - } - cdr3 := &engine.ExternalCDR{ToR: utils.VOICE, - OriginID: "TestTutIT_3", OriginHost: "192.168.1.1", Source: utils.UNIT_TEST, RequestType: utils.META_POSTPAID, - Tenant: "cgrates.org", Category: "fake", Account: "1001", Subject: "1001", Destination: "2002", - SetupTime: "2014-08-04T13:00:00Z", AnswerTime: "2014-08-04T13:00:07Z", - Usage: "1", ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}, - } - if err := tutLocalRpc.Call("CdrsV1.ProcessExternalCdr", cdr3, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if reply != utils.OK { - t.Error("Unexpected reply received: ", reply) - } - time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for CDR to be processed - req = utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, Accounts: []string{cdr3.Account}, DestinationPrefixes: []string{cdr3.Destination}} - if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(cdrs) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(cdrs)) - } else { - if cdrs[0].OriginID != cdr3.OriginID { - t.Errorf("Unexpected OriginID for Cdr received: %+v", cdrs[0]) - } - if cdrs[0].Cost != -1 { - t.Errorf("Unexpected Cost for Cdr received: %+v", cdrs[0]) - } - } -} - -// Make sure queueids were created -func TestTutITCdrStats(t *testing.T) { - var queueIds []string - eQueueIds := []string{"CDRST1", "CDRST_1001", "CDRST_1002", "CDRST_1003", "STATS_SUPPL1", "STATS_SUPPL2"} - if err := tutLocalRpc.Call("CDRStatsV1.GetQueueIds", "", &queueIds); err != nil { - t.Error("Calling CDRStatsV1.GetQueueIds, got error: ", err.Error()) - } else if len(eQueueIds) != len(queueIds) { - t.Errorf("Expecting: %v, received: %v", eQueueIds, queueIds) - } -} - -func TestTutITLeastCost(t *testing.T) { - tStart, _ := utils.ParseDate("2014-08-04T13:00:00Z") - tEnd, _ := utils.ParseDate("2014-08-04T13:01:00Z") - cd := engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1005", - Account: "1005", - Destination: "1002", - TimeStart: tStart, - TimeEnd: tEnd, - } - eStLcr := &engine.LCRCost{ - Entry: &engine.LCREntry{DestinationId: "DST_1002", RPCategory: "lcr_profile2", Strategy: engine.LCR_STRATEGY_LOWEST, StrategyParams: "", Weight: 10.0}, - SupplierCosts: []*engine.LCRSupplierCost{ - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile2:suppl3", Cost: 0.01, Duration: 60 * time.Second}, - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile2:suppl1", Cost: 0.6, Duration: 60 * time.Second}, - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile2:suppl2", Cost: 1.2, Duration: 60 * time.Second}, - }, - } - var lcr engine.LCRCost - cd.CgrID = "10" - cd.RunID = "10" - if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) - } else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.SupplierCosts, lcr.SupplierCosts) - } - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1005", - Account: "1005", - Destination: "1003", - TimeStart: tStart, - TimeEnd: tEnd, - } - eStLcr = &engine.LCRCost{ - Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_LOWEST, StrategyParams: "", Weight: 10.0}, - SupplierCosts: []*engine.LCRSupplierCost{ - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second}, - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 1.2, Duration: 60 * time.Second}, - }, - } - eStLcr2 := &engine.LCRCost{ - Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_LOWEST, StrategyParams: "", Weight: 10.0}, - SupplierCosts: []*engine.LCRSupplierCost{ - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 1.2, Duration: 60 * time.Second}, - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second}, - }, - } - cd.CgrID = "11" - cd.RunID = "11" - if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) - } else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) && !reflect.DeepEqual(eStLcr2.SupplierCosts, lcr.SupplierCosts) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.SupplierCosts[0], lcr.SupplierCosts[0]) - } -} - -// Check LCR -func TestTutITLcrStatic(t *testing.T) { - tStart, _ := utils.ParseDate("2014-08-04T13:00:00Z") - tEnd, _ := utils.ParseDate("2014-08-04T13:01:00Z") - cd := engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1002", - TimeStart: tStart, - TimeEnd: tEnd, - } - eStLcr := &engine.LCRCost{ - Entry: &engine.LCREntry{DestinationId: "DST_1002", RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_STATIC, StrategyParams: "suppl2;suppl1", Weight: 10.0}, - SupplierCosts: []*engine.LCRSupplierCost{ - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 0.6, Duration: 60 * time.Second}, - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second}, - }, - } - var lcr engine.LCRCost - cd.CgrID = "1" - cd.RunID = "1" - if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) - } else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.SupplierCosts[0], lcr.SupplierCosts[0]) - } - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1001", - Account: "1001", - Destination: "1003", - TimeStart: tStart, - TimeEnd: tEnd, - } - eStLcr = &engine.LCRCost{ - Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_STATIC, StrategyParams: "suppl1;suppl2", Weight: 10.0}, - SupplierCosts: []*engine.LCRSupplierCost{ - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second}, - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 1.2, Duration: 60 * time.Second}, - }, - } - cd.CgrID = "2" - cd.RunID = "2" - if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) - } else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.SupplierCosts[0], lcr.SupplierCosts[0]) - } -} - -func TestTutITLcrHighestCost(t *testing.T) { - tStart, _ := utils.ParseDate("2014-08-04T13:00:00Z") - tEnd, _ := utils.ParseDate("2014-08-04T13:01:00Z") - cd := engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1002", - Account: "1002", - Destination: "1002", - TimeStart: tStart, - TimeEnd: tEnd, - } - eStLcr := &engine.LCRCost{ - Entry: &engine.LCREntry{DestinationId: "DST_1002", RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_HIGHEST, StrategyParams: "", Weight: 10.0}, - SupplierCosts: []*engine.LCRSupplierCost{ - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second}, - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 0.6, Duration: 60 * time.Second}, - }, - } - var lcr engine.LCRCost - if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) - } else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.SupplierCosts[0], lcr.SupplierCosts[0]) - } - // LCR with Alias - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1006", - Account: "1006", - Destination: "1002", - TimeStart: tStart, - TimeEnd: tEnd, - } - if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) - } else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.SupplierCosts[0], lcr.SupplierCosts[0]) - } -} - -func TestTutITLcrQos(t *testing.T) { - tStart, _ := utils.ParseDate("2014-08-04T13:00:00Z") - tEnd, _ := utils.ParseDate("2014-08-04T13:01:00Z") - cd := engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1002", - Account: "1002", - Destination: "1003", - TimeStart: tStart, - TimeEnd: tEnd, - } - eStLcr := &engine.LCRCost{ - Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", - Strategy: engine.LCR_STRATEGY_QOS, StrategyParams: "", Weight: 10.0}, - SupplierCosts: []*engine.LCRSupplierCost{ - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", - Cost: 1.2, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: -1, engine.ACC: -1, engine.TCC: -1, - engine.ASR: -1, engine.ACD: -1, engine.DDC: -1}}, - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", - Cost: 1.2, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: -1, engine.ACC: -1, engine.TCC: -1, - engine.ASR: -1, engine.ACD: -1, engine.DDC: -1}}, - }, - } - /* - eStLcr2 := &engine.LCRCost{ - Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", - Strategy: engine.LCR_STRATEGY_QOS, StrategyParams: "", Weight: 10.0}, - SupplierCosts: []*engine.LCRSupplierCost{ - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", - Cost: 1.2, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: -1, engine.ACC: -1, engine.TCC: -1, - engine.ASR: -1, engine.ACD: -1, engine.DDC: -1}}, - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", - Cost: 1.2, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: -1, engine.ACC: -1, engine.TCC: -1, - engine.ASR: -1, engine.ACD: -1, engine.DDC: -1}}, - }, - } - */ - var lcr engine.LCRCost - // Since there is no real quality difference, the suppliers will come in random order here - cd.CgrID = "3" - cd.RunID = "3" - /* - if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) - } else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) && - !reflect.DeepEqual(eStLcr2.SupplierCosts, lcr.SupplierCosts) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.SupplierCosts[0], lcr.SupplierCosts[0]) - } - */ - // Post some CDRs to influence stats - testCdr1 := &engine.CDR{CGRID: utils.Sha1("testcdr1", - time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - ToR: utils.VOICE, OriginID: "testcdr1", OriginHost: "192.168.1.1", - Source: "TEST_QOS_LCR", RequestType: utils.META_RATED, - Tenant: "cgrates.org", Category: "call", Account: "1001", - Subject: "1001", Destination: "1002", - SetupTime: time.Date(2014, 12, 7, 8, 42, 24, 0, time.UTC), - AnswerTime: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(2) * time.Minute, - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} - testCdr2 := &engine.CDR{CGRID: utils.Sha1("testcdr2", - time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - ToR: utils.VOICE, OriginID: "testcdr2", OriginHost: "192.168.1.1", - Source: "TEST_QOS_LCR", RequestType: utils.META_RATED, - Tenant: "cgrates.org", Category: "call", Account: "1002", - Subject: "1002", Destination: "1003", - SetupTime: time.Date(2014, 12, 7, 8, 42, 24, 0, time.UTC), - AnswerTime: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(90) * time.Second, - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} - var reply string - for _, cdr := range []*engine.CDR{testCdr1, testCdr2} { - if err := tutLocalRpc.Call("CdrsV1.ProcessCdr", cdr, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if reply != utils.OK { - t.Error("Unexpected reply received: ", reply) - } - } - // Based on stats, supplier1 should always be better since he has a higer ACD - eStLcr = &engine.LCRCost{ - Entry: &engine.LCREntry{DestinationId: utils.ANY, - RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_QOS, - StrategyParams: "", Weight: 10.0}, - SupplierCosts: []*engine.LCRSupplierCost{ - &engine.LCRSupplierCost{ - Supplier: "*out:cgrates.org:lcr_profile1:suppl1", - Cost: 1.2, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: 240, engine.ACC: 0.35, - engine.TCC: 0.7, engine.ASR: 100, engine.ACD: 120}}, - &engine.LCRSupplierCost{ - Supplier: "*out:cgrates.org:lcr_profile1:suppl2", - Cost: 1.2, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: 90, engine.ACC: 0.325, - engine.TCC: 0.325, engine.ASR: 100, engine.ACD: 90}}, - }, - } - cd.CgrID = "4" - cd.RunID = "4" - if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) - //} else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) && !reflect.DeepEqual(eStLcr2.SupplierCosts, lcr.SupplierCosts) { - // t.Errorf("Expecting: %+v, %+v, received: %+v, %+v", eStLcr.SupplierCosts[0], eStLcr.SupplierCosts[1], lcr.SupplierCosts[0], lcr.SupplierCosts[1]) - } - testCdr3 := &engine.CDR{CGRID: utils.Sha1("testcdr3", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - ToR: utils.VOICE, OriginID: "testcdr3", OriginHost: "192.168.1.1", Source: "TEST_QOS_LCR", RequestType: utils.META_RATED, - Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1004", - SetupTime: time.Date(2014, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(180) * time.Second} - if err := tutLocalRpc.Call("CdrsV1.ProcessCdr", testCdr3, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if reply != utils.OK { - t.Error("Unexpected reply received: ", reply) - } - // Since ACD has considerably increased for supplier2, we should have it as first prio now - eStLcr = &engine.LCRCost{ - Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_QOS, StrategyParams: "", Weight: 10.0}, - SupplierCosts: []*engine.LCRSupplierCost{ - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 1.2, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: 270, engine.ACC: 0.3625, engine.TCC: 0.725, engine.ASR: 100, engine.ACD: 135}}, - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: 240, engine.ACC: 0.35, engine.TCC: 0.7, engine.ASR: 100, engine.ACD: 120}}, - }, - } - cd.CgrID = "5" - cd.RunID = "5" - if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eStLcr.Entry, lcr.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eStLcr.Entry, lcr.Entry) - //} else if !reflect.DeepEqual(eStLcr.SupplierCosts, lcr.SupplierCosts) && !reflect.DeepEqual(eStLcr2.SupplierCosts, lcr.SupplierCosts) { - // t.Errorf("Expecting: %+v, %+v, received: %+v, %+v", eStLcr.SupplierCosts[0], eStLcr.SupplierCosts[1], lcr.SupplierCosts[0], lcr.SupplierCosts[1]) - } -} - -func TestTutITLcrQosThreshold(t *testing.T) { - tStart, _ := utils.ParseDate("2014-08-04T13:00:00Z") - tEnd, _ := utils.ParseDate("2014-08-04T13:01:00Z") - cd := engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1003", - Account: "1003", - Destination: "1002", - TimeStart: tStart, - TimeEnd: tEnd, - } - eLcr := &engine.LCRCost{ - Entry: &engine.LCREntry{DestinationId: "DST_1002", RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_QOS_THRESHOLD, StrategyParams: "20;;;;2m;;;;;;;", Weight: 10.0}, - SupplierCosts: []*engine.LCRSupplierCost{ - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 0.6, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: 270, engine.ACC: 0.3625, engine.TCC: 0.725, engine.ASR: 100, engine.ACD: 135}}, - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: 240, engine.ACC: 0.35, engine.TCC: 0.7, engine.ASR: 100, engine.ACD: 120}}, - }, - } - var lcr engine.LCRCost - cd.CgrID = "6" - cd.RunID = "6" - if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eLcr.Entry, lcr.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eLcr.Entry, lcr.Entry) - //} else if !reflect.DeepEqual(eLcr.SupplierCosts, lcr.SupplierCosts) { - // t.Errorf("Expecting: %+v, %+v received: %+v, %+v", eLcr.SupplierCosts[0], eLcr.SupplierCosts[1], lcr.SupplierCosts[0], lcr.SupplierCosts[1]) - } - testCdr4 := &engine.CDR{CGRID: utils.Sha1("testcdr4", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - ToR: utils.VOICE, OriginID: "testcdr4", OriginHost: "192.168.1.1", Source: "TEST_QOS_LCR", RequestType: utils.META_RATED, - Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1004", - SetupTime: time.Date(2014, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(60) * time.Second} - var reply string - if err := tutLocalRpc.Call("CdrsV1.ProcessCdr", testCdr4, &reply); err != nil { // Should drop ACD under the 2m required by threshold, removing suppl2 from lcr - t.Error("Unexpected error: ", err.Error()) - } else if reply != utils.OK { - t.Error("Unexpected reply received: ", reply) - } - eLcr = &engine.LCRCost{ - Entry: &engine.LCREntry{DestinationId: "DST_1002", RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_QOS_THRESHOLD, StrategyParams: "20;;;;2m;;;;;;;", Weight: 10.0}, - SupplierCosts: []*engine.LCRSupplierCost{ - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: 240, engine.ACC: 0.35, engine.TCC: 0.7, engine.ASR: 100, engine.ACD: 120}}, - }, - } - cd.CgrID = "7" - cd.RunID = "7" - if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eLcr.Entry, lcr.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eLcr.Entry, lcr.Entry) - //} else if !reflect.DeepEqual(eLcr.SupplierCosts, lcr.SupplierCosts) { - // t.Errorf("Expecting: %+v, received: %+v", eLcr.SupplierCosts[0], lcr.SupplierCosts[0]) - } - cd = engine.CallDescriptor{ - Direction: "*out", - Category: "call", - Tenant: "cgrates.org", - Subject: "1003", - Account: "1003", - Destination: "1004", - TimeStart: tStart, - TimeEnd: tEnd, - } - eLcr = &engine.LCRCost{ - Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_QOS_THRESHOLD, StrategyParams: "40;;;;90s;;;;;;;", Weight: 10.0}, - SupplierCosts: []*engine.LCRSupplierCost{ - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: 240, engine.ACC: 0.35, engine.TCC: 0.7, engine.ASR: 100, engine.ACD: 120}}, - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 1.2, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: 330, engine.ACC: 0.3416666667, engine.TCC: 1.025, engine.ASR: 100, engine.ACD: 110}}, - }, - } - /*eLcr2 := &engine.LCRCost{ - Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_QOS_THRESHOLD, StrategyParams: "40;;90s;;;;;;;", Weight: 10.0}, - SupplierCosts: []*engine.LCRSupplierCost{ - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl2", Cost: 1.2, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: 330, engine.ACC: 0.3416666667, engine.TCC: 1.025, engine.ASR: 100, engine.ACD: 110}}, - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: 240, engine.ACC: 0.35, engine.TCC: 0.7, engine.ASR: 100, engine.ACD: 120}}, - }, - } - */ - cd.CgrID = "8" - cd.RunID = "8" - if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eLcr.Entry, lcr.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eLcr.Entry, lcr.Entry) - //} else if !reflect.DeepEqual(eLcr.SupplierCosts, lcr.SupplierCosts) && !reflect.DeepEqual(eLcr2.SupplierCosts, lcr.SupplierCosts) { - // t.Errorf("Expecting: %+v, received: %+v", eLcr.SupplierCosts[1], lcr.SupplierCosts[1]) - } - testCdr5 := &engine.CDR{CGRID: utils.Sha1("testcdr5", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), - ToR: utils.VOICE, OriginID: "testcdr5", OriginHost: "192.168.1.1", Source: "TEST_QOS_LCR", RequestType: utils.META_RATED, - Tenant: "cgrates.org", Category: "call", Account: "1003", Subject: "1003", Destination: "1004", - SetupTime: time.Date(2014, 12, 7, 8, 42, 24, 0, time.UTC), AnswerTime: time.Date(2014, 12, 7, 8, 42, 26, 0, time.UTC), - Usage: time.Duration(1) * time.Second} - if err := tutLocalRpc.Call("CdrsV1.ProcessCdr", testCdr5, &reply); err != nil { // Should drop ACD under the 1m required by threshold, removing suppl2 from lcr - t.Error("Unexpected error: ", err.Error()) - } else if reply != utils.OK { - t.Error("Unexpected reply received: ", reply) - } - eLcr = &engine.LCRCost{ - Entry: &engine.LCREntry{DestinationId: utils.ANY, RPCategory: "lcr_profile1", Strategy: engine.LCR_STRATEGY_QOS_THRESHOLD, StrategyParams: "40;;;;90s;;;;;;;", Weight: 10.0}, - SupplierCosts: []*engine.LCRSupplierCost{ - &engine.LCRSupplierCost{Supplier: "*out:cgrates.org:lcr_profile1:suppl1", Cost: 1.2, Duration: 60 * time.Second, - QOS: map[string]float64{engine.TCD: 240, engine.ACC: 0.35, engine.TCC: 0.7, engine.ASR: 100, engine.ACD: 120}}, - }, - } - cd.CgrID = "9" - cd.RunID = "9" - if err := tutLocalRpc.Call("Responder.GetLCR", cd, &lcr); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eLcr.Entry, lcr.Entry) { - t.Errorf("Expecting: %+v, received: %+v", eLcr.Entry, lcr.Entry) - //} else if !reflect.DeepEqual(eLcr.SupplierCosts, lcr.SupplierCosts) { - // t.Errorf("Expecting: %+v, received: %+v", eLcr.SupplierCosts[0], lcr.SupplierCosts[0]) - } -} - -// Test adding the account via API, using the data previously devined in .csv -func TestTutITSetAccount(t *testing.T) { - var reply string - attrs := &v2.AttrSetAccount{Tenant: "cgrates.org", Account: "tutacnt1", ActionPlanIDs: &[]string{"PACKAGE_10"}, ActionTriggerIDs: &[]string{"STANDARD_TRIGGERS"}, ReloadScheduler: true} - if err := tutLocalRpc.Call("ApierV2.SetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.SetAccount: ", err.Error()) - } else if reply != "OK" { - t.Errorf("Calling ApierV2.SetAccount received: %s", reply) - } - type AttrGetAccounts struct { - Tenant string - Direction string - AccountIds []string - Offset int // Set the item offset - Limit int // Limit number of items retrieved - } - time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups - var acnts []*engine.Account - if err := tutLocalRpc.Call("ApierV2.GetAccounts", utils.AttrGetAccounts{Tenant: attrs.Tenant, AccountIds: []string{attrs.Account}}, &acnts); err != nil { - t.Error(err) - } else if len(acnts) != 1 { - t.Errorf("Accounts received: %+v", acnts) - } else { - acnt := acnts[0] - dta, _ := utils.NewTAFromAccountKey(acnt.ID) - if dta.Tenant != attrs.Tenant || dta.Account != attrs.Account { - t.Error("Unexpected account id received: ", acnt.ID) - } - if balances := acnt.BalanceMap["*monetary"]; len(balances) != 1 { - t.Errorf("Unexpected balances found: %+v", balances) - } - if len(acnt.ActionTriggers) != 4 { - t.Errorf("Unexpected action triggers for account: %+v", acnt.ActionTriggers) - } - if acnt.AllowNegative { - t.Error("AllowNegative should not be set") - } - if acnt.Disabled { - t.Error("Disabled should not be set") - } - } - attrs = &v2.AttrSetAccount{Tenant: "cgrates.org", Account: "tutacnt1", ActionPlanIDs: &[]string{"PACKAGE_10"}, ActionTriggerIDs: &[]string{"STANDARD_TRIGGERS"}, AllowNegative: utils.BoolPointer(true), Disabled: utils.BoolPointer(true), ReloadScheduler: true} - - if err := tutLocalRpc.Call("ApierV2.SetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.SetAccount: ", err.Error()) - } else if reply != "OK" { - t.Errorf("Calling ApierV2.SetAccount received: %s", reply) - } - if err := tutLocalRpc.Call("ApierV2.GetAccounts", utils.AttrGetAccounts{Tenant: attrs.Tenant, AccountIds: []string{attrs.Account}}, &acnts); err != nil { - t.Error(err) - } else if len(acnts) != 1 { - t.Errorf("Accounts received: %+v", acnts) - } else { - acnt := acnts[0] - dta, _ := utils.NewTAFromAccountKey(acnt.ID) - if dta.Tenant != attrs.Tenant || dta.Account != attrs.Account { - t.Error("Unexpected account id received: ", acnt.ID) - } - if balances := acnt.BalanceMap["*monetary"]; len(balances) != 1 { - t.Errorf("Unexpected balances found: %+v", balances) - } - if len(acnt.ActionTriggers) != 4 { - t.Errorf("Unexpected action triggers for account: %+v", acnt.ActionTriggers) - } - if !acnt.AllowNegative { - t.Error("AllowNegative should be set") - } - if !acnt.Disabled { - t.Error("Disabled should be set") - } - } - attrs = &v2.AttrSetAccount{Tenant: "cgrates.org", Account: "tutacnt1", ActionPlanIDs: &[]string{"PACKAGE_1001"}, ActionTriggerIDs: &[]string{"CDRST1_WARN"}, AllowNegative: utils.BoolPointer(true), Disabled: utils.BoolPointer(true), ReloadScheduler: true} - - if err := tutLocalRpc.Call("ApierV2.SetAccount", attrs, &reply); err != nil { - t.Error("Got error on ApierV2.SetAccount: ", err.Error()) - } else if reply != "OK" { - t.Errorf("Calling ApierV2.SetAccount received: %s", reply) - } - time.Sleep(100*time.Millisecond + time.Duration(*waitRater)*time.Millisecond) // Give time for scheduler to execute topups - if err := tutLocalRpc.Call("ApierV2.GetAccounts", utils.AttrGetAccounts{Tenant: attrs.Tenant, AccountIds: []string{attrs.Account}}, &acnts); err != nil { - t.Error(err) - } else if len(acnts) != 1 { - t.Errorf("Accounts received: %+v", acnts) - } else { - acnt := acnts[0] - dta, _ := utils.NewTAFromAccountKey(acnt.ID) - if dta.Tenant != attrs.Tenant || dta.Account != attrs.Account { - t.Error("Unexpected account id received: ", acnt.ID) - } - if balances := acnt.BalanceMap["*monetary"]; len(balances) != 3 { - t.Errorf("Unexpected balances found: %+v", balances) - } - if len(acnt.ActionTriggers) != 7 { - t.Errorf("Unexpected action triggers for account: %+v", acnt.ActionTriggers) - } - if !acnt.AllowNegative { - t.Error("AllowNegative should be set") - } - if !acnt.Disabled { - t.Error("Disabled should be set") - } - } -} - -/* -// Make sure all stats queues were updated -func TestTutITCdrStatsAfter(t *testing.T) { - var statMetrics map[string]float64 - eMetrics := map[string]float64{engine.ACD: 90.2, engine.ASR: 100, engine.TCC: 1.675, engine.TCD: 451, engine.ACC: 0.335} - if err := tutLocalRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST1"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.ACC: 0.35, engine.ACD: 120, engine.ASR: 100, engine.TCC: 1.675, engine.TCD: 451} - if err := tutLocalRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1001"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.TCD: 451, engine.ACC: 0.325, engine.ACD: 90, engine.ASR: 100, engine.TCC: 1.675} - if err := tutLocalRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1002"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.TCC: 1.675, engine.TCD: 451, engine.ACC: 0.325, engine.ACD: 90, engine.ASR: 100} - if err := tutLocalRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1003"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.TCC: 0.7, engine.TCD: 240, engine.ACC: 0.35, engine.ACD: 120, engine.ASR: 100} - if err := tutLocalRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL1"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - //} else if !reflect.DeepEqual(eMetrics, statMetrics) { - // t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } - eMetrics = map[string]float64{engine.TCD: 331, engine.ACC: 0.33125, engine.ACD: 82.75, engine.ASR: 100, engine.TCC: 1.325} - if err := tutLocalRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL2"}, &statMetrics); err != nil { - t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error()) - } else if !reflect.DeepEqual(eMetrics, statMetrics) { - t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics) - } -} -*/ - -/* FixMe : In CallCost (Timespans) Increments is not populated so does not convert properly CallCost to Event - -func TestTutITPrepaidCDRWithSMCost(t *testing.T) { - cdr := &engine.CDR{CGRID: utils.Sha1("testprepaid1", time.Date(2016, 4, 6, 13, 29, 24, 0, time.UTC).String()), - ToR: utils.VOICE, OriginID: "testprepaid1", OriginHost: "192.168.1.1", - Source: "TEST_PREPAID_CDR_SMCOST1", RequestType: utils.META_PREPAID, Tenant: "cgrates.org", - RunID: utils.META_DEFAULT, - Category: "call", Account: "1001", Subject: "1001", Destination: "1003", - SetupTime: time.Date(2016, 4, 6, 13, 29, 24, 0, time.UTC), - AnswerTime: time.Date(2016, 4, 6, 13, 30, 0, 0, time.UTC), - Usage: time.Duration(90) * time.Second, - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} - - - cc := &engine.CallCost{ - Category: "call", - Account: "1001", - Subject: "1001", - Tenant: "cgrates.org", - Direction: utils.OUT, - Destination: "1003", - Timespans: []*engine.TimeSpan{ - &engine.TimeSpan{ - TimeStart: time.Date(2016, 4, 6, 13, 30, 0, 0, time.UTC), - TimeEnd: time.Date(2016, 4, 6, 13, 31, 30, 0, time.UTC), - DurationIndex: 0, - RateInterval: &engine.RateInterval{ - Rating: &engine.RIRate{ - Rates: engine.RateGroups{ - &engine.Rate{ - GroupIntervalStart: 0, - Value: 0.01, - RateIncrement: 10 * time.Second, - RateUnit: time.Second}}}}, - }, - }, - TOR: utils.VOICE} - smCost := &engine.SMCost{CGRID: cdr.CGRID, - RunID: utils.META_DEFAULT, - OriginHost: cdr.OriginHost, - OriginID: cdr.OriginID, - CostSource: "TestTutITPrepaidCDRWithSMCost", - Usage: cdr.Usage, - CostDetails: engine.NewEventCostFromCallCost(cc, cdr.CGRID, utils.META_DEFAULT), - } - var reply string - if err := tutLocalRpc.Call("CdrsV1.StoreSMCost", &engine.AttrCDRSStoreSMCost{Cost: smCost}, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if reply != utils.OK { - t.Error("Unexpected reply received: ", reply) - } - if err := tutLocalRpc.Call("CdrsV1.ProcessCdr", cdr, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if reply != utils.OK { - t.Error("Unexpected reply received: ", reply) - } - time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for CDR to be processed - var cdrs []*engine.ExternalCDR - req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, CGRIDs: []string{cdr.CGRID}} - if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(cdrs) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(cdrs)) - } else { - if cdrs[0].OriginID != cdr.OriginID { - t.Errorf("Unexpected OriginID for Cdr received: %+v", cdrs[0].OriginID) - } - if cdrs[0].Cost != 0.9 { - t.Errorf("Unexpected Cost for Cdr received: %+v", utils.ToJSON(cdrs[0].Cost)) - } - } -} -*/ - -func TestTutITPrepaidCDRWithoutSMCost(t *testing.T) { - cdr := &engine.CDR{CGRID: utils.Sha1("testprepaid2", time.Date(2016, 4, 6, 13, 29, 24, 0, time.UTC).String()), - ToR: utils.VOICE, OriginID: "testprepaid2", OriginHost: "192.168.1.1", Source: "TEST_PREPAID_CDR_NO_SMCOST1", RequestType: utils.META_PREPAID, - Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1003", - SetupTime: time.Date(2016, 4, 6, 13, 29, 24, 0, time.UTC), AnswerTime: time.Date(2016, 4, 6, 13, 30, 0, 0, time.UTC), - Usage: time.Duration(90) * time.Second, - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} - var reply string - if err := tutLocalRpc.Call("CdrsV1.ProcessCdr", cdr, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if reply != utils.OK { - t.Error("Unexpected reply received: ", reply) - } - /* - time.Sleep(time.Duration(7000) * time.Millisecond) // Give time for CDR to be processed - var cdrs []*engine.ExternalCDR - req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, CGRIDs: []string{cdr.CGRID}} - if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(cdrs) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(cdrs)) - } else { - if cdrs[0].OriginID != cdr.OriginID { - t.Errorf("Unexpected OriginID for Cdr received: %+v", cdrs[0]) - } - if cdrs[0].Cost != 0.9 { - t.Errorf("Unexpected Cost for Cdr received: %+v", cdrs[0]) - } - } - */ -} - -func TestTutITExportCDR(t *testing.T) { - cdr := &engine.CDR{ToR: utils.VOICE, OriginID: "testexportcdr1", OriginHost: "192.168.1.1", Source: "TestTutITExportCDR", RequestType: utils.META_RATED, - Tenant: "cgrates.org", Category: "call", Account: "1001", Subject: "1001", Destination: "1003", - SetupTime: time.Date(2016, 11, 30, 17, 5, 24, 0, time.UTC), AnswerTime: time.Date(2016, 11, 30, 17, 6, 4, 0, time.UTC), - Usage: time.Duration(98) * time.Second, - ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} - cdr.ComputeCGRID() - var reply string - if err := tutLocalRpc.Call("CdrsV1.ProcessCdr", cdr, &reply); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if reply != utils.OK { - t.Error("Unexpected reply received: ", reply) - } - time.Sleep(time.Duration(50) * time.Millisecond) // Give time for CDR to be processed - var cdrs []*engine.ExternalCDR - req := utils.RPCCDRsFilter{RunIDs: []string{utils.META_DEFAULT}, CGRIDs: []string{cdr.CGRID}} - if err := tutLocalRpc.Call("ApierV2.GetCdrs", req, &cdrs); err != nil { - t.Error("Unexpected error: ", err.Error()) - } else if len(cdrs) != 1 { - t.Error("Unexpected number of CDRs returned: ", len(cdrs)) - } else { - if cdrs[0].OriginID != cdr.OriginID { - t.Errorf("Unexpected OriginID for Cdr received: %+v", cdrs[0]) - } - if cdrs[0].Cost != 1.3334 { - t.Errorf("Unexpected Cost for Cdr received: %+v", cdrs[0]) - } - } - var replyExport v1.RplExportedCDRs - exportArgs := v1.ArgExportCDRs{ - ExportPath: utils.StringPointer("/tmp"), - ExportFileName: utils.StringPointer("TestTutITExportCDR.csv"), - ExportTemplate: utils.StringPointer("TestTutITExportCDR"), - RPCCDRsFilter: utils.RPCCDRsFilter{CGRIDs: []string{cdr.CGRID}, NotRunIDs: []string{utils.MetaRaw}}} - if err := tutLocalRpc.Call("ApierV1.ExportCDRs", exportArgs, &replyExport); err != nil { - t.Error(err) - } - eExportContent := `f0a92222a7d21b4d9f72744aabe82daef52e20d8,*default,testexportcdr1,*rated,cgrates.org,call,1001,1003,2016-11-30T18:06:04+01:00,98,1.33340,RETA -f0a92222a7d21b4d9f72744aabe82daef52e20d8,derived_run1,testexportcdr1,*rated,cgrates.org,call,1001,1003,2016-11-30T18:06:04+01:00,98,1.33340,RETA -` - eExportContent2 := `f0a92222a7d21b4d9f72744aabe82daef52e20d8,derived_run1,testexportcdr1,*rated,cgrates.org,call,1001,1003,2016-11-30T18:06:04+01:00,98,1.33340,RETA -f0a92222a7d21b4d9f72744aabe82daef52e20d8,*default,testexportcdr1,*rated,cgrates.org,call,1001,1003,2016-11-30T18:06:04+01:00,98,1.33340,RETA -` - expFilePath := path.Join(*exportArgs.ExportPath, *exportArgs.ExportFileName) - if expContent, err := ioutil.ReadFile(expFilePath); err != nil { - t.Error(err) - } else if eExportContent != string(expContent) && eExportContent2 != string(expContent) { // CDRs are showing up randomly so we cannot predict order of export - t.Errorf("Expecting: <%q> or <%q> received: <%q>", eExportContent, eExportContent2, string(expContent)) - } - if err := os.Remove(expFilePath); err != nil { - t.Error(err) - } - -} - -func TestTutITStopCgrEngine(t *testing.T) { - if err := engine.KillEngine(1000); err != nil { - t.Error(err) - } -} +// +build integration + +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package general_tests + +import ( + "fmt" + "net/rpc" + "net/rpc/jsonrpc" + "path" + "testing" + "time" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +var ( + tutorialCfgPath string + tutorialCfg *config.CGRConfig + tutorialRpc *rpc.Client + tutorialConfDIR string //run tests for specific configuration + tutorialDelay int + tutorialDataDir = "/usr/share/cgrates" +) + +var sTestsTutorials = []func(t *testing.T){ + testTutorialLoadConfig, + testTutorialResetDB, + testTutorialStartEngine, + testTutorialRpcConn, + testTutorialFromFolder, + testTutorialGetCost, + testTutorialStopEngine, +} + +//Test start here +func TestTutorialMongo(t *testing.T) { + if testing.Short() { + t.Skip("skipping non-short test") + } + tutorialConfDIR = "mongo_atlas" + for _, stest := range sTestsTutorials { + t.Run(tutorialConfDIR, stest) + } +} + +func TestTutorialMySQL(t *testing.T) { + tutorialConfDIR = "tutmysql" + for _, stest := range sTestsTutorials { + t.Run(tutorialConfDIR, stest) + } +} + +func testTutorialLoadConfig(t *testing.T) { + var err error + tutorialCfgPath = path.Join(tutorialDataDir, "conf", "samples", tutorialConfDIR) + fmt.Printf("Tutorial path %+v\n", tutorialCfgPath) + if tutorialCfg, err = config.NewCGRConfigFromFolder(tutorialCfgPath); err != nil { + t.Error(err) + } + fmt.Printf("Tutorial cfg %+v\n", tutorialCfg) + switch tutorialConfDIR { + case "mongo_atlas": // Mongo needs more time to reset db + tutorialDelay = 4000 + default: + tutorialDelay = 2000 + } +} + +func testTutorialResetDB(t *testing.T) { + if err := engine.InitDataDb(tutorialCfg); err != nil { + t.Fatal(err) + } + if err := engine.InitStorDb(tutorialCfg); err != nil { + t.Fatal(err) + } +} + +func testTutorialStartEngine(t *testing.T) { + if _, err := engine.StopStartEngine(tutorialCfgPath, tutorialDelay); err != nil { + t.Fatal(err) + } +} + +func testTutorialRpcConn(t *testing.T) { + var err error + tutorialRpc, err = jsonrpc.Dial("tcp", tutorialCfg.RPCJSONListen) // We connect over JSON so we can also troubleshoot if needed + if err != nil { + t.Fatal("Could not connect to rater: ", err.Error()) + } +} + +func testTutorialFromFolder(t *testing.T) { + var reply string + attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*dataDir, "tariffplans", "tutorial")} + if err := tutorialRpc.Call("ApierV1.LoadTariffPlanFromFolder", attrs, &reply); err != nil { + t.Error(err) + } + time.Sleep(500 * time.Millisecond) +} + +func testTutorialGetCost(t *testing.T) { + +} + +func testTutorialStopEngine(t *testing.T) { + if err := engine.KillEngine(tutorialDelay); err != nil { + t.Error(err) + } +}