add and revise action type tests

This commit is contained in:
arberkatellari
2025-05-26 19:32:35 +02:00
committed by Dan Christian Bogos
parent f3986cbcdc
commit 6d206954bd
26 changed files with 748 additions and 142 deletions

View File

@@ -702,3 +702,69 @@ func TestActionTimingGetNextStartTimesMonthlyEstimated(t *testing.T) {
})
}
}
func TestVerifyFormat(t *testing.T) {
tests := []struct {
tStr string
expectedBool bool
}{
{"12:34:56", true},
{"23:59:59", true},
{"12:34", false},
{"12:34:56:78", false},
{"12:abc:56", false},
{"123:456:789", false},
{"00:00:00", true},
{"12:34:56", true},
{"t:01:t", false},
{"1,1,1", false},
{"0:0:0", true},
{"119911", false},
{"00/01/03", false},
{"t1:t2:t3", false},
}
for _, tt := range tests {
t.Run(tt.tStr, func(t *testing.T) {
result := verifyFormat(tt.tStr)
if result != tt.expectedBool {
t.Errorf("verifyFormat(%q) = %v; want %v", tt.tStr, result, tt.expectedBool)
}
})
}
}
func TestCheckDefaultTiming(t *testing.T) {
tests := []struct {
name string
tStr string
wantID string
wantIsDef bool
}{
{"Every Minute", utils.MetaEveryMinute, utils.MetaEveryMinute, true},
{"Hourly", utils.MetaHourly, utils.MetaHourly, true},
{"Daily", utils.MetaDaily, utils.MetaDaily, true},
{"Weekly", utils.MetaWeekly, utils.MetaWeekly, true},
{"Monthly", utils.MetaMonthly, utils.MetaMonthly, true},
{"Monthly Estimated", utils.MetaMonthlyEstimated, utils.MetaMonthlyEstimated, true},
{"Month End", utils.MetaMonthEnd, utils.MetaMonthEnd, true},
{"Yearly", utils.MetaYearly, utils.MetaYearly, true},
{"Unknown", "unknown", "", false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, isDef := checkDefaultTiming(tt.tStr)
if isDef != tt.wantIsDef {
t.Errorf("checkDefaultTiming(%q) isDefault = %v, want %v", tt.tStr, isDef, tt.wantIsDef)
}
if isDef && got.ID != tt.wantID {
t.Errorf("checkDefaultTiming(%q) got.ID = %v, want %v", tt.tStr, got.ID, tt.wantID)
}
if !isDef && got != nil {
t.Errorf("checkDefaultTiming(%q) expected nil, got non-nil", tt.tStr)
}
})
}
}

View File

