mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-24 00:28:44 +05:00
added new dynopts function GetDurationPointerOpts
This commit is contained in:
committed by
Dan Christian Bogos
parent
14515404bb
commit
18b0e4d417
@@ -73,6 +73,33 @@ func GetDurationOpts(ctx *context.Context, tnt string, dP utils.DataProvider, fS
|
||||
return
|
||||
}
|
||||
|
||||
// GetDurationPointerOpts checks the specified option names in order among the keys in APIOpts returning the first value it finds as *time.Duration, otherwise it
|
||||
// returns the config option if at least one filter passes or the default value if none of them do
|
||||
func GetDurationPointerOpts(ctx *context.Context, tnt string, dP utils.DataProvider, fS *FilterS, dynOpts []*config.DynamicDurationPointerOpt,
|
||||
optNames ...string) (cfgOpt *time.Duration, err error) {
|
||||
if opt, err := optIfaceFromDP(dP, optNames); err == nil {
|
||||
var value time.Duration
|
||||
value, err = utils.IfaceAsDuration(opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return utils.DurationPointer(value), nil
|
||||
} else if !errors.Is(err, utils.ErrNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
for _, opt := range dynOpts { // iterate through the options
|
||||
if !slices.Contains([]string{utils.EmptyString, utils.MetaAny, tnt}, opt.Tenant) {
|
||||
continue
|
||||
}
|
||||
if pass, err := fS.Pass(ctx, tnt, opt.FilterIDs, dP); err != nil { // check if the filter is passing for the DataProvider and return the option if it does
|
||||
return nil, err
|
||||
} else if pass {
|
||||
return opt.Value(dP)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetStringOpts checks the specified option names in order among the keys in APIOpts returning the first value it finds as string, otherwise it
|
||||
// returns the config option if at least one filter passes or the default value if none of them do
|
||||
func GetStringOpts(ctx *context.Context, tnt string, dP utils.DataProvider, fS *FilterS, dynOpts []*config.DynamicStringOpt,
|
||||
|
||||
@@ -340,6 +340,118 @@ func TestLibFiltersGetDurationOptsReturnDefaultOpt(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLibFiltersGetDurationPointerOptsReturnOptFromAPIOpts(t *testing.T) {
|
||||
cfg := config.NewDefaultCGRConfig()
|
||||
dataDB := NewInternalDB(nil, nil, nil)
|
||||
dm := NewDataManager(dataDB, cfg.CacheCfg(), 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(), 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)
|
||||
dm := NewDataManager(dataDB, cfg.CacheCfg(), 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(), 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)
|
||||
dm := NewDataManager(dataDB, cfg.CacheCfg(), 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(), 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)
|
||||
dm := NewDataManager(dataDB, cfg.CacheCfg(), 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(), 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)
|
||||
@@ -1563,6 +1675,106 @@ func TestDynamicDurationOptsDynVal(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
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(), 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
|
||||
|
||||
Reference in New Issue
Block a user