diff --git a/agents/libdiam.go b/agents/libdiam.go index cbb69275b..522750f36 100644 --- a/agents/libdiam.go +++ b/agents/libdiam.go @@ -293,7 +293,7 @@ func newDADataProvider(c diam.Conn, m *diam.Message) utils.DataProvider { } -// diameterDP implements engine.DataProvider, serving as diam.Message data decoder +// diameterDP implements utils.DataProvider, serving as diam.Message data decoder // decoded data is only searched once and cached type diameterDP struct { c diam.Conn @@ -301,13 +301,13 @@ type diameterDP struct { cache *config.NavigableMap } -// String is part of engine.DataProvider interface +// String is part of utils.DataProvider interface // when called, it will display the already parsed values out of cache func (dP *diameterDP) String() string { return dP.m.String() } -// FieldAsString is part of engine.DataProvider interface +// FieldAsString is part of utils.DataProvider interface func (dP *diameterDP) FieldAsString(fldPath []string) (data string, err error) { var valIface interface{} valIface, err = dP.FieldAsInterface(fldPath) @@ -317,12 +317,12 @@ func (dP *diameterDP) FieldAsString(fldPath []string) (data string, err error) { return utils.IfaceAsString(valIface), nil } -// RemoteHost is part of engine.DataProvider interface +// RemoteHost is part of utils.DataProvider interface func (dP *diameterDP) RemoteHost() net.Addr { return utils.NewNetAddr(dP.c.RemoteAddr().Network(), dP.c.RemoteAddr().String()) } -// FieldAsInterface is part of engine.DataProvider interface +// FieldAsInterface is part of utils.DataProvider interface func (dP *diameterDP) FieldAsInterface(fldPath []string) (data interface{}, err error) { if data, err = dP.cache.FieldAsInterface(fldPath); err != nil { if err != utils.ErrNotFound { // item found in cache diff --git a/agents/libdns.go b/agents/libdns.go index a3e96d47b..147a914dc 100644 --- a/agents/libdns.go +++ b/agents/libdns.go @@ -73,13 +73,13 @@ type dnsDP struct { cache *config.NavigableMap } -// String is part of engine.DataProvider interface +// String is part of utils.DataProvider interface // when called, it will display the already parsed values out of cache func (dP *dnsDP) String() string { return utils.ToJSON(dP.req) } -// FieldAsString is part of engine.DataProvider interface +// FieldAsString is part of utils.DataProvider interface func (dP *dnsDP) FieldAsString(fldPath []string) (data string, err error) { var valIface interface{} valIface, err = dP.FieldAsInterface(fldPath) @@ -89,12 +89,12 @@ func (dP *dnsDP) FieldAsString(fldPath []string) (data string, err error) { return utils.IfaceAsString(valIface), nil } -// RemoteHost is part of engine.DataProvider interface +// RemoteHost is part of utils.DataProvider interface func (dP *dnsDP) RemoteHost() net.Addr { return utils.NewNetAddr(dP.w.RemoteAddr().Network(), dP.w.RemoteAddr().String()) } -// FieldAsInterface is part of engine.DataProvider interface +// FieldAsInterface is part of utils.DataProvider interface func (dP *dnsDP) FieldAsInterface(fldPath []string) (data interface{}, err error) { if data, err = dP.cache.FieldAsInterface(fldPath); err != nil { if err != utils.ErrNotFound { // item found in cache diff --git a/agents/libhttpagent.go b/agents/libhttpagent.go index 5779ff11a..be5c44160 100644 --- a/agents/libhttpagent.go +++ b/agents/libhttpagent.go @@ -52,21 +52,21 @@ func newHTTPUrlDP(req *http.Request) (dP utils.DataProvider, err error) { return } -// httpUrlDP implements engine.DataProvider, serving as url data decoder +// httpUrlDP implements utils.DataProvider, serving as url data decoder // decoded data is only searched once and cached type httpUrlDP struct { req *http.Request cache *config.NavigableMap } -// String is part of engine.DataProvider interface +// String is part of utils.DataProvider interface // when called, it will display the already parsed values out of cache func (hU *httpUrlDP) String() string { byts, _ := httputil.DumpRequest(hU.req, true) return string(byts) } -// FieldAsInterface is part of engine.DataProvider interface +// FieldAsInterface is part of utils.DataProvider interface func (hU *httpUrlDP) FieldAsInterface(fldPath []string) (data interface{}, err error) { if len(fldPath) != 1 { return nil, utils.ErrNotFound @@ -84,7 +84,7 @@ func (hU *httpUrlDP) FieldAsInterface(fldPath []string) (data interface{}, err e return } -// FieldAsString is part of engine.DataProvider interface +// FieldAsString is part of utils.DataProvider interface func (hU *httpUrlDP) FieldAsString(fldPath []string) (data string, err error) { var valIface interface{} valIface, err = hU.FieldAsInterface(fldPath) @@ -94,7 +94,7 @@ func (hU *httpUrlDP) FieldAsString(fldPath []string) (data string, err error) { return utils.IfaceAsString(valIface), nil } -// RemoteHost is part of engine.DataProvider interface +// RemoteHost is part of utils.DataProvider interface func (hU *httpUrlDP) RemoteHost() net.Addr { return utils.NewNetAddr("TCP", hU.req.RemoteAddr) } @@ -113,7 +113,7 @@ func newHTTPXmlDP(req *http.Request) (dP utils.DataProvider, err error) { return } -// httpXmlDP implements engine.DataProvider, serving as xml data decoder +// httpXmlDP implements utils.DataProvider, serving as xml data decoder // decoded data is only searched once and cached type httpXmlDP struct { cache *config.NavigableMap @@ -121,13 +121,13 @@ type httpXmlDP struct { addr string } -// String is part of engine.DataProvider interface +// String is part of utils.DataProvider interface // when called, it will display the already parsed values out of cache func (hU *httpXmlDP) String() string { return hU.xmlDoc.OutputXML(true) } -// FieldAsInterface is part of engine.DataProvider interface +// FieldAsInterface is part of utils.DataProvider interface func (hU *httpXmlDP) FieldAsInterface(fldPath []string) (data interface{}, err error) { //if path is missing return here error because if it arrived in xmlquery library will panic if len(fldPath) == 0 { @@ -172,7 +172,7 @@ func (hU *httpXmlDP) FieldAsInterface(fldPath []string) (data interface{}, err e return } -// FieldAsString is part of engine.DataProvider interface +// FieldAsString is part of utils.DataProvider interface func (hU *httpXmlDP) FieldAsString(fldPath []string) (data string, err error) { var valIface interface{} valIface, err = hU.FieldAsInterface(fldPath) @@ -182,7 +182,7 @@ func (hU *httpXmlDP) FieldAsString(fldPath []string) (data string, err error) { return utils.IfaceAsString(valIface), nil } -// RemoteHost is part of engine.DataProvider interface +// RemoteHost is part of utils.DataProvider interface func (hU *httpXmlDP) RemoteHost() net.Addr { return utils.NewNetAddr("TCP", hU.addr) } diff --git a/agents/librad.go b/agents/librad.go index c53c955fd..a3f1a8d4a 100644 --- a/agents/librad.go +++ b/agents/librad.go @@ -66,20 +66,20 @@ func newRADataProvider(req *radigo.Packet) (dP utils.DataProvider) { return } -// radiusDP implements engine.DataProvider, serving as radigo.Packet data decoder +// radiusDP implements utils.DataProvider, serving as radigo.Packet data decoder // decoded data is only searched once and cached type radiusDP struct { req *radigo.Packet cache *config.NavigableMap } -// String is part of engine.DataProvider interface +// String is part of utils.DataProvider interface // when called, it will display the already parsed values out of cache func (pk *radiusDP) String() string { return utils.ToIJSON(pk.req) // return ToJSON because Packet don't have a string method } -// FieldAsInterface is part of engine.DataProvider interface +// FieldAsInterface is part of utils.DataProvider interface func (pk *radiusDP) FieldAsInterface(fldPath []string) (data interface{}, err error) { if len(fldPath) != 1 { return nil, utils.ErrNotFound @@ -99,7 +99,7 @@ func (pk *radiusDP) FieldAsInterface(fldPath []string) (data interface{}, err er return } -// FieldAsString is part of engine.DataProvider interface +// FieldAsString is part of utils.DataProvider interface func (pk *radiusDP) FieldAsString(fldPath []string) (data string, err error) { var valIface interface{} valIface, err = pk.FieldAsInterface(fldPath) @@ -109,7 +109,7 @@ func (pk *radiusDP) FieldAsString(fldPath []string) (data string, err error) { return utils.IfaceAsString(valIface), nil } -// RemoteHost is part of engine.DataProvider interface +// RemoteHost is part of utils.DataProvider interface func (pk *radiusDP) RemoteHost() net.Addr { return utils.NewNetAddr(pk.req.RemoteAddr().Network(), pk.req.RemoteAddr().String()) } diff --git a/apier/v1/caches_it_test.go b/apier/v1/caches_it_test.go index fbe720095..af6df189f 100644 --- a/apier/v1/caches_it_test.go +++ b/apier/v1/caches_it_test.go @@ -348,7 +348,7 @@ func testCacheSClear(t *testing.T) { func testCacheSPrecacheStatus(t *testing.T) { var reply map[string]string expected := make(map[string]string) - for k := range utils.CachePartitions.Data() { + for k := range utils.CachePartitions { expected[k] = utils.MetaReady } if err := chcRPC.Call(utils.CacheSv1PrecacheStatus, &utils.AttrCacheIDsWithArgDispatcher{}, &reply); err != nil { diff --git a/apier/v1/config_it_test.go b/apier/v1/config_it_test.go index 49cb69359..4e0987bcf 100644 --- a/apier/v1/config_it_test.go +++ b/apier/v1/config_it_test.go @@ -154,7 +154,9 @@ func testConfigSReloadConfigFromJSONSessionS(t *testing.T) { "StoreSCosts": false, "AlterableFields": map[string]interface{}{}, "STIRCfg": map[string]interface{}{ - "AllowedAttest": map[string]interface{}{}, + "AllowedAttest": map[string]interface{}{ + utils.META_ANY: map[string]interface{}{}, + }, "DefaultAttest": "A", "PayloadMaxduration": -1., "PrivateKeyPath": "", @@ -175,7 +177,7 @@ func testConfigSReloadConfigFromJSONSessionS(t *testing.T) { }, &rpl); err != nil { t.Error(err) } else if !reflect.DeepEqual(exp, rpl) { - t.Errorf("Expected %+v , received: %+v ", exp, rpl) + t.Errorf("Expected %+v , received: %+v ", utils.ToJSON(exp), utils.ToJSON(rpl)) } } diff --git a/config/config_it_test.go b/config/config_it_test.go index 031fdd865..e81567ee8 100644 --- a/config/config_it_test.go +++ b/config/config_it_test.go @@ -438,17 +438,20 @@ func testCGRConfigReloadERs(t *testing.T) { flags, _ := utils.FlagsWithParamsFromSlice([]string{"*dryrun"}) flagsDefault, _ := utils.FlagsWithParamsFromSlice([]string{}) content := []*FCTemplate{ - &FCTemplate{Tag: utils.ToR, Path: utils.MetaCgreq + utils.NestingSep + utils.ToR, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.2", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, - &FCTemplate{Tag: utils.OriginID, Path: utils.MetaCgreq + utils.NestingSep + utils.OriginID, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.3", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, - &FCTemplate{Tag: utils.RequestType, Path: utils.MetaCgreq + utils.NestingSep + utils.RequestType, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.4", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, - &FCTemplate{Tag: utils.Tenant, Path: utils.MetaCgreq + utils.NestingSep + utils.Tenant, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.6", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, - &FCTemplate{Tag: utils.Category, Path: utils.MetaCgreq + utils.NestingSep + utils.Category, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.7", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, - &FCTemplate{Tag: utils.Account, Path: utils.MetaCgreq + utils.NestingSep + utils.Account, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.8", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, - &FCTemplate{Tag: utils.Subject, Path: utils.MetaCgreq + utils.NestingSep + utils.Subject, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.9", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, - &FCTemplate{Tag: utils.Destination, Path: utils.MetaCgreq + utils.NestingSep + utils.Destination, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.10", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, - &FCTemplate{Tag: utils.SetupTime, Path: utils.MetaCgreq + utils.NestingSep + utils.SetupTime, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.11", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, - &FCTemplate{Tag: utils.AnswerTime, Path: utils.MetaCgreq + utils.NestingSep + utils.AnswerTime, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.12", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, - &FCTemplate{Tag: utils.Usage, Path: utils.MetaCgreq + utils.NestingSep + utils.Usage, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.13", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, + {Tag: utils.ToR, Path: utils.MetaCgreq + utils.NestingSep + utils.ToR, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.2", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, + {Tag: utils.OriginID, Path: utils.MetaCgreq + utils.NestingSep + utils.OriginID, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.3", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, + {Tag: utils.RequestType, Path: utils.MetaCgreq + utils.NestingSep + utils.RequestType, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.4", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, + {Tag: utils.Tenant, Path: utils.MetaCgreq + utils.NestingSep + utils.Tenant, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.6", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, + {Tag: utils.Category, Path: utils.MetaCgreq + utils.NestingSep + utils.Category, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.7", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, + {Tag: utils.Account, Path: utils.MetaCgreq + utils.NestingSep + utils.Account, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.8", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, + {Tag: utils.Subject, Path: utils.MetaCgreq + utils.NestingSep + utils.Subject, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.9", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, + {Tag: utils.Destination, Path: utils.MetaCgreq + utils.NestingSep + utils.Destination, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.10", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, + {Tag: utils.SetupTime, Path: utils.MetaCgreq + utils.NestingSep + utils.SetupTime, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.11", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, + {Tag: utils.AnswerTime, Path: utils.MetaCgreq + utils.NestingSep + utils.AnswerTime, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.12", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, + {Tag: utils.Usage, Path: utils.MetaCgreq + utils.NestingSep + utils.Usage, Type: utils.MetaVariable, Value: NewRSRParsersMustCompile("~*req.13", true, utils.INFIELD_SEP), Mandatory: true, Layout: time.RFC3339}, + } + for _, v := range content { + v.ComputePath() } expAttr := &ERsCfg{ Enabled: true, diff --git a/config/multifiles_it_test.go b/config/multifiles_it_test.go index 4fd3fb838..f85f5a4d6 100644 --- a/config/multifiles_it_test.go +++ b/config/multifiles_it_test.go @@ -212,6 +212,16 @@ func TestMfHttpAgentMultipleFields(t *testing.T) { ReplyFields: []*FCTemplate{}, }}}, } + for _, profile := range expected { + for _, rp := range profile.RequestProcessors { + for _, v := range rp.ReplyFields { + v.ComputePath() + } + for _, v := range rp.RequestFields { + v.ComputePath() + } + } + } if !reflect.DeepEqual(mfCgrCfg.HttpAgentCfg(), expected) { t.Errorf("Expected: %+v\n, recived: %+v", utils.ToJSON(expected), utils.ToJSON(mfCgrCfg.HttpAgentCfg())) diff --git a/config/navigablemap_test.go b/config/navigablemap_test.go index 19dadf7b9..38e8e8841 100644 --- a/config/navigablemap_test.go +++ b/config/navigablemap_test.go @@ -1182,3 +1182,333 @@ func TestNavMapGetKeys(t *testing.T) { t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(expKeys), utils.ToJSON(keys)) } } + +func TestNMAsXMLElements(t *testing.T) { + nM := utils.NewOrderedNavigableMap() + order := []utils.PathItems{ + {{Field: "FirstLevel2"}, {Field: "SecondLevel2"}, {Field: "Field2"}}, + {{Field: "FirstLevel"}, {Field: "SecondLevel"}, {Field: "ThirdLevel"}, {Field: "Fld1"}}, + {{Field: "FirstLevel2"}, {Field: "Field3"}}, + {{Field: "FirstLevel2"}, {Field: "Field5"}}, + {{Field: "Field4"}}, + {{Field: "FirstLevel2"}, {Field: "Field6"}}, + } + if _, err := nM.Set(&utils.FullPath{Path: order[0].String(), PathItems: order[0]}, &utils.NMSlice{ + &NMItem{Path: strings.Split(order[0].String(), utils.NestingSep), + Data: "attrVal1", + Config: &FCTemplate{Tag: "AttributeTest", AttributeID: "attribute1"}}, + &NMItem{Path: strings.Split(order[0].String(), utils.NestingSep), + Data: "Value2"}}); err != nil { + t.Error(err) + } + if _, err := nM.Set(&utils.FullPath{Path: order[1].String(), PathItems: order[1]}, &utils.NMSlice{ + &NMItem{Path: strings.Split(order[1].String(), utils.NestingSep), + Data: "Val1"}}); err != nil { + t.Error(err) + } + if _, err := nM.Set(&utils.FullPath{Path: order[2].String(), PathItems: order[2]}, &utils.NMSlice{ + &NMItem{Path: strings.Split(order[2].String(), utils.NestingSep), + Data: "Value3"}}); err != nil { + t.Error(err) + } + if _, err := nM.Set(&utils.FullPath{Path: order[3].String(), PathItems: order[3]}, &utils.NMSlice{ + &NMItem{Path: strings.Split(order[3].String(), utils.NestingSep), + Data: "Value5"}, + &NMItem{Path: strings.Split(order[3].String(), utils.NestingSep), + Data: "attrVal5", + Config: &FCTemplate{Tag: "AttributeTest", AttributeID: "attribute5"}}}); err != nil { + t.Error(err) + } + if _, err := nM.Set(&utils.FullPath{Path: order[4].String(), PathItems: order[4]}, &utils.NMSlice{ + &NMItem{Path: strings.Split(order[4].String(), utils.NestingSep), + Data: "Val4"}, + &NMItem{Path: strings.Split(order[4].String(), utils.NestingSep), + Data: "attrVal2", + Config: &FCTemplate{Tag: "AttributeTest", AttributeID: "attribute2"}}}); err != nil { + t.Error(err) + } + if _, err := nM.Set(&utils.FullPath{Path: order[5].String(), PathItems: order[5]}, &utils.NMSlice{ + &NMItem{Path: strings.Split(order[5].String(), utils.NestingSep), + Data: "Value6", + Config: &FCTemplate{Tag: "NewBranchTest", NewBranch: true}}, + &NMItem{Path: strings.Split(order[5].String(), utils.NestingSep), + Data: "attrVal6", + Config: &FCTemplate{Tag: "AttributeTest", AttributeID: "attribute6"}}}); err != nil { + t.Error(err) + } + eXMLElmnts := []*XMLElement{ + &XMLElement{ + XMLName: xml.Name{Local: order[0][0].String()}, + Elements: []*XMLElement{ + &XMLElement{ + XMLName: xml.Name{Local: order[0][1].String()}, + Elements: []*XMLElement{ + &XMLElement{ + XMLName: xml.Name{Local: order[0][2].String()}, + Attributes: []*xml.Attr{ + &xml.Attr{ + Name: xml.Name{Local: "attribute1"}, + Value: "attrVal1", + }, + }, + Value: "Value2", + }, + }, + }, + &XMLElement{ + XMLName: xml.Name{Local: "Field3"}, + Value: "Value3", + }, + &XMLElement{ + XMLName: xml.Name{Local: order[3][1].String()}, + Attributes: []*xml.Attr{ + &xml.Attr{ + Name: xml.Name{Local: "attribute5"}, + Value: "attrVal5", + }, + }, + Value: "Value5", + }, + }, + }, + &XMLElement{ + XMLName: xml.Name{Local: order[1][0].String()}, + Elements: []*XMLElement{ + &XMLElement{ + XMLName: xml.Name{Local: order[1][1].String()}, + Elements: []*XMLElement{ + &XMLElement{ + XMLName: xml.Name{Local: order[1][2].String()}, + Elements: []*XMLElement{ + &XMLElement{ + XMLName: xml.Name{Local: "Fld1"}, + Value: "Val1", + }, + }, + }, + }, + }, + }, + }, + &XMLElement{ + XMLName: xml.Name{Local: order[4][0].String()}, + Attributes: []*xml.Attr{ + &xml.Attr{ + Name: xml.Name{Local: "attribute2"}, + Value: "attrVal2", + }, + }, + Value: "Val4", + }, + &XMLElement{ + XMLName: xml.Name{Local: order[5][0].String()}, + Elements: []*XMLElement{ + &XMLElement{ + XMLName: xml.Name{Local: order[5][1].String()}, + Attributes: []*xml.Attr{ + &xml.Attr{ + Name: xml.Name{Local: "attribute6"}, + Value: "attrVal6", + }, + }, + Value: "Value6", + }, + }, + }, + } + xmlEnts, err := NMAsXMLElements(nM) + if err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eXMLElmnts, xmlEnts) { + t.Errorf("expecting: %s, received: %s", utils.ToJSON(eXMLElmnts), utils.ToJSON(xmlEnts)) + } + eXML := []byte(` + + Value2 + + Value3 + Value5 + + + + + Val1 + + + +Val4 + + Value6 +`) + if output, err := xml.MarshalIndent(xmlEnts, "", " "); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eXML, output) { + t.Errorf("expecting: \n%s, received: \n%s\n", string(eXML), string(output)) + } +} + +func TestNMAsCGREvent(t *testing.T) { + if cgrEv := NMAsCGREvent(nil, "cgrates.org", + utils.NestingSep); cgrEv != nil { + t.Errorf("expecting: %+v, \nreceived: %+v", utils.ToJSON(nil), utils.ToJSON(cgrEv.Event)) + } + + nM := utils.NewOrderedNavigableMap() + if cgrEv := NMAsCGREvent(nM, "cgrates.org", + utils.NestingSep); cgrEv != nil { + t.Errorf("expecting: %+v, \nreceived: %+v", utils.ToJSON(nil), utils.ToJSON(cgrEv.Event)) + } + + path := utils.PathItems{{Field: "FirstLevel"}, {Field: "SecondLevel"}, {Field: "ThirdLevel"}, {Field: "Fld1"}} + if _, err := nM.Set(&utils.FullPath{Path: path.String(), PathItems: path}, &utils.NMSlice{&NMItem{ + Path: strings.Split(path.String(), utils.NestingSep), + Data: "Val1", + }}); err != nil { + t.Error(err) + } + + path = utils.PathItems{{Field: "FirstLevel2"}, {Field: "SecondLevel2"}, {Field: "Field2"}} + if _, err := nM.Set(&utils.FullPath{Path: path.String(), PathItems: path}, &utils.NMSlice{&NMItem{ + Path: strings.Split(path.String(), utils.NestingSep), + Data: "attrVal1", + Config: &FCTemplate{Tag: "AttributeTest", + AttributeID: "attribute1"}, + }, &NMItem{ + Path: strings.Split(path.String(), utils.NestingSep), + Data: "Value2", + }}); err != nil { + t.Error(err) + } + + path = utils.PathItems{{Field: "FirstLevel2"}, {Field: "Field3"}} + if _, err := nM.Set(&utils.FullPath{Path: path.String(), PathItems: path}, &utils.NMSlice{&NMItem{ + Path: strings.Split(path.String(), utils.NestingSep), + Data: "Value3", + }}); err != nil { + t.Error(err) + } + + path = utils.PathItems{{Field: "FirstLevel2"}, {Field: "Field5"}} + if _, err := nM.Set(&utils.FullPath{Path: path.String(), PathItems: path}, &utils.NMSlice{&NMItem{ + Path: strings.Split(path.String(), utils.NestingSep), + Data: "Value5", + }, &NMItem{ + Path: strings.Split(path.String(), utils.NestingSep), + Data: "attrVal5", + Config: &FCTemplate{Tag: "AttributeTest", + AttributeID: "attribute5"}, + }}); err != nil { + t.Error(err) + } + + path = utils.PathItems{{Field: "FirstLevel2"}, {Field: "Field6"}} + if _, err := nM.Set(&utils.FullPath{Path: path.String(), PathItems: path}, &utils.NMSlice{&NMItem{ + Path: strings.Split(path.String(), utils.NestingSep), + Data: "Value6", + Config: &FCTemplate{Tag: "NewBranchTest", + NewBranch: true}, + }, &NMItem{ + Path: strings.Split(path.String(), utils.NestingSep), + Data: "attrVal6", + Config: &FCTemplate{Tag: "AttributeTest", + AttributeID: "attribute6"}, + }}); err != nil { + t.Error(err) + } + + path = utils.PathItems{{Field: "Field4"}} + if _, err := nM.Set(&utils.FullPath{Path: path.String(), PathItems: path}, &utils.NMSlice{&NMItem{ + Path: strings.Split(path.String(), utils.NestingSep), + Data: "Val4", + }, &NMItem{ + Path: strings.Split(path.String(), utils.NestingSep), + Data: "attrVal2", + Config: &FCTemplate{Tag: "AttributeTest", + AttributeID: "attribute2"}, + }}); err != nil { + t.Error(err) + } + eEv := map[string]interface{}{ + "FirstLevel2.SecondLevel2.Field2": "Value2", + "FirstLevel.SecondLevel.ThirdLevel.Fld1": "Val1", + "FirstLevel2.Field3": "Value3", + "FirstLevel2.Field5": "Value5", + "FirstLevel2.Field6": "Value6", + "Field4": "Val4", + } + if cgrEv := NMAsCGREvent(nM, "cgrates.org", + utils.NestingSep); cgrEv.Tenant != "cgrates.org" || + cgrEv.Time == nil || + !reflect.DeepEqual(eEv, cgrEv.Event) { + t.Errorf("expecting: %+v, \nreceived: %+v", utils.ToJSON(eEv), utils.ToJSON(cgrEv.Event)) + } +} + +func TestNMItemLen(t *testing.T) { + var nm utils.NMInterface = &NMItem{Data: "1001"} + if rply := nm.Len(); rply != 0 { + t.Errorf("Expected 0 ,received: %v", rply) + } +} + +func TestNMItemString(t *testing.T) { + var nm utils.NMInterface = &NMItem{Data: "1001"} + expected := "{\"Path\":null,\"Data\":\"1001\",\"Config\":null}" + if rply := nm.String(); rply != expected { + t.Errorf("Expected %q ,received: %q", expected, rply) + } +} + +func TestNMItemInterface(t *testing.T) { + var nm utils.NMInterface = &NMItem{Data: "1001"} + expected := "1001" + if rply := nm.Interface(); rply != expected { + t.Errorf("Expected %q ,received: %q", expected, rply) + } +} + +func TestNMItemField(t *testing.T) { + var nm utils.NMInterface = &NMItem{Data: "1001"} + if _, err := nm.Field(nil); err != utils.ErrNotImplemented { + t.Error(err) + } +} + +func TestNMItemRemove(t *testing.T) { + var nm utils.NMInterface = &NMItem{Data: "1001"} + if err := nm.Remove(nil); err != utils.ErrNotImplemented { + t.Error(err) + } +} + +func TestNMItemEmpty(t *testing.T) { + var nm utils.NMInterface = &NMItem{Data: "1001"} + if nm.Empty() { + t.Error("Expected not empty type") + } + nm = &NMItem{Data: nil} + if !nm.Empty() { + t.Error("Expected empty type") + } +} + +func TestNMItemType(t *testing.T) { + var nm utils.NMInterface = &NMItem{Data: "1001"} + if nm.Type() != utils.NMDataType { + t.Errorf("Expected %v ,received: %v", utils.NMDataType, nm.Type()) + } +} + +func TestNMItemSet(t *testing.T) { + var nm utils.NMInterface = &NMItem{Data: "1001"} + if _, err := nm.Set(utils.PathItems{{}}, nil); err != utils.ErrWrongPath { + t.Error(err) + } + if _, err := nm.Set(nil, &NMItem{Data: "1002"}); err != nil { + t.Error(err) + } + expected := "1002" + if rply := nm.Interface(); rply != expected { + t.Errorf("Expected %q ,received: %q", expected, rply) + } +} diff --git a/engine/action.go b/engine/action.go index 74bed805d..0ed3b4774 100644 --- a/engine/action.go +++ b/engine/action.go @@ -898,20 +898,20 @@ func newCdrLogProvider(acnt *Account, action *Action) (dP utils.DataProvider) { return } -// cdrLogProvider implements engine.DataProvider so we can pass it to filters +// cdrLogProvider implements utils.DataProvider so we can pass it to filters type cdrLogProvider struct { acnt *Account action *Action cache *config.NavigableMap } -// String is part of engine.DataProvider interface +// String is part of utils.DataProvider interface // when called, it will display the already parsed values out of cache func (cdrP *cdrLogProvider) String() string { return utils.ToJSON(cdrP) } -// FieldAsInterface is part of engine.DataProvider interface +// FieldAsInterface is part of utils.DataProvider interface func (cdrP *cdrLogProvider) FieldAsInterface(fldPath []string) (data interface{}, err error) { if len(fldPath) != 1 { return nil, utils.ErrNotFound @@ -967,7 +967,7 @@ func (cdrP *cdrLogProvider) FieldAsInterface(fldPath []string) (data interface{} return } -// FieldAsString is part of engine.DataProvider interface +// FieldAsString is part of utils.DataProvider interface func (cdrP *cdrLogProvider) FieldAsString(fldPath []string) (data string, err error) { var valIface interface{} valIface, err = cdrP.FieldAsInterface(fldPath) @@ -977,7 +977,7 @@ func (cdrP *cdrLogProvider) FieldAsString(fldPath []string) (data string, err er return utils.IfaceAsString(valIface), nil } -// RemoteHost is part of engine.DataProvider interface +// RemoteHost is part of utils.DataProvider interface func (cdrP *cdrLogProvider) RemoteHost() net.Addr { return utils.LocalAddr() } diff --git a/general_tests/cdrs_onlexp_it_test.go b/general_tests/cdrs_onlexp_it_test.go index 97ff9f16a..4e65cad1e 100644 --- a/general_tests/cdrs_onlexp_it_test.go +++ b/general_tests/cdrs_onlexp_it_test.go @@ -503,8 +503,8 @@ func testCDRsOnExpFileFailover(t *testing.T) { t.Errorf("For file <%s> and event <%s> received %s", filePath, utils.ToJSON(ev), err) } } - if !reflect.DeepEqual(expectedFormats.Data(), rcvFormats.Data()) { - t.Errorf("Missing format expecting: %s received: %s", utils.ToJSON(expectedFormats.Data()), utils.ToJSON(rcvFormats.Data())) + if !reflect.DeepEqual(expectedFormats, rcvFormats) { + t.Errorf("Missing format expecting: %s received: %s", utils.ToJSON(expectedFormats), utils.ToJSON(rcvFormats)) } } diff --git a/loaders/libloader.go b/loaders/libloader.go index 57632db41..1f06cd03b 100644 --- a/loaders/libloader.go +++ b/loaders/libloader.go @@ -89,20 +89,20 @@ func newCsvProvider(record []string, fileName string) (dP utils.DataProvider) { return } -// csvProvider implements engine.DataProvider so we can pass it to filters +// csvProvider implements utils.DataProvider so we can pass it to filters type csvProvider struct { req []string fileName string cache *config.NavigableMap } -// String is part of engine.DataProvider interface +// String is part of utils.DataProvider interface // when called, it will display the already parsed values out of cache func (cP *csvProvider) String() string { return utils.ToJSON(cP) } -// FieldAsInterface is part of engine.DataProvider interface +// FieldAsInterface is part of utils.DataProvider interface func (cP *csvProvider) FieldAsInterface(fldPath []string) (data interface{}, err error) { if data, err = cP.cache.FieldAsInterface(fldPath); err == nil || err != utils.ErrNotFound { // item found in cache @@ -129,7 +129,7 @@ func (cP *csvProvider) FieldAsInterface(fldPath []string) (data interface{}, err return } -// FieldAsString is part of engine.DataProvider interface +// FieldAsString is part of utils.DataProvider interface func (cP *csvProvider) FieldAsString(fldPath []string) (data string, err error) { var valIface interface{} valIface, err = cP.FieldAsInterface(fldPath) @@ -139,7 +139,7 @@ func (cP *csvProvider) FieldAsString(fldPath []string) (data string, err error) return utils.IfaceAsString(valIface), nil } -// RemoteHost is part of engine.DataProvider interface +// RemoteHost is part of utils.DataProvider interface func (cP *csvProvider) RemoteHost() net.Addr { return utils.LocalAddr() }