@@ -4843,7 +4843,7 @@ func TestActionsAlterAndDisconnectSessions(t *testing.T) {
{
name: "WrongNumberOfParams",
extraParams: "tenant;;1;",
expectedErr: "invalid number of parameters; expected 5",
expectedErr: "invalid number of parameters <4> expected 5",
},
{
name: "InvalidEventMap",
@@ -5044,7 +5044,7 @@ func TestDynamicThreshold(t *testing.T) {
{
name: "WrongNumberOfParams",
extraParams: "tenant;;1;",
expectedErr: "invalid number of parameters; expected 12",
expectedErr: "invalid number of parameters <4> expected 12",
},
{
name: "ActivationIntervalLengthFail",
@@ -5291,7 +5291,7 @@ func TestDynamicStats(t *testing.T) {
{
name: "WrongNumberOfParams",
extraParams: "tenant;;1;",
expectedErr: "invalid number of parameters; expected 14",
expectedErr: "invalid number of parameters <4> expected 14",
},
{
name: "ActivationIntervalLengthFail",
@@ -5514,7 +5514,7 @@ func TestDynamicAttribute(t *testing.T) {
{
name: "WrongNumberOfParams",
extraParams: "tenant;;1;",
expectedErr: "invalid number of parameters; expected 12",
expectedErr: "invalid number of parameters <4> expected 12",
},
{
name: "ActivationIntervalLengthFail",
@@ -5600,3 +5600,463 @@ func TestDynamicAttribute(t *testing.T) {
})
}
}
func TestDynamicActionPlan(t *testing.T) {
tempConn := connMgr
tmpDm := dm
tmpCache := Cache
defer func() {
config.SetCgrConfig(config.NewDefaultCGRConfig())
SetConnManager(tempConn)
dm = tmpDm
Cache = tmpCache
}()
Cache.Clear(nil)
var ap *AttrSetActionPlan
ccMock := &ccMock{
calls: map[string]func(ctx *context.Context, args any, reply any) error{
utils.APIerSv1SetActionPlan: func(ctx *context.Context, args, reply any) error {
var canCast bool
if ap, canCast = args.(*AttrSetActionPlan); !canCast {
return fmt.Errorf("couldnt cast AttrSetActionPlan")
}
return nil
},
utils.APIerSv1GetActions: func(ctx *context.Context, args2, reply any) error {
return nil
},
utils.APIerSv1GetTiming: func(ctx *context.Context, args3, reply any) error {
var canCast bool
if args3, canCast = args3.(*utils.ArgsGetTimingID); !canCast {
return fmt.Errorf("couldnt cast ArgsGetTimingID")
}
var exp *utils.TPTiming
if utils.ToJSON(args3) == utils.ToJSON(&utils.ArgsGetTimingID{ID: "Timing_1"}) {
exp = &utils.TPTiming{
ID: "Timing_1",
Years: utils.Years{2025},
Months: utils.Months{2},
MonthDays: utils.MonthDays{3},
WeekDays: utils.WeekDays{1, 2, 3},
StartTime: "00:12:12",
EndTime: "12:12:12",
}
}
if utils.ToJSON(args3) == utils.ToJSON(&utils.ArgsGetTimingID{ID: "*asap"}) {
exp = &utils.TPTiming{
ID: "*asap",
Years: utils.Years{2025},
Months: utils.Months{},
MonthDays: utils.MonthDays{},
WeekDays: utils.WeekDays{},
StartTime: "*asap",
}
}
if exp == nil {
return utils.ErrNotFound
}
*reply.(*utils.TPTiming) = *exp
return nil
},
},
}
connID := utils.ConcatenatedKey(utils.MetaInternal, utils.MetaApier)
clientconn := make(chan birpc.ClientConnector, 1)
clientconn <- ccMock
NewConnManager(config.NewDefaultCGRConfig(), map[string]chan birpc.ClientConnector{
connID: clientconn,
})
testcases := []struct {
name string
extraParams string
connIDs []string
expAp *AttrSetActionPlan
expectedErr string
}{
{
name: "SuccessfulRequest",
connIDs: []string{connID},
expAp: &AttrSetActionPlan{
Id: "ActPl_1",
ActionPlan: []*AttrActionPlan{
{
ActionsId: "Action_1",
TimingID: "Timing_1",
Years: "2025",
Months: "2",
MonthDays: "3",
WeekDays: "1;2;3",
Time: "00:12:12;12:12:12",
Weight: 10,
},
},
Overwrite: true,
ReloadScheduler: true,
},
extraParams: "ActPl_1;Action_1;Timing_1;10;true",
},
{
name: "SuccessfulRequestWithDynamicPaths",
connIDs: []string{connID},
expAp: &AttrSetActionPlan{
Id: "ActPl_1",
ActionPlan: []*AttrActionPlan{
{
ActionsId: "Action_1001",
TimingID: "*asap",
Years: "2025",
Months: "*any",
MonthDays: "*any",
WeekDays: "*any",
Time: "*asap",
Weight: 10,
},
},
Overwrite: false,
ReloadScheduler: true,
},
extraParams: "ActPl_1;Action_<~*req.Account>;*asap;10;",
},
{
name: "SuccessfulRequestEmptyFields",
connIDs: []string{connID},
expAp: &AttrSetActionPlan{
Id: "ActPl_1",
ActionPlan: []*AttrActionPlan{
{
ActionsId: "Action_1",
TimingID: "",
Weight: 0,
},
},
Overwrite: false,
ReloadScheduler: true,
},
extraParams: "ActPl_1;Action_1;;;",
},
{
name: "MissingConns",
extraParams: "ActPl_1;Action_1;*asap;10;",
expectedErr: "MANDATORY_IE_MISSING: [connIDs]",
},
{
name: "WrongNumberOfParams",
extraParams: "ActPl_1;Action_1;*asap;10;;;",
expectedErr: "invalid number of parameters <7> expected 5",
},
{
name: "ActionIdEmptyFail",
extraParams: "ActPl_1;;*asap;10;",
expectedErr: `empty ActionsId for <ActPl_1> dynamic_action_plan`,
},
{
name: "WeightFail",
connIDs: []string{connID},
extraParams: "ActPl_1;Action_1;*asap;BadString;",
expectedErr: `strconv.ParseFloat: parsing "BadString": invalid syntax`,
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
action := &Action{ExtraParameters: tc.extraParams}
ev := &utils.CGREvent{
Tenant: "cgrates.org",
ID: "evID",
Time: &time.Time{},
Event: map[string]any{
utils.AccountField: "1001",
},
}
t.Cleanup(func() {
ap = nil
})
err := dynamicActionPlan(nil, action, nil, nil, ev,
SharedActionsData{}, ActionConnCfg{
ConnIDs: tc.connIDs,
})
if tc.expectedErr != "" {
if err == nil || err.Error() != tc.expectedErr {
t.Errorf("expected error <%v>, received <%v>", tc.expectedErr, err)
}
} else if err != nil {
t.Error(err)
} else if utils.ToJSON(ap) != utils.ToJSON(tc.expAp) {
t.Errorf("Expected <%v>\nReceived\n<%v>", utils.ToJSON(tc.expAp), utils.ToJSON(ap))
}
})
}
}
func TestDynamicActionAll(t *testing.T) {
tempConn := connMgr
tmpDm := dm
tmpCache := Cache
defer func() {
config.SetCgrConfig(config.NewDefaultCGRConfig())
SetConnManager(tempConn)
dm = tmpDm
Cache = tmpCache
}()
Cache.Clear(nil)
var a *utils.AttrSetActions
ccMock := &ccMock{
calls: map[string]func(ctx *context.Context, args any, reply any) error{
utils.APIerSv2SetActions: func(ctx *context.Context, args, reply any) error {
var canCast bool
if a, canCast = args.(*utils.AttrSetActions); !canCast {
return fmt.Errorf("couldnt cast")
}
return nil
},
},
}
connID := utils.ConcatenatedKey(utils.MetaInternal, utils.MetaApier)
clientconn := make(chan birpc.ClientConnector, 1)
clientconn <- ccMock
NewConnManager(config.NewDefaultCGRConfig(), map[string]chan birpc.ClientConnector{
connID: clientconn,
})
testcases := []struct {
name string
extraParams string
connIDs []string
expA *utils.AttrSetActions
expectedErr string
}{
{
name: "SuccessfulRequest",
connIDs: []string{connID},
expA: &utils.AttrSetActions{
ActionsId: "Alter_Session_10",
Actions: []*utils.TPAction{
{
Identifier: utils.MetaAlterSessions,
ExtraParameters: "cgrates.org;*string:~*req.Account:1001;1;*radCoATemplate:mycoa;CustomFilter:mycustomvalue",
Filters: "*string:~*req.Account:1001;filter2",
BalanceId: "badID",
BalanceType: utils.MetaMonetary,
Categories: "call;data",
DestinationIds: "1002;1003",
RatingSubject: "SPECIAL_1002",
SharedGroups: "SHARED_A;SHARED_B",
ExpiryTime: "*unlimited",
TimingTags: "weekdays;offpeak",
Units: "10",
BalanceWeight: "10",
BalanceBlocker: "true",
BalanceDisabled: "true",
Weight: 10,
},
},
Overwrite: false,
},
extraParams: "Alter_Session_10;*alter_sessions;\fcgrates.org;*string:~*req.Account:1001;1;*radCoATemplate:mycoa;CustomFilter:mycustomvalue\f;*string:~*req.Account:1001&filter2;badID;*monetary;call&data;1002&1003;SPECIAL_1002;SHARED_A&SHARED_B;*unlimited;weekdays&offpeak;10;10;true;true;10",
},
{
name: "SuccessfulRequestWithDynamicPaths",
connIDs: []string{connID},
expA: &utils.AttrSetActions{
ActionsId: "CDR_Log_1001",
Actions: []*utils.TPAction{
{
Identifier: utils.CDRLog,
ExtraParameters: "{\"Account\":\"1001\",\"RequestType\":\"*pseudoprepaid\",\"Subject\":\"DifferentThanAccount\", \"ToR\":\"~ActionType:s/^\\*(.*)$/did_$1/\"}",
Filters: "*string:~*req.Account:1001;filter2",
BalanceId: "badID",
BalanceType: utils.MetaMonetary,
Categories: "call;data",
DestinationIds: "1002;1003",
RatingSubject: "SPECIAL_1002",
SharedGroups: "SHARED_A;SHARED_B",
ExpiryTime: "*unlimited",
TimingTags: "weekdays;offpeak",
Units: "10",
BalanceWeight: "10",
BalanceBlocker: "true",
BalanceDisabled: "true",
Weight: 10,
},
},
Overwrite: false,
},
extraParams: "CDR_Log_<~*req.Account>;*cdrlog;\f{\"Account\":\"<~*req.Account>\",\"RequestType\":\"*pseudoprepaid\",\"Subject\":\"DifferentThanAccount\", \"ToR\":\"~ActionType:s/^\\*(.*)$/did_$1/\"}\f;*string:~*req.Account:<~*req.Account>&filter2;badID;*monetary;call&data;1002&1003;SPECIAL_1002;SHARED_A&SHARED_B;*unlimited;weekdays&offpeak;10;10;true;true;10",
},
{
name: "SuccessfulRequestEmptyFields",
connIDs: []string{connID},
expA: &utils.AttrSetActions{
ActionsId: "DISABLE_ACC",
Actions: []*utils.TPAction{
{
Identifier: utils.MetaDisableAccount,
},
},
},
extraParams: "DISABLE_ACC;*disable_account;;;;;;;;;;;;;;;",
},
{
name: "MissingConns",
extraParams: "TOPUP_MONETARY_10;*topup;;*string:~*req.Account:1001&filter2;badID;*monetary;call&data;1002&1003;SPECIAL_1002;SHARED_A&SHARED_B;*unlimited;weekdays&offpeak;10;10;true;true;10",
expectedErr: "MANDATORY_IE_MISSING: [connIDs]",
},
{
name: "WrongNumberOfParams",
extraParams: "TOPUP_MONETARY_10;*topup;;*string:~*req.Account:1001&filter2;badID;*monetary;call&data;1002&1003;SPECIAL_1002;SHARED_A&SHARED_B;*unlimited;weekdays&offpeak;10;10;true;true;10;;;",
expectedErr: "invalid number of parameters <20> expected 17",
},
{
name: "ActionIdEmptyFail",
extraParams: "DISABLE_ACC;;;;;;;;;;;;;;;;",
expectedErr: `empty Action for <DISABLE_ACC> dynamic_action`,
},
{
name: "ActionIdEmptyFail",
extraParams: ";;;;;;;;;;;;;;;;",
expectedErr: `empty ActionsId for dynamic_action`,
},
{
name: "WeightFail",
extraParams: "TOPUP_MONETARY_10;*topup;;*string:~*req.Account:1001&filter2;badID;*monetary;call&data;1002&1003;SPECIAL_1002;SHARED_A&SHARED_B;*unlimited;weekdays&offpeak;10;10;true;true;BadString",
expectedErr: `strconv.ParseFloat: parsing "BadString": invalid syntax`,
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
action := &Action{ExtraParameters: tc.extraParams}
ev := &utils.CGREvent{
Tenant: "cgrates.org",
ID: "evID",
Time: &time.Time{},
Event: map[string]any{
utils.AccountField: "1001",
},
}
t.Cleanup(func() {
a = nil
})
err := dynamicAction(nil, action, nil, nil, ev,
SharedActionsData{}, ActionConnCfg{
ConnIDs: tc.connIDs,
})
if tc.expectedErr != "" {
if err == nil || err.Error() != tc.expectedErr {
t.Errorf("expected error <%v>, received <%v>", tc.expectedErr, err)
}
} else if err != nil {
t.Error(err)
} else if utils.ToJSON(a) != utils.ToJSON(tc.expA) {
t.Errorf("Expected <%v>\nReceived\n<%v>", utils.ToJSON(tc.expA), utils.ToJSON(a))
}
})
}
}
func TestDynamicDestination(t *testing.T) {
tempConn := connMgr
tmpDm := dm
tmpCache := Cache
defer func() {
config.SetCgrConfig(config.NewDefaultCGRConfig())
SetConnManager(tempConn)
dm = tmpDm
Cache = tmpCache
}()
Cache.Clear(nil)
var dest *utils.AttrSetDestination
ccMock := &ccMock{
calls: map[string]func(ctx *context.Context, args any, reply any) error{
utils.APIerSv1SetDestination: func(ctx *context.Context, args, reply any) error {
var canCast bool
if dest, canCast = args.(*utils.AttrSetDestination); !canCast {
return fmt.Errorf("couldnt cast")
}
return nil
},
},
}
connID := utils.ConcatenatedKey(utils.MetaInternal, utils.MetaApier)
clientconn := make(chan birpc.ClientConnector, 1)
clientconn <- ccMock
NewConnManager(config.NewDefaultCGRConfig(), map[string]chan birpc.ClientConnector{
connID: clientconn,
})
testcases := []struct {
name string
extraParams string
connIDs []string
expDest *utils.AttrSetDestination
expectedErr string
}{
{
name: "SuccessfulRequest",
connIDs: []string{connID},
expDest: &utils.AttrSetDestination{
Id: "DST_1002&1003",
Prefixes: []string{"1002", "1003"},
Overwrite: false,
},
extraParams: "DST_1002&1003;1002&1003",
},
{
name: "SuccessfulRequestWithDynamicPaths",
connIDs: []string{connID},
expDest: &utils.AttrSetDestination{
Id: "DST_1001&1003",
Prefixes: []string{"1001", "1003"},
Overwrite: false,
},
extraParams: "DST_1001&1003;<~*req.Account>&1003",
},
{
name: "SuccessfulRequestEmptyFields",
connIDs: []string{connID},
expDest: &utils.AttrSetDestination{
Id: "DST_Any",
Overwrite: false,
},
extraParams: "DST_Any;",
},
{
name: "MissingConns",
extraParams: "DST_1002&1003;1002&1003",
expectedErr: "MANDATORY_IE_MISSING: [connIDs]",
},
{
name: "WrongNumberOfParams",
extraParams: "DST_1002&1003;1002&1003;;;",
expectedErr: "invalid number of parameters <5> expected 2",
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
action := &Action{ExtraParameters: tc.extraParams}
ev := &utils.CGREvent{
Tenant: "cgrates.org",
ID: "evID",
Time: &time.Time{},
Event: map[string]any{
utils.AccountField: "1001",
},
}
t.Cleanup(func() {
dest = nil
})
err := dynamicDestination(nil, action, nil, nil, ev,
SharedActionsData{}, ActionConnCfg{
ConnIDs: tc.connIDs,
})
if tc.expectedErr != "" {
if err == nil || err.Error() != tc.expectedErr {
t.Errorf("expected error <%v>, received <%v>", tc.expectedErr, err)
}
} else if err != nil {
t.Error(err)
} else if utils.ToJSON(dest) != utils.ToJSON(tc.expDest) {
t.Errorf("Expected <%v>\nReceived\n<%v>", utils.ToJSON(tc.expDest), utils.ToJSON(dest))
}
})
}
}