Files
cgrates/general_tests/routes_cases_it_test.go
arberkatellari 746846eaaf Revise tests
2025-06-24 17:57:09 +02:00

1638 lines
44 KiB
Go

//go:build integration
// +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 <http://www.gnu.org/licenses/>
*/
package general_tests
import (
"path"
"reflect"
"sort"
"testing"
"time"
"github.com/cgrates/birpc"
"github.com/cgrates/birpc/context"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/engine"
"github.com/cgrates/cgrates/utils"
)
var (
rtsCaseSv1CfgPath string
rtsCaseSv1Cfg *config.CGRConfig
rtsCaseSv1Rpc *birpc.Client
rtsCasePrf *engine.RouteWithAPIOpts
rtsCaseSv1ConfDIR string //run tests for specific configuration
sTestsRtsCaseSV1 = []func(t *testing.T){
testV1RtsCaseLoadConfig,
testV1RtsCaseInitDataDb,
testV1RtsCaseResetStorDb,
testV1RtsCaseStartEngine,
testV1RtsCaseRpcConn,
testV1RtsCaseFromFolder,
testV1RtsCaseGetRoutesAfterLoading,
testV1RtsCasesSortingRoutesWeightAccountValue,
testV1RtsCasesSortingRoutesWeightAllRoutes,
testV1RtsCasesSortingRoutesWeightNotMatchingValue,
testV1RtsCasesSortingRoutesLowestCost,
testV1RtsCasesSortingRoutesLowestCostDefaultUsage,
testV1RtsCasesSortingRoutesLCSetStatsAndResForMatching,
testV1RtsCasesSortingRoutesLowestCostStats,
testV1RtsCasesSortingRoutesLowestCosMatchingAllRoutes,
testV1RtsCasesSortingRoutesLowestCosMaxCost,
testV1RtsCasesSortingRoutesLowestCosMaxCostNotMatch,
testV1RtsCasesSortingRoutesProcessMetrics,
testV1RtsCasesSortingRoutesQOS,
testV1RtsCasesSortingRoutesQOSAllRoutes,
testV1RtsCasesSortingRoutesQOSNotFound,
testV1RtsCasesSortingRoutesAllocateResources,
testV1RtsCasesSortingRoutesReasNotAllRoutes,
testV1RtsCasesSortingRoutesReasAllRoutes,
testV1RtsCasesRoutesProcessStatsForLoadRtsSorting,
testV1RtsCasesRoutesLoadRtsSorting,
testV1RtsCasesSortRoutesHigherCostV2V3,
testV1RtsCasesSortRoutesHigherCostAllocateRes,
testV1RtsCasesSortRoutesHigherCostV1V3,
testV1RtsCasesSortRoutesHigherCostAllRoutes,
testV1RtsCaseStopEngine,
}
)
// Test start here
func TestRoutesCaseV1IT(t *testing.T) {
switch *utils.DBType {
case utils.MetaInternal:
rtsCaseSv1ConfDIR = "tutinternal"
case utils.MetaMySQL:
rtsCaseSv1ConfDIR = "tutmysql"
case utils.MetaMongo:
rtsCaseSv1ConfDIR = "tutmongo"
case utils.MetaPostgres:
t.SkipNow()
default:
t.Fatal("Unknown Database type")
}
for _, stest := range sTestsRtsCaseSV1 {
t.Run(rtsCaseSv1ConfDIR, stest)
}
}
func testV1RtsCaseLoadConfig(t *testing.T) {
var err error
rtsCaseSv1CfgPath = path.Join(*utils.DataDir, "conf", "samples", rtsCaseSv1ConfDIR)
if rtsCaseSv1Cfg, err = config.NewCGRConfigFromPath(rtsCaseSv1CfgPath); err != nil {
t.Error(err)
}
}
func testV1RtsCaseInitDataDb(t *testing.T) {
if err := engine.InitDataDB(rtsCaseSv1Cfg); err != nil {
t.Fatal(err)
}
}
// Wipe out the cdr database
func testV1RtsCaseResetStorDb(t *testing.T) {
if err := engine.InitStorDb(rtsCaseSv1Cfg); err != nil {
t.Fatal(err)
}
}
func testV1RtsCaseStartEngine(t *testing.T) {
if _, err := engine.StopStartEngine(rtsCaseSv1CfgPath, *utils.WaitRater); err != nil {
t.Fatal(err)
}
}
func testV1RtsCaseRpcConn(t *testing.T) {
rtsCaseSv1Rpc = engine.NewRPCClient(t, rtsCaseSv1Cfg.ListenCfg())
}
func testV1RtsCaseFromFolder(t *testing.T) {
var reply string
attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*utils.DataDir, "tariffplans", "tutroutes")}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.APIerSv1LoadTariffPlanFromFolder, attrs, &reply); err != nil {
t.Error(err)
}
time.Sleep(100 * time.Millisecond)
}
func testV1RtsCaseGetRoutesAfterLoading(t *testing.T) {
// ROUTE_ACNT_1001
expRt1 := &engine.RouteProfile{
ID: "ROUTE_ACNT_1001",
Tenant: "cgrates.org",
FilterIDs: []string{"*string:~*req.Account:1001"},
Sorting: "*weight",
SortingParameters: []string{},
Routes: []*engine.Route{
{
ID: "vendor1",
FilterIDs: []string{"FLTR_DEST_1003"},
Weight: 10,
},
{
ID: "vendor2",
FilterIDs: []string{"*gte:~*accounts.1001.BalanceMap.*monetary[0].Value:10"},
Weight: 20,
},
{
ID: "vendor3",
FilterIDs: []string{"FLTR_DEST_1003", "*prefix:~*req.Account:10"},
Weight: 40,
},
{
ID: "vendor4",
Weight: 35,
},
},
}
var reply *engine.RouteProfile
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.APIerSv1GetRouteProfile,
&utils.TenantID{ID: "ROUTE_ACNT_1001", Tenant: "cgrates.org"},
&reply); err != nil {
t.Error(err)
} else {
sort.Slice(reply.Routes, func(i, j int) bool {
return reply.Routes[i].ID < reply.Routes[j].ID
})
if !reflect.DeepEqual(expRt1, reply) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expRt1), utils.ToJSON(reply))
}
}
// ROUTE_ACNT_1002
expRt2 := &engine.RouteProfile{
ID: "ROUTE_ACNT_1002",
Tenant: "cgrates.org",
FilterIDs: []string{"*string:~*req.Account:1002"},
Sorting: "*lc",
SortingParameters: []string{},
Routes: []*engine.Route{
{
ID: "vendor1",
FilterIDs: []string{"*lte:~*resources.RES_GRP1.TotalUsage:5"},
RatingPlanIDs: []string{"RP_VENDOR1"},
Weight: 0,
},
{
ID: "vendor2",
FilterIDs: []string{"*gte:~*stats.STATS_VENDOR_2.*acd:1m"},
RatingPlanIDs: []string{"RP_VENDOR2"},
Weight: 0,
},
{
ID: "vendor3",
RatingPlanIDs: []string{"RP_VENDOR2"},
Weight: 10,
},
{
ID: "vendor4",
FilterIDs: []string{"*ai:~*req.AnswerTime:2013-06-01T00:00:00Z|2013-06-01T10:00:00Z"},
RatingPlanIDs: []string{"RP_STANDARD"},
Weight: 30,
},
},
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.APIerSv1GetRouteProfile,
&utils.TenantID{ID: "ROUTE_ACNT_1002", Tenant: "cgrates.org"},
&reply); err != nil {
t.Error(err)
} else {
sort.Slice(reply.Routes, func(i, j int) bool {
return reply.Routes[i].ID < reply.Routes[j].ID
})
if !reflect.DeepEqual(expRt2, reply) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expRt2), utils.ToJSON(reply))
}
}
// ROUTE_ACNT_1003
expRt3 := &engine.RouteProfile{
ID: "ROUTE_ACNT_1003",
Tenant: "cgrates.org",
FilterIDs: []string{"*string:~*req.Account:1003"},
Sorting: "*qos",
SortingParameters: []string{"*acd", "*tcc"},
Routes: []*engine.Route{
{
ID: "vendor1",
StatIDs: []string{"STATS_VENDOR_1"},
Weight: 0,
},
{
ID: "vendor2",
FilterIDs: []string{"*prefix:~*req.Destination:10"},
StatIDs: []string{"STATS_VENDOR_2"},
Weight: 0,
},
{
ID: "vendor3",
FilterIDs: []string{"*gte:~*stats.STATS_VENDOR_1.*tcc:6"},
StatIDs: []string{"STATS_VENDOR_1"},
Weight: 20,
},
},
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.APIerSv1GetRouteProfile,
&utils.TenantID{ID: "ROUTE_ACNT_1003", Tenant: "cgrates.org"},
&reply); err != nil {
t.Error(err)
} else {
sort.Slice(reply.Routes, func(i, j int) bool {
return reply.Routes[i].ID < reply.Routes[j].ID
})
sort.Strings(reply.SortingParameters)
sort.Strings(expRt1.SortingParameters)
if !reflect.DeepEqual(expRt3, reply) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expRt3), utils.ToJSON(reply))
}
}
// ROUTE_ACNT_1004
expRt4 := &engine.RouteProfile{
ID: "ROUTE_ACNT_1004",
Tenant: "cgrates.org",
FilterIDs: []string{"*string:~*req.Account:1004"},
Sorting: "*reas",
SortingParameters: []string{},
Routes: []*engine.Route{
{
ID: "vendor1",
ResourceIDs: []string{"RES_GRP1"},
Weight: 0,
},
{
ID: "vendor2",
ResourceIDs: []string{"RES_GRP2"},
Weight: 0,
},
{
ID: "vendor3",
FilterIDs: []string{"*gte:~*resources.RES_GRP1.TotalUsage:9"},
ResourceIDs: []string{"RES_GRP2"},
Weight: 10,
},
},
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.APIerSv1GetRouteProfile,
&utils.TenantID{ID: "ROUTE_ACNT_1004", Tenant: "cgrates.org"},
&reply); err != nil {
t.Error(err)
} else {
sort.Slice(reply.Routes, func(i, j int) bool {
return reply.Routes[i].ID < reply.Routes[j].ID
})
if !reflect.DeepEqual(expRt4, reply) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expRt4), utils.ToJSON(reply))
}
}
// ROUTE_ACNT_1005
expRt5 := &engine.RouteProfile{
ID: "ROUTE_ACNT_1005",
Tenant: "cgrates.org",
FilterIDs: []string{"*string:~*req.Account:1005"},
Sorting: "*load",
SortingParameters: []string{"vendor1:3", "*default:2"},
Routes: []*engine.Route{
{
ID: "vendor1",
StatIDs: []string{"STATS_VENDOR_1:*sum#1"},
},
{
ID: "vendor2",
StatIDs: []string{"STATS_VENDOR_2:*sum#1"},
Weight: 10,
},
{
ID: "vendor3",
StatIDs: []string{"STATS_VENDOR_2:*distinct#~*req.Usage"},
},
},
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.APIerSv1GetRouteProfile,
&utils.TenantID{ID: "ROUTE_ACNT_1005", Tenant: "cgrates.org"},
&reply); err != nil {
t.Error(err)
} else {
sort.Slice(reply.Routes, func(i, j int) bool {
return reply.Routes[i].ID < reply.Routes[j].ID
})
sort.Strings(reply.SortingParameters)
sort.Strings(expRt5.SortingParameters)
if !reflect.DeepEqual(expRt5, reply) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expRt5), utils.ToJSON(reply))
}
}
// ROUTE_STATS1
expRt6 := &engine.RouteProfile{
ID: "ROUTE_HC1",
Tenant: "cgrates.org",
FilterIDs: []string{"Fltr_tcc"},
Sorting: "*hc",
SortingParameters: []string{},
Routes: []*engine.Route{
{
ID: "route1",
FilterIDs: []string{"*gte:~*resources.RES_GRP2.Available:6"},
RatingPlanIDs: []string{"RP_VENDOR2"},
ResourceIDs: []string{"RES_GRP2"},
Weight: 20,
},
{
ID: "route2",
FilterIDs: []string{"*gte:~*resources.RES_GRP1.TotalUsage:9"},
RatingPlanIDs: []string{"RP_VENDOR1"},
ResourceIDs: []string{"RES_GRP1"},
Weight: 20,
},
{
ID: "route3",
RatingPlanIDs: []string{"RP_VENDOR1"},
ResourceIDs: []string{"RES_GRP2"},
Weight: 10,
},
},
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.APIerSv1GetRouteProfile,
&utils.TenantID{ID: "ROUTE_HC1", Tenant: "cgrates.org"},
&reply); err != nil {
t.Error(err)
} else {
sort.Slice(reply.Routes, func(i, j int) bool {
return reply.Routes[i].ID < reply.Routes[j].ID
})
if !reflect.DeepEqual(expRt6, reply) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expRt6), utils.ToJSON(reply))
}
}
}
func testV1RtsCasesSortingRoutesWeightAccountValue(t *testing.T) {
ev := &utils.CGREvent{
ID: "WEIGHT_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1001",
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_ACNT_1001",
Sorting: "*weight",
Routes: []*engine.SortedRoute{
{
RouteID: "vendor4",
SortingData: map[string]any{
utils.Weight: 35.,
},
},
{
RouteID: "vendor2",
SortingData: map[string]any{
utils.Weight: 20.,
},
},
},
},
}
var reply *engine.SortedRoutesList
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expSrtdRoutes, reply) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCasesSortingRoutesWeightAllRoutes(t *testing.T) {
ev := &utils.CGREvent{
ID: "WEIGHT_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1001",
utils.Destination: "1003",
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_ACNT_1001",
Sorting: "*weight",
Routes: []*engine.SortedRoute{
{
RouteID: "vendor3",
SortingData: map[string]any{
utils.Weight: 40.,
},
},
{
RouteID: "vendor4",
SortingData: map[string]any{
utils.Weight: 35.,
},
},
{
RouteID: "vendor2",
SortingData: map[string]any{
utils.Weight: 20.,
},
},
{
RouteID: "vendor1",
SortingData: map[string]any{
utils.Weight: 10.,
},
},
},
},
}
var reply *engine.SortedRoutesList
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expSrtdRoutes, reply) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCasesSortingRoutesWeightNotMatchingValue(t *testing.T) {
//change account 1001 balance for not matching vendor2
attrBal := &utils.AttrSetBalance{
Tenant: "cgrates.org",
Account: "1001",
BalanceType: utils.MetaMonetary,
Value: 5,
Balance: map[string]any{
utils.ID: utils.MetaDefault,
},
}
var result string
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.APIerSv1SetBalance, attrBal,
&result); err != nil {
t.Error(err)
} else if result != utils.OK {
t.Errorf("Unexpected result returned")
}
ev := &utils.CGREvent{
ID: "WEIGHT_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1001",
utils.Destination: "1003",
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_ACNT_1001",
Sorting: "*weight",
Routes: []*engine.SortedRoute{
{
RouteID: "vendor3",
SortingData: map[string]any{
utils.Weight: 40.,
},
},
{
RouteID: "vendor4",
SortingData: map[string]any{
utils.Weight: 35.,
},
},
{
RouteID: "vendor1",
SortingData: map[string]any{
utils.Weight: 10.,
},
},
},
},
}
var reply *engine.SortedRoutesList
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expSrtdRoutes, reply) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCasesSortingRoutesLowestCost(t *testing.T) {
ev := &utils.CGREvent{
ID: "LC_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1002",
utils.Destination: "1003",
utils.SetupTime: "2013-06-01T00:00:00Z",
utils.Usage: "2m30s",
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_ACNT_1002",
Sorting: "*lc",
Routes: []*engine.SortedRoute{
{
RouteID: "vendor3",
SortingData: map[string]any{
utils.Cost: 0.1245,
utils.RatingPlanID: "RP_VENDOR2",
utils.Weight: 10.,
},
},
{
RouteID: "vendor1",
SortingData: map[string]any{
utils.Cost: 0.2505,
utils.RatingPlanID: "RP_VENDOR1",
utils.Weight: 0.,
},
},
},
},
}
var reply *engine.SortedRoutesList
//gonna match one route because the totalUsage by ne-allocated resources is 0
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expSrtdRoutes, reply) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCasesSortingRoutesLowestCostDefaultUsage(t *testing.T) {
// default usage given by routes is 1m
ev := &utils.CGREvent{
ID: "LC_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1002",
utils.Destination: "1003",
utils.SetupTime: "2013-06-01T00:00:00Z",
utils.AnswerTime: "2013-06-01T05:00:00Z",
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_ACNT_1002",
Sorting: "*lc",
Routes: []*engine.SortedRoute{
{
RouteID: "vendor3",
SortingData: map[string]any{
utils.Cost: 0.0498,
utils.RatingPlanID: "RP_VENDOR2",
utils.Weight: 10.,
},
},
{
RouteID: "vendor1",
SortingData: map[string]any{
utils.Cost: 0.1002,
utils.RatingPlanID: "RP_VENDOR1",
utils.Weight: 0.,
},
},
{
RouteID: "vendor4",
SortingData: map[string]any{
utils.Cost: 0.6,
utils.RatingPlanID: "RP_STANDARD",
utils.Weight: 30.,
},
},
},
},
}
var reply *engine.SortedRoutesList
//gonna match one route because the totalUsage by ne-allocated resources is 0
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expSrtdRoutes, reply) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCasesSortingRoutesLCSetStatsAndResForMatching(t *testing.T) {
//not gonna match our vendor1 filter because 6 > 5
ev := &utils.CGREvent{
Tenant: "cgrates.org",
ID: utils.UUIDSha1Prefix(),
Event: map[string]any{
"Account": "1002",
},
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "651a8db2-4f67-4cf8-b622-169e8a482e51",
utils.OptsResourcesUnits: 6,
},
}
var reply string
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.ResourceSv1AllocateResources,
ev, &reply); err != nil {
t.Error(err)
} else if reply != "RES_GRP1" {
t.Errorf("Unexpected reply returned: %s", reply)
}
//gonna match one stats for matching vendor 2 acd filter
var result []string
expected := []string{"STATS_VENDOR_2", "STATS_TCC1"}
ev1 := &utils.CGREvent{
Tenant: "cgrates.org",
ID: "event1",
Event: map[string]any{
utils.AccountField: "1004",
utils.Category: "vendor2",
utils.Usage: "2m30s",
utils.AnswerTime: "2013-06-01T05:00:00Z",
utils.Cost: 1.0,
},
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.StatSv1ProcessEvent, ev1, &result); err != nil {
t.Error(err)
} else {
sort.Strings(result)
sort.Strings(expected)
if !reflect.DeepEqual(result, expected) {
t.Errorf("Expecting: %+v, received: %+v", expected, result)
}
}
}
func testV1RtsCasesSortingRoutesLowestCostStats(t *testing.T) {
//not gonna match vendor1 because of its TotalUsage by allocating resources
ev := &utils.CGREvent{
ID: "LC_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1002",
utils.Destination: "1003",
utils.SetupTime: "2013-06-01T00:00:00Z",
utils.AnswerTime: "2013-06-01T05:00:00Z",
utils.Usage: "2m30s",
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_ACNT_1002",
Sorting: "*lc",
Routes: []*engine.SortedRoute{
{
RouteID: "vendor3",
SortingData: map[string]any{
utils.Cost: 0.1245,
utils.RatingPlanID: "RP_VENDOR2",
utils.Weight: 10.,
},
},
{
RouteID: "vendor2",
SortingData: map[string]any{
utils.Cost: 0.1245,
utils.RatingPlanID: "RP_VENDOR2",
utils.Weight: 0.,
},
},
{
RouteID: "vendor4",
SortingData: map[string]any{
utils.Cost: 1.5,
utils.RatingPlanID: "RP_STANDARD",
utils.Weight: 30.,
},
},
},
},
}
var reply *engine.SortedRoutesList
//gonna match one route because the totalUsage by ne-allocated resources is 0
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expSrtdRoutes, reply) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCasesSortingRoutesLowestCosMatchingAllRoutes(t *testing.T) {
// deallocate resources for matching vendor1
evRes := &utils.CGREvent{
Tenant: "cgrates.org",
ID: utils.UUIDSha1Prefix(),
Event: map[string]any{
"Account": "1002",
},
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "651a8db2-4f67-4cf8-b622-169e8a482e51",
utils.OptsResourcesUnits: 4,
},
}
var result string
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.ResourceSv1AllocateResources,
evRes, &result); err != nil {
t.Error(err)
} else if result != "RES_GRP1" {
t.Errorf("Unexpected result returned: %s", result)
}
ev := &utils.CGREvent{
ID: "LC_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1002",
utils.Destination: "1003",
utils.SetupTime: "2013-06-01T00:00:00Z",
utils.AnswerTime: "2013-06-01T05:00:00Z",
utils.Usage: "2m30s",
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_ACNT_1002",
Sorting: "*lc",
Routes: []*engine.SortedRoute{
{
RouteID: "vendor3",
SortingData: map[string]any{
utils.Cost: 0.1245,
utils.RatingPlanID: "RP_VENDOR2",
utils.Weight: 10.,
},
},
{
RouteID: "vendor2",
SortingData: map[string]any{
utils.Cost: 0.1245,
utils.RatingPlanID: "RP_VENDOR2",
utils.Weight: 0.,
},
},
{
RouteID: "vendor1",
SortingData: map[string]any{
utils.Cost: 0.2505,
utils.RatingPlanID: "RP_VENDOR1",
utils.Weight: 0.,
},
},
{
RouteID: "vendor4",
SortingData: map[string]any{
utils.Cost: 1.5,
utils.RatingPlanID: "RP_STANDARD",
utils.Weight: 30.,
},
},
},
},
}
var reply *engine.SortedRoutesList
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expSrtdRoutes, reply) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCasesSortingRoutesLowestCosMaxCost(t *testing.T) {
ev := &utils.CGREvent{
ID: "LC_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1002",
utils.Destination: "1003",
utils.SetupTime: "2013-06-01T00:00:00Z",
utils.AnswerTime: "2013-06-01T05:00:00Z",
utils.Usage: "2m30s",
},
APIOpts: map[string]any{
utils.OptsRoutesMaxCost: 0.35,
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_ACNT_1002",
Sorting: "*lc",
Routes: []*engine.SortedRoute{
{
RouteID: "vendor3",
SortingData: map[string]any{
utils.Cost: 0.1245,
utils.RatingPlanID: "RP_VENDOR2",
utils.Weight: 10.,
},
},
{
RouteID: "vendor2",
SortingData: map[string]any{
utils.Cost: 0.1245,
utils.RatingPlanID: "RP_VENDOR2",
utils.Weight: 0.,
},
},
{
RouteID: "vendor1",
SortingData: map[string]any{
utils.Cost: 0.2505,
utils.RatingPlanID: "RP_VENDOR1",
utils.Weight: 0.,
},
},
},
},
}
var reply *engine.SortedRoutesList
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(expSrtdRoutes, reply) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCasesSortingRoutesLowestCosMaxCostNotMatch(t *testing.T) {
ev := &utils.CGREvent{
ID: "LC_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1002",
utils.Destination: "1003",
utils.SetupTime: "2013-06-01T00:00:00Z",
utils.AnswerTime: "2013-06-01T05:00:00Z",
utils.Usage: "2m30s",
},
APIOpts: map[string]any{
utils.OptsRoutesMaxCost: 0.05,
},
}
var reply *engine.SortedRoutesList
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
t.Errorf("Expected %+v, received %+v", utils.ErrNotFound, err)
}
}
func testV1RtsCasesSortingRoutesProcessMetrics(t *testing.T) {
//we will process this stats 2 times
//Vendor2
expected := []string{"STATS_TCC1", "STATS_VENDOR_2"}
ev1 := &utils.CGREvent{
Tenant: "cgrates.org",
ID: "event1",
Event: map[string]any{
utils.AccountField: "1004",
utils.Category: "vendor2",
utils.Usage: "2m30s",
utils.AnswerTime: "2013-06-01T05:00:00Z",
utils.Cost: 1.0,
},
}
var result []string
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.StatSv1ProcessEvent, ev1, &result); err != nil {
t.Error(err)
} else {
sort.Strings(expected)
sort.Strings(result)
if !reflect.DeepEqual(result, expected) {
t.Errorf("Expecting: %+v, received: %+v", expected, result)
}
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.StatSv1ProcessEvent, ev1, &result); err != nil {
t.Error(err)
} else {
sort.Strings(expected)
sort.Strings(result)
if !reflect.DeepEqual(result, expected) {
t.Errorf("Expecting: %+v, received: %+v", expected, result)
}
}
//Vendor1
expected = []string{"STATS_TCC1", "STATS_VENDOR_1"}
ev1 = &utils.CGREvent{
Tenant: "cgrates.org",
ID: "event1",
Event: map[string]any{
utils.AccountField: "1004",
utils.Category: "vendor1",
utils.Usage: "2m30s",
utils.AnswerTime: "2013-06-01T05:00:00Z",
utils.Cost: 1.0,
},
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.StatSv1ProcessEvent, ev1, &result); err != nil {
t.Error(err)
} else {
sort.Strings(expected)
sort.Strings(result)
if !reflect.DeepEqual(result, expected) {
t.Errorf("Expecting: %+v, received: %+v", expected, result)
}
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.StatSv1ProcessEvent, ev1, &result); err != nil {
t.Error(err)
} else {
sort.Strings(expected)
sort.Strings(result)
if !reflect.DeepEqual(result, expected) {
t.Errorf("Expecting: %+v, received: %+v", expected, result)
}
}
}
func testV1RtsCasesSortingRoutesQOS(t *testing.T) {
//not gonna match vendor3 because *tcc is not bigger that 6
ev := &utils.CGREvent{
ID: "LC_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1003",
utils.Destination: "1007",
utils.SetupTime: "2013-06-01T00:00:00Z",
utils.AnswerTime: "2013-06-01T05:00:00Z",
utils.Usage: "50s",
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_ACNT_1003",
Sorting: "*qos",
Routes: []*engine.SortedRoute{
{
RouteID: "vendor2",
SortingData: map[string]any{
utils.MetaACC: 1.,
utils.MetaACD: 150. * 1e9,
"*sum#1": 3.,
"*distinct#~*req.Usage": 1.,
utils.MetaTCC: 3.,
utils.MetaTCD: 450. * 1e9,
utils.Weight: 0.,
},
},
{
RouteID: "vendor1",
SortingData: map[string]any{
utils.MetaACC: 1.,
utils.MetaACD: 150. * 1e9,
"*sum#1": 2.,
utils.MetaTCC: 2.,
utils.MetaTCD: 300. * 1e9,
utils.Weight: 0.,
},
},
},
},
}
var reply *engine.SortedRoutesList
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(reply, expSrtdRoutes) {
t.Errorf("Expecting: %+v \n, received: %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCasesSortingRoutesQOSAllRoutes(t *testing.T) {
// process *tcc metric for matching vendor3
ev1 := &utils.CGREvent{
Tenant: "cgrates.org",
ID: "event1",
Event: map[string]any{
utils.AccountField: "1004",
utils.Category: "vendor1",
utils.Usage: "2m30s",
utils.AnswerTime: "2013-06-01T05:00:00Z",
utils.Cost: 10.0,
},
}
var result []string
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.StatSv1ProcessEvent, ev1, &result); err != nil {
t.Error(err)
}
// match all 3 routes
ev := &utils.CGREvent{
ID: "LC_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1003",
utils.Destination: "1007",
utils.SetupTime: "2013-06-01T00:00:00Z",
utils.AnswerTime: "2013-06-01T05:00:00Z",
utils.Usage: "50s",
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_ACNT_1003",
Sorting: "*qos",
Routes: []*engine.SortedRoute{
{
RouteID: "vendor3",
SortingData: map[string]any{
utils.MetaACC: 4.,
utils.MetaACD: 150. * 1e9,
"*sum#1": 3.,
utils.MetaTCC: 12.,
utils.MetaTCD: 450. * 1e9,
utils.Weight: 20.,
},
},
{
RouteID: "vendor1",
SortingData: map[string]any{
utils.MetaACC: 4.,
utils.MetaACD: 150. * 1e9,
"*sum#1": 3.,
utils.MetaTCC: 12.,
utils.MetaTCD: 450. * 1e9,
utils.Weight: 0.,
},
},
{
RouteID: "vendor2",
SortingData: map[string]any{
utils.MetaACC: 1.,
utils.MetaACD: 150. * 1e9,
"*sum#1": 3.,
"*distinct#~*req.Usage": 1.,
utils.MetaTCC: 3.,
utils.MetaTCD: 450. * 1e9,
utils.Weight: 0.,
},
},
},
},
}
var reply *engine.SortedRoutesList
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(reply, expSrtdRoutes) {
t.Errorf("Expecting: %+v \n, received: %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCasesSortingRoutesQOSNotFound(t *testing.T) {
ev := &utils.CGREvent{
ID: "LC_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1008",
utils.Destination: "1007",
utils.SetupTime: "2013-06-01T00:00:00Z",
utils.AnswerTime: "2013-06-01T05:00:00Z",
utils.Usage: "50s",
},
}
var reply *engine.SortedRoutesList
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
t.Errorf("Expected %+v, received %+v", utils.ErrNotFound, err)
}
}
func testV1RtsCasesSortingRoutesAllocateResources(t *testing.T) {
ev := &utils.CGREvent{
Tenant: "cgrates.org",
ID: utils.UUIDSha1Prefix(),
Event: map[string]any{
"Account": "1002",
},
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "651a8db2-4f67-4cf8-b622-169e8a482e51",
utils.OptsResourcesUnits: 6,
},
}
var reply string
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.ResourceSv1AllocateResources,
ev, &reply); err != nil {
t.Error(err)
} else if reply != "RES_GRP1" {
t.Errorf("Unexpected reply returned: %s", reply)
}
ev = &utils.CGREvent{
Tenant: "cgrates.org",
ID: utils.UUIDSha1Prefix(),
Event: map[string]any{
"Account": "1004",
},
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "651a8db2-4f67-4cf8-b622-169e8a482e31",
utils.OptsResourcesUnits: 7,
},
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.ResourceSv1AllocateResources,
ev, &reply); err != nil {
t.Error(err)
} else if reply != "RES_GRP2" {
t.Errorf("Unexpected reply returned: %s", reply)
}
}
func testV1RtsCasesSortingRoutesReasNotAllRoutes(t *testing.T) {
ev := &utils.CGREvent{
ID: "LC_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1004",
utils.Destination: "1007",
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_ACNT_1004",
Sorting: "*reas",
Routes: []*engine.SortedRoute{
{
RouteID: "vendor1",
SortingData: map[string]any{
utils.ResourceUsage: 6.0,
utils.Weight: 0.,
},
},
{
RouteID: "vendor2",
SortingData: map[string]any{
utils.ResourceUsage: 7.0,
utils.Weight: 0.,
},
},
},
},
}
var reply *engine.SortedRoutesList
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(reply, expSrtdRoutes) {
t.Errorf("Expecting: %+v \n, received: %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCasesSortingRoutesReasAllRoutes(t *testing.T) {
evRs := &utils.CGREvent{
Tenant: "cgrates.org",
ID: utils.UUIDSha1Prefix(),
Event: map[string]any{
"Account": "1002",
},
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "651a8db2-4f67-4cf8-b622-169e8a482e51",
utils.OptsResourcesUnits: 9,
},
}
var replyStr string
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.ResourceSv1AllocateResources,
evRs, &replyStr); err != nil {
t.Error(err)
} else if replyStr != "RES_GRP1" {
t.Errorf("Unexpected reply returned: %s", replyStr)
}
//allocate more resources for matching
ev := &utils.CGREvent{
ID: "LC_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1004",
utils.Destination: "1007",
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_ACNT_1004",
Sorting: "*reas",
Routes: []*engine.SortedRoute{
{
RouteID: "vendor3",
SortingData: map[string]any{
utils.ResourceUsage: 7.0,
utils.Weight: 10.,
},
},
{
RouteID: "vendor2",
SortingData: map[string]any{
utils.ResourceUsage: 7.0,
utils.Weight: 0.,
},
},
{
RouteID: "vendor1",
SortingData: map[string]any{
utils.ResourceUsage: 9.0,
utils.Weight: 0.,
},
},
},
},
}
var reply *engine.SortedRoutesList
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(reply, expSrtdRoutes) {
t.Errorf("Expecting: %+v \n, received: %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCasesRoutesProcessStatsForLoadRtsSorting(t *testing.T) {
// "STATS_VENDOR_1"
var reply []string
expected := []string{"STATS_VENDOR_1", "STATS_TCC1"}
ev1 := &utils.CGREvent{
Tenant: "cgrates.org",
ID: "event1",
Event: map[string]any{
//utils.AccountField: "1004",
utils.Category: "vendor1",
utils.Usage: "1m20s",
utils.AnswerTime: "2013-06-01T05:00:00Z",
utils.Cost: 1.8,
},
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.StatSv1ProcessEvent, ev1, &reply); err != nil {
t.Error(err)
} else if err := rtsCaseSv1Rpc.Call(context.Background(), utils.StatSv1ProcessEvent, ev1, &reply); err != nil {
t.Error(err)
} else {
sort.Strings(expected)
sort.Strings(reply)
if !reflect.DeepEqual(reply, expected) {
t.Errorf("Expecting: %+v, received: %+v", expected, reply)
}
}
// different usage for *distinct metric
ev1 = &utils.CGREvent{
Tenant: "cgrates.org",
ID: "event1",
Event: map[string]any{
//utils.AccountField: "1004",
utils.Category: "vendor1",
utils.Usage: "20s",
utils.AnswerTime: "2013-06-01T05:00:00Z",
utils.Cost: 1.8,
},
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.StatSv1ProcessEvent, ev1, &reply); err != nil {
t.Error(err)
} else if err := rtsCaseSv1Rpc.Call(context.Background(), utils.StatSv1ProcessEvent, ev1, &reply); err != nil {
t.Error(err)
} else {
sort.Strings(expected)
sort.Strings(reply)
if !reflect.DeepEqual(reply, expected) {
t.Errorf("Expecting: %+v, received: %+v", expected, reply)
}
}
// "STATS_VENDOR_2"
expected = []string{"STATS_VENDOR_2", "STATS_TCC1"}
ev1 = &utils.CGREvent{
Tenant: "cgrates.org",
ID: "event1",
Event: map[string]any{
//utils.AccountField: "1004",
utils.Category: "vendor2",
utils.Usage: "30s",
utils.AnswerTime: "2013-06-01T05:00:00Z",
utils.Cost: 0.77,
},
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.StatSv1ProcessEvent, ev1, &reply); err != nil {
t.Error(err)
} else {
sort.Strings(expected)
sort.Strings(reply)
if !reflect.DeepEqual(reply, expected) {
t.Errorf("Expecting: %+v, received: %+v", expected, reply)
}
}
}
func testV1RtsCasesRoutesLoadRtsSorting(t *testing.T) {
ev := &utils.CGREvent{
ID: "LC_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1005",
//utils.Destination: "1007",
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_ACNT_1005",
Sorting: "*load",
Routes: []*engine.SortedRoute{
{
RouteID: "vendor3",
SortingData: map[string]any{
utils.Load: 2.,
utils.Ratio: 2.,
utils.Weight: 0.,
},
},
{
RouteID: "vendor2",
SortingData: map[string]any{
utils.Load: 4.,
utils.Ratio: 2.,
utils.Weight: 10.,
},
},
{
RouteID: "vendor1",
SortingData: map[string]any{
utils.Load: 7.,
utils.Ratio: 3.,
utils.Weight: 0.,
},
},
},
},
}
var reply *engine.SortedRoutesList
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(reply, expSrtdRoutes) {
t.Errorf("Expecting: %+v \n, received: %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCasesSortRoutesHigherCostV2V3(t *testing.T) {
ev := &utils.CGREvent{
ID: "LC_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1008",
utils.Destination: "1007",
utils.SetupTime: "2013-06-01T00:00:00Z",
utils.Usage: "3m25s",
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_HC1",
Sorting: "*hc",
Routes: []*engine.SortedRoute{
{
RouteID: "route2",
SortingData: map[string]any{
utils.Cost: 0.34235,
utils.RatingPlanID: "RP_VENDOR1",
utils.ResourceUsage: 9.,
utils.Weight: 20.,
},
},
{
RouteID: "route3",
SortingData: map[string]any{
utils.Cost: 0.34235,
utils.RatingPlanID: "RP_VENDOR1",
utils.ResourceUsage: 7.,
utils.Weight: 10.,
},
},
},
},
}
var reply *engine.SortedRoutesList
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(reply, expSrtdRoutes) {
t.Errorf("Expecting: %+v \n, received: %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCasesSortRoutesHigherCostAllocateRes(t *testing.T) {
// to match route 1, RES_GRP2 must have *gte available 6 resources
// first we have to remove them
var result string
evRs := &utils.CGREvent{
Tenant: "cgrates.org",
ID: utils.UUIDSha1Prefix(),
Event: map[string]any{
"Account": "1004",
},
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "651a8db2-4f67-4cf8-b622-169e8a482e31",
utils.OptsResourcesUnits: 7,
},
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.ResourceSv1ReleaseResources,
evRs, &result); err != nil {
t.Error(err)
} else if result != utils.OK {
t.Errorf("Unexpected result returned: %s", result)
}
evRs = &utils.CGREvent{
Tenant: "cgrates.org",
ID: utils.UUIDSha1Prefix(),
Event: map[string]any{
"Account": "1002",
},
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "651a8db2-4f67-4cf8-b622-169e8a482e51",
utils.OptsResourcesUnits: 7,
},
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.ResourceSv1ReleaseResources,
evRs, &result); err != nil {
t.Error(err)
} else if result != utils.OK {
t.Errorf("Unexpected result returned: %s", result)
}
evRs = &utils.CGREvent{
Tenant: "cgrates.org",
ID: utils.UUIDSha1Prefix(),
Event: map[string]any{
"Account": "1004",
},
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "651a8db2-4f67-4cf8-b622-169e8a482e31",
utils.OptsResourcesUnits: 1,
},
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.ResourceSv1AllocateResources,
evRs, &result); err != nil {
t.Error(err)
} else if result != "RES_GRP2" {
t.Errorf("Unexpected result returned: %s", result)
}
// also, to not match route2, totalUsage of RES_GRP1 must be lower than 9
evRs = &utils.CGREvent{
Tenant: "cgrates.org",
ID: utils.UUIDSha1Prefix(),
Event: map[string]any{
"Account": "1002",
},
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "651a8db2-4f67-4cf8-b622-169e8a482e51",
utils.OptsResourcesUnits: 4,
},
}
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.ResourceSv1AllocateResources,
evRs, &result); err != nil {
t.Error(err)
} else if result != "RES_GRP1" {
t.Errorf("Unexpected result returned: %s", result)
}
}
func testV1RtsCasesSortRoutesHigherCostV1V3(t *testing.T) {
ev := &utils.CGREvent{
ID: "LC_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1008",
utils.Destination: "1007",
utils.SetupTime: "2013-06-01T00:00:00Z",
utils.Usage: "3m25s",
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_HC1",
Sorting: "*hc",
Routes: []*engine.SortedRoute{
{
RouteID: "route3",
SortingData: map[string]any{
utils.Cost: 0.34235,
utils.RatingPlanID: "RP_VENDOR1",
utils.ResourceUsage: 1.,
utils.Weight: 10.,
},
},
{
RouteID: "route1",
SortingData: map[string]any{
utils.Cost: 0.17015,
utils.RatingPlanID: "RP_VENDOR2",
utils.ResourceUsage: 1.,
utils.Weight: 20.,
},
},
},
},
}
var reply *engine.SortedRoutesList
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(reply, expSrtdRoutes) {
t.Errorf("Expecting: %+v \n, received: %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCasesSortRoutesHigherCostAllRoutes(t *testing.T) {
//allocate for matching all routes
evRs := &utils.CGREvent{
Tenant: "cgrates.org",
ID: utils.UUIDSha1Prefix(),
Event: map[string]any{
"Account": "1002"},
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "651a8db2-4f67-4cf8-b622-169e8a482e51",
utils.OptsResourcesUnits: 9,
},
}
var result string
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.ResourceSv1AllocateResources,
evRs, &result); err != nil {
t.Error(err)
} else if result != "RES_GRP1" {
t.Errorf("Unexpected result returned: %s", result)
}
ev := &utils.CGREvent{
ID: "LC_SORT",
Tenant: "cgrates.org",
Event: map[string]any{
utils.AccountField: "1008",
utils.Destination: "1007",
utils.SetupTime: "2013-06-01T00:00:00Z",
utils.Usage: "3m25s",
},
}
expSrtdRoutes := &engine.SortedRoutesList{
{
ProfileID: "ROUTE_HC1",
Sorting: "*hc",
Routes: []*engine.SortedRoute{
{
RouteID: "route2",
SortingData: map[string]any{
utils.Cost: 0.34235,
utils.RatingPlanID: "RP_VENDOR1",
utils.ResourceUsage: 9.,
utils.Weight: 20.,
},
},
{
RouteID: "route3",
SortingData: map[string]any{
utils.Cost: 0.34235,
utils.RatingPlanID: "RP_VENDOR1",
utils.ResourceUsage: 1.,
utils.Weight: 10.,
},
},
{
RouteID: "route1",
SortingData: map[string]any{
utils.Cost: 0.17015,
utils.RatingPlanID: "RP_VENDOR2",
utils.ResourceUsage: 1.,
utils.Weight: 20.,
},
},
},
},
}
var reply *engine.SortedRoutesList
if err := rtsCaseSv1Rpc.Call(context.Background(), utils.RouteSv1GetRoutes,
ev, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(reply, expSrtdRoutes) {
t.Errorf("Expecting: %+v \n, received: %+v", utils.ToJSON(expSrtdRoutes), utils.ToJSON(reply))
}
}
func testV1RtsCaseStopEngine(t *testing.T) {
if err := engine.KillEngine(100); err != nil {
t.Error(err)
}
}