mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-15 05:09:54 +05:00
condition language parser and tests
This commit is contained in:
@@ -697,17 +697,20 @@ func (acc *Account) DebitConnectionFee(cc *CallCost, usefulMoneyBalances Balance
|
||||
}
|
||||
}
|
||||
|
||||
func (acc *Account) matchConditions(condition string) (bool, error) {
|
||||
condMap := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(condition), condMap); err != nil {
|
||||
return false, err
|
||||
func (acc *Account) matchConditions(condition, balanceType string) (bool, error) {
|
||||
|
||||
cl := &utils.CondLoader{}
|
||||
cl.Parse(condition)
|
||||
for _, b := range acc.BalanceMap[balanceType] {
|
||||
check, err := cl.Check(b)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if check {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
operator, found := condMap["Operator"]
|
||||
if !found {
|
||||
operator = utils.COND_EQ
|
||||
}
|
||||
_ = operator
|
||||
return true, nil
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// used in some api for transition
|
||||
|
||||
@@ -628,7 +628,7 @@ func transferMonetaryDefault(acc *Account, sq *StatsQueueTriggered, a *Action, a
|
||||
}
|
||||
|
||||
func conditionalDebitAction(acc *Account, sq *StatsQueueTriggered, a *Action, acs Actions) error {
|
||||
if matched, err := acc.matchConditions(a.ExtraParameters); matched {
|
||||
if matched, err := acc.matchConditions(a.ExtraParameters, a.BalanceType); matched {
|
||||
return debitAction(acc, sq, a, acs)
|
||||
} else {
|
||||
return err
|
||||
@@ -636,7 +636,7 @@ func conditionalDebitAction(acc *Account, sq *StatsQueueTriggered, a *Action, ac
|
||||
}
|
||||
|
||||
func conditionalDebitResetAction(acc *Account, sq *StatsQueueTriggered, a *Action, acs Actions) error {
|
||||
if matched, err := acc.matchConditions(a.ExtraParameters); matched {
|
||||
if matched, err := acc.matchConditions(a.ExtraParameters, a.BalanceType); matched {
|
||||
return debitResetAction(acc, sq, a, acs)
|
||||
} else {
|
||||
return err
|
||||
@@ -644,7 +644,7 @@ func conditionalDebitResetAction(acc *Account, sq *StatsQueueTriggered, a *Actio
|
||||
}
|
||||
|
||||
func conditionalTopupAction(acc *Account, sq *StatsQueueTriggered, a *Action, acs Actions) error {
|
||||
if matched, err := acc.matchConditions(a.ExtraParameters); matched {
|
||||
if matched, err := acc.matchConditions(a.ExtraParameters, a.BalanceType); matched {
|
||||
return topupAction(acc, sq, a, acs)
|
||||
} else {
|
||||
return err
|
||||
@@ -652,7 +652,7 @@ func conditionalTopupAction(acc *Account, sq *StatsQueueTriggered, a *Action, ac
|
||||
}
|
||||
|
||||
func conditionalTopupResetAction(acc *Account, sq *StatsQueueTriggered, a *Action, acs Actions) error {
|
||||
if matched, err := acc.matchConditions(a.ExtraParameters); matched {
|
||||
if matched, err := acc.matchConditions(a.ExtraParameters, a.BalanceType); matched {
|
||||
return topupResetAction(acc, sq, a, acs)
|
||||
} else {
|
||||
return err
|
||||
|
||||
@@ -2,88 +2,164 @@ package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
COND_EQ = "*eq"
|
||||
COND_GT = "*gt"
|
||||
COND_LT = "*lt"
|
||||
COND_EXP = "*exp"
|
||||
CondEQ = "*eq"
|
||||
CondGT = "*gt"
|
||||
CondGTE = "*gte"
|
||||
CondLT = "*lt"
|
||||
CondLTE = "*lte"
|
||||
CondEXP = "*exp"
|
||||
CondOR = "*or"
|
||||
CondAND = "*and"
|
||||
)
|
||||
|
||||
type CondElement interface {
|
||||
AddChild(CondElement)
|
||||
CheckStruct(interface{}) (bool, error)
|
||||
var (
|
||||
ErrNotNumerical = errors.New("NOT_NUMERICAL")
|
||||
)
|
||||
|
||||
type condElement interface {
|
||||
addChild(condElement) error
|
||||
checkStruct(interface{}) (bool, error)
|
||||
}
|
||||
|
||||
type OperatorSlice struct {
|
||||
Operator string
|
||||
Slice []CondElement
|
||||
type operatorSlice struct {
|
||||
operator string
|
||||
slice []condElement
|
||||
}
|
||||
|
||||
func (os *OperatorSlice) AddChild(ce CondElement) {
|
||||
os.Slice = append(os.Slice, ce)
|
||||
func (os *operatorSlice) addChild(ce condElement) error {
|
||||
os.slice = append(os.slice, ce)
|
||||
return nil
|
||||
}
|
||||
func (os *OperatorSlice) CheckStruct(o interface{}) (bool, error) { return true, nil }
|
||||
|
||||
type KeyStruct struct {
|
||||
Key string
|
||||
Struct CondElement
|
||||
func (os *operatorSlice) checkStruct(o interface{}) (bool, error) {
|
||||
switch os.operator {
|
||||
case CondOR:
|
||||
for _, cond := range os.slice {
|
||||
check, err := cond.checkStruct(o)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if check {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
case CondAND:
|
||||
accumulator := true
|
||||
for _, cond := range os.slice {
|
||||
check, err := cond.checkStruct(o)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
accumulator = accumulator && check
|
||||
}
|
||||
return accumulator, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (ks *KeyStruct) AddChild(ce CondElement) {
|
||||
ks.Struct = ce
|
||||
}
|
||||
func (ks *KeyStruct) CheckStruct(o interface{}) (bool, error) { return true, nil }
|
||||
|
||||
type OperatorValue struct {
|
||||
Operator string
|
||||
Value interface{}
|
||||
type keyStruct struct {
|
||||
key string
|
||||
elem condElement
|
||||
}
|
||||
|
||||
func (ov *OperatorValue) AddChild(CondElement) {}
|
||||
func (ov *OperatorValue) CheckStruct(o interface{}) (bool, error) { return true, nil }
|
||||
|
||||
type KeyValue struct {
|
||||
Key string
|
||||
Value interface{}
|
||||
func (ks *keyStruct) addChild(ce condElement) error {
|
||||
ks.elem = ce
|
||||
return nil
|
||||
}
|
||||
func (ks *keyStruct) checkStruct(o interface{}) (bool, error) {
|
||||
obj := reflect.ValueOf(o)
|
||||
if obj.Kind() == reflect.Ptr {
|
||||
obj = obj.Elem()
|
||||
}
|
||||
value := obj.FieldByName(ks.key)
|
||||
return ks.elem.checkStruct(value.Interface())
|
||||
}
|
||||
|
||||
func (os *KeyValue) AddChild(CondElement) {}
|
||||
func (os *KeyValue) CheckStruct(o interface{}) (bool, error) { return true, nil }
|
||||
type operatorValue struct {
|
||||
operator string
|
||||
value interface{}
|
||||
}
|
||||
|
||||
func (ov *operatorValue) addChild(condElement) error { return ErrNotImplemented }
|
||||
func (ov *operatorValue) checkStruct(o interface{}) (bool, error) {
|
||||
if ov.operator == CondEQ {
|
||||
return ov.value == o, nil
|
||||
}
|
||||
var of, vf float64
|
||||
var ok bool
|
||||
if of, ok = o.(float64); !ok {
|
||||
return false, ErrNotNumerical
|
||||
}
|
||||
if vf, ok = ov.value.(float64); !ok {
|
||||
return false, ErrNotNumerical
|
||||
}
|
||||
switch ov.operator {
|
||||
case CondGT:
|
||||
return of > vf, nil
|
||||
case CondGTE:
|
||||
return of >= vf, nil
|
||||
case CondLT:
|
||||
return of < vf, nil
|
||||
case CondLTE:
|
||||
return of <= vf, nil
|
||||
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
type keyValue struct {
|
||||
key string
|
||||
value interface{}
|
||||
}
|
||||
|
||||
func (kv *keyValue) addChild(condElement) error { return ErrNotImplemented }
|
||||
func (kv *keyValue) checkStruct(o interface{}) (bool, error) {
|
||||
obj := reflect.ValueOf(o)
|
||||
if obj.Kind() == reflect.Ptr {
|
||||
obj = obj.Elem()
|
||||
}
|
||||
value := obj.FieldByName(kv.key)
|
||||
return value.Interface() == kv.value, nil
|
||||
}
|
||||
|
||||
func isOperator(s string) bool {
|
||||
return strings.HasPrefix(s, "*")
|
||||
}
|
||||
|
||||
type CondLoader struct{}
|
||||
type CondLoader struct {
|
||||
rootElement condElement
|
||||
}
|
||||
|
||||
func (cp *CondLoader) Load(a map[string]interface{}, parentElement CondElement) (CondElement, error) {
|
||||
func (cp *CondLoader) load(a map[string]interface{}, parentElement condElement) (condElement, error) {
|
||||
for key, value := range a {
|
||||
var currentElement CondElement
|
||||
var currentElement condElement
|
||||
switch t := value.(type) {
|
||||
case []interface{}:
|
||||
currentElement = &OperatorSlice{Operator: key}
|
||||
currentElement = &operatorSlice{operator: key}
|
||||
for _, e := range t {
|
||||
cp.Load(e.(map[string]interface{}), currentElement)
|
||||
cp.load(e.(map[string]interface{}), currentElement)
|
||||
}
|
||||
case map[string]interface{}:
|
||||
currentElement = &KeyStruct{Key: key}
|
||||
currentElement = &keyStruct{key: key}
|
||||
//log.Print("map: ", t)
|
||||
cp.Load(t, currentElement)
|
||||
cp.load(t, currentElement)
|
||||
case interface{}:
|
||||
if isOperator(key) {
|
||||
currentElement = &OperatorValue{Operator: key, Value: t}
|
||||
currentElement = &operatorValue{operator: key, value: t}
|
||||
} else {
|
||||
currentElement = &KeyValue{Key: key, Value: t}
|
||||
currentElement = &keyValue{key: key, value: t}
|
||||
}
|
||||
//log.Print("generic interface: ", t)
|
||||
default:
|
||||
return nil, ErrParserError
|
||||
}
|
||||
if parentElement != nil {
|
||||
parentElement.AddChild(currentElement)
|
||||
parentElement.addChild(currentElement)
|
||||
} else {
|
||||
return currentElement, nil
|
||||
}
|
||||
@@ -91,10 +167,15 @@ func (cp *CondLoader) Load(a map[string]interface{}, parentElement CondElement)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (cp *CondLoader) Parse(s string) (root CondElement, err error) {
|
||||
func (cp *CondLoader) Parse(s string) (err error) {
|
||||
a := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte([]byte(s)), &a); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
return cp.Load(a, nil)
|
||||
cp.rootElement, err = cp.load(a, nil)
|
||||
return
|
||||
}
|
||||
|
||||
func (cp *CondLoader) Check(o interface{}) (bool, error) {
|
||||
return cp.rootElement.checkStruct(o)
|
||||
}
|
||||
|
||||
@@ -4,8 +4,260 @@ import "testing"
|
||||
|
||||
func TestCondLoader(t *testing.T) {
|
||||
cl := &CondLoader{}
|
||||
root, err := cl.Parse(`{"*or":[{"test":1},{"field":{"*gt":1}},{"best":"coco"}]}`)
|
||||
if err != nil || root == nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(root), err)
|
||||
err := cl.Parse(`{"*or":[{"test":1},{"field":{"*gt":1}},{"best":"coco"}]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCondKeyValue(t *testing.T) {
|
||||
o := struct {
|
||||
Test string
|
||||
Field float64
|
||||
Other bool
|
||||
}{
|
||||
Test: "test",
|
||||
Field: 6.0,
|
||||
Other: true,
|
||||
}
|
||||
cl := &CondLoader{}
|
||||
err := cl.Parse(`{"Test":"test"}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":6}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Other":true}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCondKeyValuePointer(t *testing.T) {
|
||||
o := &struct {
|
||||
Test string
|
||||
Field float64
|
||||
Other bool
|
||||
}{
|
||||
Test: "test",
|
||||
Field: 6.0,
|
||||
Other: true,
|
||||
}
|
||||
cl := &CondLoader{}
|
||||
err := cl.Parse(`{"Test":"test"}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":6}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Other":true}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCondOperatorValue(t *testing.T) {
|
||||
root := &operatorValue{operator: "*gt", value: 3.4}
|
||||
if check, err := root.checkStruct(3.5); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(root))
|
||||
}
|
||||
root = &operatorValue{operator: "*eq", value: 3.4}
|
||||
if check, err := root.checkStruct(3.5); check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(root))
|
||||
}
|
||||
root = &operatorValue{operator: "*eq", value: 3.4}
|
||||
if check, err := root.checkStruct(3.4); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(root))
|
||||
}
|
||||
root = &operatorValue{operator: "*eq", value: "zinc"}
|
||||
if check, err := root.checkStruct("zinc"); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(root))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCondKeyStruct(t *testing.T) {
|
||||
o := struct {
|
||||
Test string
|
||||
Field float64
|
||||
Other bool
|
||||
}{
|
||||
Test: "test",
|
||||
Field: 6.0,
|
||||
Other: true,
|
||||
}
|
||||
cl := &CondLoader{}
|
||||
err := cl.Parse(`{"Field":{"*gt": 5}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Test":{"*gt": 5}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); check || err != ErrNotNumerical {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*gte": 6}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*lt": 7}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*lte": 6}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*eq": 6}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Test":{"*eq": "test"}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCondKeyStructPointer(t *testing.T) {
|
||||
o := &struct {
|
||||
Test string
|
||||
Field float64
|
||||
Other bool
|
||||
}{
|
||||
Test: "test",
|
||||
Field: 6.0,
|
||||
Other: true,
|
||||
}
|
||||
cl := &CondLoader{}
|
||||
err := cl.Parse(`{"Field":{"*gt": 5}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Test":{"*gt": 5}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); check || err != ErrNotNumerical {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*gte": 6}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*lt": 7}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*lte": 6}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*eq": 6}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Test":{"*eq": "test"}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCondOperatorSlice(t *testing.T) {
|
||||
o := &struct {
|
||||
Test string
|
||||
Field float64
|
||||
Other bool
|
||||
}{
|
||||
Test: "test",
|
||||
Field: 6.0,
|
||||
Other: true,
|
||||
}
|
||||
cl := &CondLoader{}
|
||||
err := cl.Parse(`{"*or":[{"Test":"test"},{"Field":{"*gt":5}},{"Other":true}]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"*or":[{"Test":"test"},{"Field":{"*gt":7}},{"Other":false}]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"*and":[{"Test":"test"},{"Field":{"*gt":5}},{"Other":true}]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"*and":[{"Test":"test"},{"Field":{"*gt":7}},{"Other":false}]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", ToIJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Check(o); check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, ToIJSON(cl.rootElement))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user