diff --git a/engine/route_cost_sort_test.go b/engine/route_cost_sort_test.go
index d5536e1c8..6e9214549 100644
--- a/engine/route_cost_sort_test.go
+++ b/engine/route_cost_sort_test.go
@@ -19,13 +19,16 @@ along with this program. If not, see
package engine
import (
+ "bytes"
"reflect"
+ "strings"
"testing"
"github.com/cgrates/birpc"
"github.com/cgrates/birpc/context"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/utils"
+ "github.com/ericlagergren/decimal"
)
func TestPopulateCostForRoutesConnRefused(t *testing.T) {
@@ -175,91 +178,276 @@ func TestHightCostSorterSortRoutesErr(t *testing.T) {
}
-// unfinished
-// func TestHightCostSorterSortRoutesOK(t *testing.T) {
+func TestHightCostSorterSortRoutesOK(t *testing.T) {
-// cfg := config.NewDefaultCGRConfig()
-// cfg.RouteSCfg().RateSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaRates)}
-// cfg.RouteSCfg().AccountSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAccounts)}
+ cfg := config.NewDefaultCGRConfig()
+ cfg.RouteSCfg().RateSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaRates)}
+ cfg.RouteSCfg().AccountSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAccounts)}
-// cc := make(chan birpc.ClientConnector, 1)
-// cc <- &ccMock{
+ cc := make(chan birpc.ClientConnector, 1)
+ cc <- &ccMock{
-// calls: map[string]func(ctx *context.Context, args interface{}, reply interface{}) error{
-// utils.AccountSv1MaxAbstracts: func(ctx *context.Context, args, reply interface{}) error {
-// return nil
-// },
-// },
-// }
+ calls: map[string]func(ctx *context.Context, args interface{}, reply interface{}) error{
+ utils.AccountSv1MaxAbstracts: func(ctx *context.Context, args, reply interface{}) error {
+ return nil
+ },
+ },
+ }
-// cM := NewConnManager(cfg)
-// cM.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAccounts), utils.AccountSv1, cc)
+ cM := NewConnManager(cfg)
+ cM.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAccounts), utils.AccountSv1, cc)
-// fltrS := NewFilterS(cfg, cM, nil)
-// hcs := NewHighestCostSorter(cfg, cM, fltrS)
+ fltrS := NewFilterS(cfg, cM, nil)
+ hcs := NewHighestCostSorter(cfg, cM, fltrS)
-// routeWW := map[string]*RouteWithWeight{
-// "RW1": {
-// Route: &Route{
-// ID: "RouteId",
-// RouteParameters: "RouteParam",
-// Weights: utils.DynamicWeights{{Weight: 1}},
-// Blockers: utils.DynamicBlockers{{Blocker: false}},
-// AccountIDs: []string{"AccId"},
-// RateProfileIDs: []string{"RateProfileId"},
-// ResourceIDs: []string{"ResourceId"},
-// StatIDs: []string{"StatId"},
-// },
-// Weight: 10,
-// },
-// "RW2": {
-// Route: &Route{
-// ID: "RouteId2",
-// RouteParameters: "RouteParam2",
-// Weights: utils.DynamicWeights{{Weight: 10}},
-// Blockers: utils.DynamicBlockers{{Blocker: false}},
-// AccountIDs: []string{"AccId2"},
-// RateProfileIDs: []string{"RateProfileId2"},
-// ResourceIDs: []string{"ResourceId2"},
-// StatIDs: []string{"StatId2"},
-// },
-// Weight: 1,
-// },
-// }
-// ev := &utils.CGREvent{
-// APIOpts: map[string]interface{}{
-// utils.MetaUsage: 400,
-// },
-// }
+ routeWW := map[string]*RouteWithWeight{
+ "RW1": {
+ Route: &Route{
+ ID: "RouteId",
+ RouteParameters: "RouteParam",
+ Weights: utils.DynamicWeights{{Weight: 1}},
+ Blockers: utils.DynamicBlockers{{Blocker: false}},
+ AccountIDs: []string{"AccId"},
+ RateProfileIDs: []string{"RateProfileId"},
+ ResourceIDs: []string{"ResourceId"},
+ StatIDs: []string{"StatId"},
+ },
+ Weight: 10,
+ },
+ "RW2": {
+ Route: &Route{
+ ID: "RouteId2",
+ RouteParameters: "RouteParam2",
+ Weights: utils.DynamicWeights{{Weight: 10}},
+ Blockers: utils.DynamicBlockers{{Blocker: false}},
+ AccountIDs: []string{"AccId2"},
+ RateProfileIDs: []string{"RateProfileId2"},
+ ResourceIDs: []string{"ResourceId2"},
+ StatIDs: []string{"StatId2"},
+ },
+ Weight: 1,
+ blocker: true,
+ },
+ }
+ ev := &utils.CGREvent{
+ APIOpts: map[string]interface{}{
+ utils.MetaUsage: 400,
+ },
+ }
-// exp := &SortedRoutes{
-// ProfileID: "profID1",
-// Sorting: utils.MetaHC,
-// Routes: []*SortedRoute{
-// {
-// RouteID: "RouteId2",
-// RouteParameters: "RouteParam2",
-// SortingData: map[string]interface{}{
-// utils.AccountIDs: []string{},
-// utils.Cost: nil,
-// utils.Weight: 10,
-// },
-// },
-// {
-// RouteID: "RouteId",
-// RouteParameters: "RouteParam",
-// SortingData: map[string]interface{}{
-// utils.AccountIDs: []string{},
-// utils.Cost: nil,
-// utils.Weight: 1,
-// },
-// },
-// },
-// }
-// if rcv, err := hcs.SortRoutes(context.Background(), "profID1", routeWW, ev, &optsGetRoutes{}); err != nil {
-// t.Error(err)
-// } else if !reflect.DeepEqual(utils.ToJSON(exp), utils.ToJSON(rcv)) {
-// t.Errorf("Expecting \n<%+v>,\n received \n<%+v>", utils.ToJSON(exp), utils.ToJSON(rcv))
-// }
+ exp := &SortedRoutes{
+ ProfileID: "profID1",
+ Sorting: utils.MetaHC,
+ Routes: []*SortedRoute{
+ {
+ RouteID: "RouteId",
+ RouteParameters: "RouteParam",
+ SortingData: map[string]interface{}{
+ utils.AccountIDs: []string{},
+ utils.Cost: nil,
+ utils.Weight: 10,
+ },
+ },
+ {
+ RouteID: "RouteId2",
+ RouteParameters: "RouteParam2",
+ SortingData: map[string]interface{}{
+ utils.AccountIDs: []string{},
+ utils.Cost: nil,
+ utils.Weight: 1,
+ utils.Blocker: true,
+ },
+ },
+ },
+ }
+ if rcv, err := hcs.SortRoutes(context.Background(), "profID1", routeWW, ev, &optsGetRoutes{}); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(utils.ToJSON(exp), utils.ToJSON(rcv)) {
+ t.Errorf("Expecting \n<%+v>,\n received \n<%+v>", utils.ToJSON(exp), utils.ToJSON(rcv))
+ }
-// }
+}
+
+func TestPopulateCostForRoutesGetDecimalBigOptsErr(t *testing.T) {
+
+ cfg := config.NewDefaultCGRConfig()
+ cfg.RouteSCfg().RateSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaRates)}
+ cfg.RouteSCfg().Opts.Usage = []*utils.DynamicDecimalBigOpt{
+ {
+ FilterIDs: []string{"*string.invalid:filter"},
+ Tenant: "cgrates.org",
+ Value: decimal.New(-1, 0),
+ },
+ }
+ connMgr := NewConnManager(cfg)
+ fltrS := NewFilterS(cfg, connMgr, nil)
+ routes := map[string]*RouteWithWeight{
+ "RW": {
+ Route: &Route{
+ ID: "local",
+ RateProfileIDs: []string{"RP_LOCAL"},
+ },
+ Weight: 10,
+ },
+ }
+ ev := &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "TestEvent",
+ Event: map[string]interface{}{
+ utils.AccountField: 1001,
+ },
+ APIOpts: map[string]interface{}{},
+ }
+ extraOpts := &optsGetRoutes{}
+
+ experr := `inline parse error for string: <*string.invalid:filter>`
+ _, err := populateCostForRoutes(context.Background(), cfg, connMgr, fltrS, routes, ev, extraOpts)
+ if err == nil || err.Error() != experr {
+ t.Errorf("Expected error \n<%v>\n but received \n<%v>", experr, err)
+ }
+
+}
+
+func TestPopulateCostForRoutesMissingIdsErr(t *testing.T) {
+
+ defer func() {
+ Cache = NewCacheS(config.NewDefaultCGRConfig(), nil, nil, nil)
+ }()
+
+ cfg := config.NewDefaultCGRConfig()
+ cfg.RouteSCfg().RateSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaRates)}
+
+ connMgr := NewConnManager(cfg)
+ fltrS := NewFilterS(cfg, connMgr, nil)
+ routes := map[string]*RouteWithWeight{
+ "RW": {
+ Route: &Route{
+ ID: "local",
+ RateProfileIDs: []string{},
+ AccountIDs: []string{},
+ },
+ Weight: 10,
+ },
+ }
+ ev := &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "TestEvent",
+ Event: map[string]interface{}{
+ utils.AccountField: 1001,
+ },
+ APIOpts: map[string]interface{}{},
+ }
+ extraOpts := &optsGetRoutes{}
+
+ experr := `MANDATORY_IE_MISSING: [RateProfileIDs or AccountIDs]`
+ _, err := populateCostForRoutes(context.Background(), cfg, connMgr, fltrS, routes, ev, extraOpts)
+ if err == nil || err.Error() != experr {
+ t.Errorf("Expected error \n<%v>\n but received \n<%v>", experr, err)
+ }
+
+}
+
+func TestPopulateCostForRoutesAccountSConnsIgnoreErr(t *testing.T) {
+
+ var buf bytes.Buffer
+ utils.Logger = utils.NewStdLoggerWithWriter(&buf, "", 7)
+
+ cfg := config.NewDefaultCGRConfig()
+ cfg.RouteSCfg().RateSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaRates)}
+ cfg.RouteSCfg().AccountSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAccounts)}
+
+ cc := make(chan birpc.ClientConnector, 1)
+ cc <- &ccMock{
+
+ calls: map[string]func(ctx *context.Context, args interface{}, reply interface{}) error{
+ utils.AccountSv1MaxAbstracts: func(ctx *context.Context, args, reply interface{}) error {
+ return utils.ErrNotImplemented
+ },
+ },
+ }
+
+ cM := NewConnManager(cfg)
+ cM.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAccounts), utils.AccountSv1, cc)
+
+ fltrS := NewFilterS(cfg, cM, nil)
+ routes := map[string]*RouteWithWeight{
+ "RW": {
+ Route: &Route{
+ ID: "local",
+ AccountIDs: []string{"accID1"},
+ },
+ Weight: 10,
+ },
+ }
+ ev := &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "TestEvent",
+ Event: map[string]interface{}{
+ utils.AccountField: 1001,
+ },
+ APIOpts: map[string]interface{}{},
+ }
+ extraOpts := &optsGetRoutes{
+ ignoreErrors: true,
+ }
+
+ rcv, err := populateCostForRoutes(context.Background(), cfg, cM, fltrS, routes, ev, extraOpts)
+ if err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(rcv, []*SortedRoute{}) {
+ t.Errorf("Received <%+v>", rcv)
+ }
+
+ expected := "CGRateS <> [WARNING] ignoring route with ID: local, err: NOT_IMPLEMENTED"
+ if rcv := buf.String(); !strings.Contains(rcv, expected) {
+ t.Errorf("Expected <%+v>, received <%+v>", expected, rcv)
+ }
+
+}
+
+func TestPopulateCostForRoutesAccountSConnsErr(t *testing.T) {
+
+ cfg := config.NewDefaultCGRConfig()
+ cfg.RouteSCfg().RateSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaRates)}
+ cfg.RouteSCfg().AccountSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAccounts)}
+
+ cc := make(chan birpc.ClientConnector, 1)
+ cc <- &ccMock{
+
+ calls: map[string]func(ctx *context.Context, args interface{}, reply interface{}) error{
+ utils.AccountSv1MaxAbstracts: func(ctx *context.Context, args, reply interface{}) error {
+ return utils.ErrNotImplemented
+ },
+ },
+ }
+
+ cM := NewConnManager(cfg)
+ cM.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal, utils.MetaAccounts), utils.AccountSv1, cc)
+
+ fltrS := NewFilterS(cfg, cM, nil)
+ routes := map[string]*RouteWithWeight{
+ "RW": {
+ Route: &Route{
+ ID: "local",
+ AccountIDs: []string{"accID1"},
+ },
+ Weight: 10,
+ },
+ }
+ ev := &utils.CGREvent{
+ Tenant: "cgrates.org",
+ ID: "TestEvent",
+ Event: map[string]interface{}{
+ utils.AccountField: 1001,
+ },
+ APIOpts: map[string]interface{}{},
+ }
+ extraOpts := &optsGetRoutes{}
+
+ expErr := "ACCOUNTS_ERROR:NOT_IMPLEMENTED"
+ _, err := populateCostForRoutes(context.Background(), cfg, cM, fltrS, routes, ev, extraOpts)
+ if err == nil || err.Error() != expErr {
+ t.Errorf("Expected error \n<%v>\n but received \n<%v>", expErr, err)
+ }
+
+}