From 4cc5fa8a018efc1815121fd6920134f34338af05 Mon Sep 17 00:00:00 2001 From: arberkatellari Date: Tue, 30 May 2023 10:59:07 -0400 Subject: [PATCH] Add coverage tests for engine --- engine/route_qos_test.go | 357 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 357 insertions(+) create mode 100644 engine/route_qos_test.go diff --git a/engine/route_qos_test.go b/engine/route_qos_test.go new file mode 100644 index 000000000..bd93d4d32 --- /dev/null +++ b/engine/route_qos_test.go @@ -0,0 +1,357 @@ +/* +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 engine + +import ( + "reflect" + "testing" + + "github.com/cgrates/birpc" + "github.com/cgrates/birpc/context" + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/utils" +) + +func TestPopulatStatsForQOSRouteCallErr(t *testing.T) { + + cfg := config.NewDefaultCGRConfig() + cM := NewConnManager(cfg) + + expErr := "MANDATORY_IE_MISSING: [connIDs]" + if _, err := populatStatsForQOSRoute(context.Background(), cfg, cM, []string{"stat1", "stat2"}, "cgrates.org"); err == nil || err.Error() != expErr { + t.Errorf("Expected error <%v>, received <%v>", expErr, err) + } + +} + +func TestPopulatStatsForQOSRouteOK(t *testing.T) { + + defer func() { + Cache = NewCacheS(config.NewDefaultCGRConfig(), nil, nil, nil) + }() + + cfg := config.NewDefaultCGRConfig() + cfg.RouteSCfg().StatSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats)} + + metrics := &map[string]*utils.Decimal{ + "stat": utils.NewDecimal(5, 0), + } + + cc := make(chan birpc.ClientConnector, 1) + cc <- &ccMock{ + + calls: map[string]func(ctx *context.Context, args interface{}, reply interface{}) error{ + utils.StatSv1GetQueueDecimalMetrics: func(ctx *context.Context, args, reply interface{}) error { + rplCast, canCast := reply.(*map[string]*utils.Decimal) + if !canCast { + t.Errorf("Wrong argument type : %T", reply) + return nil + } + *rplCast = *metrics + return nil + }, + }, + } + + cM := NewConnManager(cfg) + cM.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats), utils.StatSv1, cc) + + exp := map[string]*utils.Decimal{ + "stat": utils.NewDecimal(5, 0), + } + + if rcv, err := populatStatsForQOSRoute(context.Background(), cfg, cM, []string{"stat1", "stat2"}, "cgrates.org"); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(rcv, exp) { + t.Errorf("Expected \n<%+v>,\n received \n<%+v>", exp, rcv) + } + +} + +func TestQOSRouteSorterRoutesNoStatSConns(t *testing.T) { + + cfg := config.NewDefaultCGRConfig() + cM := NewConnManager(cfg) + qos := NewQOSRouteSorter(cfg, cM) + ctx := context.Background() + prflID := "prfId" + routes := map[string]*RouteWithWeight{} + + cgrEv := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "EV", + Event: map[string]interface{}{}, + APIOpts: map[string]interface{}{}, + } + + extraOpts := &optsGetRoutes{} + + expErr := "MANDATORY_IE_MISSING: [connIDs]" + if _, err := qos.SortRoutes(ctx, prflID, routes, cgrEv, extraOpts); err == nil || err.Error() != expErr { + t.Errorf("Expected error <%v>, received <%v>", expErr, err) + } + +} + +func TestQOSRouteSorterRoutesOK(t *testing.T) { + + defer func() { + Cache = NewCacheS(config.NewDefaultCGRConfig(), nil, nil, nil) + }() + + cfg := config.NewDefaultCGRConfig() + cfg.RouteSCfg().StatSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats)} + + metrics := &map[string]*utils.Decimal{ + "*tcd": utils.NewDecimal(5, 0), + } + + cc := make(chan birpc.ClientConnector, 1) + cc <- &ccMock{ + calls: map[string]func(ctx *context.Context, args interface{}, reply interface{}) error{ + utils.StatSv1GetQueueDecimalMetrics: func(ctx *context.Context, args, reply interface{}) error { + rplCast, canCast := reply.(*map[string]*utils.Decimal) + if !canCast { + t.Errorf("Wrong argument type : %T", reply) + return nil + } + *rplCast = *metrics + return nil + }, + }, + } + + cM := NewConnManager(cfg) + cM.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats), utils.StatSv1, cc) + qos := NewQOSRouteSorter(cfg, cM) + ctx := context.Background() + prflID := "prfId" + routes := map[string]*RouteWithWeight{ + "RW": { + Route: &Route{ + ID: "local", + StatIDs: []string{"stat1"}, + }, + blocker: true, + Weight: 10, + }, + } + + cgrEv := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "EV", + Event: map[string]interface{}{}, + APIOpts: map[string]interface{}{}, + } + + extraOpts := &optsGetRoutes{} + + exp := &SortedRoutes{ + ProfileID: "prfId", + Sorting: "*qos", + Routes: []*SortedRoute{{ + RouteID: "local", + RouteParameters: "", + SortingData: map[string]interface{}{ + utils.Blocker: true, + utils.MetaTCD: 5, + utils.Weight: 10, + }, + }, + }, + } + + if rcv, err := qos.SortRoutes(ctx, prflID, routes, cgrEv, extraOpts); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(utils.ToJSON(exp), utils.ToJSON(rcv)) { + t.Errorf("Expected \n<%+v>,\n received \n<%+v>", utils.ToJSON(exp), utils.ToJSON(rcv)) + } + +} + +func TestQOSRouteSorterRoutesLazyPassErr(t *testing.T) { + + defer func() { + Cache = NewCacheS(config.NewDefaultCGRConfig(), nil, nil, nil) + }() + + cfg := config.NewDefaultCGRConfig() + cfg.RouteSCfg().StatSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats)} + + metrics := &map[string]*utils.Decimal{ + "*tcd": utils.NewDecimal(5, 0), + } + + cc := make(chan birpc.ClientConnector, 1) + cc <- &ccMock{ + calls: map[string]func(ctx *context.Context, args interface{}, reply interface{}) error{ + utils.StatSv1GetQueueDecimalMetrics: func(ctx *context.Context, args, reply interface{}) error { + rplCast, canCast := reply.(*map[string]*utils.Decimal) + if !canCast { + t.Errorf("Wrong argument type : %T", reply) + return nil + } + *rplCast = *metrics + return nil + }, + }, + } + + cM := NewConnManager(cfg) + cM.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats), utils.StatSv1, cc) + qos := NewQOSRouteSorter(cfg, cM) + ctx := context.Background() + prflID := "prfId" + routes := map[string]*RouteWithWeight{ + "RW": { + Route: &Route{ + ID: "local", + StatIDs: []string{"stat1"}, + }, + Weight: 10, + lazyCheckRules: []*FilterRule{ + { + Type: "inexistent", + Element: "inexistent", + Values: []string{"inexistent"}, + }, + }, + }, + } + + cgrEv := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "EV", + Event: map[string]interface{}{}, + APIOpts: map[string]interface{}{}, + } + + extraOpts := &optsGetRoutes{} + + expErr := "NOT_IMPLEMENTED:inexistent" + if _, err := qos.SortRoutes(ctx, prflID, routes, cgrEv, extraOpts); err == nil || err.Error() != expErr { + t.Errorf("Expected error <%v>, received <%v>", expErr, err) + } + +} + +func TestQOSRouteSorterRoutesIgnoreErr(t *testing.T) { + + defer func() { + Cache = NewCacheS(config.NewDefaultCGRConfig(), nil, nil, nil) + }() + + cfg := config.NewDefaultCGRConfig() + cfg.RouteSCfg().StatSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats)} + + cc := make(chan birpc.ClientConnector, 1) + cc <- &ccMock{ + calls: map[string]func(ctx *context.Context, args interface{}, reply interface{}) error{ + utils.StatSv1GetQueueDecimalMetrics: func(ctx *context.Context, args, reply interface{}) error { + return utils.ErrNotImplemented + }, + }, + } + + cM := NewConnManager(cfg) + cM.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats), utils.StatSv1, cc) + qos := NewQOSRouteSorter(cfg, cM) + ctx := context.Background() + prflID := "prfId" + routes := map[string]*RouteWithWeight{ + "RW": { + Route: &Route{ + ID: "local", + StatIDs: []string{"stat1"}, + }, + Weight: 10, + }, + } + + cgrEv := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "EV", + Event: map[string]interface{}{}, + APIOpts: map[string]interface{}{}, + } + + extraOpts := &optsGetRoutes{ + ignoreErrors: true, + } + + exp := &SortedRoutes{ + ProfileID: "prfId", + Sorting: "*qos", + Routes: []*SortedRoute{}, + } + + if rcv, err := qos.SortRoutes(ctx, prflID, routes, cgrEv, extraOpts); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(utils.ToJSON(exp), utils.ToJSON(rcv)) { + t.Errorf("Expected \n<%+v>,\n received \n<%+v>", utils.ToJSON(exp), utils.ToJSON(rcv)) + } + +} + +func TestQOSRouteSorterRoutesPopulateErr(t *testing.T) { + + defer func() { + Cache = NewCacheS(config.NewDefaultCGRConfig(), nil, nil, nil) + }() + + cfg := config.NewDefaultCGRConfig() + cfg.RouteSCfg().StatSConns = []string{utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats)} + + cc := make(chan birpc.ClientConnector, 1) + cc <- &ccMock{ + calls: map[string]func(ctx *context.Context, args interface{}, reply interface{}) error{ + utils.StatSv1GetQueueDecimalMetrics: func(ctx *context.Context, args, reply interface{}) error { + return utils.ErrNotImplemented + }, + }, + } + + cM := NewConnManager(cfg) + cM.AddInternalConn(utils.ConcatenatedKey(utils.MetaInternal, utils.MetaStats), utils.StatSv1, cc) + qos := NewQOSRouteSorter(cfg, cM) + ctx := context.Background() + prflID := "prfId" + routes := map[string]*RouteWithWeight{ + "RW": { + Route: &Route{ + ID: "local", + StatIDs: []string{"stat1"}, + }, + Weight: 10, + }, + } + + cgrEv := &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "EV", + Event: map[string]interface{}{}, + APIOpts: map[string]interface{}{}, + } + + extraOpts := &optsGetRoutes{} + + if _, err := qos.SortRoutes(ctx, prflID, routes, cgrEv, extraOpts); err != utils.ErrNotImplemented { + t.Errorf("Expected error \n<%v>\n but received \n<%v>", utils.ErrNotImplemented, err) + } +}