mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-12 02:26:26 +05:00
Removed unsused
This commit is contained in:
committed by
Dan Christian Bogos
parent
c437b5209d
commit
0ced58b994
@@ -280,22 +280,3 @@ func getDerivedEvents(events map[string]*utils.CGREvent, derivedReply bool) map[
|
||||
utils.MetaRaw: events[utils.MetaRaw],
|
||||
}
|
||||
}
|
||||
|
||||
// getDerivedMaxUsage returns only the *raw MaxUsage if derivedReply flag is not specified
|
||||
func getDerivedMaxUsage(maxUsages map[string]time.Duration, derivedReply bool) (out map[string]time.Duration) {
|
||||
if derivedReply {
|
||||
out = maxUsages
|
||||
} else {
|
||||
out = make(map[string]time.Duration)
|
||||
}
|
||||
var maxUsage time.Duration
|
||||
var maxUsageSet bool // so we know if we have set the 0 on purpose
|
||||
for _, rplyMaxUsage := range maxUsages {
|
||||
if !maxUsageSet || rplyMaxUsage < maxUsage {
|
||||
maxUsage = rplyMaxUsage
|
||||
maxUsageSet = true
|
||||
}
|
||||
}
|
||||
out[utils.MetaRaw] = maxUsage
|
||||
return
|
||||
}
|
||||
|
||||
@@ -349,27 +349,3 @@ func TestGetDerivedEvents(t *testing.T) {
|
||||
t.Errorf("Expected %s received %s", utils.ToJSON(exp), utils.ToJSON(rply))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDerivedMaxUsage(t *testing.T) {
|
||||
max := map[string]time.Duration{
|
||||
utils.MetaDefault: time.Second,
|
||||
"CustomRoute": time.Hour,
|
||||
}
|
||||
|
||||
exp := map[string]time.Duration{
|
||||
utils.MetaRaw: time.Second,
|
||||
utils.MetaDefault: time.Second,
|
||||
"CustomRoute": time.Hour,
|
||||
}
|
||||
|
||||
if rply := getDerivedMaxUsage(max, true); !reflect.DeepEqual(exp, rply) {
|
||||
t.Errorf("Expected %s received %s", utils.ToJSON(exp), utils.ToJSON(rply))
|
||||
}
|
||||
|
||||
exp = map[string]time.Duration{
|
||||
utils.MetaRaw: time.Second,
|
||||
}
|
||||
if rply := getDerivedMaxUsage(max, false); !reflect.DeepEqual(exp, rply) {
|
||||
t.Errorf("Expected %s received %s", utils.ToJSON(exp), utils.ToJSON(rply))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,29 +265,6 @@ func (sr *SRun) Clone() (clsr *SRun) {
|
||||
return
|
||||
}
|
||||
|
||||
// debitReserve attempty to debit from ExtraDuration and returns remaining duration
|
||||
// if lastUsage is not nil, the ExtraDuration is corrected
|
||||
func (sr *SRun) debitReserve(dur time.Duration, lastUsage *time.Duration) (rDur time.Duration) {
|
||||
if lastUsage != nil &&
|
||||
sr.LastUsage != *lastUsage {
|
||||
diffUsage := sr.LastUsage - *lastUsage
|
||||
sr.ExtraDuration += diffUsage
|
||||
sr.TotalUsage -= sr.LastUsage
|
||||
sr.TotalUsage += *lastUsage
|
||||
sr.LastUsage = *lastUsage
|
||||
}
|
||||
// debit from reserved
|
||||
if sr.ExtraDuration >= dur {
|
||||
sr.ExtraDuration -= dur
|
||||
sr.LastUsage = dur
|
||||
sr.TotalUsage += dur
|
||||
} else {
|
||||
rDur = dur - sr.ExtraDuration
|
||||
sr.ExtraDuration = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// updateSRuns updates the SRuns event with the alterable fields (is not thread safe)
|
||||
func (s *Session) updateSRuns(updEv engine.MapEvent, alterableFields utils.StringSet) {
|
||||
if alterableFields.Size() == 0 {
|
||||
|
||||
@@ -141,155 +141,6 @@ func TestSessionClone(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
//Test1 ExtraDuration 0 and LastUsage < initial
|
||||
|
||||
//Test1 ExtraDuration 0 and LastUsage < initial
|
||||
func TestSRunDebitReserve(t *testing.T) {
|
||||
lastUsage := time.Minute + 30*time.Second
|
||||
duration := 2 * time.Minute
|
||||
sr := &SRun{
|
||||
ExtraDuration: 0,
|
||||
LastUsage: duration,
|
||||
TotalUsage: duration,
|
||||
}
|
||||
if rDur := sr.debitReserve(duration, &lastUsage); rDur != lastUsage {
|
||||
t.Errorf("Expecting: %+v, received: %+v", lastUsage, rDur)
|
||||
}
|
||||
//start with extraDuration 0 and the difference go in rDur
|
||||
if sr.ExtraDuration != 0 {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 0, sr.ExtraDuration)
|
||||
}
|
||||
if sr.LastUsage != lastUsage {
|
||||
t.Errorf("Expecting: %+v, received: %+v", lastUsage, sr.LastUsage)
|
||||
}
|
||||
if sr.TotalUsage != lastUsage {
|
||||
t.Errorf("Expecting: %+v, received: %+v", lastUsage, sr.TotalUsage)
|
||||
}
|
||||
}
|
||||
|
||||
//Test2 ExtraDuration 0 and LastUsage > initial
|
||||
func TestSRunDebitReserve2(t *testing.T) {
|
||||
lastUsage := 2*time.Minute + 30*time.Second
|
||||
duration := 2 * time.Minute
|
||||
sr := &SRun{
|
||||
ExtraDuration: 0,
|
||||
LastUsage: duration,
|
||||
TotalUsage: duration,
|
||||
}
|
||||
if rDur := sr.debitReserve(duration, &lastUsage); rDur != lastUsage {
|
||||
t.Errorf("Expecting: %+v, received: %+v", lastUsage, rDur)
|
||||
}
|
||||
if sr.ExtraDuration != 0 {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 0, sr.ExtraDuration)
|
||||
}
|
||||
if sr.LastUsage != lastUsage {
|
||||
t.Errorf("Expecting: %+v, received: %+v", lastUsage, sr.LastUsage)
|
||||
}
|
||||
if sr.TotalUsage != lastUsage {
|
||||
t.Errorf("Expecting: %+v, received: %+v", lastUsage, sr.TotalUsage)
|
||||
}
|
||||
}
|
||||
|
||||
//Test3 ExtraDuration ( 1m < duration) and LastUsage < initial
|
||||
func TestSRunDebitReserve3(t *testing.T) {
|
||||
lastUsage := time.Minute + 30*time.Second
|
||||
duration := 2 * time.Minute
|
||||
sr := &SRun{
|
||||
ExtraDuration: time.Minute,
|
||||
LastUsage: duration,
|
||||
TotalUsage: duration,
|
||||
}
|
||||
if rDur := sr.debitReserve(duration, &lastUsage); rDur != (duration - lastUsage) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", lastUsage, rDur)
|
||||
}
|
||||
if sr.ExtraDuration != 0 {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 0, sr.ExtraDuration)
|
||||
}
|
||||
if sr.LastUsage != lastUsage {
|
||||
t.Errorf("Expecting: %+v, received: %+v", lastUsage, sr.LastUsage)
|
||||
}
|
||||
if sr.TotalUsage != lastUsage {
|
||||
t.Errorf("Expecting: %+v, received: %+v", lastUsage, sr.TotalUsage)
|
||||
}
|
||||
}
|
||||
|
||||
//Test4 ExtraDuration 1m and LastUsage > initial
|
||||
func TestSRunDebitReserve4(t *testing.T) {
|
||||
lastUsage := 2*time.Minute + 30*time.Second
|
||||
duration := 2 * time.Minute
|
||||
sr := &SRun{
|
||||
ExtraDuration: time.Minute,
|
||||
LastUsage: duration,
|
||||
TotalUsage: duration,
|
||||
}
|
||||
//We have extraDuration 1 minute and 30s different
|
||||
if rDur := sr.debitReserve(duration, &lastUsage); rDur != time.Minute+30*time.Second {
|
||||
t.Errorf("Expecting: %+v, received: %+v", time.Minute+30*time.Second, rDur)
|
||||
}
|
||||
if sr.ExtraDuration != 0 {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 0, sr.ExtraDuration)
|
||||
}
|
||||
if sr.LastUsage != lastUsage {
|
||||
t.Errorf("Expecting: %+v, received: %+v", lastUsage, sr.LastUsage)
|
||||
}
|
||||
if sr.TotalUsage != lastUsage {
|
||||
t.Errorf("Expecting: %+v, received: %+v", lastUsage, sr.TotalUsage)
|
||||
}
|
||||
}
|
||||
|
||||
//Test5 ExtraDuration 3m ( > initialDuration) and LastUsage < initial
|
||||
func TestSRunDebitReserve5(t *testing.T) {
|
||||
lastUsage := time.Minute + 30*time.Second
|
||||
duration := 2 * time.Minute
|
||||
sr := &SRun{
|
||||
ExtraDuration: 3 * time.Minute,
|
||||
LastUsage: duration,
|
||||
TotalUsage: duration,
|
||||
}
|
||||
//in debit reserve we start with an extraDuration 3m
|
||||
//after we add the different dur-lastUsed (+30s)
|
||||
if rDur := sr.debitReserve(duration, &lastUsage); rDur != 0 {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 0, rDur)
|
||||
}
|
||||
//ExtraDuration (3m30s - 2m)
|
||||
if sr.ExtraDuration != time.Minute+30*time.Second {
|
||||
t.Errorf("Expecting: %+v, received: %+v", time.Minute+30*time.Second, sr.ExtraDuration)
|
||||
}
|
||||
if sr.LastUsage != duration {
|
||||
t.Errorf("Expecting: %+v, received: %+v", duration, sr.LastUsage)
|
||||
}
|
||||
if sr.TotalUsage != 3*time.Minute+30*time.Second {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 3*time.Minute+30*time.Second, sr.TotalUsage)
|
||||
}
|
||||
}
|
||||
|
||||
//Test6 ExtraDuration 3m ( > initialDuration) and LastUsage > initial
|
||||
func TestSRunDebitReserve6(t *testing.T) {
|
||||
lastUsage := 2*time.Minute + 30*time.Second
|
||||
duration := 2 * time.Minute
|
||||
sr := &SRun{
|
||||
ExtraDuration: 3 * time.Minute,
|
||||
LastUsage: duration,
|
||||
TotalUsage: duration,
|
||||
}
|
||||
//in debit reserve we start with an extraDuration 3m
|
||||
//after we add the different dur-lastUsed (-30s)
|
||||
if rDur := sr.debitReserve(duration, &lastUsage); rDur != 0 {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 0, rDur)
|
||||
}
|
||||
//ExtraDuration (2m30s - 2m)
|
||||
if sr.ExtraDuration != 30*time.Second {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 30*time.Second, sr.ExtraDuration)
|
||||
}
|
||||
if sr.LastUsage != duration {
|
||||
t.Errorf("Expecting: %+v, received: %+v", duration, sr.LastUsage)
|
||||
}
|
||||
// 2m(initial Total) + 2m30s(correction)
|
||||
if sr.TotalUsage != 4*time.Minute+30*time.Second {
|
||||
t.Errorf("Expecting: %+v, received: %+v", 4*time.Minute+30*time.Second, sr.TotalUsage)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSessionAsCGREventsRawEvent(t *testing.T) {
|
||||
ev := map[string]interface{}{
|
||||
utils.EventName: "TEST_EVENT",
|
||||
|
||||
@@ -430,9 +430,6 @@ func (sS *SessionS) debitSession(s *Session, sRunIdx int, dur time.Duration,
|
||||
return
|
||||
}
|
||||
|
||||
func (sS *SessionS) pause(sr *SRun, dur time.Duration) {
|
||||
}
|
||||
|
||||
// debitLoopSession will periodically debit sessions, ie: automatic prepaid
|
||||
// threadSafe since it will run into it's own goroutine
|
||||
func (sS *SessionS) debitLoopSession(s *Session, sRunIdx int,
|
||||
@@ -519,20 +516,6 @@ func (sS *SessionS) debitLoopSession(s *Session, sRunIdx int,
|
||||
}
|
||||
}
|
||||
|
||||
// refundSession will refund the extra usage debitted by the end of session
|
||||
// not thread-safe so the locks need to be done in a layer above
|
||||
// rUsage represents the amount of usage to be refunded
|
||||
func (sS *SessionS) refundSession(s *Session, sRunIdx int, rUsage time.Duration) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// storeSCost will post the session cost to CDRs
|
||||
// not thread safe, need to be handled in a layer above
|
||||
func (sS *SessionS) storeSCost(s *Session, sRunIdx int) (err error) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// disconnectSession will send disconnect from SessionS to clients
|
||||
// not thread safe, it considers that the session is already stopped by this time
|
||||
func (sS *SessionS) disconnectSession(s *Session, rsn string) (err error) {
|
||||
@@ -733,9 +716,6 @@ func (sS *SessionS) getIndexedFilters(tenant string, fltrs []string) (
|
||||
f, err := sS.dm.GetFilter(tenant, fltrID,
|
||||
true, true, utils.NonTransactional)
|
||||
if err != nil {
|
||||
if err == utils.ErrNotFound {
|
||||
err = utils.ErrPrefixNotFound(fltrID)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if f.ActivationInterval != nil &&
|
||||
@@ -964,26 +944,6 @@ func (sS *SessionS) newSession(cgrEv *utils.CGREvent, resID, clntConnID string,
|
||||
return
|
||||
}
|
||||
s.SRuns = make([]*SRun, len(chrgrs))
|
||||
for i, chrgr := range chrgrs {
|
||||
me := engine.MapEvent(chrgr.CGREvent.Event)
|
||||
startTime := me.GetTimeIgnoreErrors(utils.AnswerTime,
|
||||
sS.cgrCfg.GeneralCfg().DefaultTimezone)
|
||||
if startTime.IsZero() { // AnswerTime not parsable, try SetupTime
|
||||
startTime = s.EventStart.GetTimeIgnoreErrors(utils.SetupTime,
|
||||
sS.cgrCfg.GeneralCfg().DefaultTimezone)
|
||||
}
|
||||
category := me.GetStringIgnoreErrors(utils.Category)
|
||||
if len(category) == 0 {
|
||||
category = sS.cgrCfg.GeneralCfg().DefaultCategory
|
||||
}
|
||||
subject := me.GetStringIgnoreErrors(utils.Subject)
|
||||
if len(subject) == 0 {
|
||||
subject = me.GetStringIgnoreErrors(utils.AccountField)
|
||||
}
|
||||
s.SRuns[i] = &SRun{
|
||||
Event: me,
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1277,7 +1237,7 @@ func (sS *SessionS) updateSession(s *Session, updtEv, opts engine.MapEvent, isMs
|
||||
}
|
||||
|
||||
var reqMaxUsage time.Duration
|
||||
if reqMaxUsage, err = updtEv.GetDuration(utils.Usage); err != nil {
|
||||
if _, err = updtEv.GetDuration(utils.Usage); err != nil {
|
||||
if err != utils.ErrNotFound {
|
||||
return
|
||||
}
|
||||
@@ -1629,7 +1589,6 @@ func (args *V1AuthorizeArgs) ParseFlags(flags, sep string) {
|
||||
}
|
||||
}
|
||||
args.Paginator, _ = utils.GetRoutePaginatorFromOpts(args.APIOpts)
|
||||
return
|
||||
}
|
||||
|
||||
// V1AuthorizeReply are options available in auth reply
|
||||
@@ -2598,7 +2557,6 @@ func (args *V1ProcessMessageArgs) ParseFlags(flags, sep string) {
|
||||
}
|
||||
}
|
||||
args.Paginator, _ = utils.GetRoutePaginatorFromOpts(args.APIOpts)
|
||||
return
|
||||
}
|
||||
|
||||
// V1ProcessMessageReply is the reply for the ProcessMessage API
|
||||
|
||||
@@ -1,343 +0,0 @@
|
||||
/*
|
||||
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 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
package structmatcher
|
||||
|
||||
/*
|
||||
The condition syntax is a json encoded string similar to mongodb query language.
|
||||
|
||||
Examples:
|
||||
- {"Weight":{"*gt":50}} checks for a balance with weight greater than 50
|
||||
- {"*or":[{"Value":{"*eq":0}},{"Value":{"*gte":100}}] checks for a balance with value equal to 0 or equal or highr than 100
|
||||
|
||||
Available operators:
|
||||
- *eq: equal
|
||||
- *gt: greater than
|
||||
- *gte: greater or equal than
|
||||
- *lt: less then
|
||||
- *lte: less or equal than
|
||||
- *exp: expired
|
||||
- *or: logical or
|
||||
- *and: logical and
|
||||
- *not: logical not
|
||||
- *has: receives a list of elements and checks that the elements are present in the specified field (StringMap type)
|
||||
- *rsr: will apply a rsr check to the field (see utils/rsrfield.go)
|
||||
|
||||
Equal (*eq) and local and (*and) operators are implicit for shortcuts. In this way:
|
||||
|
||||
{"*and":[{"Value":{"*eq":3}},{"Weight":{"*eq":10}}]} is equivalent to: {"Value":3, "Weight":10}.
|
||||
*/
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
CondOR = "*or"
|
||||
CondAND = "*and"
|
||||
CondHAS = "*has"
|
||||
)
|
||||
|
||||
func NewErrInvalidArgument(arg interface{}) error {
|
||||
return fmt.Errorf("INVALID_ARGUMENT: %v", arg)
|
||||
}
|
||||
|
||||
type StringMap map[string]bool
|
||||
|
||||
var (
|
||||
ErrParserError = errors.New("PARSER_ERROR")
|
||||
|
||||
operatorMap = map[string]func(field, value interface{}) (bool, error){
|
||||
utils.MetaEqual: func(field, value interface{}) (bool, error) {
|
||||
return value == field, nil
|
||||
},
|
||||
utils.MetaGreaterThan: func(field, value interface{}) (bool, error) {
|
||||
var of, vf float64
|
||||
var ok bool
|
||||
if of, ok = field.(float64); !ok {
|
||||
return false, NewErrInvalidArgument(field)
|
||||
}
|
||||
if vf, ok = value.(float64); !ok {
|
||||
return false, NewErrInvalidArgument(value)
|
||||
}
|
||||
return of > vf, nil
|
||||
},
|
||||
utils.MetaGreaterOrEqual: func(field, value interface{}) (bool, error) {
|
||||
var of, vf float64
|
||||
var ok bool
|
||||
if of, ok = field.(float64); !ok {
|
||||
return false, NewErrInvalidArgument(field)
|
||||
}
|
||||
if vf, ok = value.(float64); !ok {
|
||||
return false, NewErrInvalidArgument(value)
|
||||
}
|
||||
return of >= vf, nil
|
||||
},
|
||||
utils.MetaLessThan: func(field, value interface{}) (bool, error) {
|
||||
var of, vf float64
|
||||
var ok bool
|
||||
if of, ok = field.(float64); !ok {
|
||||
return false, NewErrInvalidArgument(field)
|
||||
}
|
||||
if vf, ok = value.(float64); !ok {
|
||||
return false, NewErrInvalidArgument(value)
|
||||
}
|
||||
return of < vf, nil
|
||||
},
|
||||
utils.MetaLessOrEqual: func(field, value interface{}) (bool, error) {
|
||||
var of, vf float64
|
||||
var ok bool
|
||||
if of, ok = field.(float64); !ok {
|
||||
return false, NewErrInvalidArgument(field)
|
||||
}
|
||||
if vf, ok = value.(float64); !ok {
|
||||
return false, NewErrInvalidArgument(value)
|
||||
}
|
||||
return of <= vf, nil
|
||||
},
|
||||
utils.MetaExp: func(field, value interface{}) (bool, error) {
|
||||
var expDate time.Time
|
||||
var ok bool
|
||||
if expDate, ok = field.(time.Time); !ok {
|
||||
return false, NewErrInvalidArgument(field)
|
||||
}
|
||||
var expired bool
|
||||
if expired, ok = value.(bool); !ok {
|
||||
return false, NewErrInvalidArgument(value)
|
||||
}
|
||||
if expired { // check for expiration
|
||||
return !expDate.IsZero() && expDate.Before(time.Now()), nil
|
||||
} else { // check not expired
|
||||
return expDate.IsZero() || expDate.After(time.Now()), nil
|
||||
}
|
||||
},
|
||||
CondHAS: func(field, value interface{}) (bool, error) {
|
||||
var strMap StringMap
|
||||
var ok bool
|
||||
if strMap, ok = field.(StringMap); !ok {
|
||||
return false, NewErrInvalidArgument(field)
|
||||
}
|
||||
var strSlice []interface{}
|
||||
if strSlice, ok = value.([]interface{}); !ok {
|
||||
return false, NewErrInvalidArgument(value)
|
||||
}
|
||||
for _, str := range strSlice {
|
||||
if !strMap[str.(string)] {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
},
|
||||
utils.MetaRSR: func(field, value interface{}) (bool, error) {
|
||||
fltr, err := utils.NewRSRFilter(value.(string))
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return fltr.Pass(fmt.Sprintf("%v", field)), nil
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
type compositeElement interface {
|
||||
element
|
||||
addChild(element) error
|
||||
}
|
||||
|
||||
type element interface {
|
||||
checkStruct(interface{}) (bool, error)
|
||||
}
|
||||
|
||||
type operatorSlice struct {
|
||||
operator string
|
||||
slice []element
|
||||
}
|
||||
|
||||
func (os *operatorSlice) addChild(ce element) error {
|
||||
os.slice = append(os.slice, ce)
|
||||
return nil
|
||||
}
|
||||
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, utils.MetaNot:
|
||||
accumulator := true
|
||||
for _, cond := range os.slice {
|
||||
check, err := cond.checkStruct(o)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
accumulator = accumulator && check
|
||||
}
|
||||
if os.operator == CondAND {
|
||||
return accumulator, nil
|
||||
} else {
|
||||
return !accumulator, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
type keyStruct struct {
|
||||
key string
|
||||
elem element
|
||||
}
|
||||
|
||||
func (ks *keyStruct) addChild(ce element) 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)
|
||||
if !value.IsValid() {
|
||||
return false, NewErrInvalidArgument(ks.key)
|
||||
}
|
||||
return ks.elem.checkStruct(value.Interface())
|
||||
}
|
||||
|
||||
type operatorValue struct {
|
||||
operator string
|
||||
value interface{}
|
||||
}
|
||||
|
||||
func (ov *operatorValue) checkStruct(o interface{}) (bool, error) {
|
||||
if f, ok := operatorMap[ov.operator]; ok {
|
||||
return f(o, ov.value)
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
type keyValue struct {
|
||||
key string
|
||||
value interface{}
|
||||
}
|
||||
|
||||
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)
|
||||
if !value.IsValid() {
|
||||
return false, NewErrInvalidArgument(kv.key)
|
||||
}
|
||||
return value.Interface() == kv.value, nil
|
||||
}
|
||||
|
||||
type trueElement struct{}
|
||||
|
||||
func (te *trueElement) checkStruct(o interface{}) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func isOperator(s string) bool {
|
||||
return strings.HasPrefix(s, "*")
|
||||
}
|
||||
|
||||
func notEmpty(x interface{}) bool {
|
||||
return !reflect.DeepEqual(x, reflect.Zero(reflect.TypeOf(x)).Interface())
|
||||
}
|
||||
|
||||
type StructMatcher struct {
|
||||
rootElement element
|
||||
}
|
||||
|
||||
func NewStructMatcher(q string) (sm *StructMatcher, err error) {
|
||||
sm = &StructMatcher{}
|
||||
err = sm.Parse(q)
|
||||
return
|
||||
}
|
||||
|
||||
func (sm *StructMatcher) load(a map[string]interface{}, parentElement compositeElement) (element, error) {
|
||||
for key, value := range a {
|
||||
var currentElement element
|
||||
switch t := value.(type) {
|
||||
case []interface{}:
|
||||
if key == CondHAS {
|
||||
currentElement = &operatorValue{operator: key, value: t}
|
||||
} else {
|
||||
currentElement = &operatorSlice{operator: key}
|
||||
for _, e := range t {
|
||||
sm.load(e.(map[string]interface{}), currentElement.(compositeElement))
|
||||
}
|
||||
}
|
||||
case map[string]interface{}:
|
||||
currentElement = &keyStruct{key: key}
|
||||
//log.Print("map: ", t)
|
||||
sm.load(t, currentElement.(compositeElement))
|
||||
case interface{}:
|
||||
if isOperator(key) {
|
||||
currentElement = &operatorValue{operator: key, value: t}
|
||||
} else {
|
||||
currentElement = &keyValue{key: key, value: t}
|
||||
}
|
||||
//log.Print("generic interface: ", t)
|
||||
default:
|
||||
return nil, ErrParserError
|
||||
}
|
||||
if parentElement != nil { // normal recurrent action
|
||||
parentElement.addChild(currentElement)
|
||||
} else {
|
||||
if len(a) > 1 { // we have more keys in the map
|
||||
parentElement = &operatorSlice{operator: CondAND}
|
||||
parentElement.addChild(currentElement)
|
||||
} else { // it was only one key value
|
||||
return currentElement, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return parentElement, nil
|
||||
}
|
||||
|
||||
func (sm *StructMatcher) Parse(s string) (err error) {
|
||||
a := make(map[string]interface{})
|
||||
if len(s) != 0 {
|
||||
if err := json.Unmarshal([]byte([]byte(s)), &a); err != nil {
|
||||
return err
|
||||
}
|
||||
sm.rootElement, err = sm.load(a, nil)
|
||||
} else {
|
||||
sm.rootElement = &trueElement{}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (sm *StructMatcher) Match(o interface{}) (bool, error) {
|
||||
if sm.rootElement == nil {
|
||||
return false, ErrParserError
|
||||
}
|
||||
return sm.rootElement.checkStruct(o)
|
||||
}
|
||||
@@ -1,483 +0,0 @@
|
||||
/*
|
||||
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 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
package structmatcher
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
func toJSON(v interface{}) string {
|
||||
b, _ := json.MarshalIndent(v, "", " ")
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func TestStructMatcher(t *testing.T) {
|
||||
cl := &StructMatcher{}
|
||||
err := cl.Parse(`{"*or":[{"test":1},{"field":{"*gt":1}},{"best":"coco"}]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
|
||||
err = cl.Parse(`{"*has":["NAT","RET","EUR"]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
err = cl.Parse(`{"Field":7, "Other":true}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
err = cl.Parse(``)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructMatcherKeyValue(t *testing.T) {
|
||||
o := struct {
|
||||
Test string
|
||||
Field float64
|
||||
Other bool
|
||||
ExpDate time.Time
|
||||
}{
|
||||
Test: "test",
|
||||
Field: 6.0,
|
||||
Other: true,
|
||||
ExpDate: time.Date(2016, 1, 19, 20, 47, 0, 0, time.UTC),
|
||||
}
|
||||
cl := &StructMatcher{}
|
||||
err := cl.Parse(`{"Test":"test"}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":6}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Other":true}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":6, "Other":true}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":7, "Other":true}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":6, "Other":false}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Other":true, "Field":{"*gt":5}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"*not":[{"Other":true, "Field":{"*gt":5}}]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Other":true, "Field":{"*gt":7}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(``)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"ExpDate":{"*exp":true}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"ExpDate":{"*exp":false}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"*and":[{"Field":{"*gte":50}},{"Test":{"*eq":"test"}}]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"WrongFieldName":{"*eq":1}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); check || err == nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAndMatchError(t *testing.T) {
|
||||
sMatch := &StructMatcher{}
|
||||
expected := "invalid character 'C' looking for beginning of value"
|
||||
err := sMatch.Parse("Can't unmarshal this")
|
||||
if err == nil || err.Error() != expected {
|
||||
t.Errorf("Expected %+v, received %+v", expected, err)
|
||||
}
|
||||
matchStr := &struct{}{}
|
||||
_, err = sMatch.Match(matchStr)
|
||||
if err == nil || err.Error() != ErrParserError.Error() {
|
||||
t.Errorf("Expected %+v, received %+v", ErrParserError, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructMatcherKeyValuePointer(t *testing.T) {
|
||||
o := &struct {
|
||||
Test string
|
||||
Field float64
|
||||
Other bool
|
||||
}{
|
||||
Test: "test",
|
||||
Field: 6.0,
|
||||
Other: true,
|
||||
}
|
||||
cl := &StructMatcher{}
|
||||
err := cl.Parse(`{"Test":"test"}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":6}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Other":true}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructMatcherOperatorValue(t *testing.T) {
|
||||
root := &operatorValue{operator: utils.MetaGreaterThan, value: 3.4}
|
||||
if check, err := root.checkStruct(3.5); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(root))
|
||||
}
|
||||
root = &operatorValue{operator: utils.MetaEqual, value: 3.4}
|
||||
if check, err := root.checkStruct(3.5); check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(root))
|
||||
}
|
||||
root = &operatorValue{operator: utils.MetaEqual, value: 3.4}
|
||||
if check, err := root.checkStruct(3.4); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(root))
|
||||
}
|
||||
root = &operatorValue{operator: utils.MetaEqual, value: "zinc"}
|
||||
if check, err := root.checkStruct("zinc"); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(root))
|
||||
}
|
||||
root = &operatorValue{operator: CondHAS, value: []interface{}{"NAT", "RET", "EUR"}}
|
||||
if check, err := root.checkStruct(StringMap{"WOR": true, "EUR": true, "NAT": true, "RET": true, "ROM": true}); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", !check, err, toJSON(root))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructMatcherKeyStruct(t *testing.T) {
|
||||
o := struct {
|
||||
Test string
|
||||
Field float64
|
||||
Other bool
|
||||
}{
|
||||
Test: "test",
|
||||
Field: 6.0,
|
||||
Other: true,
|
||||
}
|
||||
cl := &StructMatcher{}
|
||||
err := cl.Parse(`{"Field":{"*gt": 5}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Test":{"*gt": 5}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); check || !strings.HasPrefix(err.Error(), "INVALID_ARGUMENT") {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*gte": 6}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*lt": 7}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*lte": 6}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*eq": 6}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Test":{"*eq": "test"}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructMatcherKeyStructPointer(t *testing.T) {
|
||||
o := &struct {
|
||||
Test string
|
||||
Field float64
|
||||
Other bool
|
||||
}{
|
||||
Test: "test",
|
||||
Field: 6.0,
|
||||
Other: true,
|
||||
}
|
||||
cl := &StructMatcher{}
|
||||
err := cl.Parse(`{"Field":{"*gt": 5}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Test":{"*gt": 5}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); check || !strings.HasPrefix(err.Error(), "INVALID_ARGUMENT") {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*gte": 6}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*lt": 7}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*lte": 6}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Field":{"*eq": 6}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"Test":{"*eq": "test"}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructMatcherOperatorSlice(t *testing.T) {
|
||||
o := &struct {
|
||||
Test string
|
||||
Field float64
|
||||
Other bool
|
||||
}{
|
||||
Test: "test",
|
||||
Field: 6.0,
|
||||
Other: true,
|
||||
}
|
||||
cl := &StructMatcher{}
|
||||
err := cl.Parse(`{"*or":[{"Test":"test"},{"Field":{"*gt":5}},{"Other":true}]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"*or":[{"Test":"test"},{"Field":{"*gt":7}},{"Other":false}]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"*not":[{"*or":[{"Test":"test"},{"Field":{"*gt":7}},{"Other":false}]}]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"*and":[{"Test":"test"},{"Field":{"*gt":5}},{"Other":true}]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"*not":[{"*and":[{"Test":"test"},{"Field":{"*gt":5}},{"Other":true}]}]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"*and":[{"Test":"test"},{"Field":{"*gt":7}},{"Other":false}]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructMatcherMixed(t *testing.T) {
|
||||
o := &struct {
|
||||
Test string
|
||||
Field float64
|
||||
Categories StringMap
|
||||
Other bool
|
||||
}{
|
||||
Test: "test",
|
||||
Field: 6.0,
|
||||
Categories: StringMap{"call": true, "data": true, "voice": true},
|
||||
Other: true,
|
||||
}
|
||||
cl := &StructMatcher{}
|
||||
err := cl.Parse(`{"*and":[{"Test":"test"},{"Field":{"*gt":5}},{"Other":true},{"Categories":{"*has":["data", "call"]}}]}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructMatcherBalanceType(t *testing.T) {
|
||||
type Balance struct {
|
||||
Value float64
|
||||
}
|
||||
|
||||
o := &struct {
|
||||
BalanceType string
|
||||
Balance
|
||||
}{
|
||||
BalanceType: "*monetary",
|
||||
Balance: Balance{Value: 10},
|
||||
}
|
||||
cl := &StructMatcher{}
|
||||
err := cl.Parse(`{"BalanceType":"*monetary","Value":10}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", !check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStructMatcherRSR(t *testing.T) {
|
||||
o := &struct {
|
||||
BalanceType string
|
||||
}{
|
||||
BalanceType: "*monetary",
|
||||
}
|
||||
cl := &StructMatcher{}
|
||||
err := cl.Parse(`{"BalanceType":{"*rsr":"^*mon"}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); !check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", !check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
err = cl.Parse(`{"BalanceType":{"*rsr":"^*min"}}`)
|
||||
if err != nil {
|
||||
t.Errorf("Error loading structure: %+v (%v)", toJSON(cl.rootElement), err)
|
||||
}
|
||||
if check, err := cl.Match(o); check || err != nil {
|
||||
t.Errorf("Error checking struct: %v %v (%v)", !check, err, toJSON(cl.rootElement))
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OerS) 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 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package utils
|
||||
@@ -187,7 +187,7 @@ func TestFieldAsInterface(t *testing.T) {
|
||||
///
|
||||
testPath = []string{"path"}
|
||||
dn.Map = map[string]*DataNode{
|
||||
"notPath": &DataNode{
|
||||
"notPath": {
|
||||
Type: 1,
|
||||
},
|
||||
}
|
||||
@@ -235,7 +235,7 @@ func TestSet(t *testing.T) {
|
||||
dn := new(DataNode)
|
||||
testPath := make([]string, 0)
|
||||
val1 := map[string]*DataNode{
|
||||
"test": &DataNode{
|
||||
"test": {
|
||||
Type: 1,
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user