Add support for RSRFilter for > , >= , < , <=

This commit is contained in:
TeoV
2018-11-08 10:35:04 -05:00
committed by Dan Christian Bogos
parent dda6a2ec7d
commit 1192df9843
6 changed files with 188 additions and 1 deletions

View File

@@ -122,3 +122,36 @@ func TestAgReqAsNavigableMap(t *testing.T) {
t.Errorf("expecting: %+v, received: %+v", eMp, mpOut)
}
}
func TestAgReqMaxCost(t *testing.T) {
data, _ := engine.NewMapStorage()
dm := engine.NewDataManager(data)
cfg, _ := config.NewDefaultCGRConfig()
filterS := engine.NewFilterS(cfg, nil, dm)
agReq := newAgentRequest(nil, nil, nil, nil, "cgrates.org", "", filterS)
// populate request, emulating the way will be done in HTTPAgent
agReq.CGRRequest.Set([]string{utils.CapMaxUsage}, "120s", false)
cgrRply := map[string]interface{}{
utils.CapMaxUsage: time.Duration(120 * time.Second),
}
agReq.CGRReply = config.NewNavigableMap(cgrRply)
tplFlds := []*config.FCTemplate{
&config.FCTemplate{Tag: "MaxUsage",
FieldId: "MaxUsage", Type: utils.META_COMPOSED,
Filters: []string{"*rsr::~*cgrep.MaxUsage(>0s)"},
Value: config.NewRSRParsersMustCompile(
"~*cgrep.MaxUsage{*duration_seconds}", true)},
}
eMp := config.NewNavigableMap(nil)
eMp.Set([]string{"MaxUsage"}, []*config.NMItem{
&config.NMItem{Data: "120", Path: []string{"MaxUsage"},
Config: tplFlds[0]}}, true)
if mpOut, err := agReq.AsNavigableMap(tplFlds); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(eMp, mpOut) {
t.Errorf("expecting: %+v, received: %+v", eMp, mpOut)
}
}

View File

@@ -353,7 +353,7 @@ func (fltr *FilterRule) passGreaterThan(dP config.DataProvider) (bool, error) {
return false, err
} else if utils.IsSliceMember([]string{MetaGreaterThan, MetaGreaterOrEqual}, fltr.Type) && gte {
return true, nil
} else if !gte && utils.IsSliceMember([]string{MetaLessThan, MetaLessOrEqual}, fltr.Type) && !gte {
} else if utils.IsSliceMember([]string{MetaLessThan, MetaLessOrEqual}, fltr.Type) && !gte {
return true, nil
}
}

View File

@@ -467,3 +467,43 @@ func TestPassFiltersForEventWithEmptyFilter(t *testing.T) {
t.Errorf("Expecting: %+v, received: %+v", true, pass)
}
}
func TestPassFilterMaxCost(t *testing.T) {
data, _ := NewMapStorage()
dmFilterPass := NewDataManager(data)
cfg, _ := config.NewDefaultCGRConfig()
filterS := FilterS{
cfg: cfg,
dm: dmFilterPass,
}
//check with max usage -1 should fail
passEvent1 := map[string]interface{}{
"MaxUsage": time.Duration(-1),
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*rsr::~MaxUsage{*duration_nanoseconds}(>0)"}, config.NewNavigableMap(passEvent1)); err != nil {
t.Errorf(err.Error())
} else if pass {
t.Errorf("Expecting: false , received: %+v", pass)
}
//check with max usage 0 should fail
passEvent2 := map[string]interface{}{
"MaxUsage": time.Duration(0),
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*rsr::~MaxUsage{*duration_nanoseconds}(>0)"}, config.NewNavigableMap(passEvent2)); err != nil {
t.Errorf(err.Error())
} else if pass {
t.Errorf("Expecting: false, received: %+v", pass)
}
//check with max usage 123 should pass
passEvent3 := map[string]interface{}{
"MaxUsage": time.Duration(123),
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*rsr::~MaxUsage{*duration_nanoseconds}(>0)"}, config.NewNavigableMap(passEvent3)); err != nil {
t.Errorf(err.Error())
} else if !pass {
t.Errorf("Expecting: true, received: %+v", pass)
}
}

View File

