From 61fa86126f57adc745b395a2f55aa6efbbf46e7a Mon Sep 17 00:00:00 2001 From: arberkatellari Date: Wed, 24 May 2023 12:00:05 -0400 Subject: [PATCH] Add coverage tests for engine --- engine/route_cost_sort_test.go | 348 +++++++++++++++++++++++++-------- 1 file changed, 268 insertions(+), 80 deletions(-) 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) + } + +}