diff --git a/data/tariffplans/tutorial/CdrStats.csv b/data/tariffplans/tutorial/CdrStats.csv index 8720b4312..cadb59d11 100644 --- a/data/tariffplans/tutorial/CdrStats.csv +++ b/data/tariffplans/tutorial/CdrStats.csv @@ -12,13 +12,13 @@ CDRST_1002,,,ACD,,,,,,,,,,,,,,,,,,, CDRST_1002,,,ACC,,,,,,,,,,,,,,,,,,, CDRST_1003,,,ASR,,,,,,,cgrates.org,,,,1003,,,,default,,,,CDRST3_WARN CDRST_1003,,,ACD,,,,,,,,,,,,,,,,,,, -STATS_SUPPL1,,,ACD,,,,,,,,,,,,,supplier1,,,,,, -STATS_SUPPL1,,,ASR,,,,,,,,,,,,,supplier1,,,,,, -STATS_SUPPL1,,,ACC,,,,,,,,,,,,,supplier1,,,,,, -STATS_SUPPL1,,,TCD,,,,,,,,,,,,,supplier1,,,,,, -STATS_SUPPL1,,,TCC,,,,,,,,,,,,,supplier1,,,,,, -STATS_SUPPL2,,,ACD,,,,,,,,,,,,,supplier2,,,,,, -STATS_SUPPL2,,,ASR,,,,,,,,,,,,,supplier2,,,,,, -STATS_SUPPL2,,,ACC,,,,,,,,,,,,,supplier2,,,,,, -STATS_SUPPL2,,,TCD,,,,,,,,,,,,,supplier2,,,,,, -STATS_SUPPL2,,,TCC,,,,,,,,,,,,,supplier2,,,,,, +STATS_SUPPL1,,,ACD,,,,,,,,,,,,,suppl1,,,,,, +STATS_SUPPL1,,,ASR,,,,,,,,,,,,,suppl1,,,,,, +STATS_SUPPL1,,,ACC,,,,,,,,,,,,,suppl1,,,,,, +STATS_SUPPL1,,,TCD,,,,,,,,,,,,,suppl1,,,,,, +STATS_SUPPL1,,,TCC,,,,,,,,,,,,,suppl1,,,,,, +STATS_SUPPL2,,,ACD,,,,,,,,,,,,,suppl2,,,,,, +STATS_SUPPL2,,,ASR,,,,,,,,,,,,,suppl2,,,,,, +STATS_SUPPL2,,,ACC,,,,,,,,,,,,,suppl2,,,,,, +STATS_SUPPL2,,,TCD,,,,,,,,,,,,,suppl2,,,,,, +STATS_SUPPL2,,,TCC,,,,,,,,,,,,,suppl2,,,,,, diff --git a/data/tariffplans/tutorial/LcrRules.csv b/data/tariffplans/tutorial/LcrRules.csv index 2d71fcd1f..c893832a6 100644 --- a/data/tariffplans/tutorial/LcrRules.csv +++ b/data/tariffplans/tutorial/LcrRules.csv @@ -4,6 +4,6 @@ *out,cgrates.org,call,1002,*any,DST_1002,lcr_profile1,*highest_cost,,2014-01-14T00:00:00Z,10 *out,cgrates.org,call,1002,*any,*any,lcr_profile1,*qos,,2014-01-14T00:00:00Z,10 *out,cgrates.org,call,1003,*any,DST_1002,lcr_profile1,*qos_threshold,20;;2m;;;;;;;,2014-01-14T00:00:00Z,10 -*out,cgrates.org,call,1003,*any,*any,lcr_profile1,*qos_threshold,40;;4m;;;;;;;,2014-01-14T00:00:00Z,10 +*out,cgrates.org,call,1003,*any,*any,lcr_profile1,*qos_threshold,40;;90s;;;;;;;,2014-01-14T00:00:00Z,10 *out,cgrates.org,call,*any,*any,DST_1002,lcr_profile2,*lowest_cost,,2014-01-14T00:00:00Z,10 *out,cgrates.org,call,*any,*any,*any,lcr_profile1,*lowest_cost,,2014-01-14T00:00:00Z,10 \ No newline at end of file diff --git a/general_tests/tutorial_local_test.go b/general_tests/tutorial_local_test.go index fb19adddc..ac4618da3 100644 --- a/general_tests/tutorial_local_test.go +++ b/general_tests/tutorial_local_test.go @@ -339,10 +339,6 @@ func TestTutFsCallsCdrStats(t *testing.T) { } // Check LCR -//FixMe: -/*{"id":16,"result":{"Entry":{"DestinationId":"*any","RPCategory":"lcr_profile1","Strategy":"*static","StrategyParams":"suppl1;suppl2","Weight":10},"SupplierCosts":[{"Supplier":"*out:cgrates.org:lcr_profile1:suppl1","Cost":0,"Duration":0,"Error":{},"QOS":null},{"Supplier":"*out:cgrates.org:lcr_profile1:suppl2","Cost":0,"Duration":0,"Error":{},"QOS":null}]},"error":null} - */ - func TestTutLocalLcrStatic(t *testing.T) { if !*testLocal { return @@ -400,6 +396,326 @@ func TestTutLocalLcrStatic(t *testing.T) { } } +func TestTutLocalLcrHighestCost(t *testing.T) { + if !*testLocal { + return + } + 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]) + } +} + +func TestTutLocalLcrQos(t *testing.T) { + if !*testLocal { + return + } + 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.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}}, + }, + } + 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.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}}, + }, + } + var lcr engine.LCRCost + // Since there is no real quality difference, the suppliers will come in random order here + 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.StoredCdr{CgrId: utils.Sha1("testcdr1", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), + TOR: utils.VOICE, AccId: "testcdr1", CdrHost: "192.168.1.1", CdrSource: "TEST_QOS_LCR", ReqType: utils.META_RATED, + Direction: "*out", 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, Supplier: "suppl1", + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} + testCdr2 := &engine.StoredCdr{CgrId: utils.Sha1("testcdr2", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), + TOR: utils.VOICE, AccId: "testcdr2", CdrHost: "192.168.1.1", CdrSource: "TEST_QOS_LCR", ReqType: utils.META_RATED, + Direction: "*out", 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, Supplier: "suppl2", + ExtraFields: map[string]string{"field_extr1": "val_extr1", "fieldextr2": "valextr2"}} + var reply string + for _, cdr := range []*engine.StoredCdr{testCdr1, testCdr2} { + if err := tutLocalRpc.Call("CdrsV2.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}}, + }, + } + 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[1], lcr.SupplierCosts[1]) + } + testCdr3 := &engine.StoredCdr{CgrId: utils.Sha1("testcdr3", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), + TOR: utils.VOICE, AccId: "testcdr3", CdrHost: "192.168.1.1", CdrSource: "TEST_QOS_LCR", ReqType: utils.META_RATED, + Direction: "*out", 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, Supplier: "suppl2"} + if err := tutLocalRpc.Call("CdrsV2.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}}, + }, + } + 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]) + } +} + +func TestTutLocalLcrQosThreshold(t *testing.T) { + if !*testLocal { + return + } + 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 + 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]) + } + testCdr4 := &engine.StoredCdr{CgrId: utils.Sha1("testcdr4", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), + TOR: utils.VOICE, AccId: "testcdr4", CdrHost: "192.168.1.1", CdrSource: "TEST_QOS_LCR", ReqType: utils.META_RATED, + Direction: "*out", 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, Supplier: "suppl2"} + var reply string + if err := tutLocalRpc.Call("CdrsV2.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}}, + }, + } + 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}}, + }, + } + 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.StoredCdr{CgrId: utils.Sha1("testcdr5", time.Date(2013, 12, 7, 8, 42, 24, 0, time.UTC).String()), + TOR: utils.VOICE, AccId: "testcdr5", CdrHost: "192.168.1.1", CdrSource: "TEST_QOS_LCR", ReqType: utils.META_RATED, + Direction: "*out", 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, Supplier: "suppl2"} + if err := tutLocalRpc.Call("CdrsV2.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}}, + }, + } + 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]) + } +} + +func TestTutLocalLeastCost(t *testing.T) { + if !*testLocal { + return + } + 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: "1004", + Account: "1004", + 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 + 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[2], lcr.SupplierCosts[2]) + } + cd = engine.CallDescriptor{ + Direction: "*out", + Category: "call", + Tenant: "cgrates.org", + Subject: "1004", + Account: "1004", + 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}, + }, + } + 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 TestTutLocalStopCgrEngine(t *testing.T) { if !*testLocal { return