@@ -315,6 +315,10 @@ const (
MetaString = "*string"
NegativePrefix = "!"
MatchStartPrefix = "^"
MatchGreaterThanOrEqual = ">="
MatchLessThanOrEqual = "<="
MatchGreaterThan = ">"
MatchLessThan = "<"
MatchEndPrefix = "$"
MetaGrouped = "*grouped"
MetaRaw = "*raw"

View File

@@ -254,6 +254,47 @@ func (rsrFltr *RSRFilter) Pass(val string) bool {
if rsrFltr.filterRule[lastIdx:] == MatchEndPrefix {
return strings.HasSuffix(val, rsrFltr.filterRule[:lastIdx]) != rsrFltr.negative
}
if len(rsrFltr.filterRule) > 2 && rsrFltr.filterRule[:2] == MatchGreaterThanOrEqual {
gt, err := GreaterThan(StringToInterface(val),
StringToInterface(rsrFltr.filterRule[2:]), true)
if err != nil {
Logger.Warning(fmt.Sprintf("<RSRFilter> rule: <%s>, err: <%s>", rsrFltr.filterRule, err.Error()))
return false
}
return gt && !rsrFltr.negative
}
if len(rsrFltr.filterRule) > 2 && rsrFltr.filterRule[:2] == MatchLessThanOrEqual {
gt, err := GreaterThan(StringToInterface(rsrFltr.filterRule[2:]), // compare the rule with the val
StringToInterface(val),
true)
if err != nil {
Logger.Warning(fmt.Sprintf("<RSRFilter> rule: <%s>, err: <%s>", rsrFltr.filterRule, err.Error()))
return false
}
return gt && !rsrFltr.negative
}
if rsrFltr.filterRule[:1] == MatchGreaterThan {
gt, err := GreaterThan(StringToInterface(val),
StringToInterface(rsrFltr.filterRule[1:]), false)
if err != nil {
Logger.Warning(fmt.Sprintf("<RSRFilter> rule: <%s>, err: <%s>", rsrFltr.filterRule, err.Error()))
return false
}
return gt && !rsrFltr.negative
}
if rsrFltr.filterRule[:1] == MatchLessThan {
gt, err := GreaterThan(StringToInterface(rsrFltr.filterRule[1:]), // compare the rule with the val
StringToInterface(val),
false)
if err != nil {
Logger.Warning(fmt.Sprintf("<RSRFilter> rule: <%s>, err: <%s>", rsrFltr.filterRule, err.Error()))
return false
}
return gt && !rsrFltr.negative
}
return (strings.Index(val, rsrFltr.filterRule) != -1) != rsrFltr.negative // default is string index
}

View File

@@ -481,6 +481,75 @@ func TestRSRFilterPass(t *testing.T) {
if !fltr.Pass("") {
t.Error("Passing!")
}
// compare greaterThan
fltr, err = NewRSRFilter(">0s")
if err != nil {
t.Error(err)
}
if fltr.Pass("0s") {
t.Error("passing!")
}
if fltr.Pass("13") {
t.Error("passing!")
}
if !fltr.Pass("12s") {
t.Error("not passing!")
}
// compare greaterThanOrEqual
fltr, err = NewRSRFilter(">=0s")
if err != nil {
t.Error(err)
}
if fltr.Pass("-1s") {
t.Error("passing!")
}
if !fltr.Pass("0s") {
t.Error("not passing!")
}
if fltr.Pass("13") {
t.Error("passing!")
}
if !fltr.Pass("12s") {
t.Error("not passing!")
}
// compare lessThan
fltr, err = NewRSRFilter("<0s")
if err != nil {
t.Error(err)
}
if fltr.Pass("1ns") {
t.Error("passing!")
}
if fltr.Pass("13") {
t.Error("passing!")
}
if fltr.Pass("12s") {
t.Error("passing!")
}
if !fltr.Pass("-12s") {
t.Error("not passing!")
}
// compare lessThanOrEqual
fltr, err = NewRSRFilter("<=0s")
if err != nil {
t.Error(err)
}
if !fltr.Pass("-1s") {
t.Error("not passing!")
}
if !fltr.Pass("0s") {
t.Error("not passing!")
}
if fltr.Pass("13") {
t.Error("passing!")
}
if fltr.Pass("12s") {
t.Error("passing!")
}
}
func TestRSRFiltersPass(t *testing.T) {