mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
3274 lines
103 KiB
Go
3274 lines
103 KiB
Go
/*
|
|
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 Affero 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 Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>
|
|
*/
|
|
|
|
package engine
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/cgrates/birpc/context"
|
|
"github.com/cgrates/cgrates/config"
|
|
"github.com/cgrates/cgrates/utils"
|
|
"github.com/ericlagergren/decimal"
|
|
)
|
|
|
|
func TestLibFiltersGetFloat64OptsReturnConfigOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicFloat64Opt{
|
|
// tenant will not be recognized, will ignore this opt
|
|
config.NewDynamicFloat64Opt([]string{"*string:~*req.Account:1001"}, "cgrates.net", 3, nil),
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicFloat64Opt([]string{"*string:~*req.Account:1002"}, "cgrates.org", 4, nil),
|
|
config.NewDynamicFloat64Opt([]string{"*string:~*req.Account:1001"}, "cgrates.org", 5, nil),
|
|
}
|
|
|
|
expected := 5.
|
|
if rcv, err := GetFloat64Opts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsResourcesUnits); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetFloat64OptsFilterCheckErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicFloat64Opt{
|
|
// function will return error after trying to parse the filter
|
|
|
|
config.NewDynamicFloat64Opt([]string{"*string.invalid:filter"}, "cgrates.org", 4, nil),
|
|
}
|
|
|
|
experr := `inline parse error for string: <*string.invalid:filter>`
|
|
if _, err := GetFloat64Opts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsResourcesUnits); err == nil ||
|
|
err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetFloat64OptsReturnDefaultOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicFloat64Opt{
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicFloat64Opt([]string{"*string:~*req.Account:1002"}, "cgrates.org", 4, nil),
|
|
config.NewDynamicFloat64Opt(nil, utils.EmptyString, config.ResourcesUnitsDftOpt, nil),
|
|
}
|
|
|
|
if rcv, err := GetFloat64Opts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsResourcesUnits); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.ResourcesUnitsDftOpt {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", config.ResourcesUnitsDftOpt, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetFloat64OptsReturnOptFromAPIOpts(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.OptsResourcesUnits: 6,
|
|
},
|
|
}
|
|
dynOpts := []*config.DynamicFloat64Opt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicFloat64Opt([]string{"*string:~*req.Account:1001"}, "cgrates.org", 5, nil),
|
|
}
|
|
|
|
expected := 6.
|
|
if rcv, err := GetFloat64Opts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
"nonExistingAPIOpt", utils.OptsResourcesUnits); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetStringOptsReturnConfigOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicStringOpt{
|
|
// tenant will not be recognized, will ignore this opt
|
|
|
|
config.NewDynamicStringOpt([]string{"*string:~*req.Account:1001"}, "cgrates.net", "value1", nil),
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicStringOpt([]string{"*string:~*req.Account:1002"}, "cgrates.net", "value2", nil),
|
|
config.NewDynamicStringOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", "value3", nil),
|
|
}
|
|
|
|
expected := "value3"
|
|
if rcv, err := GetStringOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
config.ResourcesUsageIDDftOpt, utils.OptsResourcesUsageID); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetStringOptsFilterCheckErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicStringOpt{
|
|
// function will return error after trying to parse the filter
|
|
config.NewDynamicStringOpt([]string{"*string.invalid:filter"}, "cgrates.org", "value2", nil),
|
|
}
|
|
|
|
experr := `inline parse error for string: <*string.invalid:filter>`
|
|
if _, err := GetStringOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
config.ResourcesUsageIDDftOpt, utils.OptsResourcesUsageID); err == nil ||
|
|
err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetStringOptsReturnDefaultOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicStringOpt{
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicStringOpt([]string{"*string:~*req.Account:1002"}, "cgrates.org", "value2", nil),
|
|
}
|
|
|
|
if rcv, err := GetStringOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
config.ResourcesUsageIDDftOpt, utils.OptsResourcesUsageID); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.ResourcesUsageIDDftOpt {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", config.ResourcesUsageIDDftOpt, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetStringOptsReturnOptFromAPIOpts(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.OptsResourcesUsageID: "value4",
|
|
},
|
|
}
|
|
dynOpts := []*config.DynamicStringOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicStringOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", "value3", nil),
|
|
}
|
|
|
|
expected := "value4"
|
|
if rcv, err := GetStringOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
config.ResourcesUsageIDDftOpt, "nonExistingAPIOpt", utils.OptsResourcesUsageID); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationOptsReturnConfigOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicDurationOpt{
|
|
// tenant will not be recognized, will ignore this opt
|
|
config.NewDynamicDurationOpt([]string{"*string:~*req.Account:1001"}, "cgrates.net", time.Millisecond, nil),
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicDurationOpt([]string{"*string:~*req.Account:1002"}, "cgrates.net", time.Second, nil),
|
|
config.NewDynamicDurationOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", time.Minute, nil),
|
|
}
|
|
|
|
expected := time.Minute
|
|
if rcv, err := GetDurationOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsResourcesUsageTTL); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationOptsFilterCheckErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicDurationOpt{
|
|
// function will return error after trying to parse the filter
|
|
config.NewDynamicDurationOpt([]string{"*string.invalid:filter"}, "cgrates.org", time.Second, nil),
|
|
}
|
|
|
|
experr := `inline parse error for string: <*string.invalid:filter>`
|
|
if _, err := GetDurationOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsResourcesUsageTTL); err == nil ||
|
|
err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationOptsReturnDefaultOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicDurationOpt{
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicDurationOpt([]string{"*string:~*req.Account:1002"}, "cgrates.org", time.Second, nil),
|
|
config.NewDynamicDurationOpt(nil, "", config.ResourcesUsageTTLDftOpt, nil),
|
|
}
|
|
|
|
if rcv, err := GetDurationOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsResourcesUsageTTL); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.ResourcesUsageTTLDftOpt {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", config.ResourcesUsageTTLDftOpt, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationPointerOptsReturnOptFromAPIOpts(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.OptsResourcesUsageTTL: time.Hour,
|
|
},
|
|
}
|
|
dynOpts := []*config.DynamicDurationPointerOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicDurationPointerOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", utils.DurationPointer(time.Minute), nil),
|
|
}
|
|
|
|
expected := time.Hour
|
|
if rcv, err := GetDurationPointerOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
"nonExistingAPIOpt", utils.OptsResourcesUsageTTL); err != nil {
|
|
t.Error(err)
|
|
} else if *rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
func TestLibFiltersGetDurationPointerOptsReturnConfigOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicDurationPointerOpt{
|
|
// tenant will not be recognized, will ignore this opt
|
|
config.NewDynamicDurationPointerOpt([]string{"*string:~*req.Account:1001"}, "cgrates.net", utils.DurationPointer(time.Millisecond), nil),
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicDurationPointerOpt([]string{"*string:~*req.Account:1002"}, "cgrates.net", utils.DurationPointer(time.Second), nil),
|
|
config.NewDynamicDurationPointerOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", utils.DurationPointer(time.Minute), nil),
|
|
}
|
|
|
|
expected := time.Minute
|
|
if rcv, err := GetDurationPointerOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsResourcesUsageTTL); err != nil {
|
|
t.Error(err)
|
|
} else if *rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationPointerOptsFilterCheckErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicDurationPointerOpt{
|
|
// function will return error after trying to parse the filter
|
|
config.NewDynamicDurationPointerOpt([]string{"*string.invalid:filter"}, "cgrates.org", utils.DurationPointer(time.Second), nil),
|
|
}
|
|
|
|
experr := `inline parse error for string: <*string.invalid:filter>`
|
|
if _, err := GetDurationPointerOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsResourcesUsageTTL); err == nil ||
|
|
err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationPointerOptsReturnDefaultOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicDurationPointerOpt{
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicDurationPointerOpt([]string{"*string:~*req.Account:1002"}, "cgrates.org", utils.DurationPointer(time.Second), nil),
|
|
config.NewDynamicDurationPointerOpt(nil, "", utils.DurationPointer(config.ResourcesUsageTTLDftOpt), nil),
|
|
}
|
|
|
|
if rcv, err := GetDurationPointerOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsResourcesUsageTTL); err != nil {
|
|
t.Error(err)
|
|
} else if *rcv != config.ResourcesUsageTTLDftOpt {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", config.ResourcesUsageTTLDftOpt, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationOptsReturnOptFromAPIOpts(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.OptsResourcesUsageTTL: time.Hour,
|
|
},
|
|
}
|
|
dynOpts := []*config.DynamicDurationOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicDurationOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", time.Minute, nil),
|
|
}
|
|
|
|
expected := time.Hour
|
|
if rcv, err := GetDurationOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
"nonExistingAPIOpt", utils.OptsResourcesUsageTTL); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetIntOptsReturnConfigOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicIntOpt{
|
|
// tenant will not be recognized, will ignore this opt
|
|
config.NewDynamicIntOpt([]string{"*string:~*req.Account:1002"}, "cgrates.net", 3, nil),
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicIntOpt([]string{"*string:~*req.Account:1002"}, "cgrates.org", 4, nil),
|
|
config.NewDynamicIntOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", 5, nil),
|
|
}
|
|
|
|
expected := 5
|
|
if rcv, err := GetIntOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsAttributesProcessRuns); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetIntOptsFilterCheckErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicIntOpt{
|
|
// function will return error after trying to parse the filter
|
|
config.NewDynamicIntOpt([]string{"*string.invalid:filter"}, "cgrates.org", 4, nil),
|
|
}
|
|
|
|
experr := `inline parse error for string: <*string.invalid:filter>`
|
|
if _, err := GetIntOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsAttributesProcessRuns); err == nil ||
|
|
err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetIntOptsReturnDefaultOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicIntOpt{
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicIntOpt([]string{"*string:~*req.Account:1002"}, "cgrates.org", 4, nil),
|
|
config.NewDynamicIntOpt(nil, utils.EmptyString, config.AttributesProcessRunsDftOpt, nil),
|
|
}
|
|
|
|
if rcv, err := GetIntOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsAttributesProcessRuns); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.AttributesProcessRunsDftOpt {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", config.AttributesProcessRunsDftOpt, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetIntOptsReturnOptFromAPIOptsOK(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.OptsAttributesProcessRuns: 6,
|
|
},
|
|
}
|
|
dynOpts := []*config.DynamicIntOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicIntOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", 5, nil),
|
|
}
|
|
|
|
expected := 6
|
|
if rcv, err := GetIntOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
"nonExistingAPIOpt", utils.OptsAttributesProcessRuns); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetIntOptsReturnOptFromAPIOptsErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.OptsAttributesProcessRuns: true,
|
|
},
|
|
}
|
|
dynOpts := []*config.DynamicIntOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicIntOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", 5, nil),
|
|
}
|
|
|
|
experr := `cannot convert field<bool>: true to int`
|
|
if _, err := GetIntOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
"nonExistingAPIOpt", utils.OptsAttributesProcessRuns); err == nil || err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetTimeOptsReturnConfigOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicStringOpt{
|
|
// tenant will not be recognized, will ignore this opt
|
|
config.NewDynamicStringOpt([]string{"*string:~*req.Account:1001"}, "cgrates.net", "2022-03-07T15:04:05", nil),
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicStringOpt([]string{"*string:~*req.Account:1002"}, "cgrates.org", "*daily", nil),
|
|
config.NewDynamicStringOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", "*monthly", nil),
|
|
}
|
|
|
|
expected := time.Now().AddDate(0, 1, 0)
|
|
if rcv, err := GetTimeOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
cfg.GeneralCfg().DefaultTimezone, config.RatesStartTimeDftOpt, utils.OptsRatesStartTime); err != nil {
|
|
t.Error(err)
|
|
} else if !dateEqual(rcv, expected) {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetTimeOptsFilterCheckErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicStringOpt{
|
|
// function will return error after trying to parse the filter
|
|
config.NewDynamicStringOpt([]string{"*string.invalid:filter"}, "cgrates.org", "*daily", nil),
|
|
}
|
|
|
|
experr := `inline parse error for string: <*string.invalid:filter>`
|
|
if _, err := GetTimeOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
cfg.GeneralCfg().DefaultTimezone, config.RatesStartTimeDftOpt, utils.OptsRatesStartTime); err == nil ||
|
|
err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetTimeOptsReturnDefaultOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
expected, err := utils.ParseTimeDetectLayout(config.RatesStartTimeDftOpt, cfg.GeneralCfg().DefaultTimezone)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
dynOpts := []*config.DynamicStringOpt{
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicStringOpt([]string{"*string:~*req.Account:1002"}, "cgrates.org", "*daily", nil),
|
|
config.NewDynamicStringOpt(nil, "", config.RatesStartTimeDftOpt, nil),
|
|
}
|
|
|
|
if rcv, err := GetTimeOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
cfg.GeneralCfg().DefaultTimezone, config.RatesStartTimeDftOpt, utils.OptsRatesStartTime); err != nil {
|
|
t.Error(err)
|
|
} else if !dateEqual(rcv, expected) {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetTimeOptsReturnOptFromAPIOpts(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.OptsRatesStartTime: "*yearly",
|
|
},
|
|
}
|
|
dynOpts := []*config.DynamicStringOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicStringOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", "*monthly", nil),
|
|
}
|
|
|
|
expected := time.Now().AddDate(1, 0, 0)
|
|
if rcv, err := GetTimeOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
cfg.GeneralCfg().DefaultTimezone, config.RatesStartTimeDftOpt, "nonExistingAPIOpt", utils.OptsRatesStartTime); err != nil {
|
|
t.Error(err)
|
|
} else if !dateEqual(rcv, expected) {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func dateEqual(date1, date2 time.Time) bool {
|
|
y1, m1, d1 := date1.Date()
|
|
y2, m2, d2 := date2.Date()
|
|
return y1 == y2 && m1 == m2 && d1 == d2
|
|
}
|
|
|
|
func TestLibFiltersGetBoolOptsReturnConfigOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicBoolOpt{
|
|
// tenant will not be recognized, will ignore this opt
|
|
config.NewDynamicBoolOpt([]string{"*string:~*req.Account:1001"}, "cgrates.net", false, nil),
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicBoolOpt([]string{"*string:~*req.Account:1002"}, "cgrates.org", false, nil),
|
|
config.NewDynamicBoolOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", true, nil),
|
|
}
|
|
|
|
expected := true
|
|
if rcv, err := GetBoolOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.MetaProfileIgnoreFilters); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetBoolOptsFilterCheckErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicBoolOpt{
|
|
// function will return error after trying to parse the filter
|
|
config.NewDynamicBoolOpt([]string{"*string.invalid:filter"}, "cgrates.org", false, nil),
|
|
}
|
|
|
|
experr := `inline parse error for string: <*string.invalid:filter>`
|
|
if _, err := GetBoolOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.MetaProfileIgnoreFilters); err == nil ||
|
|
err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetBoolOptsReturnDefaultOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicBoolOpt{
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicBoolOpt([]string{"*string:~*req.Account:1002"}, "cgrates.org", true, nil),
|
|
}
|
|
|
|
if rcv, err := GetBoolOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.MetaProfileIgnoreFilters); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.ThresholdsProfileIgnoreFiltersDftOpt {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", config.ThresholdsProfileIgnoreFiltersDftOpt, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetBoolOptsReturnOptFromAPIOpts(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.MetaProfileIgnoreFilters: true,
|
|
},
|
|
}
|
|
dynOpts := []*config.DynamicBoolOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicBoolOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", false, nil),
|
|
}
|
|
|
|
expected := true
|
|
if rcv, err := GetBoolOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
"nonExistingAPIOpt", utils.MetaProfileIgnoreFilters); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetInterfaceOptsReturnConfigOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicInterfaceOpt{
|
|
// tenant will not be recognized, will ignore this opt
|
|
{
|
|
FilterIDs: []string{"*string:~*req.Account:1001"},
|
|
Tenant: "cgrates.net",
|
|
Value: 1,
|
|
},
|
|
// filter will not pass, will ignore this opt
|
|
{
|
|
FilterIDs: []string{"*string:~*req.Account:1002"},
|
|
Tenant: "cgrates.org",
|
|
Value: "value2",
|
|
},
|
|
{
|
|
FilterIDs: []string{"*string:~*req.Account:1001"},
|
|
Tenant: "cgrates.org",
|
|
Value: "value3",
|
|
},
|
|
}
|
|
|
|
expected := "value3"
|
|
if rcv, err := GetInterfaceOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
config.RoutesMaxCostDftOpt, utils.OptsRoutesMaxCost); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetInterfaceOptsFilterCheckErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicInterfaceOpt{
|
|
// function will return error after trying to parse the filter
|
|
{
|
|
FilterIDs: []string{"*string.invalid:filter"},
|
|
Tenant: "cgrates.org",
|
|
Value: 2,
|
|
},
|
|
}
|
|
|
|
experr := `inline parse error for string: <*string.invalid:filter>`
|
|
if _, err := GetInterfaceOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
config.RoutesMaxCostDftOpt, utils.OptsRoutesMaxCost); err == nil ||
|
|
err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetInterfaceOptsReturnDefaultOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicInterfaceOpt{
|
|
// filter will not pass, will ignore this opt
|
|
{
|
|
FilterIDs: []string{"*string:~*req.Account:1002"},
|
|
Tenant: "cgrates.org",
|
|
Value: 2,
|
|
},
|
|
{
|
|
Value: config.RoutesMaxCostDftOpt,
|
|
},
|
|
}
|
|
|
|
if rcv, err := GetInterfaceOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsRoutesMaxCost); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.RoutesMaxCostDftOpt {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", utils.ToJSON(config.RoutesMaxCostDftOpt), rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetInterfaceOptsReturnOptFromAPIOpts(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.OptsRoutesMaxCost: 4,
|
|
},
|
|
}
|
|
dynOpts := []*config.DynamicInterfaceOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
{
|
|
FilterIDs: []string{"*string:~*req.Account:1001"},
|
|
Tenant: "cgrates.org",
|
|
Value: "value3",
|
|
},
|
|
}
|
|
|
|
expected := 4
|
|
if rcv, err := GetInterfaceOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
config.RoutesMaxCostDftOpt, "nonExistingAPIOpt", utils.OptsRoutesMaxCost); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetStringSliceOptsReturnConfigOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicStringSliceOpt{
|
|
// tenant will not be recognized, will ignore this opt
|
|
{
|
|
FilterIDs: []string{"*string:~*req.Account:1001"},
|
|
Tenant: "cgrates.net",
|
|
Values: []string{"value1"},
|
|
},
|
|
// filter will not pass, will ignore this opt
|
|
{
|
|
FilterIDs: []string{"*string:~*req.Account:1002"},
|
|
Tenant: "cgrates.org",
|
|
Values: []string{"value2"},
|
|
},
|
|
{
|
|
FilterIDs: []string{"*string:~*req.Account:1001"},
|
|
Tenant: "cgrates.org",
|
|
Values: []string{"value3"},
|
|
},
|
|
}
|
|
|
|
expected := []string{"value3"}
|
|
if rcv, err := GetStringSliceOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
config.AttributesProfileIDsDftOpt, utils.OptsAttributesProfileIDs); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(rcv, expected) {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetStringSliceOptsFilterCheckErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicStringSliceOpt{
|
|
// function will return error after trying to parse the filter
|
|
{
|
|
FilterIDs: []string{"*string.invalid:filter"},
|
|
Tenant: "cgrates.org",
|
|
Values: []string{"value2"},
|
|
},
|
|
}
|
|
|
|
experr := `inline parse error for string: <*string.invalid:filter>`
|
|
if _, err := GetStringSliceOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
config.AttributesProfileIDsDftOpt, utils.OptsAttributesProfileIDs); err == nil ||
|
|
err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetStringSliceOptsReturnDefaultOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicStringSliceOpt{
|
|
// filter will not pass, will ignore this opt
|
|
{
|
|
FilterIDs: []string{"*string:~*req.Account:1002"},
|
|
Tenant: "cgrates.org",
|
|
Values: []string{"value2"},
|
|
},
|
|
}
|
|
|
|
if rcv, err := GetStringSliceOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
config.AttributesProfileIDsDftOpt, utils.OptsAttributesProfileIDs); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(rcv, config.AttributesProfileIDsDftOpt) {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", config.AttributesProfileIDsDftOpt, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetStringSliceOptsReturnOptFromAPIOpts(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.OptsAttributesProfileIDs: []string{"value4"},
|
|
},
|
|
}
|
|
dynOpts := []*config.DynamicStringSliceOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
{
|
|
FilterIDs: []string{"*string:~*req.Account:1001"},
|
|
Tenant: "cgrates.org",
|
|
Values: []string{"value3"},
|
|
},
|
|
}
|
|
|
|
expected := []string{"value4"}
|
|
if rcv, err := GetStringSliceOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
config.AttributesProfileIDsDftOpt, "nonExistingAPIOpt", utils.OptsAttributesProfileIDs); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(rcv, expected) {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDecimalBigOptsReturnConfigOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
strOpts := []*config.DynamicInterfaceOpt{
|
|
{
|
|
FilterIDs: []string{"*string:~*req.Account:1001"},
|
|
Tenant: "cgrates.net",
|
|
Value: "42",
|
|
},
|
|
// filter will not pass, will ignore this opt
|
|
{
|
|
FilterIDs: []string{"*string:~*req.Account:1002"},
|
|
Tenant: "cgrates.org",
|
|
Value: "-1",
|
|
},
|
|
{
|
|
FilterIDs: []string{"*string:~*req.Account:1001"},
|
|
Tenant: "cgrates.org",
|
|
Value: "1234",
|
|
},
|
|
}
|
|
dynOpts, _ := config.IfaceToDecimalBigDynamicOpts(strOpts)
|
|
|
|
expected := decimal.New(1234, 0)
|
|
if rcv, err := GetDecimalBigOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsRatesUsage); err != nil {
|
|
t.Error(err)
|
|
} else if rcv.Cmp(expected) != 0 {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestDynamicDecimalBigOptsDynVal(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
dynOpts []*config.DynamicInterfaceOpt
|
|
expVal int64
|
|
expErr error
|
|
}{
|
|
{
|
|
name: "DynOptsVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*opts.*usage",
|
|
},
|
|
},
|
|
expVal: int64(time.Second * 27),
|
|
},
|
|
{
|
|
name: "DynReqVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.Usage",
|
|
},
|
|
},
|
|
expVal: int64(time.Second * 12),
|
|
},
|
|
{
|
|
name: "StaticVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: 4334,
|
|
},
|
|
},
|
|
expVal: 4334,
|
|
},
|
|
{
|
|
name: "NotFound",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.RandomField",
|
|
},
|
|
},
|
|
expErr: utils.ErrNotFound,
|
|
},
|
|
{
|
|
name: "ValueNotConvertedCorrectly",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.Usage2",
|
|
},
|
|
},
|
|
expErr: fmt.Errorf("can't convert <twenty-five> to decimal"),
|
|
},
|
|
}
|
|
|
|
ev := &utils.CGREvent{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "testIDEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: "1001",
|
|
utils.Usage: "12s",
|
|
"Usage2": "twenty-five",
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.MetaUsage: "27s",
|
|
},
|
|
}
|
|
fs := NewFilterS(config.CgrConfig(), nil, nil)
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
dynOpts, err := config.IfaceToDecimalBigDynamicOpts(tt.dynOpts)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
out, err := GetDecimalBigOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fs, dynOpts, utils.OptsRatesUsage)
|
|
if tt.expErr != nil {
|
|
if err == nil {
|
|
t.Error("expected err,received nil")
|
|
}
|
|
if err.Error() != tt.expErr.Error() {
|
|
t.Errorf("expected error %v,received %v", tt.expErr, err)
|
|
}
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Errorf("unexpected err %v", err)
|
|
}
|
|
val, _ := out.Int64()
|
|
if tt.expVal != val {
|
|
t.Errorf("expected %d,received %d", tt.expVal, val)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
func TestDynamicIntOptsDynVal(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
dynOpts []*config.DynamicInterfaceOpt
|
|
expVal int
|
|
expErr error
|
|
}{
|
|
{
|
|
name: "DynOptsVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*opts.*destination",
|
|
},
|
|
},
|
|
expVal: 6548454,
|
|
},
|
|
{
|
|
name: "DynReqVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.Destination",
|
|
},
|
|
},
|
|
expVal: 34534353,
|
|
},
|
|
{
|
|
name: "StaticVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: 5346633,
|
|
},
|
|
},
|
|
expVal: 5346633,
|
|
},
|
|
{
|
|
name: "NotFound",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.RandomField",
|
|
},
|
|
},
|
|
expErr: utils.ErrNotFound,
|
|
},
|
|
{
|
|
name: "ValueNotConvertedCorrectly",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.Usage2",
|
|
},
|
|
},
|
|
expErr: fmt.Errorf("strconv.Atoi: parsing \"twenty-five\": invalid syntax"),
|
|
},
|
|
}
|
|
|
|
ev := &utils.CGREvent{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "testIDEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: "1001",
|
|
utils.Destination: 34534353,
|
|
"Usage2": "twenty-five",
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.MetaDestination: 6548454,
|
|
},
|
|
}
|
|
fs := NewFilterS(config.CgrConfig(), nil, nil)
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
dynOpts, err := config.IfaceToIntDynamicOpts(tt.dynOpts)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
out, err := GetIntOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fs, dynOpts, utils.OptsRatesUsage)
|
|
if tt.expErr != nil {
|
|
if err == nil {
|
|
t.Error("expected err,received nil")
|
|
}
|
|
if err.Error() != tt.expErr.Error() {
|
|
t.Errorf("expected error %v,received %v", tt.expErr, err)
|
|
}
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Errorf("unexpected err %v", err)
|
|
}
|
|
if tt.expVal != out {
|
|
t.Errorf("expected %d,received %d", tt.expVal, out)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDynamicFloat64OptsDynVal(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
dynOpts []*config.DynamicInterfaceOpt
|
|
expVal float64
|
|
expErr error
|
|
}{
|
|
{
|
|
name: "DynOptsVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*opts.*acc",
|
|
},
|
|
},
|
|
expVal: 3434,
|
|
},
|
|
{
|
|
name: "DynReqVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.*acd",
|
|
},
|
|
},
|
|
expVal: 2213.,
|
|
},
|
|
{
|
|
name: "StaticVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: 23.1,
|
|
},
|
|
},
|
|
expVal: 23.1,
|
|
},
|
|
{
|
|
name: "NotFound",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.RandomField",
|
|
},
|
|
},
|
|
expErr: utils.ErrNotFound,
|
|
},
|
|
{
|
|
name: "ValueNotConvertedCorrectly",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.Usage2",
|
|
},
|
|
},
|
|
expErr: fmt.Errorf("strconv.ParseFloat: parsing \"twenty-five\": invalid syntax"),
|
|
},
|
|
}
|
|
|
|
ev := &utils.CGREvent{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "testIDEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: "1001",
|
|
"*acd": 2213,
|
|
"Usage2": "twenty-five",
|
|
},
|
|
APIOpts: map[string]any{
|
|
"*acc": 3434,
|
|
},
|
|
}
|
|
fs := NewFilterS(config.CgrConfig(), nil, nil)
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
dynOpts, err := config.InterfaceToFloat64DynamicOpts(tt.dynOpts)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
out, err := GetFloat64Opts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fs, dynOpts, utils.OptsRatesUsage)
|
|
if tt.expErr != nil {
|
|
if err == nil {
|
|
t.Error("expected err,received nil")
|
|
}
|
|
if err.Error() != tt.expErr.Error() {
|
|
t.Errorf("expected error %v,received %v", tt.expErr, err)
|
|
}
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Errorf("unexpected err %v", err)
|
|
}
|
|
if tt.expVal != out {
|
|
t.Errorf("expected %f,received %f", tt.expVal, out)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDynamicBoolOptsDynVal(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
dynOpts []*config.DynamicInterfaceOpt
|
|
expVal bool
|
|
expErr error
|
|
}{
|
|
{
|
|
name: "DynOptsVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*opts.Field2",
|
|
},
|
|
},
|
|
expVal: true,
|
|
},
|
|
{
|
|
name: "DynReqVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.Field1",
|
|
},
|
|
},
|
|
expVal: false,
|
|
},
|
|
{
|
|
name: "StaticVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: true,
|
|
},
|
|
},
|
|
expVal: true,
|
|
},
|
|
{
|
|
name: "NotFound",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.RandomField",
|
|
},
|
|
},
|
|
expErr: utils.ErrNotFound,
|
|
},
|
|
{
|
|
name: "ValueNotConvertedCorrectly",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.Usage2",
|
|
},
|
|
},
|
|
expErr: fmt.Errorf("strconv.ParseBool: parsing \"twenty-five\": invalid syntax"),
|
|
},
|
|
}
|
|
|
|
ev := &utils.CGREvent{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "testIDEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: "1001",
|
|
"Field1": false,
|
|
"Usage2": "twenty-five",
|
|
},
|
|
APIOpts: map[string]any{
|
|
"Field2": true,
|
|
},
|
|
}
|
|
fs := NewFilterS(config.CgrConfig(), nil, nil)
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
dynOpts, err := config.IfaceToBoolDynamicOpts(tt.dynOpts)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
out, err := GetBoolOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fs, dynOpts, utils.OptsRatesUsage)
|
|
if tt.expErr != nil {
|
|
if err == nil {
|
|
t.Error("expected err,received nil")
|
|
}
|
|
if err.Error() != tt.expErr.Error() {
|
|
t.Errorf("expected error %v,received %v", tt.expErr, err)
|
|
}
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Errorf("unexpected err %v", err)
|
|
}
|
|
if tt.expVal != out {
|
|
t.Errorf("expected %v,received %v", tt.expVal, out)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDynamicDurationOptsDynVal(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
dynOpts []*config.DynamicInterfaceOpt
|
|
expVal time.Duration
|
|
expErr error
|
|
}{
|
|
{
|
|
name: "DynOptsVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*opts.Usage",
|
|
},
|
|
},
|
|
expVal: time.Second * 10,
|
|
},
|
|
{
|
|
name: "DynReqVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.*acd",
|
|
},
|
|
},
|
|
expVal: 3500000,
|
|
},
|
|
{
|
|
name: "StaticVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: 1000000000,
|
|
},
|
|
},
|
|
expVal: 1 * time.Second,
|
|
},
|
|
{
|
|
name: "NotFound",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.RandomField",
|
|
},
|
|
},
|
|
expErr: utils.ErrNotFound,
|
|
},
|
|
{
|
|
name: "ValueNotConvertedCorrectly",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.Usage2",
|
|
},
|
|
},
|
|
expErr: fmt.Errorf("time: invalid duration \"twenty-five\""),
|
|
},
|
|
}
|
|
|
|
ev := &utils.CGREvent{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "testIDEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: "1001",
|
|
"*acd": 3500000,
|
|
"Usage2": "twenty-five",
|
|
},
|
|
APIOpts: map[string]any{
|
|
"Usage": "10s",
|
|
},
|
|
}
|
|
fs := NewFilterS(config.CgrConfig(), nil, nil)
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
dynOpts, err := config.IfaceToDurationDynamicOpts(tt.dynOpts)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
out, err := GetDurationOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fs, dynOpts, utils.OptsRatesUsage)
|
|
if tt.expErr != nil {
|
|
if err == nil {
|
|
t.Error("expected err,received nil")
|
|
}
|
|
if err.Error() != tt.expErr.Error() {
|
|
t.Errorf("expected error %v,received %v", tt.expErr, err)
|
|
}
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Errorf("unexpected err %v", err)
|
|
}
|
|
if tt.expVal != out {
|
|
t.Errorf("expected %v,received %v", tt.expVal, out)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDynamicDurationPointerOptsDynVal(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
dynOpts []*config.DynamicInterfaceOpt
|
|
expVal *time.Duration
|
|
expErr error
|
|
}{
|
|
{
|
|
name: "DynOptsVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*opts.Usage",
|
|
},
|
|
},
|
|
expVal: utils.DurationPointer(time.Second * 10),
|
|
},
|
|
{
|
|
name: "DynReqVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.*acd",
|
|
},
|
|
},
|
|
expVal: utils.DurationPointer(3500000),
|
|
},
|
|
{
|
|
name: "StaticVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: 1000000000,
|
|
},
|
|
},
|
|
expVal: utils.DurationPointer(1 * time.Second),
|
|
},
|
|
{
|
|
name: "NotFound",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.RandomField",
|
|
},
|
|
},
|
|
expErr: utils.ErrNotFound,
|
|
},
|
|
{
|
|
name: "ValueNotConvertedCorrectly",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.Usage2",
|
|
},
|
|
},
|
|
expErr: fmt.Errorf("time: invalid duration \"twenty-five\""),
|
|
},
|
|
}
|
|
|
|
ev := &utils.CGREvent{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "testIDEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: "1001",
|
|
"*acd": 3500000,
|
|
"Usage2": "twenty-five",
|
|
},
|
|
APIOpts: map[string]any{
|
|
"Usage": "10s",
|
|
},
|
|
}
|
|
fs := NewFilterS(config.CgrConfig(), nil, nil)
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
dynOpts, err := config.IfaceToDurationPointerDynamicOpts(tt.dynOpts)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
out, err := GetDurationPointerOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fs, dynOpts, utils.OptsRatesUsage)
|
|
if tt.expErr != nil {
|
|
if err == nil {
|
|
t.Error("expected err,received nil")
|
|
}
|
|
if err.Error() != tt.expErr.Error() {
|
|
t.Errorf("expected error %v,received %v", tt.expErr, err)
|
|
}
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Errorf("unexpected err %v", err)
|
|
}
|
|
if *tt.expVal != *out {
|
|
t.Errorf("expected %v,received %v", tt.expVal, out)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestDynamicStringOptsDynVal(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
dynOpts []*config.DynamicInterfaceOpt
|
|
expVal string
|
|
expErr error
|
|
}{
|
|
{
|
|
name: "DynOptsVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*opts.*context",
|
|
},
|
|
},
|
|
expVal: "chargers",
|
|
},
|
|
{
|
|
name: "DynReqVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "~*req.Supplier",
|
|
},
|
|
},
|
|
expVal: "Supplier1",
|
|
},
|
|
{
|
|
name: "StaticVal",
|
|
dynOpts: []*config.DynamicInterfaceOpt{
|
|
{
|
|
Tenant: "cgrates.org",
|
|
Value: "value",
|
|
},
|
|
},
|
|
expVal: "value",
|
|
},
|
|
}
|
|
|
|
ev := &utils.CGREvent{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "testIDEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: "1001",
|
|
"Supplier": "Supplier1",
|
|
},
|
|
APIOpts: map[string]any{
|
|
"*context": "chargers",
|
|
},
|
|
}
|
|
fs := NewFilterS(config.CgrConfig(), nil, nil)
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
dynOpts, err := config.InterfaceToDynamicStringOpts(tt.dynOpts)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
out, err := GetStringOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fs, dynOpts)
|
|
if tt.expErr != nil {
|
|
if err == nil {
|
|
t.Error("expected err,received nil")
|
|
}
|
|
if err.Error() != tt.expErr.Error() {
|
|
t.Errorf("expected error %v,received %v", tt.expErr, err)
|
|
}
|
|
return
|
|
}
|
|
if err != nil {
|
|
t.Errorf("unexpected err %v", err)
|
|
}
|
|
if tt.expVal != out {
|
|
t.Errorf("expected %v,received %v", tt.expVal, out)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAttrDynamicOptsFromJson(t *testing.T) {
|
|
cfgJSONStr := `{
|
|
"attributes": {
|
|
"enabled": true,
|
|
"stats_conns": ["*internal"],
|
|
"resources_conns": ["*internal"],
|
|
"accounts_conns": ["*internal"],
|
|
"prefix_indexed_fields": ["*req.index1","*req.index2"],
|
|
"string_indexed_fields": ["*req.index1"],
|
|
"exists_indexed_fields": ["*req.index1","*req.index2"],
|
|
"notexists_indexed_fields": ["*req.index1"],
|
|
"opts": {
|
|
"*processRuns": [
|
|
{
|
|
"Value": "~*req.ProcessRuns",
|
|
"FilterIDs": ["*string:~*req.Account:1001"]
|
|
},
|
|
{
|
|
"Value": 11,
|
|
"FilterIDs": ["*string:~*req.Account:1003"]
|
|
},
|
|
],
|
|
"*profileRuns": [
|
|
{
|
|
"FilterIDs": ["*string:~*req.Account:1001"],
|
|
"Value": "~*opts.ProfileRuns"
|
|
}
|
|
],
|
|
"*profileIgnoreFilters": [
|
|
{
|
|
"FilterIDs": ["*string:~*req.Account:1001"],
|
|
"Value": "~*req.IgnoreFilters"
|
|
}
|
|
]
|
|
},
|
|
},
|
|
}`
|
|
|
|
cgrCfg, err := config.NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
ev := &utils.CGREvent{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "testIDEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: "1001",
|
|
"ProcessRuns": 4,
|
|
"IgnoreFilters": true,
|
|
},
|
|
APIOpts: map[string]any{
|
|
"ProfileRuns": 5,
|
|
},
|
|
}
|
|
ev2 := &utils.CGREvent{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "testIDEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: "1002",
|
|
"ProcessRuns": 4,
|
|
"IgnoreFilters": true,
|
|
},
|
|
APIOpts: map[string]any{
|
|
"ProfileRuns": 5,
|
|
},
|
|
}
|
|
ev3 := &utils.CGREvent{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "testIDEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: "1003",
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
fltrs := NewFilterS(cgrCfg, nil, nil)
|
|
if rcv, err := GetIntOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fltrs, cgrCfg.AttributeSCfg().Opts.ProcessRuns); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != 4 {
|
|
t.Errorf("expected %d,received %d", 4, rcv)
|
|
}
|
|
if rcv, err := GetIntOpts(context.Background(), "cgrates.org", ev3.AsDataProvider(), nil, fltrs, cgrCfg.AttributeSCfg().Opts.ProcessRuns); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != 11 {
|
|
t.Errorf("expected %d,received %d", 11, rcv)
|
|
}
|
|
if rcv, err := GetIntOpts(context.Background(), "cgrates.org", ev2.AsDataProvider(), nil, fltrs, cgrCfg.AttributeSCfg().Opts.ProcessRuns); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.AttributesProcessRunsDftOpt {
|
|
t.Errorf("expected %d,received %d", config.AttributesProcessRunsDftOpt, rcv)
|
|
}
|
|
|
|
if rcv, err := GetIntOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fltrs, cgrCfg.AttributeSCfg().Opts.ProfileRuns); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != 5 {
|
|
t.Errorf("expected %d,received %d", 5, rcv)
|
|
}
|
|
if rcv, err := GetIntOpts(context.Background(), "cgrates.org", ev2.AsDataProvider(), nil, fltrs, cgrCfg.AttributeSCfg().Opts.ProfileRuns); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.AttributesProfileRunsDftOpt {
|
|
t.Errorf("expected %d,received %d", config.AttributesProcessRunsDftOpt, rcv)
|
|
}
|
|
|
|
if rcv, err := GetBoolOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fltrs, cgrCfg.AttributeSCfg().Opts.ProfileIgnoreFilters); err != nil {
|
|
t.Error(err)
|
|
} else if !rcv {
|
|
t.Errorf("expected true,received %v", rcv)
|
|
}
|
|
if rcv, err := GetBoolOpts(context.Background(), "cgrates.org", ev2.AsDataProvider(), nil, fltrs, cgrCfg.AttributeSCfg().Opts.ProfileIgnoreFilters); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.AttributesProfileIgnoreFiltersDftOpt {
|
|
t.Errorf("expected %v,received %v", config.AttributesProcessRunsDftOpt, rcv)
|
|
}
|
|
}
|
|
|
|
func TestSessionDynamicOptsFromJson(t *testing.T) {
|
|
cfgJSONStr := `{
|
|
"sessions": {
|
|
"enabled": true,
|
|
"listen_bijson": "127.0.0.1:2018",
|
|
"replication_conns": ["*localhost"],
|
|
"store_session_costs": true,
|
|
"min_dur_low_balance": "1s",
|
|
"client_protocol": 2.0,
|
|
"terminate_attempts": 10,
|
|
"opts": {
|
|
"*accounts": [
|
|
{
|
|
"FilterIDs": ["*string:~*req.Account:1001"],
|
|
"Value": "~*opts.*accounts"
|
|
}
|
|
],
|
|
"*attributes": [
|
|
{
|
|
"FilterIDs": ["*string:~*req.Account:1001"],
|
|
"Value": "~*opts.*attributes"
|
|
}
|
|
],
|
|
"*ttl": [
|
|
{
|
|
"FilterIDs": ["*string:~*req.Account:1001"],
|
|
"Value": "~*req.TTL",
|
|
},
|
|
],
|
|
"*debitInterval": [
|
|
{
|
|
"FilterIDs": ["*string:~*req.Account:1001"],
|
|
"Value": "~*req.Usage",
|
|
},
|
|
],
|
|
},
|
|
},
|
|
}`
|
|
|
|
cgrCfg, err := config.NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
ev := &utils.CGREvent{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "testIDEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: "1001",
|
|
utils.Usage: 8 * time.Second,
|
|
utils.TTL: "1s",
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.MetaAttributes: true,
|
|
utils.MetaAccounts: true,
|
|
},
|
|
}
|
|
ev2 := &utils.CGREvent{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "testIDEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: "1002",
|
|
utils.Usage: 8 * time.Second,
|
|
utils.TTL: "1s",
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.MetaAttributes: true,
|
|
utils.MetaAccounts: true,
|
|
},
|
|
}
|
|
fltrs := NewFilterS(cgrCfg, nil, nil)
|
|
if rcv, err := GetBoolOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fltrs, cgrCfg.SessionSCfg().Opts.Accounts); err != nil {
|
|
t.Error(err)
|
|
} else if !rcv {
|
|
t.Errorf("expected true,received %v", rcv)
|
|
}
|
|
if rcv, err := GetBoolOpts(context.Background(), "cgrates.org", ev2.AsDataProvider(), nil, fltrs, cgrCfg.SessionSCfg().Opts.Accounts); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.SessionsAccountsDftOpt {
|
|
t.Errorf("expected %v,received %v", config.SessionsAccountsDftOpt, rcv)
|
|
}
|
|
|
|
if rcv, err := GetBoolOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fltrs, cgrCfg.SessionSCfg().Opts.Attributes); err != nil {
|
|
t.Error(err)
|
|
} else if !rcv {
|
|
t.Errorf("expected true,received %v", rcv)
|
|
}
|
|
if rcv, err := GetBoolOpts(context.Background(), "cgrates.org", ev2.AsDataProvider(), nil, fltrs, cgrCfg.SessionSCfg().Opts.Attributes); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.SessionsAttributesDftOpt {
|
|
t.Errorf("expected %v,received %v", config.SessionsAttributesDftOpt, rcv)
|
|
}
|
|
|
|
if rcv, err := GetDurationOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fltrs, cgrCfg.SessionSCfg().Opts.TTL); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != time.Second {
|
|
t.Errorf("expected %v,received %v", time.Second, rcv)
|
|
}
|
|
if rcv, err := GetDurationOpts(context.Background(), "cgrates.org", ev2.AsDataProvider(), nil, fltrs, cgrCfg.SessionSCfg().Opts.TTL); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.SessionsTTLDftOpt {
|
|
t.Errorf("expected %v,received %v", config.SessionsTTLDftOpt, rcv)
|
|
}
|
|
|
|
if rcv, err := GetDurationOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fltrs, cgrCfg.SessionSCfg().Opts.DebitInterval); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != (8 * time.Second) {
|
|
t.Errorf("expected %v,received %v", 8*time.Second, rcv)
|
|
}
|
|
if rcv, err := GetDurationOpts(context.Background(), "cgrates.org", ev2.AsDataProvider(), nil, fltrs, cgrCfg.SessionSCfg().Opts.DebitInterval); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.SessionsDebitIntervalDftOpt {
|
|
t.Errorf("expected %v,received %v", config.SessionsDebitIntervalDftOpt, rcv)
|
|
}
|
|
}
|
|
|
|
func TestResDynamicOptsFromJson(t *testing.T) {
|
|
cfgJSONStr := `{
|
|
"resources": {
|
|
"enabled": true,
|
|
"store_interval": "7m",
|
|
"thresholds_conns": ["*internal:*thresholds", "*conn1"],
|
|
"indexed_selects":true,
|
|
"nested_fields": true,
|
|
"opts":{
|
|
"*usageID": [
|
|
{
|
|
"FilterIDs": ["*string:~*req.Account:1001"],
|
|
"Value": "~*req.UsageID"
|
|
}
|
|
],
|
|
"*usageTTL": [
|
|
{
|
|
"FilterIDs": ["*string:~*req.Account:1001"],
|
|
"Value": "~*req.UsageTTL"
|
|
}
|
|
],
|
|
"*units": [
|
|
{
|
|
"FilterIDs": ["*string:~*req.Account:1001"],
|
|
"Value": "~*opts.*units"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
}`
|
|
|
|
cgrCfg, err := config.NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
ev := &utils.CGREvent{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "testIDEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: "1001",
|
|
"UsageID": "UsgID3232",
|
|
"UsageTTL": 3 * time.Second,
|
|
},
|
|
APIOpts: map[string]any{
|
|
"*units": 23.22,
|
|
},
|
|
}
|
|
ev2 := &utils.CGREvent{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "testIDEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: "1002",
|
|
"UsageID": "UsgID3232",
|
|
"UsageTTL": 3 * time.Second,
|
|
},
|
|
APIOpts: map[string]any{
|
|
"*units": 23.22,
|
|
},
|
|
}
|
|
fltrs := NewFilterS(cgrCfg, nil, nil)
|
|
if rcv, err := GetStringOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fltrs, cgrCfg.ResourceSCfg().Opts.UsageID); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != "UsgID3232" {
|
|
t.Errorf("expected %s,received %s", "UsgID3232", rcv)
|
|
}
|
|
if rcv, err := GetStringOpts(context.Background(), "cgrates.org", ev2.AsDataProvider(), nil, fltrs, cgrCfg.ResourceSCfg().Opts.UsageID); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.ResourcesUsageIDDftOpt {
|
|
t.Errorf("expected %s,received %s", config.ResourcesUsageTTLDftOpt, rcv)
|
|
}
|
|
|
|
if rcv, err := GetDurationOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fltrs, cgrCfg.ResourceSCfg().Opts.UsageTTL); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != 3*time.Second {
|
|
t.Errorf("expected %v,received %d", 3*time.Second, rcv)
|
|
}
|
|
if rcv, err := GetDurationOpts(context.Background(), "cgrates.org", ev2.AsDataProvider(), nil, fltrs, cgrCfg.ResourceSCfg().Opts.UsageTTL); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.ResourcesUsageTTLDftOpt {
|
|
t.Errorf("expected %d,received %d", config.ResourcesUsageTTLDftOpt, rcv)
|
|
}
|
|
|
|
if rcv, err := GetFloat64Opts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fltrs, cgrCfg.ResourceSCfg().Opts.Units); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != 23.22 {
|
|
t.Errorf("expected %f,received %f", 23.22, rcv)
|
|
}
|
|
if rcv, err := GetFloat64Opts(context.Background(), "cgrates.org", ev2.AsDataProvider(), nil, fltrs, cgrCfg.ResourceSCfg().Opts.Units); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.ResourcesUnitsDftOpt {
|
|
t.Errorf("expected %v,received %v", config.ResourcesUnitsDftOpt, rcv)
|
|
}
|
|
}
|
|
|
|
func TestRoutesDynamicOptsFromJson(t *testing.T) {
|
|
routeJsnStr := `{
|
|
"routes": {
|
|
"enabled": true,
|
|
"indexed_selects":false,
|
|
"opts":{
|
|
"*usage": [
|
|
{
|
|
"FilterIDs": ["*string:~*req.Account:1001"],
|
|
"Value": "~*req.Usage"
|
|
},
|
|
{
|
|
"FilterIDs": ["*string:~*req.Account:1002"],
|
|
"Value": 15555
|
|
},
|
|
{
|
|
"FilterIDs": ["*string:~*req.Account:1003"],
|
|
"Value": "5m"
|
|
},
|
|
{
|
|
"FilterIDs": ["*string:~*req.Account:1004"],
|
|
"Value": "~*opts.*usage"
|
|
},
|
|
]
|
|
}
|
|
}
|
|
}`
|
|
|
|
cgrCfg, err := config.NewCGRConfigFromJSONStringWithDefaults(routeJsnStr)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
ev := &utils.CGREvent{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "testIDEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: "1001",
|
|
utils.Usage: 43364.4,
|
|
},
|
|
APIOpts: map[string]any{
|
|
"*usage": "12m",
|
|
},
|
|
}
|
|
var dec decimal.Big
|
|
dec.SetFloat64(43364.4)
|
|
|
|
fltrs := NewFilterS(cgrCfg, nil, nil)
|
|
if rcv, err := GetDecimalBigOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fltrs, cgrCfg.RouteSCfg().Opts.Usage); err != nil {
|
|
t.Error(err)
|
|
} else if rcv.Cmp(&dec) != 0 {
|
|
t.Errorf("expected %v,received %v", dec.String(), rcv.String())
|
|
}
|
|
ev.Event[utils.AccountField] = 1002
|
|
dec.SetUint64(15555)
|
|
if rcv, err := GetDecimalBigOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fltrs, cgrCfg.RouteSCfg().Opts.Usage); err != nil {
|
|
t.Error(err)
|
|
} else if rcv.Cmp(&dec) != 0 {
|
|
t.Errorf("expected %v,received %v", dec.String(), rcv.String())
|
|
}
|
|
ev.Event[utils.AccountField] = 1003
|
|
dec = *decimal.New(int64(5*time.Minute), 0)
|
|
if rcv, err := GetDecimalBigOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fltrs, cgrCfg.RouteSCfg().Opts.Usage); err != nil {
|
|
t.Error(err)
|
|
} else if rcv.Cmp(&dec) != 0 {
|
|
t.Errorf("expected %v,received %v", dec.String(), rcv.String())
|
|
}
|
|
ev.Event[utils.AccountField] = 1004
|
|
dec = *decimal.New(int64(12*time.Minute), 0)
|
|
if rcv, err := GetDecimalBigOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fltrs, cgrCfg.RouteSCfg().Opts.Usage); err != nil {
|
|
t.Error(err)
|
|
} else if rcv.Cmp(&dec) != 0 {
|
|
t.Errorf("expected %v,received %v", dec.String(), rcv.String())
|
|
}
|
|
ev.Event[utils.AccountField] = 1005
|
|
if rcv, err := GetDecimalBigOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fltrs, cgrCfg.RouteSCfg().Opts.Usage); err != nil {
|
|
t.Error(err)
|
|
} else if rcv.Cmp(config.RatesUsageDftOpt) != 0 {
|
|
t.Errorf("expected %v,received %v", config.RatesUsageDftOpt.String(), rcv.String())
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDecimalBigOptsFilterCheckErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
strOpts := []*config.DynamicInterfaceOpt{
|
|
// function will return error after trying to parse the filter
|
|
{
|
|
FilterIDs: []string{"*string.invalid:filter"},
|
|
Tenant: "cgrates.org",
|
|
Value: -1,
|
|
},
|
|
}
|
|
dynOpts, _ := config.IfaceToDecimalBigDynamicOpts(strOpts)
|
|
experr := `inline parse error for string: <*string.invalid:filter>`
|
|
if _, err := GetDecimalBigOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsRatesUsage); err == nil ||
|
|
err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDecimalBigOptsReturnDefaultOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
strOpts := []*config.DynamicInterfaceOpt{
|
|
{
|
|
FilterIDs: []string{"*string:~*req.Account:1002"},
|
|
Tenant: "cgrates.org",
|
|
Value: -1,
|
|
},
|
|
{Value: config.RatesUsageDftOpt},
|
|
}
|
|
dynOpts, err := config.IfaceToDecimalBigDynamicOpts(strOpts)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if rcv, err := GetDecimalBigOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsRatesUsage); err != nil {
|
|
t.Error(err)
|
|
} else if rcv.Cmp(config.RatesUsageDftOpt) != 0 {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", config.RatesUsageDftOpt, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDecimalBigOptsReturnOptFromAPIOpts(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.OptsRatesUsage: decimal.New(4321, 5),
|
|
},
|
|
}
|
|
|
|
strOpts := []*config.DynamicInterfaceOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
{
|
|
FilterIDs: []string{"*string:~*req.Account:1001"},
|
|
Tenant: "cgrates.org",
|
|
Value: decimal.New(1234, 5),
|
|
},
|
|
}
|
|
dynOpts, _ := config.IfaceToDecimalBigDynamicOpts(strOpts)
|
|
|
|
expected := decimal.New(4321, 5)
|
|
if rcv, err := GetDecimalBigOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
"nonExistingAPIOpt", utils.OptsRatesUsage); err != nil {
|
|
t.Error(err)
|
|
} else if rcv.Cmp(expected) != 0 {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetIntPointerOptsReturnConfigOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicIntPointerOpt{
|
|
// tenant will not be recognized, will ignore this opt
|
|
config.NewDynamicIntPointerOpt([]string{"*string:~*req.Account:1001"}, "cgrates.net", utils.IntPointer(3), nil),
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicIntPointerOpt([]string{"*string:~*req.Account:1002"}, "cgrates.org", utils.IntPointer(4), nil),
|
|
config.NewDynamicIntPointerOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", utils.IntPointer(5), nil),
|
|
}
|
|
|
|
expected := 5
|
|
if rcv, err := GetIntPointerOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsRoutesProfilesCount); err != nil {
|
|
t.Error(err)
|
|
} else if *rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, *rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetIntPointerOptsFilterCheckErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicIntPointerOpt{
|
|
// function will return error after trying to parse the filter
|
|
config.NewDynamicIntPointerOpt([]string{"*string.invalid:filter"}, "cgrates.org", utils.IntPointer(4), nil),
|
|
}
|
|
|
|
experr := `inline parse error for string: <*string.invalid:filter>`
|
|
if _, err := GetIntPointerOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsRoutesProfilesCount); err == nil ||
|
|
err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetIntPointerOptsReturnDft(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{},
|
|
}
|
|
dynOpts := []*config.DynamicIntPointerOpt{
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicIntPointerOpt([]string{"*string:~*req.Account:1002"}, "cgrates.org", utils.IntPointer(4), nil),
|
|
}
|
|
|
|
if rcv, err := GetIntPointerOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
utils.OptsRoutesProfilesCount); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != nil {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", nil, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetIntPointerOptsReturnOptFromAPIOptsOK(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.OptsRoutesProfilesCount: 6,
|
|
},
|
|
}
|
|
dynOpts := []*config.DynamicIntPointerOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicIntPointerOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", utils.IntPointer(5), nil),
|
|
}
|
|
|
|
expected := 6
|
|
if rcv, err := GetIntPointerOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
"nonExistingAPIOpt", utils.OptsRoutesProfilesCount); err != nil {
|
|
t.Error(err)
|
|
} else if *rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetIntPointerOptsReturnOptFromAPIOptsErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
ev := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "TestEvent",
|
|
Event: map[string]any{
|
|
utils.AccountField: 1001,
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.OptsRoutesProfilesCount: true,
|
|
},
|
|
}
|
|
dynOpts := []*config.DynamicIntPointerOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicIntPointerOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", utils.IntPointer(5), nil),
|
|
}
|
|
|
|
experr := `cannot convert field<bool>: true to int`
|
|
if _, err := GetIntPointerOpts(context.Background(), "cgrates.org", ev.AsDataProvider(), nil, fS, dynOpts,
|
|
"nonExistingAPIOpt", utils.OptsRoutesProfilesCount); err == nil || err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationOptsFromMultipleMapsReturnConfigOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
eventStart := map[string]any{
|
|
utils.AccountField: 1001,
|
|
}
|
|
apiOpts := map[string]any{}
|
|
startOpts := map[string]any{}
|
|
dynOpts := []*config.DynamicDurationOpt{
|
|
// tenant will not be recognized, will ignore this opt
|
|
config.NewDynamicDurationOpt([]string{"*string:~*req.Account:1001"}, "cgrates.net", time.Millisecond, nil),
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicDurationOpt([]string{"*string:~*req.Account:1002"}, "cgrates.net", time.Second, nil),
|
|
config.NewDynamicDurationOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", time.Minute, nil),
|
|
}
|
|
|
|
expected := time.Minute
|
|
if rcv, err := GetDurationOptsFromMultipleMaps(context.Background(), "cgrates.org", eventStart, apiOpts, startOpts, fS, dynOpts,
|
|
config.SessionsTTLDftOpt, utils.OptsSesTTL); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationOptsFromMultipleMapsFilterCheckErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
eventStart := map[string]any{
|
|
utils.AccountField: 1001,
|
|
}
|
|
apiOpts := map[string]any{}
|
|
startOpts := map[string]any{}
|
|
dynOpts := []*config.DynamicDurationOpt{
|
|
// function will return error after trying to parse the filter
|
|
config.NewDynamicDurationOpt([]string{"*string.invalid:filter"}, "cgrates.org", time.Second, nil),
|
|
}
|
|
|
|
experr := `inline parse error for string: <*string.invalid:filter>`
|
|
if _, err := GetDurationOptsFromMultipleMaps(context.Background(), "cgrates.org", eventStart, apiOpts, startOpts, fS, dynOpts,
|
|
config.SessionsTTLDftOpt, utils.OptsSesTTL); err == nil ||
|
|
err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationOptsFromMultipleMapsErrNotFound(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
eventStart := map[string]any{
|
|
utils.AccountField: 1001,
|
|
}
|
|
apiOpts := map[string]any{}
|
|
startOpts := map[string]any{}
|
|
dynOpts := []*config.DynamicDurationOpt{
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicDurationOpt([]string{"*string:~*req.Account:1002"}, "cgrates.org", time.Second, nil),
|
|
}
|
|
|
|
if rcv, err := GetDurationOptsFromMultipleMaps(context.Background(), "cgrates.org", eventStart, apiOpts, startOpts, fS, dynOpts,
|
|
config.SessionsTTLDftOpt, utils.OptsSesTTL); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != config.SessionsTTLDftOpt {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", config.SessionsTTLDftOpt, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationOptsFromMultipleMapsReturnOptFromAPIOptsOK(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
eventStart := map[string]any{
|
|
utils.AccountField: 1001,
|
|
}
|
|
apiOpts := map[string]any{
|
|
utils.OptsSesTTL: time.Hour,
|
|
}
|
|
startOpts := map[string]any{}
|
|
dynOpts := []*config.DynamicDurationOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicDurationOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", time.Minute, nil),
|
|
}
|
|
|
|
expected := time.Hour
|
|
if rcv, err := GetDurationOptsFromMultipleMaps(context.Background(), "cgrates.org", eventStart, apiOpts, startOpts, fS, dynOpts,
|
|
config.SessionsTTLDftOpt, utils.OptsSesTTL); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationOptsFromMultipleMapsReturnOptFromAPIOptsErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
eventStart := map[string]any{
|
|
utils.AccountField: 1001,
|
|
}
|
|
apiOpts := map[string]any{
|
|
utils.OptsSesTTL: true,
|
|
}
|
|
startOpts := map[string]any{}
|
|
dynOpts := []*config.DynamicDurationOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicDurationOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", time.Minute, nil),
|
|
}
|
|
|
|
experr := `cannot convert field: true to time.Duration`
|
|
if _, err := GetDurationOptsFromMultipleMaps(context.Background(), "cgrates.org", eventStart, apiOpts, startOpts, fS, dynOpts,
|
|
config.SessionsTTLDftOpt, utils.OptsSesTTL); err == nil || err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationOptsFromMultipleMapsReturnOptFromStartOptsOK(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
eventStart := map[string]any{
|
|
utils.AccountField: 1001,
|
|
}
|
|
apiOpts := map[string]any{}
|
|
startOpts := map[string]any{
|
|
utils.OptsSesTTL: time.Hour,
|
|
}
|
|
dynOpts := []*config.DynamicDurationOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicDurationOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", time.Minute, nil),
|
|
}
|
|
|
|
expected := time.Hour
|
|
if rcv, err := GetDurationOptsFromMultipleMaps(context.Background(), "cgrates.org", eventStart, apiOpts, startOpts, fS, dynOpts,
|
|
config.SessionsTTLDftOpt, utils.OptsSesTTL); err != nil {
|
|
t.Error(err)
|
|
} else if rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationOptsFromMultipleMapsReturnOptFromStartOptsErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
eventStart := map[string]any{
|
|
utils.AccountField: 1001,
|
|
}
|
|
apiOpts := map[string]any{}
|
|
startOpts := map[string]any{
|
|
utils.OptsSesTTL: true,
|
|
}
|
|
dynOpts := []*config.DynamicDurationOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicDurationOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", time.Minute, nil),
|
|
}
|
|
|
|
experr := `cannot convert field: true to time.Duration`
|
|
if _, err := GetDurationOptsFromMultipleMaps(context.Background(), "cgrates.org", eventStart, apiOpts, startOpts, fS, dynOpts,
|
|
config.SessionsTTLDftOpt, utils.OptsSesTTL); err == nil || err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationPointerOptsFromMultipleMapsReturnConfigOpt(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
eventStart := map[string]any{
|
|
utils.AccountField: 1001,
|
|
}
|
|
apiOpts := map[string]any{}
|
|
startOpts := map[string]any{}
|
|
dynOpts := []*config.DynamicDurationPointerOpt{
|
|
// tenant will not be recognized, will ignore this opt
|
|
config.NewDynamicDurationPointerOpt([]string{"*string:~*req.Account:1001"}, "cgrates.net", utils.DurationPointer(time.Millisecond), nil),
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicDurationPointerOpt([]string{"*string:~*req.Account:1002"}, "cgrates.org", utils.DurationPointer(time.Second), nil),
|
|
config.NewDynamicDurationPointerOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", utils.DurationPointer(time.Minute), nil),
|
|
}
|
|
|
|
expected := time.Minute
|
|
if rcv, err := GetDurationPointerOptsFromMultipleMaps(context.Background(), "cgrates.org", eventStart, apiOpts, startOpts, fS, dynOpts,
|
|
utils.OptsSesTTLUsage); err != nil {
|
|
t.Error(err)
|
|
} else if *rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationPointerOptsFromMultipleMapsFilterCheckErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
eventStart := map[string]any{
|
|
utils.AccountField: 1001,
|
|
}
|
|
apiOpts := map[string]any{}
|
|
startOpts := map[string]any{}
|
|
dynOpts := []*config.DynamicDurationPointerOpt{
|
|
// function will return error after trying to parse the filter
|
|
config.NewDynamicDurationPointerOpt([]string{"*string.invalid:filter"}, "cgrates.org", utils.DurationPointer(time.Second), nil),
|
|
}
|
|
|
|
experr := `inline parse error for string: <*string.invalid:filter>`
|
|
if _, err := GetDurationPointerOptsFromMultipleMaps(context.Background(), "cgrates.org", eventStart, apiOpts, startOpts, fS, dynOpts,
|
|
utils.OptsSesTTLUsage); err == nil ||
|
|
err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationPointerOptsFromMultipleMapsReturnDft(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
eventStart := map[string]any{
|
|
utils.AccountField: 1001,
|
|
}
|
|
apiOpts := map[string]any{}
|
|
startOpts := map[string]any{}
|
|
dynOpts := []*config.DynamicDurationPointerOpt{
|
|
// filter will not pass, will ignore this opt
|
|
config.NewDynamicDurationPointerOpt([]string{"*string:~*req.Account:1002"}, "cgrates.org", utils.DurationPointer(time.Second), nil),
|
|
}
|
|
|
|
if _, err := GetDurationPointerOptsFromMultipleMaps(context.Background(), "cgrates.org", eventStart, apiOpts, startOpts, fS, dynOpts,
|
|
utils.OptsSesTTLUsage); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationPointerOptsFromMultipleMapsReturnOptFromAPIOptsOK(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
eventStart := map[string]any{
|
|
utils.AccountField: 1001,
|
|
}
|
|
apiOpts := map[string]any{
|
|
utils.OptsSesTTLUsage: time.Hour,
|
|
}
|
|
startOpts := map[string]any{}
|
|
dynOpts := []*config.DynamicDurationPointerOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicDurationPointerOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", utils.DurationPointer(time.Minute), nil),
|
|
}
|
|
|
|
expected := time.Hour
|
|
if rcv, err := GetDurationPointerOptsFromMultipleMaps(context.Background(), "cgrates.org", eventStart, apiOpts, startOpts, fS, dynOpts,
|
|
utils.OptsSesTTLUsage); err != nil {
|
|
t.Error(err)
|
|
} else if *rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationPointerOptsFromMultipleMapsReturnOptFromAPIOptsErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
eventStart := map[string]any{
|
|
utils.AccountField: 1001,
|
|
}
|
|
apiOpts := map[string]any{
|
|
utils.OptsSesTTLUsage: true,
|
|
}
|
|
startOpts := map[string]any{}
|
|
dynOpts := []*config.DynamicDurationPointerOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicDurationPointerOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", utils.DurationPointer(time.Minute), nil),
|
|
}
|
|
|
|
experr := `cannot convert field: true to time.Duration`
|
|
if _, err := GetDurationPointerOptsFromMultipleMaps(context.Background(), "cgrates.org", eventStart, apiOpts, startOpts, fS, dynOpts,
|
|
utils.OptsSesTTLUsage); err == nil || err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationPointerOptsFromMultipleMapsReturnOptFromStartOptsOK(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
eventStart := map[string]any{
|
|
utils.AccountField: 1001,
|
|
}
|
|
apiOpts := map[string]any{}
|
|
startOpts := map[string]any{
|
|
utils.OptsSesTTLUsage: time.Hour,
|
|
}
|
|
dynOpts := []*config.DynamicDurationPointerOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicDurationPointerOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", utils.DurationPointer(time.Minute), nil),
|
|
}
|
|
|
|
expected := time.Hour
|
|
if rcv, err := GetDurationPointerOptsFromMultipleMaps(context.Background(), "cgrates.org", eventStart, apiOpts, startOpts, fS, dynOpts,
|
|
utils.OptsSesTTLUsage); err != nil {
|
|
t.Error(err)
|
|
} else if *rcv != expected {
|
|
t.Errorf("expected: <%+v>,\nreceived: <%+v>", expected, rcv)
|
|
}
|
|
}
|
|
|
|
func TestLibFiltersGetDurationPointerOptsFromMultipleMapsReturnOptFromStartOptsErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
eventStart := map[string]any{
|
|
utils.AccountField: 1001,
|
|
}
|
|
apiOpts := map[string]any{}
|
|
startOpts := map[string]any{
|
|
utils.OptsSesTTLUsage: true,
|
|
}
|
|
dynOpts := []*config.DynamicDurationPointerOpt{
|
|
// will never get to this opt because it will return once it
|
|
// finds the one set in APIOpts
|
|
config.NewDynamicDurationPointerOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", utils.DurationPointer(time.Minute), nil),
|
|
}
|
|
|
|
experr := `cannot convert field: true to time.Duration`
|
|
if _, err := GetDurationPointerOptsFromMultipleMaps(context.Background(), "cgrates.org", eventStart, apiOpts, startOpts, fS, dynOpts,
|
|
utils.OptsSesTTLUsage); err == nil || err.Error() != experr {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err)
|
|
}
|
|
}
|
|
|
|
func TestGetBoolOptsFieldAsInterfaceErr(t *testing.T) {
|
|
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
dynOpts := []*config.DynamicBoolOpt{
|
|
config.NewDynamicBoolOpt([]string{"*string:~*req.Account:1"}, "cgrates.org", false, nil),
|
|
}
|
|
|
|
if _, err := GetBoolOpts(context.Background(), "cgrates.org", new(mockDP), nil, fS, dynOpts,
|
|
"nonExistingAPIOpt", utils.MetaProfileIgnoreFilters); err != utils.ErrAccountNotFound {
|
|
t.Errorf("Expecting error <%+v>,\n Recevied error <%+v>", utils.ErrAccountNotFound, err)
|
|
}
|
|
|
|
}
|
|
|
|
func TestGetBoolOptsCantCastErr(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
dataDB, _ := NewInternalDB(nil, nil, nil, nil)
|
|
dbCM := NewDBConnManager(map[string]DataDB{utils.MetaDefault: dataDB}, cfg.DbCfg())
|
|
dm := NewDataManager(dbCM, cfg, nil)
|
|
fS := NewFilterS(cfg, nil, dm)
|
|
dynOpts := []*config.DynamicBoolOpt{
|
|
config.NewDynamicBoolOpt([]string{"*string:~*req.Account:1001"}, "cgrates.org", false, nil),
|
|
}
|
|
if _, err := GetBoolOpts(context.Background(), "cgrates.org", utils.StringSet{utils.MetaOpts: {}}, nil, fS, dynOpts,
|
|
"nonExistingAPIOpt", utils.MetaProfileIgnoreFilters); err.Error() != "cannot convert to map[string]any" {
|
|
t.Errorf("Expecting error <%+v>,\n Recevied error <%+v>", utils.ErrCastFailed, err)
|
|
}
|
|
|
|
}
|
|
|
|
func TestOptIfaceFromDP(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
values []string
|
|
exp any
|
|
err error
|
|
}{
|
|
{name: "TestOptBoolValue", values: []string{utils.MetaProfileIgnoreFilters}, exp: true, err: nil},
|
|
{name: "TestOptBoolValue", values: []string{utils.OptsRoutesIgnoreErrors}, exp: true, err: nil},
|
|
{name: "TestOptFloat64Value", values: []string{utils.OptsAttributesProcessRuns}, exp: 5, err: nil},
|
|
{name: "TestOptIntValue", values: []string{utils.OptsResourcesUnits}, exp: float64(23.1), err: nil},
|
|
{name: "TestOptIntValue", values: []string{utils.OptsAttributesProfileRuns}, exp: 3, err: nil},
|
|
{name: "TestOptStringValue", values: []string{utils.OptsRatesStartTime}, exp: "2021-01-01T00:00:00Z", err: nil},
|
|
{name: "TestOptFloat64Value", values: []string{utils.OptsResourcesUsageID}, exp: "RES1", err: nil},
|
|
{name: "TestFieldNotExist", values: []string{"field1"}, err: utils.ErrNotFound},
|
|
}
|
|
cgrEv := utils.MapStorage{
|
|
utils.MetaReq: map[string]any{},
|
|
utils.MetaOpts: map[string]any{
|
|
utils.MetaProfileIgnoreFilters: true,
|
|
utils.OptsRoutesIgnoreErrors: true,
|
|
utils.OptsAttributesProcessRuns: 5,
|
|
utils.OptsAttributesProfileRuns: 3,
|
|
utils.OptsRatesStartTime: "2021-01-01T00:00:00Z",
|
|
utils.OptsResourcesUsageID: "RES1",
|
|
utils.OptsResourcesUnits: 23.1,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if rcv, err := optIfaceFromDP(cgrEv, nil, tt.values); err != tt.err {
|
|
t.Errorf("expected: <%v>,\nreceived: <%v>", tt.err, err)
|
|
} else if rcv != tt.exp {
|
|
t.Errorf("expected: <%v>,\nreceived: <%v>", tt.exp, rcv)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConvertOptsToMapStringAny(t *testing.T) {
|
|
t.Run("MapEvent_Account", func(t *testing.T) {
|
|
accountEvent := MapEvent{
|
|
"Account": "1001",
|
|
"Tenant": "cgrates.org",
|
|
"BalanceMap": map[string]float64{"*monetary": 100.5},
|
|
"ActionTriggers": []string{"STANDARD_TRIGGERS"},
|
|
}
|
|
|
|
result, err := ConvertOptsToMapStringAny(accountEvent)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if len(result) != 4 {
|
|
t.Fatalf("Expected 4 keys, got %d", len(result))
|
|
}
|
|
|
|
if result["Account"] != "1001" {
|
|
t.Errorf("Expected Account=1001, got %v", result["Account"])
|
|
}
|
|
if result["Tenant"] != "cgrates.org" {
|
|
t.Errorf("Expected Tenant=cgrates.org, got %v", result["Tenant"])
|
|
}
|
|
})
|
|
|
|
t.Run("MapEvent_CDR", func(t *testing.T) {
|
|
cdrEvent := MapEvent{
|
|
"CGRID": "cdr123456789",
|
|
"OrderID": 12345,
|
|
"OriginHost": "192.168.1.1",
|
|
"Source": "SessionS",
|
|
"OriginID": "session_001",
|
|
"ToR": "*voice",
|
|
"RequestType": "*prepaid",
|
|
"Tenant": "cgrates.org",
|
|
"Category": "call",
|
|
"Account": "1001",
|
|
"Subject": "1001",
|
|
"Destination": "+4986517174963",
|
|
"SetupTime": "2024-01-15T10:30:00Z",
|
|
"AnswerTime": "2024-01-15T10:30:05Z",
|
|
"Usage": 300.0,
|
|
"Cost": 2.5,
|
|
}
|
|
|
|
result, err := ConvertOptsToMapStringAny(cdrEvent)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if result["CGRID"] != "cdr123456789" {
|
|
t.Errorf("Expected CGRID=cdr123456789, got %v", result["CGRID"])
|
|
}
|
|
if result["Account"] != "1001" {
|
|
t.Errorf("Expected Account=1001, got %v", result["Account"])
|
|
}
|
|
if result["Usage"] != 300.0 {
|
|
t.Errorf("Expected Usage=300.0, got %v", result["Usage"])
|
|
}
|
|
})
|
|
|
|
t.Run("MapStorage_RatingProfile", func(t *testing.T) {
|
|
ratingStorage := utils.MapStorage{
|
|
"Tenant": "cgrates.org",
|
|
"Category": "call",
|
|
"Subject": "*any",
|
|
"RatingPlanActivations": []map[string]any{
|
|
{
|
|
"ActivationTime": "2024-01-01T00:00:00Z",
|
|
"RatingPlanId": "RP_RETAIL",
|
|
"FallbackKeys": []string{"*any"},
|
|
},
|
|
},
|
|
}
|
|
|
|
result, err := ConvertOptsToMapStringAny(ratingStorage)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if result["Tenant"] != "cgrates.org" {
|
|
t.Errorf("Expected Tenant=cgrates.org, got %v", result["Tenant"])
|
|
}
|
|
if result["Subject"] != "*any" {
|
|
t.Errorf("Expected Subject=*any, got %v", result["Subject"])
|
|
}
|
|
})
|
|
|
|
t.Run("MapStorage_Destination", func(t *testing.T) {
|
|
destStorage := utils.MapStorage{
|
|
"Id": "DST_GERMANY",
|
|
"Prefixes": []string{"+49", "+4915", "+4916"},
|
|
}
|
|
|
|
result, err := ConvertOptsToMapStringAny(destStorage)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if result["Id"] != "DST_GERMANY" {
|
|
t.Errorf("Expected Id=DST_GERMANY, got %v", result["Id"])
|
|
}
|
|
|
|
prefixes, ok := result["Prefixes"].([]string)
|
|
if !ok || len(prefixes) != 3 {
|
|
t.Errorf("Expected Prefixes to be []string with 3 elements, got %v", result["Prefixes"])
|
|
}
|
|
})
|
|
|
|
t.Run("DirectMapStringAny", func(t *testing.T) {
|
|
directMap := map[string]any{
|
|
"ActionId": "TOPUP_MONETARY_10",
|
|
"ActionType": "*topup_reset",
|
|
"ExtraParameters": map[string]string{
|
|
"*balance_type": "*monetary",
|
|
"*units": "10",
|
|
},
|
|
}
|
|
|
|
result, err := ConvertOptsToMapStringAny(directMap)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(result, directMap) {
|
|
t.Errorf("Expected result to be identical to input map")
|
|
}
|
|
|
|
if result["ActionId"] != "TOPUP_MONETARY_10" {
|
|
t.Errorf("Expected ActionId=TOPUP_MONETARY_10, got %v", result["ActionId"])
|
|
}
|
|
})
|
|
|
|
t.Run("EmptyMapEvent", func(t *testing.T) {
|
|
emptyEvent := MapEvent{}
|
|
|
|
result, err := ConvertOptsToMapStringAny(emptyEvent)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if len(result) != 0 {
|
|
t.Errorf("Expected empty map, got %v", result)
|
|
}
|
|
})
|
|
|
|
t.Run("EmptyMapStorage", func(t *testing.T) {
|
|
emptyStorage := utils.MapStorage{}
|
|
|
|
result, err := ConvertOptsToMapStringAny(emptyStorage)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if len(result) != 0 {
|
|
t.Errorf("Expected empty map, got %v", result)
|
|
}
|
|
})
|
|
|
|
t.Run("UnsupportedType_String", func(t *testing.T) {
|
|
_, err := ConvertOptsToMapStringAny("invalid_string")
|
|
if err == nil {
|
|
t.Fatal("Expected error for unsupported type, got nil")
|
|
}
|
|
|
|
expectedErr := "cannot convert to map[string]any"
|
|
if err.Error() != expectedErr {
|
|
t.Errorf("Expected error '%s', got '%s'", expectedErr, err.Error())
|
|
}
|
|
})
|
|
|
|
t.Run("UnsupportedType_Int", func(t *testing.T) {
|
|
_, err := ConvertOptsToMapStringAny(12345)
|
|
if err == nil {
|
|
t.Fatal("Expected error for unsupported type, got nil")
|
|
}
|
|
})
|
|
|
|
t.Run("UnsupportedType_Slice", func(t *testing.T) {
|
|
_, err := ConvertOptsToMapStringAny([]string{"account1", "account2"})
|
|
if err == nil {
|
|
t.Fatal("Expected error for unsupported type, got nil")
|
|
}
|
|
})
|
|
|
|
t.Run("MapEvent_Session", func(t *testing.T) {
|
|
sessionEvent := MapEvent{
|
|
"CGRID": "session_abc123",
|
|
"Tenant": "cgrates.org",
|
|
"Account": "1002",
|
|
"Destination": "+4986517174999",
|
|
"InitialMaxUsage": 3600.0,
|
|
"MaxUsage": 1800.0,
|
|
"LastUsed": 600.0,
|
|
"LoopIndex": 0,
|
|
"DurationIndex": 600.0,
|
|
}
|
|
|
|
result, err := ConvertOptsToMapStringAny(sessionEvent)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if result["Account"] != "1002" {
|
|
t.Errorf("Expected Account=1002, got %v", result["Account"])
|
|
}
|
|
if result["MaxUsage"] != 1800.0 {
|
|
t.Errorf("Expected MaxUsage=1800.0, got %v", result["MaxUsage"])
|
|
}
|
|
})
|
|
|
|
t.Run("MapStorage_ActionPlan", func(t *testing.T) {
|
|
actionPlanStorage := utils.MapStorage{
|
|
"Id": "PACKAGE_10_SHARED_A_5",
|
|
"ActionTimings": []map[string]any{
|
|
{
|
|
"Uuid": "088fc6cc-192c-4d8e-9f5e-7b9c3d2c5b8d",
|
|
"Timing": "*asap",
|
|
"ActionsId": "TOPUP_RST_10",
|
|
"Weight": 10.0,
|
|
},
|
|
},
|
|
}
|
|
|
|
result, err := ConvertOptsToMapStringAny(actionPlanStorage)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if result["Id"] != "PACKAGE_10_SHARED_A_5" {
|
|
t.Errorf("Expected Id=PACKAGE_10_SHARED_A_5, got %v", result["Id"])
|
|
}
|
|
})
|
|
|
|
t.Run("MapEvent_ResourceEvent", func(t *testing.T) {
|
|
resourceEvent := MapEvent{
|
|
"Tenant": "cgrates.org",
|
|
"ID": "RES_GRP_1",
|
|
"UsageID": "call_usage_001",
|
|
"ResourceID": "RES_ACNT_1001",
|
|
"Units": 1.0,
|
|
"Account": "1001",
|
|
"Destination": "+4986517174963",
|
|
}
|
|
|
|
result, err := ConvertOptsToMapStringAny(resourceEvent)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if result["ID"] != "RES_GRP_1" {
|
|
t.Errorf("Expected ID=RES_GRP_1, got %v", result["ID"])
|
|
}
|
|
if result["Units"] != 1.0 {
|
|
t.Errorf("Expected Units=1.0, got %v", result["Units"])
|
|
}
|
|
})
|
|
|
|
t.Run("MapStorage_ThresholdProfile", func(t *testing.T) {
|
|
thresholdStorage := utils.MapStorage{
|
|
"Tenant": "cgrates.org",
|
|
"ID": "THD_ACNT_1001",
|
|
"FilterIDs": []string{"*string:~*req.Account:1001"},
|
|
"ActivationInterval": map[string]any{
|
|
"ActivationTime": "2024-01-01T00:00:00Z",
|
|
"ExpiryTime": "*never",
|
|
},
|
|
"MaxHits": -1,
|
|
"MinHits": 1,
|
|
"MinSleep": "1s",
|
|
"Blocker": false,
|
|
"Weight": 20.0,
|
|
"ActionIDs": []string{"LOG_WARNING"},
|
|
}
|
|
|
|
result, err := ConvertOptsToMapStringAny(thresholdStorage)
|
|
if err != nil {
|
|
t.Fatalf("Expected no error, got: %v", err)
|
|
}
|
|
|
|
if result["ID"] != "THD_ACNT_1001" {
|
|
t.Errorf("Expected ID=THD_ACNT_1001, got %v", result["ID"])
|
|
}
|
|
if result["Weight"] != 20.0 {
|
|
t.Errorf("Expected Weight=20.0, got %v", result["Weight"])
|
|
}
|
|
})
|
|
}
|