mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
NavigableMap should not analyze values internally to keep flexibility and speed
This commit is contained in:
@@ -116,9 +116,7 @@ func (ar *AgentRequest) AsNavigableMap(tplFlds []*config.CfgCdrField) (
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nM.Set(
|
||||
&engine.NMItem{Path: strings.Split(tplFld.FieldId,
|
||||
utils.HIERARCHY_SEP), Data: out}, true)
|
||||
nM.Set(strings.Split(tplFld.FieldId, utils.HIERARCHY_SEP), out, true)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -36,15 +36,15 @@ func TestAgReqAsNavigableMap(t *testing.T) {
|
||||
agReq := newAgentRequest(nil, nil,
|
||||
"cgrates.org", filterS)
|
||||
// populate request, emulating the way will be done in HTTPAgent
|
||||
agReq.CGRRequest.Set(&engine.NMItem{Path: []string{utils.CGRID},
|
||||
Data: utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String())}, false)
|
||||
agReq.CGRRequest.Set(&engine.NMItem{Path: []string{utils.ToR}, Data: utils.VOICE}, false)
|
||||
agReq.CGRRequest.Set(&engine.NMItem{Path: []string{utils.Account}, Data: "1001"}, false)
|
||||
agReq.CGRRequest.Set(&engine.NMItem{Path: []string{utils.Destination}, Data: "1002"}, false)
|
||||
agReq.CGRRequest.Set(&engine.NMItem{Path: []string{utils.AnswerTime},
|
||||
Data: time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC)}, false)
|
||||
agReq.CGRRequest.Set(&engine.NMItem{Path: []string{utils.RequestType}, Data: utils.META_PREPAID}, false)
|
||||
agReq.CGRRequest.Set(&engine.NMItem{Path: []string{utils.Usage}, Data: time.Duration(3 * time.Minute)}, false)
|
||||
agReq.CGRRequest.Set([]string{utils.CGRID},
|
||||
utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()), false)
|
||||
agReq.CGRRequest.Set([]string{utils.ToR}, utils.VOICE, false)
|
||||
agReq.CGRRequest.Set([]string{utils.Account}, "1001", false)
|
||||
agReq.CGRRequest.Set([]string{utils.Destination}, "1002", false)
|
||||
agReq.CGRRequest.Set([]string{utils.AnswerTime},
|
||||
time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC), false)
|
||||
agReq.CGRRequest.Set([]string{utils.RequestType}, utils.META_PREPAID, false)
|
||||
agReq.CGRRequest.Set([]string{utils.Usage}, time.Duration(3*time.Minute), false)
|
||||
|
||||
cgrRply := map[string]interface{}{
|
||||
utils.CapAttributes: map[string]interface{}{
|
||||
@@ -99,12 +99,12 @@ func TestAgReqAsNavigableMap(t *testing.T) {
|
||||
"*cgrReply>Error", utils.INFIELD_SEP)},
|
||||
}
|
||||
eMp := engine.NewNavigableMap(nil)
|
||||
eMp.Set(&engine.NMItem{Path: []string{utils.Tenant}, Data: "cgrates.org"}, true)
|
||||
eMp.Set(&engine.NMItem{Path: []string{utils.Account}, Data: "1001"}, true)
|
||||
eMp.Set(&engine.NMItem{Path: []string{utils.Destination}, Data: "1002"}, true)
|
||||
eMp.Set(&engine.NMItem{Path: []string{"RequestedUsage"}, Data: "180"}, true)
|
||||
eMp.Set(&engine.NMItem{Path: []string{"PaypalAccount"}, Data: "cgrates@paypal.com"}, true)
|
||||
eMp.Set(&engine.NMItem{Path: []string{"MaxUsage"}, Data: "120"}, true)
|
||||
eMp.Set([]string{utils.Tenant}, "cgrates.org", true)
|
||||
eMp.Set([]string{utils.Account}, "1001", true)
|
||||
eMp.Set([]string{utils.Destination}, "1002", true)
|
||||
eMp.Set([]string{"RequestedUsage"}, "180", true)
|
||||
eMp.Set([]string{"PaypalAccount"}, "cgrates@paypal.com", true)
|
||||
eMp.Set([]string{"MaxUsage"}, "120", true)
|
||||
if mpOut, err := agReq.AsNavigableMap(tplFlds); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eMp, mpOut) {
|
||||
|
||||
@@ -211,8 +211,7 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.HttpAgntProcCfg,
|
||||
var rplyCDRs string
|
||||
if err = ha.sessionS.Call(utils.SessionSv1ProcessCDR,
|
||||
*cgrEv, &rplyCDRs); err != nil {
|
||||
agReq.CGRReply.Set(
|
||||
&engine.NMItem{Path: []string{utils.Error}, Data: err.Error()}, false)
|
||||
agReq.CGRReply.Set([]string{utils.Error}, err.Error(), false)
|
||||
}
|
||||
}
|
||||
if nM, err := agReq.AsNavigableMap(reqProcessor.ReplyFields); err != nil {
|
||||
|
||||
@@ -67,7 +67,7 @@ func (hU *httpUrlDP) FieldAsInterface(fldPath []string) (data interface{}, err e
|
||||
}
|
||||
err = nil // cancel previous err
|
||||
data = hU.req.FormValue(fldPath[0])
|
||||
hU.cache.Set(&engine.NMItem{Path: fldPath, Data: data}, false)
|
||||
hU.cache.Set(fldPath, data, false)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -411,6 +411,6 @@ func NewCGRReply(rply engine.NavigableMapper,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mp.Set(&engine.NMItem{Path: []string{utils.Error}, Data: ""}, false) // enforce empty error
|
||||
mp.Set([]string{utils.Error}, "", false) // enforce empty error
|
||||
return mp, nil
|
||||
}
|
||||
|
||||
@@ -450,7 +450,7 @@ func TestNewCGRReply(t *testing.T) {
|
||||
},
|
||||
}
|
||||
eCgrRply = engine.NewNavigableMap(ev)
|
||||
eCgrRply.Set(&engine.NMItem{Path: []string{utils.Error}, Data: ""}, false)
|
||||
eCgrRply.Set([]string{utils.Error}, "", false)
|
||||
if rpl, err := NewCGRReply(engine.NavigableMapper(ev), nil); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCgrRply, rpl) {
|
||||
|
||||
@@ -34,6 +34,9 @@ func NewCfgCdrFieldFromCdrFieldJsonCfg(jsnCfgFld *CdrFieldJsonCfg) (*CfgCdrField
|
||||
if jsnCfgFld.Field_id != nil {
|
||||
cfgFld.FieldId = *jsnCfgFld.Field_id
|
||||
}
|
||||
if jsnCfgFld.Attribute_id != nil {
|
||||
cfgFld.AttributeID = *jsnCfgFld.Attribute_id
|
||||
}
|
||||
if jsnCfgFld.Handler_id != nil {
|
||||
cfgFld.HandlerId = *jsnCfgFld.Handler_id
|
||||
}
|
||||
@@ -93,9 +96,10 @@ func NewCfgCdrFieldFromCdrFieldJsonCfg(jsnCfgFld *CdrFieldJsonCfg) (*CfgCdrField
|
||||
}
|
||||
|
||||
type CfgCdrField struct {
|
||||
Tag string // Identifier for the administrator
|
||||
Type string // Type of field
|
||||
FieldId string // Field identifier
|
||||
Tag string // Identifier for the administrator
|
||||
Type string // Type of field
|
||||
FieldId string // Field identifier
|
||||
AttributeID string
|
||||
Filters []string // list of filter profiles
|
||||
HandlerId string
|
||||
Value utils.RSRFields
|
||||
|
||||
@@ -145,6 +145,7 @@ type CdrFieldJsonCfg struct {
|
||||
Tag *string
|
||||
Type *string
|
||||
Field_id *string
|
||||
Attribute_id *string
|
||||
Handler_id *string
|
||||
Value *string
|
||||
Append *bool
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"reflect"
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
@@ -57,11 +57,11 @@ type NavigableMap struct {
|
||||
}
|
||||
|
||||
// Add will add items into NavigableMap populating also order
|
||||
func (nM *NavigableMap) Set(itm *NMItem, ordered bool) {
|
||||
func (nM *NavigableMap) Set(path []string, data interface{}, ordered bool) {
|
||||
mp := nM.data
|
||||
for i, spath := range itm.Path {
|
||||
if i == len(itm.Path)-1 { // last path
|
||||
mp[spath] = itm
|
||||
for i, spath := range path {
|
||||
if i == len(path)-1 { // last path
|
||||
mp[spath] = data
|
||||
return
|
||||
}
|
||||
if _, has := mp[spath]; !has {
|
||||
@@ -70,7 +70,7 @@ func (nM *NavigableMap) Set(itm *NMItem, ordered bool) {
|
||||
mp = mp[spath].(map[string]interface{}) // so we can check further down
|
||||
}
|
||||
if ordered {
|
||||
nM.order = append(nM.order, itm.Path)
|
||||
nM.order = append(nM.order, path)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,30 +85,27 @@ func (nM *NavigableMap) FieldAsInterface(fldPath []string) (fldVal interface{},
|
||||
var canCast bool
|
||||
for i, spath := range fldPath {
|
||||
if i == lenPath-1 { // lastElement
|
||||
itmIface, has := lastMp[spath]
|
||||
var has bool
|
||||
fldVal, has = lastMp[spath]
|
||||
if !has {
|
||||
return nil, utils.ErrNotFound
|
||||
}
|
||||
if itm, cast := itmIface.(*NMItem); cast {
|
||||
return itm.Data, nil
|
||||
}
|
||||
return itmIface, nil
|
||||
} else {
|
||||
elmnt, has := lastMp[spath]
|
||||
if !has {
|
||||
err = fmt.Errorf("no map at path: <%s>", spath)
|
||||
return
|
||||
}
|
||||
elmnt, has := lastMp[spath]
|
||||
if !has {
|
||||
err = fmt.Errorf("no map at path: <%s>", spath)
|
||||
return
|
||||
}
|
||||
lastMp, canCast = elmnt.(map[string]interface{})
|
||||
if !canCast {
|
||||
lastMpNM, canCast := elmnt.(*NavigableMap) // attempt to cast into NavigableMap
|
||||
if !canCast {
|
||||
err = fmt.Errorf("cannot cast field: <%+v> type: %T with path: <%s> to map[string]interface{}",
|
||||
elmnt, elmnt, spath)
|
||||
return
|
||||
}
|
||||
lastMp, canCast = elmnt.(map[string]interface{})
|
||||
if !canCast {
|
||||
lastMpNM, canCast := elmnt.(*NavigableMap) // attempt to cast into NavigableMap
|
||||
if !canCast {
|
||||
err = fmt.Errorf("cannot cast field: <%+v> type: %T with path: <%s> to map[string]interface{}",
|
||||
elmnt, elmnt, spath)
|
||||
return
|
||||
}
|
||||
lastMp = lastMpNM.data
|
||||
}
|
||||
lastMp = lastMpNM.data
|
||||
}
|
||||
}
|
||||
err = errors.New("end of function")
|
||||
@@ -140,43 +137,38 @@ func (nM *NavigableMap) AsMapStringInterface() map[string]interface{} {
|
||||
}
|
||||
|
||||
// indexMapElements will recursively go through map and index the element paths into elmns
|
||||
func indexMapElements(mp map[string]interface{}, path []string, elms *[]*NMItem) {
|
||||
func indexMapElements(mp map[string]interface{}, path []string, vals *[]interface{}) {
|
||||
for k, v := range mp {
|
||||
vPath := append(path, k)
|
||||
if mpIface, isMap := v.(map[string]interface{}); isMap {
|
||||
indexMapElements(mpIface, vPath, elms)
|
||||
indexMapElements(mpIface, vPath, vals)
|
||||
continue
|
||||
}
|
||||
var elmsOut []*NMItem
|
||||
if nMItem, isNMItem := v.(*NMItem); isNMItem {
|
||||
elmsOut = append(*elms, nMItem)
|
||||
} else {
|
||||
elmsOut = append(*elms, &NMItem{Path: vPath, Data: v})
|
||||
}
|
||||
|
||||
*elms = elmsOut
|
||||
valsOut := append(*vals, v)
|
||||
*vals = valsOut
|
||||
}
|
||||
}
|
||||
|
||||
// Items returns the items in map, ordered by order information
|
||||
func (nM *NavigableMap) Items() (itms []*NMItem) {
|
||||
// Values returns the values in map, ordered by order information
|
||||
func (nM *NavigableMap) Values() (vals []interface{}) {
|
||||
if len(nM.data) == 0 {
|
||||
return
|
||||
}
|
||||
if len(nM.order) == 0 {
|
||||
indexMapElements(nM.data, []string{}, &itms)
|
||||
indexMapElements(nM.data, []string{}, &vals)
|
||||
return
|
||||
}
|
||||
itms = make([]*NMItem, len(nM.order))
|
||||
vals = make([]interface{}, len(nM.order))
|
||||
for i, path := range nM.order {
|
||||
val, _ := nM.FieldAsInterface(path)
|
||||
itms[i] = &NMItem{Data: val, Path: path}
|
||||
vals[i] = val
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AsNavigableMap implements both NavigableMapper as well as DataProvider interfaces
|
||||
func (nM *NavigableMap) AsNavigableMap(tpl []*config.CfgCdrField) (oNM *NavigableMap, err error) {
|
||||
func (nM *NavigableMap) AsNavigableMap(
|
||||
tpl []*config.CfgCdrField) (oNM *NavigableMap, err error) {
|
||||
return nil, utils.ErrNotImplemented
|
||||
}
|
||||
|
||||
@@ -193,32 +185,67 @@ func (nM *NavigableMap) Merge(nM2 *NavigableMap) {
|
||||
}
|
||||
}
|
||||
|
||||
// addNMItemToTokens will add a NMItem to tockens
|
||||
// if itm.Config.IsAttribute the item data is added as Attribute to lastElmnt
|
||||
// tokens and lastElmntIdx are overloaded on each function call
|
||||
func addNMItemToTokens(tokens *[]xml.Token, lastElmntIdx *int, itm *NMItem,
|
||||
lastPath []string) (err error) {
|
||||
strVal, canCast := utils.CastFieldIfToString(itm.Data)
|
||||
if !canCast {
|
||||
return fmt.Errorf("cannot cast field: %s to string", utils.ToJSON(itm.Data))
|
||||
}
|
||||
if *lastElmntIdx == -1 || len(itm.Path) <= 1 ||
|
||||
!reflect.DeepEqual(itm.Path[:len(itm.Path)-1], lastPath) {
|
||||
charData := []byte("")
|
||||
if itm.Config == nil ||
|
||||
itm.Config.AttributeID == "" { // not attribute but value
|
||||
charData = []byte(strVal)
|
||||
}
|
||||
var elmLocal string
|
||||
if len(itm.Path) != 0 {
|
||||
elmLocal = itm.Path[len(itm.Path)-1]
|
||||
}
|
||||
t := xml.StartElement{Name: xml.Name{Local: elmLocal}}
|
||||
*lastElmntIdx = len(*tokens)
|
||||
tOut := append(*tokens, t, xml.CharData(charData), xml.EndElement{t.Name})
|
||||
*tokens = tOut
|
||||
}
|
||||
if itm.Config != nil && itm.Config.AttributeID != "" {
|
||||
tkns := *tokens
|
||||
lstElm := tkns[*lastElmntIdx].(xml.StartElement)
|
||||
lstElm.Attr = append(lstElm.Attr,
|
||||
xml.Attr{xml.Name{Local: itm.Config.AttributeID}, strVal})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalXML implements xml.Marshaler
|
||||
func (nM *NavigableMap) MarshalXML(e *xml.Encoder, start xml.StartElement) (err error) {
|
||||
tokens := []xml.Token{start}
|
||||
for _, itm := range nM.Items() {
|
||||
strVal, canCast := utils.CastFieldIfToString(itm.Data)
|
||||
if !canCast {
|
||||
return fmt.Errorf("cannot cast field: %s to string", utils.ToJSON(itm.Data))
|
||||
var prevItem *NMItem
|
||||
lastElmntIdx := utils.IntPointer(-1)
|
||||
for _, itm := range nM.Values() {
|
||||
nmItems, isNMItems := itm.([]*NMItem)
|
||||
if !isNMItems {
|
||||
return fmt.Errorf("map value: <%+v> not []*NMItem", nmItems)
|
||||
}
|
||||
var lastPath []string
|
||||
if prevItem != nil {
|
||||
lastPath = prevItem.Path
|
||||
}
|
||||
for _, itm := range nmItems {
|
||||
if err = addNMItemToTokens(&tokens, lastElmntIdx, itm, lastPath); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
t := xml.StartElement{Name: xml.Name{"", strings.Join(itm.Path, ">")}}
|
||||
tokens = append(tokens, t, xml.CharData([]byte(strVal)), xml.EndElement{t.Name})
|
||||
}
|
||||
|
||||
tokens = append(tokens, xml.EndElement{start.Name})
|
||||
|
||||
//fmt.Printf("## OUT: %s\n", utils.ToJSON(tokens))
|
||||
for _, t := range tokens {
|
||||
err := e.EncodeToken(t)
|
||||
if err != nil {
|
||||
if err = e.EncodeToken(t); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// flush to ensure tokens are written
|
||||
return e.Flush()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -18,11 +18,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package engine
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
//"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
@@ -148,36 +151,32 @@ func TestNavMapAdd(t *testing.T) {
|
||||
nM := NewNavigableMap(nil)
|
||||
path := []string{"FistLever2", "SecondLevel2", "Field2"}
|
||||
data := "Value2"
|
||||
nM.Set(&NMItem{Path: path, Data: data}, true)
|
||||
nM.Set(path, data, true)
|
||||
path = []string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"}
|
||||
data = "Val1"
|
||||
nM.Set(&NMItem{Path: path, Data: data}, true)
|
||||
nM.Set(path, data, true)
|
||||
path = []string{"FistLever2", "Field3"}
|
||||
data = "Value3"
|
||||
nM.Set(&NMItem{Path: path, Data: data}, true)
|
||||
nM.Set(path, data, true)
|
||||
path = []string{"Field4"}
|
||||
data = "Val4"
|
||||
nM.Set(&NMItem{Path: path, Data: data}, true)
|
||||
nM.Set(path, data, true)
|
||||
eNavMap := NavigableMap{
|
||||
data: map[string]interface{}{
|
||||
"FirstLevel": map[string]interface{}{
|
||||
"SecondLevel": map[string]interface{}{
|
||||
"ThirdLevel": map[string]interface{}{
|
||||
"Fld1": &NMItem{Path: []string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"},
|
||||
Data: "Val1"},
|
||||
"Fld1": "Val1",
|
||||
},
|
||||
},
|
||||
},
|
||||
"FistLever2": map[string]interface{}{
|
||||
"SecondLevel2": map[string]interface{}{
|
||||
"Field2": &NMItem{Path: []string{"FistLever2", "SecondLevel2", "Field2"},
|
||||
Data: "Value2"},
|
||||
"Field2": "Value2",
|
||||
},
|
||||
"Field3": &NMItem{Path: []string{"FistLever2", "Field3"},
|
||||
Data: "Value3"},
|
||||
"Field3": "Value3",
|
||||
},
|
||||
"Field4": &NMItem{Path: []string{"Field4"},
|
||||
Data: "Val4"},
|
||||
"Field4": "Val4",
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(nM.data, eNavMap.data) {
|
||||
@@ -194,42 +193,38 @@ func TestNavMapAdd2(t *testing.T) {
|
||||
nM := NewNavigableMap(nil)
|
||||
path := []string{"FistLever2", "SecondLevel2", "Field2"}
|
||||
data := 123
|
||||
nM.Set(&NMItem{Path: path, Data: data}, true)
|
||||
nM.Set(path, data, true)
|
||||
path = []string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"}
|
||||
data1 := 123.123
|
||||
nM.Set(&NMItem{Path: path, Data: data1}, true)
|
||||
nM.Set(path, data1, true)
|
||||
path = []string{"FistLever2", "Field3"}
|
||||
data2 := "Value3"
|
||||
nM.Set(&NMItem{Path: path, Data: data2}, true)
|
||||
nM.Set(path, data2, true)
|
||||
path = []string{"Field4"}
|
||||
data3 := &testStruct{
|
||||
Item1: "Ten",
|
||||
Item2: 10,
|
||||
}
|
||||
nM.Set(&NMItem{Path: path, Data: data3}, true)
|
||||
nM.Set(path, data3, true)
|
||||
eNavMap := NavigableMap{
|
||||
data: map[string]interface{}{
|
||||
"FirstLevel": map[string]interface{}{
|
||||
"SecondLevel": map[string]interface{}{
|
||||
"ThirdLevel": map[string]interface{}{
|
||||
"Fld1": &NMItem{Path: []string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"},
|
||||
Data: 123.123},
|
||||
"Fld1": 123.123,
|
||||
},
|
||||
},
|
||||
},
|
||||
"FistLever2": map[string]interface{}{
|
||||
"SecondLevel2": map[string]interface{}{
|
||||
"Field2": &NMItem{Path: []string{"FistLever2", "SecondLevel2", "Field2"},
|
||||
Data: 123},
|
||||
"Field2": 123,
|
||||
},
|
||||
"Field3": &NMItem{Path: []string{"FistLever2", "Field3"},
|
||||
Data: "Value3"},
|
||||
"Field3": "Value3",
|
||||
},
|
||||
"Field4": &testStruct{
|
||||
Item1: "Ten",
|
||||
Item2: 10,
|
||||
},
|
||||
"Field4": &NMItem{Path: []string{"Field4"},
|
||||
Data: &testStruct{
|
||||
Item1: "Ten",
|
||||
Item2: 10,
|
||||
}},
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(nM.data, eNavMap.data) {
|
||||
@@ -273,8 +268,9 @@ func TestNavMapItems(t *testing.T) {
|
||||
Data: "Val4",
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(len(nM.Items()), len(eItems)) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eItems), utils.ToJSON(nM.Items()))
|
||||
if vals := nM.Values(); !reflect.DeepEqual(len(vals), len(eItems)) {
|
||||
t.Errorf("Expecting: %+v, received: %+v",
|
||||
utils.ToJSON(eItems), utils.ToJSON(vals))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,8 +316,9 @@ func TestNavMapItems2(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(len(nM.Items()), len(eItems)) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eItems), utils.ToJSON(nM.Items()))
|
||||
if vals := nM.Values(); !reflect.DeepEqual(len(vals), len(eItems)) {
|
||||
t.Errorf("Expecting: %+v, received: %+v",
|
||||
utils.ToJSON(eItems), utils.ToJSON(vals))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,17 +327,29 @@ func TestNavMapOrder(t *testing.T) {
|
||||
"FirstLevel": map[string]interface{}{
|
||||
"SecondLevel": map[string]interface{}{
|
||||
"ThirdLevel": map[string]interface{}{
|
||||
"Fld1": "Val1",
|
||||
"Fld1": &NMItem{
|
||||
Path: []string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"},
|
||||
Data: "Val1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"FistLever2": map[string]interface{}{
|
||||
"SecondLevel2": map[string]interface{}{
|
||||
"Field2": "Value2",
|
||||
"Field2": &NMItem{
|
||||
Path: []string{"FistLever2", "SecondLevel2", "Field2"},
|
||||
Data: "Value2",
|
||||
},
|
||||
},
|
||||
"Field3": &NMItem{
|
||||
Path: []string{"FistLever2", "Field3"},
|
||||
Data: "Value3",
|
||||
},
|
||||
"Field3": "Value3",
|
||||
},
|
||||
"Field4": "Val4",
|
||||
"Field4": &NMItem{
|
||||
Path: []string{"Field4"},
|
||||
Data: "Val4",
|
||||
},
|
||||
}
|
||||
order := [][]string{
|
||||
[]string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"},
|
||||
@@ -350,7 +359,7 @@ func TestNavMapOrder(t *testing.T) {
|
||||
}
|
||||
nM := NewNavigableMap(myData)
|
||||
nM.order = order
|
||||
eItems := []*NMItem{
|
||||
eItems := []interface{}{
|
||||
&NMItem{
|
||||
Path: []string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"},
|
||||
Data: "Val1",
|
||||
@@ -368,8 +377,9 @@ func TestNavMapOrder(t *testing.T) {
|
||||
Data: "Val4",
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(nM.Items(), eItems) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eItems), utils.ToJSON(nM.Items()))
|
||||
if vals := nM.Values(); !reflect.DeepEqual(vals, eItems) {
|
||||
t.Errorf("Expecting: %+v, received: %+v",
|
||||
utils.ToJSON(eItems), utils.ToJSON(vals))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -378,17 +388,29 @@ func TestNavMapOrder2(t *testing.T) {
|
||||
"FirstLevel": map[string]interface{}{
|
||||
"SecondLevel": map[string]interface{}{
|
||||
"ThirdLevel": map[string]interface{}{
|
||||
"Fld1": "Val1",
|
||||
"Fld1": &NMItem{
|
||||
Path: []string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"},
|
||||
Data: "Val1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"FistLever2": map[string]interface{}{
|
||||
"SecondLevel2": map[string]interface{}{
|
||||
"Field2": "Value2",
|
||||
"Field2": &NMItem{
|
||||
Path: []string{"FistLever2", "SecondLevel2", "Field2"},
|
||||
Data: "Value2",
|
||||
},
|
||||
},
|
||||
"Field3": &NMItem{
|
||||
Path: []string{"FistLever2", "Field3"},
|
||||
Data: "Value3",
|
||||
},
|
||||
"Field3": "Value3",
|
||||
},
|
||||
"Field4": "Val4",
|
||||
"Field4": &NMItem{
|
||||
Path: []string{"Field4"},
|
||||
Data: "Val4",
|
||||
},
|
||||
}
|
||||
order := [][]string{
|
||||
[]string{"FistLever2", "SecondLevel2", "Field2"},
|
||||
@@ -398,7 +420,7 @@ func TestNavMapOrder2(t *testing.T) {
|
||||
}
|
||||
nM := NewNavigableMap(myData)
|
||||
nM.order = order
|
||||
eItems := []*NMItem{
|
||||
eItems := []interface{}{
|
||||
&NMItem{
|
||||
Path: []string{"FistLever2", "SecondLevel2", "Field2"},
|
||||
Data: "Value2",
|
||||
@@ -416,13 +438,14 @@ func TestNavMapOrder2(t *testing.T) {
|
||||
Data: "Val1",
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(nM.Items(), eItems) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eItems), utils.ToJSON(nM.Items()))
|
||||
if vals := nM.Values(); !reflect.DeepEqual(eItems, vals) {
|
||||
t.Errorf("Expecting: %+v, received: %+v",
|
||||
utils.ToJSON(eItems), utils.ToJSON(vals))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNavMapIndexMapElementes(t *testing.T) {
|
||||
var elmsOut []*NMItem
|
||||
var elmsOut []interface{}
|
||||
ifaceMap := map[string]interface{}{
|
||||
"FirstLevel": map[string]interface{}{
|
||||
"SecondLevel": map[string]interface{}{
|
||||
@@ -439,24 +462,7 @@ func TestNavMapIndexMapElementes(t *testing.T) {
|
||||
},
|
||||
"Field4": "Val4",
|
||||
}
|
||||
eItems := []*NMItem{
|
||||
&NMItem{
|
||||
Path: []string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"},
|
||||
Data: "Val1",
|
||||
},
|
||||
&NMItem{
|
||||
Path: []string{"FistLever2", "SecondLevel2", "Field2"},
|
||||
Data: "Value2",
|
||||
},
|
||||
&NMItem{
|
||||
Path: []string{"FistLever2", "Field3"},
|
||||
Data: "Value3",
|
||||
},
|
||||
&NMItem{
|
||||
Path: []string{"Field4"},
|
||||
Data: "Val4",
|
||||
},
|
||||
}
|
||||
eItems := []interface{}{"Val1", "Value2", "Value3", "Val4"}
|
||||
indexMapElements(ifaceMap, []string{}, &elmsOut)
|
||||
if !reflect.DeepEqual(len(elmsOut), len(eItems)) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(eItems), utils.ToJSON(elmsOut))
|
||||
@@ -486,3 +492,44 @@ func TestNavMapString(t *testing.T) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", eStr, nM.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNavMapMarshalXML(t *testing.T) {
|
||||
nm := &NavigableMap{
|
||||
data: map[string]interface{}{
|
||||
"FirstLevel": map[string]interface{}{
|
||||
"SecondLevel": map[string]interface{}{
|
||||
"ThirdLevel": map[string]interface{}{
|
||||
"Fld1": []*NMItem{
|
||||
&NMItem{Path: []string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"},
|
||||
Data: "Val1"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"FistLever2": map[string]interface{}{
|
||||
"SecondLevel2": map[string]interface{}{
|
||||
"Field2": []*NMItem{
|
||||
&NMItem{Path: []string{"FistLever2", "SecondLevel2", "Field2"},
|
||||
Data: "Value2",
|
||||
Config: &config.CfgCdrField{Tag: "AttributeTest", AttributeID: "attribute1"}}},
|
||||
},
|
||||
"Field3": []*NMItem{
|
||||
&NMItem{Path: []string{"FistLever2", "Field3"},
|
||||
Data: "Value3"}},
|
||||
},
|
||||
"Field4": []*NMItem{
|
||||
&NMItem{Path: []string{"Field4"},
|
||||
Data: "Val4"}},
|
||||
},
|
||||
order: [][]string{
|
||||
[]string{"FistLever2", "SecondLevel2", "Field2"},
|
||||
[]string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"},
|
||||
[]string{"FistLever2", "Field3"},
|
||||
[]string{"Field4"},
|
||||
},
|
||||
}
|
||||
if output, err := xml.MarshalIndent(nm, "", " "); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual([]byte(""), output) {
|
||||
//fmt.Printf("received output: <%s>\n", output)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user