From c13a5cf790e86ec645f24e89c9dcc5f2476b1625 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Fri, 26 Mar 2021 14:10:53 +0200 Subject: [PATCH] Finished implementing the DataNode as a replacement --- actions/log.go | 2 +- agents/agentreq.go | 86 ++-- agents/agentreq_test.go | 286 +++++------ agents/diamagent.go | 2 +- agents/dnsagent.go | 2 +- agents/httpagent.go | 2 +- agents/libdiam.go | 10 +- agents/libdiam_test.go | 102 ++-- agents/libdns.go | 21 +- agents/libdns_test.go | 71 ++- agents/libhttpagent.go | 13 +- agents/librad.go | 17 +- agents/libsip.go | 10 +- agents/radagent.go | 2 +- agents/sipagent.go | 2 +- config/cdrscfg.go | 4 +- config/config.go | 23 +- config/config_it_test.go | 10 +- config/config_json.go | 164 +++--- config/configs.go | 9 +- config/configsanity.go | 10 +- config/datadbcfg.go | 1 - config/eescfg.go | 7 +- config/fctemplate.go | 25 +- config/fctemplate_test.go | 2 +- config/loaderscfg_test.go | 2 - config/navigablemap_test.go | 481 ------------------ config/rpcconn.go | 2 - ees/ees_test.go | 2 +- ees/elastic.go | 6 +- ees/httpjsonmap.go | 12 +- ees/httppost.go | 12 +- ees/posterjsonmap.go | 6 +- engine/account.go | 7 +- engine/account_test.go | 4 +- engine/action.go | 4 +- engine/actions_test.go | 25 +- engine/balances.go | 10 +- engine/callcost.go | 2 +- engine/calldesc.go | 2 +- engine/caps.go | 1 - engine/caps_test.go | 4 +- engine/cdr.go | 36 +- engine/destinations_test.go | 3 + engine/dispatcherprfl.go | 4 - engine/eventrequest.go | 28 +- engine/filters_test.go | 3 +- engine/libcdre.go | 1 - engine/libroutes_test.go | 12 +- engine/mapevent_test.go | 9 +- engine/model_helpers.go | 45 +- engine/pstr_amqp.go | 1 - engine/pstr_amqpv1.go | 9 - engine/rateinterval.go | 12 +- engine/rateinterval_test.go | 6 +- engine/routes.go | 2 - engine/safevent.go | 2 - engine/statmetrics_test.go | 20 +- engine/stats.go | 1 - engine/storage_mongo_stordb.go | 14 +- engine/storage_mysql.go | 14 +- engine/storage_postgres.go | 14 +- engine/storage_redis.go | 5 +- engine/storage_sql.go | 23 +- engine/storage_utils.go | 2 +- engine/thresholds.go | 1 - engine/tpexporter.go | 90 ++-- engine/tpimporter_csv.go | 222 ++++---- engine/z_datamanager_it_test.go | 3 +- engine/z_libcdre_it_test.go | 2 +- engine/z_stordb_it_test.go | 8 +- ers/amqp.go | 2 +- ers/amqpv1.go | 2 +- ers/filecsv.go | 2 +- ers/filefwv.go | 8 +- ers/filejson.go | 2 +- ers/filexml.go | 2 +- ers/flatstore.go | 2 +- ers/kafka.go | 2 +- ers/partial_csv.go | 2 +- ers/s3.go | 2 +- ers/sql.go | 2 +- ers/sqs.go | 2 +- packages/debian/changelog | 1 + utils/cgrevent.go | 34 ++ utils/cgrevent_test.go | 92 ++++ utils/datanode.go | 166 +++--- utils/dataprovider_test.go | 8 +- utils/orderednavigablemap.go | 101 ++-- utils/orderednavigablemap_test.go | 139 ++--- utils/pathitem.go | 13 +- utils/pathitem_test.go | 13 +- config/navigablemap.go => utils/xmlelement.go | 80 +-- utils/xmlelement_test.go | 284 +++++++++++ 94 files changed, 1398 insertions(+), 1620 deletions(-) delete mode 100644 config/navigablemap_test.go rename config/navigablemap.go => utils/xmlelement.go (54%) create mode 100644 utils/xmlelement_test.go diff --git a/actions/log.go b/actions/log.go index 3af1a6a74..2a4dca0c1 100644 --- a/actions/log.go +++ b/actions/log.go @@ -90,7 +90,7 @@ func (aL *actCDRLog) execute(_ context.Context, data utils.MapStorage, _ string) utils.CDRsV1ProcessEvent, &engine.ArgV1ProcessEvent{ Flags: []string{utils.ConcatenatedKey(utils.MetaChargers, utils.FalseStr)}, // do not try to get the chargers for cdrlog - CGREvent: *config.NMAsCGREvent(cdrLogReq.OrdNavMP[utils.MetaCDR], cdrLogReq.Tenant, + CGREvent: *utils.NMAsCGREvent(cdrLogReq.OrdNavMP[utils.MetaCDR], cdrLogReq.Tenant, utils.NestingSep, optsMS), }, &rply) } diff --git a/agents/agentreq.go b/agents/agentreq.go index 944cac99e..374d20a09 100644 --- a/agents/agentreq.go +++ b/agents/agentreq.go @@ -172,7 +172,7 @@ func (ar *AgentRequest) SetFields(tplFlds []*config.FCTemplate) (err error) { case utils.MetaNone: case utils.MetaRemove: if err = ar.Remove(&utils.FullPath{ - PathItems: tplFld.GetPathItems(), + PathSlice: tplFld.GetPathSlice(), Path: tplFld.Path, }); err != nil { return @@ -195,20 +195,16 @@ func (ar *AgentRequest) SetFields(tplFlds []*config.FCTemplate) (err error) { return } var fullPath *utils.FullPath - var itmPath []string if fullPath, err = utils.GetFullFieldPath(tplFld.Path, ar); err != nil { return } else if fullPath == nil { // no dynamic path fullPath = &utils.FullPath{ - PathItems: utils.CloneStringSlice(tplFld.GetPathItems()), // need to clone so me do not modify the template + PathSlice: utils.CloneStringSlice(tplFld.GetPathSlice()), // need to clone so me do not modify the template Path: tplFld.Path, } - itmPath = tplFld.GetPathSlice()[1:] - } else { - itmPath = fullPath.PathItems[1:] } - nMItm := &utils.DataLeaf{Data: out, Path: itmPath, NewBranch: tplFld.NewBranch, AttributeID: tplFld.AttributeID} + nMItm := &utils.DataLeaf{Data: out, NewBranch: tplFld.NewBranch, AttributeID: tplFld.AttributeID} switch tplFld.Type { case utils.MetaComposed: err = ar.Compose(fullPath, nMItm) @@ -230,35 +226,35 @@ func (ar *AgentRequest) SetFields(tplFlds []*config.FCTemplate) (err error) { // Set implements utils.NMInterface func (ar *AgentRequest) SetAsSlice(fullPath *utils.FullPath, nm *utils.DataLeaf) (err error) { - switch fullPath.PathItems[0] { + switch fullPath.PathSlice[0] { default: - return fmt.Errorf("unsupported field prefix: <%s> when set field", fullPath.PathItems[0]) + return fmt.Errorf("unsupported field prefix: <%s> when set field", fullPath.PathSlice[0]) case utils.MetaVars: - _, err = ar.Vars.Set(fullPath.PathItems[1:], []*utils.DataNode{{Type: utils.NMDataType, Value: nm}}) + _, err = ar.Vars.Set(fullPath.PathSlice[1:], []*utils.DataNode{{Type: utils.NMDataType, Value: nm}}) return case utils.MetaCgreq: return ar.CGRRequest.SetAsSlice(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], + PathSlice: fullPath.PathSlice[1:], Path: fullPath.Path[7:], }, []*utils.DataNode{{Type: utils.NMDataType, Value: nm}}) case utils.MetaCgrep: - _, err = ar.CGRReply.Set(fullPath.PathItems[1:], []*utils.DataNode{{Type: utils.NMDataType, Value: nm}}) + _, err = ar.CGRReply.Set(fullPath.PathSlice[1:], []*utils.DataNode{{Type: utils.NMDataType, Value: nm}}) return case utils.MetaRep: return ar.Reply.SetAsSlice(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], + PathSlice: fullPath.PathSlice[1:], Path: fullPath.Path[5:], }, []*utils.DataNode{{Type: utils.NMDataType, Value: nm}}) case utils.MetaDiamreq: return ar.diamreq.SetAsSlice(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], + PathSlice: fullPath.PathSlice[1:], Path: fullPath.Path[9:], }, []*utils.DataNode{{Type: utils.NMDataType, Value: nm}}) case utils.MetaTmp: - _, err = ar.tmp.Set(fullPath.PathItems[1:], []*utils.DataNode{{Type: utils.NMDataType, Value: nm}}) + _, err = ar.tmp.Set(fullPath.PathSlice[1:], []*utils.DataNode{{Type: utils.NMDataType, Value: nm}}) return case utils.MetaOpts: - return ar.Opts.Set(fullPath.PathItems[1:], nm.Data) + return ar.Opts.Set(fullPath.PathSlice[1:], nm.Data) case utils.MetaUCH: return engine.Cache.Set(utils.CacheUCH, fullPath.Path[5:], nm.Data, nil, true, utils.NonTransactional) } @@ -291,32 +287,32 @@ func (ar *AgentRequest) RemoveAll(prefix string) error { // Remove deletes the fields found at path with the given prefix func (ar *AgentRequest) Remove(fullPath *utils.FullPath) error { - switch fullPath.PathItems[0] { + switch fullPath.PathSlice[0] { default: - return fmt.Errorf("unsupported field prefix: <%s> when set fields", fullPath.PathItems[0]) + return fmt.Errorf("unsupported field prefix: <%s> when set fields", fullPath.PathSlice[0]) case utils.MetaVars: - return ar.Vars.Remove(utils.CloneStringSlice(fullPath.PathItems[1:])) + return ar.Vars.Remove(utils.CloneStringSlice(fullPath.PathSlice[1:])) case utils.MetaCgreq: return ar.CGRRequest.Remove(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], + PathSlice: fullPath.PathSlice[1:], Path: fullPath.Path[7:], }) case utils.MetaCgrep: - return ar.CGRReply.Remove(utils.CloneStringSlice(fullPath.PathItems[1:])) + return ar.CGRReply.Remove(utils.CloneStringSlice(fullPath.PathSlice[1:])) case utils.MetaRep: return ar.Reply.Remove(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], + PathSlice: fullPath.PathSlice[1:], Path: fullPath.Path[5:], }) case utils.MetaDiamreq: return ar.diamreq.Remove(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], + PathSlice: fullPath.PathSlice[1:], Path: fullPath.Path[9:], }) case utils.MetaTmp: - return ar.tmp.Remove(utils.CloneStringSlice(fullPath.PathItems[1:])) + return ar.tmp.Remove(utils.CloneStringSlice(fullPath.PathSlice[1:])) case utils.MetaOpts: - return ar.Opts.Remove(fullPath.PathItems[1:]) + return ar.Opts.Remove(fullPath.PathSlice[1:]) case utils.MetaUCH: return engine.Cache.Remove(utils.CacheUCH, fullPath.Path[5:], true, utils.NonTransactional) } @@ -498,38 +494,38 @@ func needsMaxUsage(ralsFlags utils.FlagParams) bool { ralsFlags.Has(utils.MetaUpdate)) } -// Set sets the value at the given path +// Append sets the value at the given path // this used with full path and the processed path to not calculate them for every set func (ar *AgentRequest) Append(fullPath *utils.FullPath, val *utils.DataLeaf) (err error) { - switch fullPath.PathItems[0] { + switch fullPath.PathSlice[0] { default: - return fmt.Errorf("unsupported field prefix: <%s> when set field", fullPath.PathItems[0]) + return fmt.Errorf("unsupported field prefix: <%s> when set field", fullPath.PathSlice[0]) case utils.MetaVars: - _, err = ar.Vars.Append(fullPath.PathItems[1:], val) + _, err = ar.Vars.Append(fullPath.PathSlice[1:], val) return case utils.MetaCgreq: return ar.CGRRequest.Append(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], + PathSlice: fullPath.PathSlice[1:], Path: fullPath.Path[7:], }, val) case utils.MetaCgrep: - _, err = ar.CGRReply.Append(fullPath.PathItems[1:], val) + _, err = ar.CGRReply.Append(fullPath.PathSlice[1:], val) return case utils.MetaRep: return ar.Reply.Append(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], + PathSlice: fullPath.PathSlice[1:], Path: fullPath.Path[5:], }, val) case utils.MetaDiamreq: return ar.diamreq.Append(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], + PathSlice: fullPath.PathSlice[1:], Path: fullPath.Path[9:], }, val) case utils.MetaTmp: - _, err = ar.tmp.Append(fullPath.PathItems[1:], val) + _, err = ar.tmp.Append(fullPath.PathSlice[1:], val) return case utils.MetaOpts: - return ar.Opts.Set(fullPath.PathItems[1:], val.Data) + return ar.Opts.Set(fullPath.PathSlice[1:], val.Data) case utils.MetaUCH: return engine.Cache.Set(utils.CacheUCH, fullPath.Path[5:], val.Data, nil, true, utils.NonTransactional) } @@ -538,33 +534,33 @@ func (ar *AgentRequest) Append(fullPath *utils.FullPath, val *utils.DataLeaf) (e // Set sets the value at the given path // this used with full path and the processed path to not calculate them for every set func (ar *AgentRequest) Compose(fullPath *utils.FullPath, val *utils.DataLeaf) (err error) { - switch fullPath.PathItems[0] { + switch fullPath.PathSlice[0] { default: - return fmt.Errorf("unsupported field prefix: <%s> when set field", fullPath.PathItems[0]) + return fmt.Errorf("unsupported field prefix: <%s> when set field", fullPath.PathSlice[0]) case utils.MetaVars: - return ar.Vars.Compose(fullPath.PathItems[1:], val) + return ar.Vars.Compose(fullPath.PathSlice[1:], val) case utils.MetaCgreq: return ar.CGRRequest.Compose(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], + PathSlice: fullPath.PathSlice[1:], Path: fullPath.Path[7:], }, val) case utils.MetaCgrep: - return ar.CGRReply.Compose(fullPath.PathItems[1:], val) + return ar.CGRReply.Compose(fullPath.PathSlice[1:], val) case utils.MetaRep: return ar.Reply.Compose(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], + PathSlice: fullPath.PathSlice[1:], Path: fullPath.Path[5:], }, val) case utils.MetaDiamreq: return ar.diamreq.Compose(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], + PathSlice: fullPath.PathSlice[1:], Path: fullPath.Path[9:], }, val) case utils.MetaTmp: - return ar.tmp.Compose(fullPath.PathItems[1:], val) + return ar.tmp.Compose(fullPath.PathSlice[1:], val) case utils.MetaOpts: var prv interface{} - if prv, err = ar.Opts.FieldAsInterface(fullPath.PathItems[1:]); err != nil { + if prv, err = ar.Opts.FieldAsInterface(fullPath.PathSlice[1:]); err != nil { if err != utils.ErrNotFound { return } @@ -572,7 +568,7 @@ func (ar *AgentRequest) Compose(fullPath *utils.FullPath, val *utils.DataLeaf) ( } else { prv = utils.IfaceAsString(prv) + utils.IfaceAsString(val.Data) } - return ar.Opts.Set(fullPath.PathItems[1:], prv) + return ar.Opts.Set(fullPath.PathSlice[1:], prv) case utils.MetaUCH: path := fullPath.Path[5:] diff --git a/agents/agentreq_test.go b/agents/agentreq_test.go index 43363ce67..a1a9429be 100644 --- a/agents/agentreq_test.go +++ b/agents/agentreq_test.go @@ -44,15 +44,15 @@ func TestAgReqSetFields(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CGRID, PathItems: []string{utils.CGRID}}, + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CGRID, PathSlice: []string{utils.CGRID}}, utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String())) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.MetaVoice) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, "1001") - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, "1002") - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathSlice: []string{utils.ToR}}, utils.MetaVoice) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, "1001") + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathSlice: []string{utils.Destination}}, "1002") + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathSlice: []string{utils.AnswerTime}}, time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.MetaPrepaid) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Usage, PathItems: []string{utils.Usage}}, 3*time.Minute) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathSlice: []string{utils.RequestType}}, utils.MetaPrepaid) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Usage, PathSlice: []string{utils.Usage}}, 3*time.Minute) cgrRply := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{ utils.CapAttributes: {Type: utils.NMMapType, Map: map[string]*utils.DataNode{ @@ -112,18 +112,18 @@ func TestAgReqSetFields(t *testing.T) { } eMp := utils.NewOrderedNavigableMap() - eMp.SetAsSlice(&utils.FullPath{Path: utils.Tenant, PathItems: []string{utils.Tenant}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) - eMp.SetAsSlice(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) - eMp.SetAsSlice(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{utils.Destination}}}}) - eMp.SetAsSlice(&utils.FullPath{Path: "RequestedUsage", PathItems: []string{"RequestedUsage"}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "180", Path: []string{"RequestedUsage"}}}}) - eMp.SetAsSlice(&utils.FullPath{Path: "PaypalAccount", PathItems: []string{"PaypalAccount"}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates@paypal.com", Path: []string{"PaypalAccount"}}}}) - eMp.SetAsSlice(&utils.FullPath{Path: "MaxUsage", PathItems: []string{"MaxUsage"}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "120", Path: []string{"MaxUsage"}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: utils.Tenant, PathSlice: []string{utils.Tenant}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org"}}}) + eMp.SetAsSlice(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001"}}}) + eMp.SetAsSlice(&utils.FullPath{Path: utils.Destination, PathSlice: []string{utils.Destination}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002"}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "RequestedUsage", PathSlice: []string{"RequestedUsage"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "180"}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "PaypalAccount", PathSlice: []string{"PaypalAccount"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates@paypal.com"}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "MaxUsage", PathSlice: []string{"MaxUsage"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "120"}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -493,7 +493,7 @@ func TestAgReqMaxCost(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CapMaxUsage, PathItems: []string{utils.CapMaxUsage}}, utils.NewLeafNode("120s")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CapMaxUsage, PathSlice: []string{utils.CapMaxUsage}}, utils.NewLeafNode("120s")) agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{ utils.CapMaxUsage: utils.NewLeafNode(120 * time.Second), @@ -509,8 +509,8 @@ func TestAgReqMaxCost(t *testing.T) { tplFlds[0].ComputePath() eMp := utils.NewOrderedNavigableMap() - eMp.SetAsSlice(&utils.FullPath{Path: "MaxUsage", PathItems: []string{"MaxUsage"}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "120", Path: []string{"MaxUsage"}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "MaxUsage", PathSlice: []string{"MaxUsage"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "120"}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -736,10 +736,10 @@ func TestAgReqEmptyFilter(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CGRID, PathItems: []string{utils.CGRID}}, + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CGRID, PathSlice: []string{utils.CGRID}}, utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String())) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathSlice: []string{utils.Destination}}, utils.NewLeafNode("1002")) tplFlds := []*config.FCTemplate{ {Tag: "Tenant", Filters: []string{}, @@ -758,11 +758,11 @@ func TestAgReqEmptyFilter(t *testing.T) { } eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} eMp.Set([]string{utils.Tenant}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org"}}}) eMp.Set([]string{utils.AccountField}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001"}}}) eMp.Set([]string{utils.Destination}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{utils.Destination}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002"}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -777,8 +777,8 @@ func TestAgReqMetaExponent(t *testing.T) { config.CgrConfig().CacheCfg(), nil) filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set(&utils.FullPath{Path: "Value", PathItems: []string{"Value"}}, utils.NewLeafNode("2")) - agReq.CGRRequest.Set(&utils.FullPath{Path: "Exponent", PathItems: []string{"Exponent"}}, utils.NewLeafNode("2")) + agReq.CGRRequest.Set(&utils.FullPath{Path: "Value", PathSlice: []string{"Value"}}, utils.NewLeafNode("2")) + agReq.CGRRequest.Set(&utils.FullPath{Path: "Exponent", PathSlice: []string{"Exponent"}}, utils.NewLeafNode("2")) tplFlds := []*config.FCTemplate{ {Tag: "TestExpo", Filters: []string{}, @@ -788,7 +788,7 @@ func TestAgReqMetaExponent(t *testing.T) { tplFlds[0].ComputePath() eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} eMp.Set([]string{"TestExpo"}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "200", Path: []string{"TestExpo"}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "200"}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -804,9 +804,9 @@ func TestAgReqFieldAsNone(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathSlice: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathSlice: []string{utils.Destination}}, utils.NewLeafNode("1002")) tplFlds := []*config.FCTemplate{ {Tag: "Tenant", @@ -825,9 +825,9 @@ func TestAgReqFieldAsNone(t *testing.T) { } eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} eMp.Set([]string{utils.Tenant}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org"}}}) eMp.Set([]string{utils.AccountField}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001"}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) } else if !reflect.DeepEqual(agReq.CGRReply, eMp) { @@ -842,9 +842,9 @@ func TestAgReqFieldAsNone2(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathSlice: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathSlice: []string{utils.Destination}}, utils.NewLeafNode("1002")) tplFlds := []*config.FCTemplate{ {Tag: "Tenant", @@ -863,11 +863,11 @@ func TestAgReqFieldAsNone2(t *testing.T) { } eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} eMp.Set([]string{utils.Tenant}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org"}}}) eMp.Set([]string{utils.AccountField}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001"}}}) eMp.Set([]string{utils.Destination}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{utils.Destination}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002"}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) } else if !reflect.DeepEqual(agReq.CGRReply, eMp) { @@ -882,12 +882,12 @@ func TestAgReqSetField2(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, utils.NewLeafNode( + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathSlice: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathSlice: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathSlice: []string{utils.AnswerTime}}, utils.NewLeafNode( time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathSlice: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} @@ -914,15 +914,15 @@ func TestAgReqSetField2(t *testing.T) { } eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} eMp.Set([]string{utils.Tenant}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org"}}}) eMp.Set([]string{utils.AccountField}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001"}}}) eMp.Set([]string{utils.Destination}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{utils.Destination}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002"}}}) eMp.Set([]string{"Usage"}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "30s", Path: []string{"Usage"}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "30s"}}}) eMp.Set([]string{"CalculatedUsage"}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: time.Date(2013, 12, 30, 14, 59, 31, 0, time.UTC), Path: []string{"CalculatedUsage"}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: time.Date(2013, 12, 30, 14, 59, 31, 0, time.UTC)}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -939,10 +939,10 @@ func TestAgReqFieldAsInterface(t *testing.T) { agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent agReq.CGRRequest = utils.NewOrderedNavigableMap() - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Usage, PathItems: []string{utils.Usage}}, &utils.DataNode{Type: utils.NMSliceType, Slice: []*utils.DataNode{{Type: utils.NMDataType, Value: &utils.DataLeaf{Data: 3 * time.Minute}}}}) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, &utils.DataNode{Type: utils.NMSliceType, Slice: []*utils.DataNode{{Type: utils.NMDataType, Value: &utils.DataLeaf{Data: utils.MetaVoice}}}}) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Usage, PathSlice: []string{utils.Usage}}, &utils.DataNode{Type: utils.NMSliceType, Slice: []*utils.DataNode{{Type: utils.NMDataType, Value: &utils.DataLeaf{Data: 3 * time.Minute}}}}) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathSlice: []string{utils.ToR}}, &utils.DataNode{Type: utils.NMSliceType, Slice: []*utils.DataNode{{Type: utils.NMDataType, Value: &utils.DataLeaf{Data: utils.MetaVoice}}}}) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathSlice: []string{utils.Destination}}, utils.NewLeafNode("1002")) path := []string{utils.MetaCgreq, utils.Usage} var expVal interface{} @@ -987,9 +987,9 @@ func TestAgReqNewARWithCGRRplyAndRply(t *testing.T) { rply := utils.NewOrderedNavigableMap() rply.Set(&utils.FullPath{ Path: "FirstLevel.SecondLevel.Fld1", - PathItems: []string{"FirstLevel", "SecondLevel", "Fld1"}}, utils.NewLeafNode("Val1")) + PathSlice: []string{"FirstLevel", "SecondLevel", "Fld1"}}, utils.NewLeafNode("Val1")) cgrRply := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{ - utils.CapAttributes: &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{ + utils.CapAttributes: {Type: utils.NMMapType, Map: map[string]*utils.DataNode{ "PaypalAccount": utils.NewLeafNode("cgrates@paypal.com"), }}, utils.CapMaxUsage: utils.NewLeafNode(120 * time.Second), @@ -1011,10 +1011,10 @@ func TestAgReqNewARWithCGRRplyAndRply(t *testing.T) { } eMp := utils.NewOrderedNavigableMap() - eMp.SetAsSlice(&utils.FullPath{Path: "Fld1", PathItems: []string{"Fld1"}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "Val1", Path: []string{"Fld1"}}}}) - eMp.SetAsSlice(&utils.FullPath{Path: "Fld2", PathItems: []string{"Fld2"}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates@paypal.com", Path: []string{"Fld2"}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "Fld1", PathSlice: []string{"Fld1"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "Val1"}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "Fld2", PathSlice: []string{"Fld2"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates@paypal.com"}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -1032,7 +1032,7 @@ func TestAgReqSetCGRReplyWithError(t *testing.T) { rply := utils.NewOrderedNavigableMap() rply.Set(&utils.FullPath{ Path: "FirstLevel.SecondLevel.Fld1", - PathItems: []string{"FirstLevel", "SecondLevel", "Fld1"}}, utils.NewLeafNode("Val1")) + PathSlice: []string{"FirstLevel", "SecondLevel", "Fld1"}}, utils.NewLeafNode("Val1")) agReq := NewAgentRequest(nil, nil, nil, rply, nil, nil, "cgrates.org", "", filterS, nil, nil) agReq.setCGRReply(nil, utils.ErrNotFound) @@ -1070,7 +1070,7 @@ func TestAgReqSetCGRReplyWithoutError(t *testing.T) { rply := utils.NewOrderedNavigableMap() rply.Set(&utils.FullPath{ Path: "FirstLevel.SecondLevel.Fld1", - PathItems: []string{"FirstLevel", "SecondLevel", "Fld1"}}, utils.NewLeafNode("Val1")) + PathSlice: []string{"FirstLevel", "SecondLevel", "Fld1"}}, utils.NewLeafNode("Val1")) myEv := myEv{ utils.CapAttributes: &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{ @@ -1097,10 +1097,10 @@ func TestAgReqSetCGRReplyWithoutError(t *testing.T) { v.ComputePath() } eMp := utils.NewOrderedNavigableMap() - eMp.SetAsSlice(&utils.FullPath{Path: "Fld1", PathItems: []string{"Fld1"}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "Val1", Path: []string{"Fld1"}}}}) - eMp.SetAsSlice(&utils.FullPath{Path: "Fld2", PathItems: []string{"Fld2"}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates@paypal.com", Path: []string{"Fld2"}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "Fld1", PathSlice: []string{"Fld1"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "Val1"}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "Fld2", PathSlice: []string{"Fld2"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates@paypal.com"}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -1509,12 +1509,12 @@ func TestAgReqOverwrite(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, utils.NewLeafNode( + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathSlice: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathSlice: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathSlice: []string{utils.AnswerTime}}, utils.NewLeafNode( time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathSlice: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} @@ -1561,12 +1561,12 @@ func TestAgReqGroupType(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, utils.NewLeafNode( + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathSlice: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathSlice: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathSlice: []string{utils.AnswerTime}}, utils.NewLeafNode( time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathSlice: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} @@ -1604,7 +1604,7 @@ func TestAgReqSetFieldsInTmp(t *testing.T) { dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil) filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, utils.NewLeafNode("1001")) tplFlds := []*config.FCTemplate{ {Tag: "Tenant", @@ -1619,9 +1619,9 @@ func TestAgReqSetFieldsInTmp(t *testing.T) { } eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} eMp.Set([]string{utils.Tenant}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org"}}}) eMp.Set([]string{utils.AccountField}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001"}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -1636,7 +1636,7 @@ func TestAgReqSetFieldsIp2Hex(t *testing.T) { dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil) filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set(&utils.FullPath{Path: "IP", PathItems: []string{"IP"}}, utils.NewLeafNode("62.87.114.244")) + agReq.CGRRequest.Set(&utils.FullPath{Path: "IP", PathSlice: []string{"IP"}}, utils.NewLeafNode("62.87.114.244")) tplFlds := []*config.FCTemplate{ {Tag: "IP", @@ -1648,7 +1648,7 @@ func TestAgReqSetFieldsIp2Hex(t *testing.T) { } eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} eMp.Set([]string{"IP"}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "0x3e5772f4", Path: []string{"IP"}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "0x3e5772f4"}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -1663,7 +1663,7 @@ func TestAgReqSetFieldsString2Hex(t *testing.T) { dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil) filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set(&utils.FullPath{Path: "CustomField", PathItems: []string{"CustomField"}}, utils.NewLeafNode(string([]byte{0x94, 0x71, 0x02, 0x31, 0x01, 0x59}))) + agReq.CGRRequest.Set(&utils.FullPath{Path: "CustomField", PathSlice: []string{"CustomField"}}, utils.NewLeafNode(string([]byte{0x94, 0x71, 0x02, 0x31, 0x01, 0x59}))) tplFlds := []*config.FCTemplate{ {Tag: "CustomField", @@ -1675,7 +1675,7 @@ func TestAgReqSetFieldsString2Hex(t *testing.T) { } eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} eMp.Set([]string{"CustomField"}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "0x947102310159", Path: []string{"CustomField"}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "0x947102310159"}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -1691,18 +1691,18 @@ func TestAgReqSetFieldsWithRemove(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CGRID, PathItems: []string{utils.CGRID}}, + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.CGRID, PathSlice: []string{utils.CGRID}}, utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String())) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, utils.NewLeafNode( + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathSlice: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathSlice: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathSlice: []string{utils.AnswerTime}}, utils.NewLeafNode( time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Usage, PathItems: []string{utils.Usage}}, utils.NewLeafNode(3*time.Minute)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathSlice: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Usage, PathSlice: []string{utils.Usage}}, utils.NewLeafNode(3*time.Minute)) agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{ - utils.CapAttributes: &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{ + utils.CapAttributes: {Type: utils.NMMapType, Map: map[string]*utils.DataNode{ "PaypalAccount": utils.NewLeafNode("cgrates@paypal.com"), }}, utils.CapMaxUsage: utils.NewLeafNode(120 * time.Second), @@ -1756,18 +1756,18 @@ func TestAgReqSetFieldsWithRemove(t *testing.T) { v.ComputePath() } eMp := utils.NewOrderedNavigableMap() - eMp.SetAsSlice(&utils.FullPath{Path: utils.Tenant, PathItems: []string{utils.Tenant}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) - eMp.SetAsSlice(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) - eMp.SetAsSlice(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{utils.Destination}}}}) - eMp.SetAsSlice(&utils.FullPath{Path: "RequestedUsage", PathItems: []string{"RequestedUsage"}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "180", Path: []string{"RequestedUsage"}}}}) - eMp.SetAsSlice(&utils.FullPath{Path: "PaypalAccount", PathItems: []string{"PaypalAccount"}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates@paypal.com", Path: []string{"PaypalAccount"}}}}) - eMp.SetAsSlice(&utils.FullPath{Path: "MaxUsage", PathItems: []string{"MaxUsage"}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "120", Path: []string{"MaxUsage"}}}}) + eMp.SetAsSlice(&utils.FullPath{Path: utils.Tenant, PathSlice: []string{utils.Tenant}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org"}}}) + eMp.SetAsSlice(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001"}}}) + eMp.SetAsSlice(&utils.FullPath{Path: utils.Destination, PathSlice: []string{utils.Destination}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002"}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "RequestedUsage", PathSlice: []string{"RequestedUsage"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "180"}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "PaypalAccount", PathSlice: []string{"PaypalAccount"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates@paypal.com"}}}) + eMp.SetAsSlice(&utils.FullPath{Path: "MaxUsage", PathSlice: []string{"MaxUsage"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "120"}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -1785,14 +1785,14 @@ func TestAgReqSetFieldsWithRemove(t *testing.T) { v.ComputePath() } eMpRemove := utils.NewOrderedNavigableMap() - eMpRemove.SetAsSlice(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{utils.Destination}}}}) - eMpRemove.SetAsSlice(&utils.FullPath{Path: "RequestedUsage", PathItems: []string{"RequestedUsage"}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "180", Path: []string{"RequestedUsage"}}}}) - eMpRemove.SetAsSlice(&utils.FullPath{Path: "PaypalAccount", PathItems: []string{"PaypalAccount"}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates@paypal.com", Path: []string{"PaypalAccount"}}}}) - eMpRemove.SetAsSlice(&utils.FullPath{Path: "MaxUsage", PathItems: []string{"MaxUsage"}}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "120", Path: []string{"MaxUsage"}}}}) + eMpRemove.SetAsSlice(&utils.FullPath{Path: utils.Destination, PathSlice: []string{utils.Destination}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002"}}}) + eMpRemove.SetAsSlice(&utils.FullPath{Path: "RequestedUsage", PathSlice: []string{"RequestedUsage"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "180"}}}) + eMpRemove.SetAsSlice(&utils.FullPath{Path: "PaypalAccount", PathSlice: []string{"PaypalAccount"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates@paypal.com"}}}) + eMpRemove.SetAsSlice(&utils.FullPath{Path: "MaxUsage", PathSlice: []string{"MaxUsage"}}, []*utils.DataNode{ + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "120"}}}) if err := agReq.SetFields(tplFldsRemove); err != nil { t.Error(err) @@ -1819,7 +1819,7 @@ func TestAgReqSetFieldsInCache(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) engine.NewCacheS(cfg, dm, nil) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, utils.NewLeafNode("1001")) tplFlds := []*config.FCTemplate{ {Tag: "Tenant", @@ -1862,7 +1862,7 @@ func TestAgReqSetFieldsInCacheWithTimeOut(t *testing.T) { cfg.CacheCfg().Partitions[utils.CacheUCH].TTL = time.Second engine.Cache = engine.NewCacheS(cfg, dm, nil) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, utils.NewLeafNode("1001")) tplFlds := []*config.FCTemplate{ {Tag: "Tenant", @@ -1986,15 +1986,15 @@ func TestAgReqDynamicPath(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, utils.NewLeafNode( + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathSlice: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathSlice: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathSlice: []string{utils.AnswerTime}}, utils.NewLeafNode( time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) - agReq.CGRRequest.Set(&utils.FullPath{Path: "Routes.CGR_ROUTE1", PathItems: []string{"Routes", "CGR_ROUTE1"}}, utils.NewLeafNode(1001)) - agReq.CGRRequest.Set(&utils.FullPath{Path: "Routes.CGR_ROUTE2", PathItems: []string{"Routes", "CGR_ROUTE2"}}, utils.NewLeafNode(1002)) - agReq.CGRRequest.Set(&utils.FullPath{Path: "BestRoute", PathItems: []string{"BestRoute"}}, utils.NewLeafNode("ROUTE1")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathSlice: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) + agReq.CGRRequest.Set(&utils.FullPath{Path: "Routes.CGR_ROUTE1", PathSlice: []string{"Routes", "CGR_ROUTE1"}}, utils.NewLeafNode(1001)) + agReq.CGRRequest.Set(&utils.FullPath{Path: "Routes.CGR_ROUTE2", PathSlice: []string{"Routes", "CGR_ROUTE2"}}, utils.NewLeafNode(1002)) + agReq.CGRRequest.Set(&utils.FullPath{Path: "BestRoute", PathSlice: []string{"BestRoute"}}, utils.NewLeafNode("ROUTE1")) agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} val1, err := config.NewRSRParsersFromSlice([]string{"~*cgreq.Routes."}) @@ -2028,17 +2028,17 @@ func TestAgReqDynamicPath(t *testing.T) { } eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} eMp.Set([]string{utils.Tenant}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org"}}}) eMp.Set([]string{utils.AccountField}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001"}}}) eMp.Set([]string{utils.Destination}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{utils.Destination}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002"}}}) eMp.Set([]string{"Usage"}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "30s", Path: []string{"Usage"}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "30s"}}}) eMp.Set([]string{"Route"}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{"Route"}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001"}}}) eMp.Set([]string{"Route2", "CGR_ROUTE1"}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002", Path: []string{"Route2", "CGR_ROUTE1"}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1002"}}}) if err := agReq.SetFields(tplFlds); err != nil { t.Error(err) @@ -2054,13 +2054,13 @@ func TestAgReqRoundingDecimals(t *testing.T) { filterS := engine.NewFilterS(cfg, nil, dm) agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, utils.NewLeafNode( + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathSlice: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathSlice: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathSlice: []string{utils.AnswerTime}}, utils.NewLeafNode( time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Cost, PathItems: []string{utils.Cost}}, utils.NewLeafNode(12.12645)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathSlice: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Cost, PathSlice: []string{utils.Cost}}, utils.NewLeafNode(12.12645)) agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} @@ -2120,22 +2120,22 @@ func BenchmarkAgReqSetField(b *testing.B) { } eMp := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} eMp.Set([]string{utils.Tenant}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org", Path: []string{utils.Tenant}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "cgrates.org"}}}) eMp.Set([]string{utils.AccountField, "0", "ID"}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001", Path: []string{utils.AccountField + "[0]", "ID"}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1001"}}}) eMp.Set([]string{utils.AccountField, "1", "ID"}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1003", Path: []string{utils.AccountField + "[1]", "ID"}}}}) + {Type: utils.NMDataType, Value: &utils.DataLeaf{Data: "1003"}}}) b.ResetTimer() for i := 0; i < b.N; i++ { agReq := NewAgentRequest(nil, nil, nil, nil, nil, nil, "cgrates.org", "", filterS, nil, nil) // populate request, emulating the way will be done in HTTPAgent - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathItems: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathItems: []string{utils.AccountField}}, utils.NewLeafNode("1001")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathItems: []string{utils.Destination}}, utils.NewLeafNode("1002")) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathItems: []string{utils.AnswerTime}}, utils.NewLeafNode( + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.ToR, PathSlice: []string{utils.ToR}}, utils.NewLeafNode(utils.MetaVoice)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AccountField, PathSlice: []string{utils.AccountField}}, utils.NewLeafNode("1001")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.Destination, PathSlice: []string{utils.Destination}}, utils.NewLeafNode("1002")) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.AnswerTime, PathSlice: []string{utils.AnswerTime}}, utils.NewLeafNode( time.Date(2013, 12, 30, 15, 0, 1, 0, time.UTC))) - agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathItems: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) + agReq.CGRRequest.Set(&utils.FullPath{Path: utils.RequestType, PathSlice: []string{utils.RequestType}}, utils.NewLeafNode(utils.MetaPrepaid)) agReq.CGRReply = &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} if err := agReq.SetFields(tplFlds); err != nil { diff --git a/agents/diamagent.go b/agents/diamagent.go index acd3b0869..ca2c91536 100644 --- a/agents/diamagent.go +++ b/agents/diamagent.go @@ -318,7 +318,7 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor, if err = agReq.SetFields(reqProcessor.RequestFields); err != nil { return } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) var reqType string for _, typ := range []string{ utils.MetaDryRun, utils.MetaAuthorize, diff --git a/agents/dnsagent.go b/agents/dnsagent.go index a84c67b0d..f2d8a0b00 100644 --- a/agents/dnsagent.go +++ b/agents/dnsagent.go @@ -179,7 +179,7 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor, if err = agReq.SetFields(reqProcessor.RequestFields); err != nil { return } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) var reqType string for _, typ := range []string{ utils.MetaDryRun, utils.MetaAuthorize, diff --git a/agents/httpagent.go b/agents/httpagent.go index 5bd8e7110..26912d552 100644 --- a/agents/httpagent.go +++ b/agents/httpagent.go @@ -112,7 +112,7 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor, if err = agReq.SetFields(reqProcessor.RequestFields); err != nil { return } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) var reqType string for _, typ := range []string{ utils.MetaDryRun, utils.MetaAuthorize, diff --git a/agents/libdiam.go b/agents/libdiam.go index 310896dca..ad21930e2 100644 --- a/agents/libdiam.go +++ b/agents/libdiam.go @@ -431,17 +431,15 @@ func updateDiamMsgFromNavMap(m *diam.Message, navMp *utils.OrderedNavigableMap, // write reply into message for el := navMp.GetFirstElement(); el != nil; el = el.Next() { path := el.Value - var nmIt *utils.DataLeaf - if nmIt, err = navMp.Field(path); err != nil { - return - } + nmIt, _ := navMp.Field(path) if nmIt == nil { continue // all attributes, not writable to diameter packet } + path = path[:len(path)-1] // remove the last index if err = messageSetAVPsWithPath(m, - nmIt.Path, nmIt.String(), + path, nmIt.String(), nmIt.NewBranch, tmz); err != nil { - return fmt.Errorf("setting item with path: %+v got err: %s", nmIt.Path, err.Error()) + return fmt.Errorf("setting item with path: %+v got err: %s", path, err.Error()) } } return diff --git a/agents/libdiam_test.go b/agents/libdiam_test.go index e62b1f7b4..cf065390b 100644 --- a/agents/libdiam_test.go +++ b/agents/libdiam_test.go @@ -429,31 +429,31 @@ func TestUpdateDiamMsgFromNavMap1(t *testing.T) { ) nM := utils.NewOrderedNavigableMap() + path := []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"} itm := &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, Data: datatype.Enumerated(2), }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) + path = []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"}, Data: datatype.Enumerated(2), }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) + path = []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, Data: "http://172.10.88.88/", }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) if err := updateDiamMsgFromNavMap(m2, nM, ""); err != nil { @@ -513,42 +513,42 @@ func TestUpdateDiamMsgFromNavMap2(t *testing.T) { ) nM := utils.NewOrderedNavigableMap() + path := []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"} itm := &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, Data: datatype.Enumerated(2), }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) + path = []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"}, Data: datatype.Enumerated(2), }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) + path = []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, Data: "http://172.10.88.88/", NewBranch: true, }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) + path = []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, Data: datatype.Enumerated(2), }} nM.Append( &utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, + Path: strings.Join(path, utils.NestingSep), + PathSlice: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, }, itm.Value) if err := updateDiamMsgFromNavMap(m2, nM, ""); err != nil { t.Error(err) @@ -585,40 +585,40 @@ func TestUpdateDiamMsgFromNavMap3(t *testing.T) { nM := utils.NewOrderedNavigableMap() + path := []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Final-Unit-Action"} itm := &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Final-Unit-Action"}, Data: datatype.Enumerated(1), }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) + path = []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, Data: datatype.Enumerated(2), }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) + path = []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"}, Data: datatype.Enumerated(2), }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) + path = []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, Data: "http://172.10.88.88/", }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) if err := updateDiamMsgFromNavMap(m2, nM, ""); err != nil { @@ -678,59 +678,59 @@ func TestUpdateDiamMsgFromNavMap4(t *testing.T) { nM := utils.NewOrderedNavigableMap() + path := []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Final-Unit-Action"} itm := &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Final-Unit-Action"}, Data: datatype.Enumerated(1), }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) + path = []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Address-Type"}, Data: datatype.Enumerated(2), }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) + path = []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Tariff-Change-Usage"}, Data: datatype.Enumerated(2), }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) + path = []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, Data: "http://172.10.88.88/", }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) + path = []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"} itm2 := &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Multiple-Services-Credit-Control", "Final-Unit-Indication", "Redirect-Server", "Redirect-Server-Address"}, Data: "http://172.10.88.88/", NewBranch: true, }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm, itm2}) + path = []string{"Granted-Service-Unit", "CC-Time"} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{"Granted-Service-Unit", "CC-Time"}, Data: datatype.Unsigned32(10), }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) if err := updateDiamMsgFromNavMap(m2, nM, ""); err != nil { diff --git a/agents/libdns.go b/agents/libdns.go index 64db5229e..3fc9932c1 100644 --- a/agents/libdns.go +++ b/agents/libdns.go @@ -156,15 +156,10 @@ func updateDNSMsgFromNM(msg *dns.Msg, nm *utils.OrderedNavigableMap) (err error) msgFields := make(utils.StringSet) // work around to NMap issue for el := nm.GetFirstElement(); el != nil; el = el.Next() { path := el.Value - var cfgItm *utils.DataLeaf - if cfgItm, err = nm.Field(path); err != nil { - return - } - if len(cfgItm.Path) == 0 { - return errors.New("empty path in config item") - } + cfgItm, _ := nm.Field(path) + // path = path[:len(path)-1] // no need to remove the last index here as this uses only the first level apnd := len(msg.Answer) == 0 - if msgFields.Has(cfgItm.Path[0]) { // force append if the same path was already used + if msgFields.Has(path[0]) { // force append if the same path was already used apnd = true } if apnd { @@ -174,11 +169,11 @@ func updateDNSMsgFromNM(msg *dns.Msg, nm *utils.OrderedNavigableMap) (err error) msgFields = make(utils.StringSet) // reset the fields inside since we have a new message } itmData := cfgItm.Data - switch cfgItm.Path[0] { + switch path[0] { case utils.Rcode: var itm int64 if itm, err = utils.IfaceAsInt64(itmData); err != nil { - return fmt.Errorf("item: <%s>, err: %s", cfgItm.Path[0], err.Error()) + return fmt.Errorf("item: <%s>, err: %s", path[0], err.Error()) } msg.Rcode = int(itm) case utils.Order: @@ -187,7 +182,7 @@ func updateDNSMsgFromNM(msg *dns.Msg, nm *utils.OrderedNavigableMap) (err error) } var itm int64 if itm, err = utils.IfaceAsInt64(itmData); err != nil { - return fmt.Errorf("item: <%s>, err: %s", cfgItm.Path[0], err.Error()) + return fmt.Errorf("item: <%s>, err: %s", path[0], err.Error()) } msg.Answer[len(msg.Answer)-1].(*dns.NAPTR).Order = uint16(itm) case utils.Preference: @@ -196,7 +191,7 @@ func updateDNSMsgFromNM(msg *dns.Msg, nm *utils.OrderedNavigableMap) (err error) } var itm int64 if itm, err = utils.IfaceAsInt64(itmData); err != nil { - return fmt.Errorf("item: <%s>, err: %s", cfgItm.Path[0], err.Error()) + return fmt.Errorf("item: <%s>, err: %s", path[0], err.Error()) } msg.Answer[len(msg.Answer)-1].(*dns.NAPTR).Preference = uint16(itm) case utils.Flags: @@ -221,7 +216,7 @@ func updateDNSMsgFromNM(msg *dns.Msg, nm *utils.OrderedNavigableMap) (err error) msg.Answer[len(msg.Answer)-1].(*dns.NAPTR).Replacement = utils.IfaceAsString(itmData) } - msgFields.Add(cfgItm.Path[0]) // detect new branch + msgFields.Add(path[0]) // detect new branch } return diff --git a/agents/libdns_test.go b/agents/libdns_test.go index 0f6efbe59..d4056fd85 100644 --- a/agents/libdns_test.go +++ b/agents/libdns_test.go @@ -176,24 +176,13 @@ func TestUpdateDNSMsgFromNM(t *testing.T) { m.SetQuestion("3.6.9.4.7.1.7.1.5.6.8.9.4.e164.arpa.", dns.TypeNAPTR) nM := utils.NewOrderedNavigableMap() + path := []string{utils.Rcode} itm := &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{}, - Data: "Val1", - }} - nM.SetAsSlice(&utils.FullPath{Path: "Path", PathItems: []string{"Path"}}, []*utils.DataNode{itm}) - if err := updateDNSMsgFromNM(m, nM); err == nil || - err.Error() != "empty path in config item" { - t.Error(err) - } - - nM = utils.NewOrderedNavigableMap() - itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{utils.Rcode}, Data: 10, }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err != nil { t.Fatal(err) @@ -203,13 +192,13 @@ func TestUpdateDNSMsgFromNM(t *testing.T) { } nM = utils.NewOrderedNavigableMap() + path = []string{utils.Rcode} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{utils.Rcode}, Data: "RandomValue", }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `item: , err: strconv.ParseInt: parsing "RandomValue": invalid syntax` { @@ -217,13 +206,13 @@ func TestUpdateDNSMsgFromNM(t *testing.T) { } nM = utils.NewOrderedNavigableMap() + path = []string{utils.Order} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{utils.Order}, Data: "RandomValue", }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `item: , err: strconv.ParseInt: parsing "RandomValue": invalid syntax` { @@ -231,13 +220,13 @@ func TestUpdateDNSMsgFromNM(t *testing.T) { } nM = utils.NewOrderedNavigableMap() + path = []string{utils.Preference} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{utils.Preference}, Data: "RandomValue", }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `item: , err: strconv.ParseInt: parsing "RandomValue": invalid syntax` { @@ -247,13 +236,13 @@ func TestUpdateDNSMsgFromNM(t *testing.T) { m = new(dns.Msg) m.SetQuestion("3.6.9.4.7.1.7.1.5.6.8.9.4.e164.arpa.", dns.TypeA) nM = utils.NewOrderedNavigableMap() + path = []string{utils.Order} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{utils.Order}, Data: 10, }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { @@ -261,13 +250,13 @@ func TestUpdateDNSMsgFromNM(t *testing.T) { } nM = utils.NewOrderedNavigableMap() + path = []string{utils.Preference} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{utils.Preference}, Data: 10, }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { @@ -275,13 +264,13 @@ func TestUpdateDNSMsgFromNM(t *testing.T) { } nM = utils.NewOrderedNavigableMap() + path = []string{utils.Flags} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{utils.Flags}, Data: 10, }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { @@ -289,13 +278,13 @@ func TestUpdateDNSMsgFromNM(t *testing.T) { } nM = utils.NewOrderedNavigableMap() + path = []string{utils.Service} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{utils.Service}, Data: 10, }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { @@ -303,13 +292,13 @@ func TestUpdateDNSMsgFromNM(t *testing.T) { } nM = utils.NewOrderedNavigableMap() + path = []string{utils.Regexp} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{utils.Regexp}, Data: 10, }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { @@ -317,13 +306,13 @@ func TestUpdateDNSMsgFromNM(t *testing.T) { } nM = utils.NewOrderedNavigableMap() + path = []string{utils.Replacement} itm = &utils.DataNode{Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: []string{utils.Replacement}, Data: 10, }} nM.SetAsSlice(&utils.FullPath{ - Path: strings.Join(itm.Value.Path, utils.NestingSep), - PathItems: itm.Value.Path, + Path: strings.Join(path, utils.NestingSep), + PathSlice: path, }, []*utils.DataNode{itm}) if err := updateDNSMsgFromNM(m, nM); err == nil || err.Error() != `field only works with NAPTR` { diff --git a/agents/libhttpagent.go b/agents/libhttpagent.go index ae83a80e6..7bbc8ef63 100644 --- a/agents/libhttpagent.go +++ b/agents/libhttpagent.go @@ -29,7 +29,6 @@ import ( "strings" "github.com/antchfx/xmlquery" - "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" ) @@ -214,8 +213,8 @@ type haXMLEncoder struct { // Encode implements httpAgentReplyEncoder func (xE *haXMLEncoder) Encode(nM *utils.OrderedNavigableMap) (err error) { - var xmlElmnts []*config.XMLElement - if xmlElmnts, err = config.NMAsXMLElements(nM); err != nil { + var xmlElmnts []*utils.XMLElement + if xmlElmnts, err = utils.NMAsXMLElements(nM); err != nil { return } if len(xmlElmnts) == 0 { @@ -246,11 +245,9 @@ func (xE *haTextPlainEncoder) Encode(nM *utils.OrderedNavigableMap) (err error) msgFields := make(map[string]string) // work around to NMap issue for el := nM.GetFirstElement(); el != nil; el = el.Next() { path := el.Value - var nmIt *utils.DataLeaf - if nmIt, err = nM.Field(path); err != nil { - return - } - nmPath = strings.Join(nmIt.Path, utils.NestingSep) + nmIt, _ := nM.Field(path) + path = path[:len(path)-1] // remove the last index + nmPath = strings.Join(path, utils.NestingSep) val := nmIt.String() msgFields[utils.ConcatenatedKey(nmPath, val)] = val } diff --git a/agents/librad.go b/agents/librad.go index 7129424e9..1956394ff 100644 --- a/agents/librad.go +++ b/agents/librad.go @@ -28,23 +28,20 @@ import ( // radReplyAppendAttributes appends attributes to a RADIUS reply based on predefined template func radReplyAppendAttributes(reply *radigo.Packet, rplNM *utils.OrderedNavigableMap) (err error) { for el := rplNM.GetFirstElement(); el != nil; el = el.Next() { - val := el.Value - var cfgItm *utils.DataLeaf - if cfgItm, err = rplNM.Field(val); err != nil { - return - } - - if cfgItm.Path[0] == MetaRadReplyCode { // Special case used to control the reply code of RADIUS reply + path := el.Value + cfgItm, _ := rplNM.Field(path) + path = path[:len(path)-1] // remove the last index + if path[0] == MetaRadReplyCode { // Special case used to control the reply code of RADIUS reply if err = reply.SetCodeWithName(utils.IfaceAsString(cfgItm.Data)); err != nil { return err } continue } var attrName, vendorName string - if len(cfgItm.Path) > 2 { - vendorName, attrName = cfgItm.Path[0], cfgItm.Path[1] + if len(path) > 2 { + vendorName, attrName = path[0], path[1] } else { - attrName = cfgItm.Path[0] + attrName = path[0] } if err = reply.AddAVPWithName(attrName, utils.IfaceAsString(cfgItm.Data), vendorName); err != nil { diff --git a/agents/libsip.go b/agents/libsip.go index 7b61f6096..c8fab905a 100644 --- a/agents/libsip.go +++ b/agents/libsip.go @@ -32,15 +32,13 @@ import ( func updateSIPMsgFromNavMap(m sipingo.Message, navMp *utils.OrderedNavigableMap) (err error) { // write reply into message for el := navMp.GetFirstElement(); el != nil; el = el.Next() { - val := el.Value - var itm *utils.DataLeaf - if itm, err = navMp.Field(val); err != nil { - return - } + path := el.Value + itm, _ := navMp.Field(path) if itm == nil { continue // all attributes, not writable to diameter packet } - m[strings.Join(itm.Path, utils.NestingSep)] = utils.IfaceAsString(itm.Data) + path = path[:len(path)-1] // remove the last index + m[strings.Join(path, utils.NestingSep)] = utils.IfaceAsString(itm.Data) } return } diff --git a/agents/radagent.go b/agents/radagent.go index dc5f948c9..b88621be5 100644 --- a/agents/radagent.go +++ b/agents/radagent.go @@ -170,7 +170,7 @@ func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.R if err = agReq.SetFields(reqProcessor.RequestFields); err != nil { return } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) var reqType string for _, typ := range []string{ utils.MetaDryRun, utils.MetaAuthorize, diff --git a/agents/sipagent.go b/agents/sipagent.go index 9085eab7b..9f46f2a24 100644 --- a/agents/sipagent.go +++ b/agents/sipagent.go @@ -383,7 +383,7 @@ func (sa *SIPAgent) processRequest(reqProcessor *config.RequestProcessor, if err = agReq.SetFields(reqProcessor.RequestFields); err != nil { return } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) var reqType string for _, typ := range []string{ utils.MetaDryRun, utils.MetaAuthorize, /* diff --git a/config/cdrscfg.go b/config/cdrscfg.go index bebddb5c4..4cbd0899b 100644 --- a/config/cdrscfg.go +++ b/config/cdrscfg.go @@ -108,9 +108,7 @@ func (cdrscfg *CdrsCfg) loadFromJSONCfg(jsnCdrsCfg *CdrsJsonCfg) (err error) { } } if jsnCdrsCfg.Online_cdr_exports != nil { - for _, expProfile := range *jsnCdrsCfg.Online_cdr_exports { - cdrscfg.OnlineCDRExports = append(cdrscfg.OnlineCDRExports, expProfile) - } + cdrscfg.OnlineCDRExports = append(cdrscfg.OnlineCDRExports, *jsnCdrsCfg.Online_cdr_exports...) } if jsnCdrsCfg.Scheduler_conns != nil { cdrscfg.SchedulerConns = make([]string, len(*jsnCdrsCfg.Scheduler_conns)) diff --git a/config/config.go b/config/config.go index 73b884008..cfa99ac9d 100644 --- a/config/config.go +++ b/config/config.go @@ -689,15 +689,13 @@ func (cfg *CGRConfig) loadLoaderSCfg(jsnCfg *CgrJsonCfg) (err error) { if jsnLoaderCfg, err = jsnCfg.LoaderJsonCfg(); err != nil { return } - if jsnLoaderCfg != nil { - // cfg.loaderCfg = make(LoaderSCfgs, len(jsnLoaderCfg)) - for _, profile := range jsnLoaderCfg { - loadSCfgp := NewDfltLoaderSCfg() - if err = loadSCfgp.loadFromJSONCfg(profile, cfg.templates, cfg.generalCfg.RSRSep); err != nil { - return - } - cfg.loaderCfg = append(cfg.loaderCfg, loadSCfgp) // use apend so the loaderS profile to be loaded from multiple files + // cfg.loaderCfg = make(LoaderSCfgs, len(jsnLoaderCfg)) + for _, profile := range jsnLoaderCfg { + loadSCfgp := NewDfltLoaderSCfg() + if err = loadSCfgp.loadFromJSONCfg(profile, cfg.templates, cfg.generalCfg.RSRSep); err != nil { + return } + cfg.loaderCfg = append(cfg.loaderCfg, loadSCfgp) // use append so the loaderS profile to be loaded from multiple files } return } @@ -843,11 +841,9 @@ func (cfg *CGRConfig) loadTemplateSCfg(jsnCfg *CgrJsonCfg) (err error) { if jsnTemplateCfg, err = jsnCfg.TemplateSJsonCfg(); err != nil { return } - if jsnTemplateCfg != nil { - for k, val := range jsnTemplateCfg { - if cfg.templates[k], err = FCTemplatesFromFCTemplatesJSONCfg(val, cfg.generalCfg.RSRSep); err != nil { - return - } + for k, val := range jsnTemplateCfg { + if cfg.templates[k], err = FCTemplatesFromFCTemplatesJSONCfg(val, cfg.generalCfg.RSRSep); err != nil { + return } } return @@ -1572,7 +1568,6 @@ func (cfg *CGRConfig) reloadSections(sections ...string) { cfg.rldChans[ActionSJson] <- struct{}{} } } - return } // AsMapInterface returns the config as a map[string]interface{} diff --git a/config/config_it_test.go b/config/config_it_test.go index ba8859250..01398526c 100644 --- a/config/config_it_test.go +++ b/config/config_it_test.go @@ -37,8 +37,6 @@ import ( ) var ( - cgrConfigDIR string - cgrTests = []func(t *testing.T){ testNewCgrJsonCfgFromHttp, testNewCGRConfigFromPath, @@ -1142,7 +1140,7 @@ func testLoadConfigFromFolderFileNotFound(t *testing.T) { func testLoadConfigFromFolderOpenError(t *testing.T) { newDir := "/tmp/testLoadConfigFromFolderOpenError" - if err = os.MkdirAll(newDir, 755); err != nil { + if err = os.MkdirAll(newDir, 0755); err != nil { t.Fatal(err) } cfg := NewDefaultCGRConfig() @@ -1160,7 +1158,7 @@ func testLoadConfigFromFolderOpenError(t *testing.T) { func testLoadConfigFromFolderNoConfigFound(t *testing.T) { newDir := "/tmp/[]" - if err = os.MkdirAll(newDir, 755); err != nil { + if err = os.MkdirAll(newDir, 0755); err != nil { t.Fatal(err) } cfg := NewDefaultCGRConfig() @@ -1188,7 +1186,7 @@ func testLoadConfigFromPathInvalidArgument(t *testing.T) { func testLoadConfigFromPathValidPath(t *testing.T) { newDir := "/tmp/testLoadConfigFromPathValidPath" - if err = os.MkdirAll(newDir, 755); err != nil { + if err = os.MkdirAll(newDir, 0755); err != nil { t.Fatal(err) } cfg := NewDefaultCGRConfig() @@ -1206,7 +1204,7 @@ func testLoadConfigFromPathValidPath(t *testing.T) { func testLoadConfigFromPathFile(t *testing.T) { newDir := "/tmp/testLoadConfigFromPathFile" - if err = os.MkdirAll(newDir, 755); err != nil { + if err = os.MkdirAll(newDir, 0755); err != nil { t.Fatal(err) } cfg := NewDefaultCGRConfig() diff --git a/config/config_json.go b/config/config_json.go index 7610236bd..a869c6d14 100644 --- a/config/config_json.go +++ b/config/config_json.go @@ -89,8 +89,8 @@ func NewCgrJsonCfgFromBytes(buf []byte) (cgrJsonCfg *CgrJsonCfg, err error) { // Main object holding the loaded config as section raw messages type CgrJsonCfg map[string]*json.RawMessage -func (self CgrJsonCfg) GeneralJsonCfg() (*GeneralJsonCfg, error) { - rawCfg, hasKey := self[GENERAL_JSN] +func (jsnCfg CgrJsonCfg) GeneralJsonCfg() (*GeneralJsonCfg, error) { + rawCfg, hasKey := jsnCfg[GENERAL_JSN] if !hasKey { return nil, nil } @@ -101,8 +101,8 @@ func (self CgrJsonCfg) GeneralJsonCfg() (*GeneralJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) RPCConnJsonCfg() (map[string]*RPCConnsJson, error) { - rawCfg, hasKey := self[RPCConnsJsonName] +func (jsnCfg CgrJsonCfg) RPCConnJsonCfg() (map[string]*RPCConnsJson, error) { + rawCfg, hasKey := jsnCfg[RPCConnsJsonName] if !hasKey { return nil, nil } @@ -113,8 +113,8 @@ func (self CgrJsonCfg) RPCConnJsonCfg() (map[string]*RPCConnsJson, error) { return cfg, nil } -func (self CgrJsonCfg) CacheJsonCfg() (*CacheJsonCfg, error) { - rawCfg, hasKey := self[CACHE_JSN] +func (jsnCfg CgrJsonCfg) CacheJsonCfg() (*CacheJsonCfg, error) { + rawCfg, hasKey := jsnCfg[CACHE_JSN] if !hasKey { return nil, nil } @@ -125,8 +125,8 @@ func (self CgrJsonCfg) CacheJsonCfg() (*CacheJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) ListenJsonCfg() (*ListenJsonCfg, error) { - rawCfg, hasKey := self[LISTEN_JSN] +func (jsnCfg CgrJsonCfg) ListenJsonCfg() (*ListenJsonCfg, error) { + rawCfg, hasKey := jsnCfg[LISTEN_JSN] if !hasKey { return nil, nil } @@ -137,8 +137,8 @@ func (self CgrJsonCfg) ListenJsonCfg() (*ListenJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) HttpJsonCfg() (*HTTPJsonCfg, error) { - rawCfg, hasKey := self[HTTP_JSN] +func (jsnCfg CgrJsonCfg) HttpJsonCfg() (*HTTPJsonCfg, error) { + rawCfg, hasKey := jsnCfg[HTTP_JSN] if !hasKey { return nil, nil } @@ -149,8 +149,8 @@ func (self CgrJsonCfg) HttpJsonCfg() (*HTTPJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) DbJsonCfg(section string) (*DbJsonCfg, error) { - rawCfg, hasKey := self[section] +func (jsnCfg CgrJsonCfg) DbJsonCfg(section string) (*DbJsonCfg, error) { + rawCfg, hasKey := jsnCfg[section] if !hasKey { return nil, nil } @@ -173,8 +173,8 @@ func (jsnCfg CgrJsonCfg) FilterSJsonCfg() (*FilterSJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) RalsJsonCfg() (*RalsJsonCfg, error) { - rawCfg, hasKey := self[RALS_JSN] +func (jsnCfg CgrJsonCfg) RalsJsonCfg() (*RalsJsonCfg, error) { + rawCfg, hasKey := jsnCfg[RALS_JSN] if !hasKey { return nil, nil } @@ -185,8 +185,8 @@ func (self CgrJsonCfg) RalsJsonCfg() (*RalsJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) SchedulerJsonCfg() (*SchedulerJsonCfg, error) { - rawCfg, hasKey := self[SCHEDULER_JSN] +func (jsnCfg CgrJsonCfg) SchedulerJsonCfg() (*SchedulerJsonCfg, error) { + rawCfg, hasKey := jsnCfg[SCHEDULER_JSN] if !hasKey { return nil, nil } @@ -197,8 +197,8 @@ func (self CgrJsonCfg) SchedulerJsonCfg() (*SchedulerJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) CdrsJsonCfg() (*CdrsJsonCfg, error) { - rawCfg, hasKey := self[CDRS_JSN] +func (jsnCfg CgrJsonCfg) CdrsJsonCfg() (*CdrsJsonCfg, error) { + rawCfg, hasKey := jsnCfg[CDRS_JSN] if !hasKey { return nil, nil } @@ -209,8 +209,8 @@ func (self CgrJsonCfg) CdrsJsonCfg() (*CdrsJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) ERsJsonCfg() (erSCfg *ERsJsonCfg, err error) { - rawCfg, hasKey := self[ERsJson] +func (jsnCfg CgrJsonCfg) ERsJsonCfg() (erSCfg *ERsJsonCfg, err error) { + rawCfg, hasKey := jsnCfg[ERsJson] if !hasKey { return } @@ -219,8 +219,8 @@ func (self CgrJsonCfg) ERsJsonCfg() (erSCfg *ERsJsonCfg, err error) { return } -func (self CgrJsonCfg) EEsJsonCfg() (erSCfg *EEsJsonCfg, err error) { - rawCfg, hasKey := self[EEsJson] +func (jsnCfg CgrJsonCfg) EEsJsonCfg() (erSCfg *EEsJsonCfg, err error) { + rawCfg, hasKey := jsnCfg[EEsJson] if !hasKey { return } @@ -229,8 +229,8 @@ func (self CgrJsonCfg) EEsJsonCfg() (erSCfg *EEsJsonCfg, err error) { return } -func (self CgrJsonCfg) SessionSJsonCfg() (*SessionSJsonCfg, error) { - rawCfg, hasKey := self[SessionSJson] +func (jsnCfg CgrJsonCfg) SessionSJsonCfg() (*SessionSJsonCfg, error) { + rawCfg, hasKey := jsnCfg[SessionSJson] if !hasKey { return nil, nil } @@ -241,8 +241,8 @@ func (self CgrJsonCfg) SessionSJsonCfg() (*SessionSJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) FreeswitchAgentJsonCfg() (*FreeswitchAgentJsonCfg, error) { - rawCfg, hasKey := self[FreeSWITCHAgentJSN] +func (jsnCfg CgrJsonCfg) FreeswitchAgentJsonCfg() (*FreeswitchAgentJsonCfg, error) { + rawCfg, hasKey := jsnCfg[FreeSWITCHAgentJSN] if !hasKey { return nil, nil } @@ -253,8 +253,8 @@ func (self CgrJsonCfg) FreeswitchAgentJsonCfg() (*FreeswitchAgentJsonCfg, error) return cfg, nil } -func (self CgrJsonCfg) KamAgentJsonCfg() (*KamAgentJsonCfg, error) { - rawCfg, hasKey := self[KamailioAgentJSN] +func (jsnCfg CgrJsonCfg) KamAgentJsonCfg() (*KamAgentJsonCfg, error) { + rawCfg, hasKey := jsnCfg[KamailioAgentJSN] if !hasKey { return nil, nil } @@ -265,8 +265,8 @@ func (self CgrJsonCfg) KamAgentJsonCfg() (*KamAgentJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) AsteriskAgentJsonCfg() (*AsteriskAgentJsonCfg, error) { - rawCfg, hasKey := self[AsteriskAgentJSN] +func (jsnCfg CgrJsonCfg) AsteriskAgentJsonCfg() (*AsteriskAgentJsonCfg, error) { + rawCfg, hasKey := jsnCfg[AsteriskAgentJSN] if !hasKey { return nil, nil } @@ -277,8 +277,8 @@ func (self CgrJsonCfg) AsteriskAgentJsonCfg() (*AsteriskAgentJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) DiameterAgentJsonCfg() (*DiameterAgentJsonCfg, error) { - rawCfg, hasKey := self[DA_JSN] +func (jsnCfg CgrJsonCfg) DiameterAgentJsonCfg() (*DiameterAgentJsonCfg, error) { + rawCfg, hasKey := jsnCfg[DA_JSN] if !hasKey { return nil, nil } @@ -289,8 +289,8 @@ func (self CgrJsonCfg) DiameterAgentJsonCfg() (*DiameterAgentJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) RadiusAgentJsonCfg() (*RadiusAgentJsonCfg, error) { - rawCfg, hasKey := self[RA_JSN] +func (jsnCfg CgrJsonCfg) RadiusAgentJsonCfg() (*RadiusAgentJsonCfg, error) { + rawCfg, hasKey := jsnCfg[RA_JSN] if !hasKey { return nil, nil } @@ -301,8 +301,8 @@ func (self CgrJsonCfg) RadiusAgentJsonCfg() (*RadiusAgentJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) HttpAgentJsonCfg() (*[]*HttpAgentJsonCfg, error) { - rawCfg, hasKey := self[HttpAgentJson] +func (jsnCfg CgrJsonCfg) HttpAgentJsonCfg() (*[]*HttpAgentJsonCfg, error) { + rawCfg, hasKey := jsnCfg[HttpAgentJson] if !hasKey { return nil, nil } @@ -313,8 +313,8 @@ func (self CgrJsonCfg) HttpAgentJsonCfg() (*[]*HttpAgentJsonCfg, error) { return &httpAgnt, nil } -func (self CgrJsonCfg) DNSAgentJsonCfg() (da *DNSAgentJsonCfg, err error) { - rawCfg, hasKey := self[DNSAgentJson] +func (jsnCfg CgrJsonCfg) DNSAgentJsonCfg() (da *DNSAgentJsonCfg, err error) { + rawCfg, hasKey := jsnCfg[DNSAgentJson] if !hasKey { return } @@ -347,8 +347,8 @@ func (cgrJsn CgrJsonCfg) ChargerServJsonCfg() (*ChargerSJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) ResourceSJsonCfg() (*ResourceSJsonCfg, error) { - rawCfg, hasKey := self[RESOURCES_JSON] +func (jsnCfg CgrJsonCfg) ResourceSJsonCfg() (*ResourceSJsonCfg, error) { + rawCfg, hasKey := jsnCfg[RESOURCES_JSON] if !hasKey { return nil, nil } @@ -359,8 +359,8 @@ func (self CgrJsonCfg) ResourceSJsonCfg() (*ResourceSJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) StatSJsonCfg() (*StatServJsonCfg, error) { - rawCfg, hasKey := self[STATS_JSON] +func (jsnCfg CgrJsonCfg) StatSJsonCfg() (*StatServJsonCfg, error) { + rawCfg, hasKey := jsnCfg[STATS_JSON] if !hasKey { return nil, nil } @@ -371,8 +371,8 @@ func (self CgrJsonCfg) StatSJsonCfg() (*StatServJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) ThresholdSJsonCfg() (*ThresholdSJsonCfg, error) { - rawCfg, hasKey := self[THRESHOLDS_JSON] +func (jsnCfg CgrJsonCfg) ThresholdSJsonCfg() (*ThresholdSJsonCfg, error) { + rawCfg, hasKey := jsnCfg[THRESHOLDS_JSON] if !hasKey { return nil, nil } @@ -383,8 +383,8 @@ func (self CgrJsonCfg) ThresholdSJsonCfg() (*ThresholdSJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) RouteSJsonCfg() (*RouteSJsonCfg, error) { - rawCfg, hasKey := self[RouteSJson] +func (jsnCfg CgrJsonCfg) RouteSJsonCfg() (*RouteSJsonCfg, error) { + rawCfg, hasKey := jsnCfg[RouteSJson] if !hasKey { return nil, nil } @@ -395,8 +395,8 @@ func (self CgrJsonCfg) RouteSJsonCfg() (*RouteSJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) LoaderJsonCfg() ([]*LoaderJsonCfg, error) { - rawCfg, hasKey := self[LoaderJson] +func (jsnCfg CgrJsonCfg) LoaderJsonCfg() ([]*LoaderJsonCfg, error) { + rawCfg, hasKey := jsnCfg[LoaderJson] if !hasKey { return nil, nil } @@ -407,8 +407,8 @@ func (self CgrJsonCfg) LoaderJsonCfg() ([]*LoaderJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) MailerJsonCfg() (*MailerJsonCfg, error) { - rawCfg, hasKey := self[MAILER_JSN] +func (jsnCfg CgrJsonCfg) MailerJsonCfg() (*MailerJsonCfg, error) { + rawCfg, hasKey := jsnCfg[MAILER_JSN] if !hasKey { return nil, nil } @@ -419,8 +419,8 @@ func (self CgrJsonCfg) MailerJsonCfg() (*MailerJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) SureTaxJsonCfg() (*SureTaxJsonCfg, error) { - rawCfg, hasKey := self[SURETAX_JSON] +func (jsnCfg CgrJsonCfg) SureTaxJsonCfg() (*SureTaxJsonCfg, error) { + rawCfg, hasKey := jsnCfg[SURETAX_JSON] if !hasKey { return nil, nil } @@ -431,8 +431,8 @@ func (self CgrJsonCfg) SureTaxJsonCfg() (*SureTaxJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) DispatcherSJsonCfg() (*DispatcherSJsonCfg, error) { - rawCfg, hasKey := self[DispatcherSJson] +func (jsnCfg CgrJsonCfg) DispatcherSJsonCfg() (*DispatcherSJsonCfg, error) { + rawCfg, hasKey := jsnCfg[DispatcherSJson] if !hasKey { return nil, nil } @@ -443,8 +443,8 @@ func (self CgrJsonCfg) DispatcherSJsonCfg() (*DispatcherSJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) RegistrarCJsonCfgs() (*RegistrarCJsonCfgs, error) { - rawCfg, hasKey := self[RegistrarCJson] +func (jsnCfg CgrJsonCfg) RegistrarCJsonCfgs() (*RegistrarCJsonCfgs, error) { + rawCfg, hasKey := jsnCfg[RegistrarCJson] if !hasKey { return nil, nil } @@ -455,8 +455,8 @@ func (self CgrJsonCfg) RegistrarCJsonCfgs() (*RegistrarCJsonCfgs, error) { return cfg, nil } -func (self CgrJsonCfg) LoaderCfgJson() (*LoaderCfgJson, error) { - rawCfg, hasKey := self[CgrLoaderCfgJson] +func (jsnCfg CgrJsonCfg) LoaderCfgJson() (*LoaderCfgJson, error) { + rawCfg, hasKey := jsnCfg[CgrLoaderCfgJson] if !hasKey { return nil, nil } @@ -467,8 +467,8 @@ func (self CgrJsonCfg) LoaderCfgJson() (*LoaderCfgJson, error) { return cfg, nil } -func (self CgrJsonCfg) MigratorCfgJson() (*MigratorCfgJson, error) { - rawCfg, hasKey := self[CgrMigratorCfgJson] +func (jsnCfg CgrJsonCfg) MigratorCfgJson() (*MigratorCfgJson, error) { + rawCfg, hasKey := jsnCfg[CgrMigratorCfgJson] if !hasKey { return nil, nil } @@ -479,8 +479,8 @@ func (self CgrJsonCfg) MigratorCfgJson() (*MigratorCfgJson, error) { return cfg, nil } -func (self CgrJsonCfg) TlsCfgJson() (*TlsJsonCfg, error) { - rawCfg, hasKey := self[TlsCfgJson] +func (jsnCfg CgrJsonCfg) TlsCfgJson() (*TlsJsonCfg, error) { + rawCfg, hasKey := jsnCfg[TlsCfgJson] if !hasKey { return nil, nil } @@ -491,8 +491,8 @@ func (self CgrJsonCfg) TlsCfgJson() (*TlsJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) AnalyzerCfgJson() (*AnalyzerSJsonCfg, error) { - rawCfg, hasKey := self[AnalyzerCfgJson] +func (jsnCfg CgrJsonCfg) AnalyzerCfgJson() (*AnalyzerSJsonCfg, error) { + rawCfg, hasKey := jsnCfg[AnalyzerCfgJson] if !hasKey { return nil, nil } @@ -503,8 +503,8 @@ func (self CgrJsonCfg) AnalyzerCfgJson() (*AnalyzerSJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) ApierCfgJson() (*ApierJsonCfg, error) { - rawCfg, hasKey := self[ApierS] +func (jsnCfg CgrJsonCfg) ApierCfgJson() (*ApierJsonCfg, error) { + rawCfg, hasKey := jsnCfg[ApierS] if !hasKey { return nil, nil } @@ -515,8 +515,8 @@ func (self CgrJsonCfg) ApierCfgJson() (*ApierJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) RateCfgJson() (*RateSJsonCfg, error) { - rawCfg, hasKey := self[RateSJson] +func (jsnCfg CgrJsonCfg) RateCfgJson() (*RateSJsonCfg, error) { + rawCfg, hasKey := jsnCfg[RateSJson] if !hasKey { return nil, nil } @@ -527,8 +527,8 @@ func (self CgrJsonCfg) RateCfgJson() (*RateSJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) SIPAgentJsonCfg() (*SIPAgentJsonCfg, error) { - rawCfg, hasKey := self[SIPAgentJson] +func (jsnCfg CgrJsonCfg) SIPAgentJsonCfg() (*SIPAgentJsonCfg, error) { + rawCfg, hasKey := jsnCfg[SIPAgentJson] if !hasKey { return nil, nil } @@ -539,8 +539,8 @@ func (self CgrJsonCfg) SIPAgentJsonCfg() (*SIPAgentJsonCfg, error) { return sipAgnt, nil } -func (self CgrJsonCfg) TemplateSJsonCfg() (map[string][]*FcTemplateJsonCfg, error) { - rawCfg, hasKey := self[TemplatesJson] +func (jsnCfg CgrJsonCfg) TemplateSJsonCfg() (map[string][]*FcTemplateJsonCfg, error) { + rawCfg, hasKey := jsnCfg[TemplatesJson] if !hasKey { return nil, nil } @@ -551,8 +551,8 @@ func (self CgrJsonCfg) TemplateSJsonCfg() (map[string][]*FcTemplateJsonCfg, erro return cfg, nil } -func (self CgrJsonCfg) ConfigSJsonCfg() (*ConfigSCfgJson, error) { - rawCfg, hasKey := self[ConfigSJson] +func (jsnCfg CgrJsonCfg) ConfigSJsonCfg() (*ConfigSCfgJson, error) { + rawCfg, hasKey := jsnCfg[ConfigSJson] if !hasKey { return nil, nil } @@ -563,8 +563,8 @@ func (self CgrJsonCfg) ConfigSJsonCfg() (*ConfigSCfgJson, error) { return cfg, nil } -func (self CgrJsonCfg) ApiBanCfgJson() (*APIBanJsonCfg, error) { - rawCfg, hasKey := self[APIBanCfgJson] +func (jsnCfg CgrJsonCfg) ApiBanCfgJson() (*APIBanJsonCfg, error) { + rawCfg, hasKey := jsnCfg[APIBanCfgJson] if !hasKey { return nil, nil } @@ -575,8 +575,8 @@ func (self CgrJsonCfg) ApiBanCfgJson() (*APIBanJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) CoreSCfgJson() (*CoreSJsonCfg, error) { - rawCfg, hasKey := self[CoreSCfgJson] +func (jsnCfg CgrJsonCfg) CoreSCfgJson() (*CoreSJsonCfg, error) { + rawCfg, hasKey := jsnCfg[CoreSCfgJson] if !hasKey { return nil, nil } @@ -587,8 +587,8 @@ func (self CgrJsonCfg) CoreSCfgJson() (*CoreSJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) ActionSCfgJson() (*ActionSJsonCfg, error) { - rawCfg, hasKey := self[ActionSJson] +func (jsnCfg CgrJsonCfg) ActionSCfgJson() (*ActionSJsonCfg, error) { + rawCfg, hasKey := jsnCfg[ActionSJson] if !hasKey { return nil, nil } @@ -599,8 +599,8 @@ func (self CgrJsonCfg) ActionSCfgJson() (*ActionSJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) AccountSCfgJson() (*AccountSJsonCfg, error) { - rawCfg, hasKey := self[AccountSCfgJson] +func (jsnCfg CgrJsonCfg) AccountSCfgJson() (*AccountSJsonCfg, error) { + rawCfg, hasKey := jsnCfg[AccountSCfgJson] if !hasKey { return nil, nil } diff --git a/config/configs.go b/config/configs.go index 18a5b9fe0..a2b2d0ff2 100644 --- a/config/configs.go +++ b/config/configs.go @@ -63,7 +63,7 @@ func HandlerConfigS(w http.ResponseWriter, r *http.Request) { } else { w.WriteHeader(500) } - fmt.Fprintf(w, err.Error()) + w.Write([]byte(err.Error())) return } switch mode := fi.Mode(); { @@ -72,7 +72,6 @@ func HandlerConfigS(w http.ResponseWriter, r *http.Request) { case mode.IsRegular(): handleConfigSFile(pth, w) } - return } func handleConfigSFolder(path string, w http.ResponseWriter) { @@ -80,7 +79,7 @@ func handleConfigSFolder(path string, w http.ResponseWriter) { cfg, err := newCGRConfigFromPathWithoutEnv(path) if err != nil { w.WriteHeader(500) - fmt.Fprintf(w, err.Error()) + w.Write([]byte(err.Error())) return } @@ -89,7 +88,6 @@ func handleConfigSFolder(path string, w http.ResponseWriter) { utils.Logger.Warning(fmt.Sprintf("<%s> Failed to write resonse because: %s", utils.ConfigSv1, err)) } - return } func handleConfigSFile(path string, w http.ResponseWriter) { @@ -97,14 +95,13 @@ func handleConfigSFile(path string, w http.ResponseWriter) { dat, err := os.ReadFile(path) if err != nil { w.WriteHeader(500) - fmt.Fprintf(w, err.Error()) + w.Write([]byte(err.Error())) return } if _, err := w.Write(dat); err != nil { utils.Logger.Warning(fmt.Sprintf("<%s> Failed to write resonse because: %s", utils.ConfigSv1, err)) } - return } // AsMapInterface returns the config as a map[string]interface{} diff --git a/config/configsanity.go b/config/configsanity.go index 0775b231c..0809755c9 100644 --- a/config/configsanity.go +++ b/config/configsanity.go @@ -629,21 +629,21 @@ func (cfg *CGRConfig) checkConfigSanity() error { } // DataDB sanity checks if cfg.dataDbCfg.Type == utils.INTERNAL { - if cfg.resourceSCfg.Enabled == true && cfg.resourceSCfg.StoreInterval != -1 { + if cfg.resourceSCfg.Enabled && cfg.resourceSCfg.StoreInterval != -1 { return fmt.Errorf("<%s> the StoreInterval field needs to be -1 when DataBD is *internal, received : %d", utils.ResourceS, cfg.resourceSCfg.StoreInterval) } - if cfg.statsCfg.Enabled == true && cfg.statsCfg.StoreInterval != -1 { + if cfg.statsCfg.Enabled && cfg.statsCfg.StoreInterval != -1 { return fmt.Errorf("<%s> the StoreInterval field needs to be -1 when DataBD is *internal, received : %d", utils.StatS, cfg.statsCfg.StoreInterval) } - if cfg.thresholdSCfg.Enabled == true && cfg.thresholdSCfg.StoreInterval != -1 { + if cfg.thresholdSCfg.Enabled && cfg.thresholdSCfg.StoreInterval != -1 { return fmt.Errorf("<%s> the StoreInterval field needs to be -1 when DataBD is *internal, received : %d", utils.ThresholdS, cfg.thresholdSCfg.StoreInterval) } } for item, val := range cfg.dataDbCfg.Items { - if val.Remote == true && len(cfg.dataDbCfg.RmtConns) == 0 { + if val.Remote && len(cfg.dataDbCfg.RmtConns) == 0 { return fmt.Errorf("remote connections required by: <%s>", item) } - if val.Replicate == true && len(cfg.dataDbCfg.RplConns) == 0 { + if val.Replicate && len(cfg.dataDbCfg.RplConns) == 0 { return fmt.Errorf("replicate connections required by: <%s>", item) } } diff --git a/config/datadbcfg.go b/config/datadbcfg.go index c07a061dc..44006f6ee 100644 --- a/config/datadbcfg.go +++ b/config/datadbcfg.go @@ -226,7 +226,6 @@ func (itm *ItemOpt) loadFromJSONCfg(jsonItm *ItemOptJson) { if jsonItm.Api_key != nil { itm.APIKey = *jsonItm.Api_key } - return } // Clone returns a deep copy of ItemOpt diff --git a/config/eescfg.go b/config/eescfg.go index a7e4d07b0..b4beee454 100644 --- a/config/eescfg.go +++ b/config/eescfg.go @@ -19,8 +19,6 @@ along with this program. If not, see package config import ( - "strings" - "github.com/cgrates/cgrates/utils" ) @@ -252,14 +250,11 @@ func (eeC *EventExporterCfg) ComputeFields() { switch field.GetPathSlice()[0] { case utils.MetaHdr: eeC.headerFields = append(eeC.headerFields, field) - case utils.MetaExp: + case utils.MetaExp, utils.MetaUCH: eeC.contentFields = append(eeC.contentFields, field) case utils.MetaTrl: eeC.trailerFields = append(eeC.trailerFields, field) } - if strings.HasPrefix(field.GetPathSlice()[0], utils.MetaUCH) { // special cache when loading fields that contains *uch in path - eeC.contentFields = append(eeC.contentFields, field) - } } } diff --git a/config/fctemplate.go b/config/fctemplate.go index a6a9c8903..da57d2a02 100644 --- a/config/fctemplate.go +++ b/config/fctemplate.go @@ -20,7 +20,6 @@ package config import ( "fmt" - "strings" "time" "github.com/cgrates/cgrates/utils" @@ -35,11 +34,9 @@ func NewFCTemplateFromFCTemplateJSONCfg(jsnCfg *FcTemplateJsonCfg, separator str } if jsnCfg.Path != nil { fcTmp.Path = *jsnCfg.Path - fcTmp.pathSlice = strings.Split(*jsnCfg.Path, utils.NestingSep) - fcTmp.pathItems = utils.CompilePathSlice(fcTmp.pathSlice) + fcTmp.pathSlice = utils.CompilePath(fcTmp.Path) fcTmp.Tag = fcTmp.Path } - fcTmp.Tag = fcTmp.Path if jsnCfg.Tag != nil { fcTmp.Tag = *jsnCfg.Tag } @@ -118,8 +115,7 @@ type FCTemplate struct { RoundingDecimals *int MaskDestID string MaskLen int - pathItems []string // Field identifier - pathSlice []string // Used when we set a NMItem to not recreate this slice for every itemsc + pathSlice []string // Field identifier } // FCTemplatesFromFCTemplatesJSONCfg will build a list of FCTemplates from json @@ -191,9 +187,6 @@ func (fc FCTemplate) Clone() (cln *FCTemplate) { if fc.pathSlice != nil { cln.pathSlice = utils.CloneStringSlice(fc.pathSlice) } - if fc.pathItems != nil { - cln.pathItems = utils.CloneStringSlice(fc.pathItems) - } if fc.Filters != nil { cln.Filters = utils.CloneStringSlice(fc.Filters) } @@ -242,19 +235,19 @@ func (fc *FCTemplate) AsMapInterface(separator string) (mp map[string]interface{ if fc.Padding != utils.EmptyString { mp[utils.PaddingCfg] = fc.Padding } - if fc.Mandatory != false { + if fc.Mandatory { mp[utils.MandatoryCfg] = fc.Mandatory } if fc.AttributeID != utils.EmptyString { mp[utils.AttributeIDCfg] = fc.AttributeID } - if fc.NewBranch != false { + if fc.NewBranch { mp[utils.NewBranchCfg] = fc.NewBranch } if fc.Timezone != utils.EmptyString { mp[utils.TimezoneCfg] = fc.Timezone } - if fc.Blocker != false { + if fc.Blocker { mp[utils.BlockerCfg] = fc.Blocker } if fc.Layout != time.RFC3339 { @@ -280,15 +273,9 @@ func (fc *FCTemplate) GetPathSlice() []string { return fc.pathSlice } -// GetPathItems returns the cached path as PathItems -func (fc *FCTemplate) GetPathItems() []string { - return fc.pathItems -} - // ComputePath used in test to populate private fields used to store the path func (fc *FCTemplate) ComputePath() { - fc.pathSlice = strings.Split(fc.Path, utils.NestingSep) - fc.pathItems = utils.CompilePathSlice(fc.pathSlice) + fc.pathSlice = utils.CompilePath(fc.Path) } // Clone returns a deep copy of FcTemplates diff --git a/config/fctemplate_test.go b/config/fctemplate_test.go index b88f00ca9..662a946d1 100644 --- a/config/fctemplate_test.go +++ b/config/fctemplate_test.go @@ -69,7 +69,7 @@ func TestFCTemplatePathItems(t *testing.T) { } expected := []string{"*req", "Account", "1", "Balance", "*monetary", "Value"} fcTemplate.ComputePath() - if !reflect.DeepEqual(expected, fcTemplate.GetPathItems()) { + if !reflect.DeepEqual(expected, fcTemplate.GetPathSlice()) { t.Errorf("Expected %+v, received %+v", utils.ToJSON(expected), utils.ToJSON(fcTemplate)) } } diff --git a/config/loaderscfg_test.go b/config/loaderscfg_test.go index fa6e6ef87..00a74c691 100644 --- a/config/loaderscfg_test.go +++ b/config/loaderscfg_test.go @@ -78,7 +78,6 @@ func TestLoaderSCfgloadFromJsonCfgCase1(t *testing.T) { Tag: "TenantID", Path: "Tenant", pathSlice: []string{"Tenant"}, - pathItems: []string{"Tenant"}, Type: utils.MetaComposed, Value: val, Mandatory: true, @@ -422,7 +421,6 @@ func TestLoaderSCfgsClone(t *testing.T) { Tag: "TenantID", Path: "Tenant", pathSlice: []string{"Tenant"}, - pathItems: []string{"Tenant"}, Type: utils.MetaComposed, Value: NewRSRParsersMustCompile("cgrate.org", utils.InfieldSep), Mandatory: true, diff --git a/config/navigablemap_test.go b/config/navigablemap_test.go deleted file mode 100644 index 41a2b35e6..000000000 --- a/config/navigablemap_test.go +++ /dev/null @@ -1,481 +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 -*/ -package config - -import ( - "encoding/xml" - "math/rand" - "reflect" - "strings" - "testing" - - "github.com/cgrates/cgrates/utils" -) - -func TestNMAsXMLElementsConfigEmptyID(t *testing.T) { - nM := utils.NewOrderedNavigableMap() - order := [][]string{ - {"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"}, - {"FirstLevel2", "FirestLevel3", "Field3"}, - {"FirstLevel2", "FirestLevel3", "Field5"}, - } - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(order[0], utils.NestingSep), PathItems: order[0]}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Path: order[0], - Data: "Val1"}}}); err != nil { - t.Error(err) - } - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(order[1], utils.NestingSep), PathItems: order[1]}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Path: order[1], - Data: "Value3"}}}); err != nil { - t.Error(err) - } - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(order[2], utils.NestingSep), PathItems: order[2]}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Path: order[2], - Data: "Value5", - AttributeID: "attribute5"}}, - {Type: utils.NMDataType, Value: &utils.DataLeaf{Path: order[2], - Data: "attrVal5", - AttributeID: "attribute5"}}}); err != nil { - t.Error(err) - } - if _, err := NMAsXMLElements(nM); err != nil { - t.Error(err) - } -} - -func TestNMAsXMLElements(t *testing.T) { - nM := utils.NewOrderedNavigableMap() - order := [][]string{ - {"FirstLevel2", "SecondLevel2", "Field2"}, - {"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"}, - {"FirstLevel2", "Field3"}, - {"FirstLevel2", "Field5"}, - {"Field4"}, - {"FirstLevel2", "Field6"}, - } - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(order[0], utils.NestingSep), PathItems: order[0]}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Path: order[0], - Data: "attrVal1", - AttributeID: "attribute1"}}, - {Type: utils.NMDataType, Value: &utils.DataLeaf{Path: order[0], - Data: "Value2"}}}); err != nil { - t.Error(err) - } - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(order[1], utils.NestingSep), PathItems: order[1]}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Path: order[1], - Data: "Val1"}}}); err != nil { - t.Error(err) - } - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(order[2], utils.NestingSep), PathItems: order[2]}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Path: order[2], - Data: "Value3"}}}); err != nil { - t.Error(err) - } - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(order[3], utils.NestingSep), PathItems: order[3]}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Path: order[3], - Data: "Value5"}}, - {Type: utils.NMDataType, Value: &utils.DataLeaf{Path: order[3], - Data: "attrVal5", - AttributeID: "attribute5"}}}); err != nil { - t.Error(err) - } - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(order[4], utils.NestingSep), PathItems: order[4]}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Path: order[4], - Data: "Val4"}}, - {Type: utils.NMDataType, Value: &utils.DataLeaf{Path: order[4], - Data: "attrVal2", - AttributeID: "attribute2"}}}); err != nil { - t.Error(err) - } - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(order[5], utils.NestingSep), PathItems: order[5]}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{Path: order[5], - Data: "Value6", - NewBranch: true}}, - {Type: utils.NMDataType, Value: &utils.DataLeaf{Path: order[5], - Data: "attrVal6", - AttributeID: "attribute6"}}}); err != nil { - t.Error(err) - } - - eXMLElmnts := []*XMLElement{ - { - XMLName: xml.Name{Local: order[0][0]}, - Elements: []*XMLElement{ - { - XMLName: xml.Name{Local: order[0][1]}, - Elements: []*XMLElement{ - { - XMLName: xml.Name{Local: order[0][2]}, - Attributes: []*xml.Attr{ - { - Name: xml.Name{Local: "attribute1"}, - Value: "attrVal1", - }, - }, - Value: "Value2", - }, - }, - }, - { - XMLName: xml.Name{Local: "Field3"}, - Value: "Value3", - }, - { - XMLName: xml.Name{Local: order[3][1]}, - Attributes: []*xml.Attr{ - { - Name: xml.Name{Local: "attribute5"}, - Value: "attrVal5", - }, - }, - Value: "Value5", - }, - }, - }, - { - XMLName: xml.Name{Local: order[1][0]}, - Elements: []*XMLElement{ - { - XMLName: xml.Name{Local: order[1][1]}, - Elements: []*XMLElement{ - { - XMLName: xml.Name{Local: order[1][2]}, - Elements: []*XMLElement{ - { - XMLName: xml.Name{Local: "Fld1"}, - Value: "Val1", - }, - }, - }, - }, - }, - }, - }, - { - XMLName: xml.Name{Local: order[4][0]}, - Attributes: []*xml.Attr{ - { - Name: xml.Name{Local: "attribute2"}, - Value: "attrVal2", - }, - }, - Value: "Val4", - }, - { - XMLName: xml.Name{Local: order[5][0]}, - Elements: []*XMLElement{ - { - XMLName: xml.Name{Local: order[5][1]}, - Attributes: []*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, nil); 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, nil); cgrEv != nil { - t.Errorf("expecting: %+v, \nreceived: %+v", utils.ToJSON(nil), utils.ToJSON(cgrEv.Event)) - } - - path := []string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"} - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(path, utils.NestingSep), PathItems: path}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "Val1", - }}}); err != nil { - t.Error(err) - } - - path = []string{"FirstLevel2", "SecondLevel2", "Field2"} - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(path, utils.NestingSep), PathItems: path}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "attrVal1", - AttributeID: "attribute1", - }}, - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "Value2", - }}}); err != nil { - t.Error(err) - } - - path = []string{"FirstLevel2", "Field3"} - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(path, utils.NestingSep), PathItems: path}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "Value3", - }}}); err != nil { - t.Error(err) - } - - path = []string{"FirstLevel2", "Field5"} - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(path, utils.NestingSep), PathItems: path}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "Value5", - }}, - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "attrVal5", - AttributeID: "attribute5", - }}}); err != nil { - t.Error(err) - } - - path = []string{"FirstLevel2", "Field6"} - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(path, utils.NestingSep), PathItems: path}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "Value6", - NewBranch: true, - }}, - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "attrVal6", - AttributeID: "attribute6", - }}}); err != nil { - t.Error(err) - } - - path = []string{"Field4"} - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(path, utils.NestingSep), PathItems: path}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "Val4", - }}, - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "attrVal2", - 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, utils.MapStorage{}); 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)) - } -} - -/* -goos: linux -goarch: amd64 -pkg: github.com/cgrates/cgrates/config -BenchmarkOrderdNavigableMapSet2-16 1738 6463443 ns/op -BenchmarkOrderdNavigableMapSet2-16 1792 6536313 ns/op -BenchmarkOrderdNavigableMapSet2-16 1744 6554331 ns/op -BenchmarkNavigableMapOld1Set-16 2980 3831743 ns/op -BenchmarkNavigableMapOld1Set-16 2758 3789885 ns/op -BenchmarkNavigableMapOld1Set-16 2916 3741273 ns/op -PASS -ok github.com/cgrates/cgrates/config 71.065s -*/ -var generator = rand.New(rand.NewSource(42)) -var gen = generateRandomTemplate(10_000) - -type benchData struct { - path []string - strPath string - data string -} - -func generateRandomPath() (out []string) { - size := generator.Intn(16) + 1 - out = make([]string, size) - for i := 0; i < size; i++ { - out[i] = utils.Sha1(utils.GenUUID()) - } - return -} -func generateRandomTemplate(size int) (out []benchData) { - out = make([]benchData, size) - for i := 0; i < size; i++ { - out[i].path = generateRandomPath() - out[i].data = utils.UUIDSha1Prefix() - out[i].strPath = strings.Join(out[i].path, utils.NestingSep) - } - return -} - -func BenchmarkOrderdNavigableMapSet2(b *testing.B) { - nm := utils.NewOrderedNavigableMap() - b.ResetTimer() - for n := 0; n < b.N; n++ { - for _, data := range gen { - if err := nm.Set(&utils.FullPath{PathItems: data.path, Path: data.strPath}, data.data); err != nil { - b.Log(err, data.path) - } - } - } -} - -// func BenchmarkNavigableMapOld1Set(b *testing.B) { -// nm := NewNavigableMap(nil) -// b.ResetTimer() -// for n := 0; n < b.N; n++ { -// for _, data := range gen { -// nm.Set(data.path, data.data, false, true) -// } -// } -// } - -func TestNMAsMapInterface(t *testing.T) { - nM := utils.NewOrderedNavigableMap() - if cgrEv := NMAsMapInterface(nM, utils.NestingSep); !reflect.DeepEqual(cgrEv, map[string]interface{}{}) { - t.Errorf("expecting: %+v, \nreceived: %+v", utils.ToJSON(map[string]interface{}{}), utils.ToJSON(cgrEv)) - } - - path := []string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"} - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(path, utils.NestingSep), PathItems: path}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "Val1", - }}}); err != nil { - t.Error(err) - } - - path = []string{"FirstLevel2", "SecondLevel2", "Field2"} - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(path, utils.NestingSep), PathItems: path}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "attrVal1", - AttributeID: "attribute1", - }}, - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "Value2", - }}}); err != nil { - t.Error(err) - } - - path = []string{"FirstLevel2", "Field3"} - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(path, utils.NestingSep), PathItems: path}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "Value3", - }}}); err != nil { - t.Error(err) - } - - path = []string{"FirstLevel2", "Field5"} - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(path, utils.NestingSep), PathItems: path}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "Value5", - }}, - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "attrVal5", - AttributeID: "attribute5"}, - }}); err != nil { - t.Error(err) - } - - path = []string{"FirstLevel2", "Field6"} - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(path, utils.NestingSep), PathItems: path}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "Value6", - NewBranch: true}, - }, - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "attrVal6", - AttributeID: "attribute6"}, - }}); err != nil { - t.Error(err) - } - - path = []string{"Field4"} - if err := nM.SetAsSlice(&utils.FullPath{Path: strings.Join(path, utils.NestingSep), PathItems: path}, []*utils.DataNode{ - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "Val4", - }}, - {Type: utils.NMDataType, Value: &utils.DataLeaf{ - Path: path, - Data: "attrVal2", - 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 := NMAsMapInterface(nM, utils.NestingSep); !reflect.DeepEqual(eEv, cgrEv) { - t.Errorf("expecting: %+v, \nreceived: %+v", utils.ToJSON(eEv), utils.ToJSON(cgrEv)) - } -} diff --git a/config/rpcconn.go b/config/rpcconn.go index a456eb59e..7e81fdfde 100644 --- a/config/rpcconn.go +++ b/config/rpcconn.go @@ -82,7 +82,6 @@ func (rC *RPCConn) loadFromJSONCfg(jsnCfg *RPCConnsJson) { rC.Conns[idx].loadFromJSONCfg(jsnHaCfg) //To review if the function signature changes } } - return } // AsMapInterface returns the config as a map[string]interface{} @@ -147,7 +146,6 @@ func (rh *RemoteHost) loadFromJSONCfg(jsnCfg *RemoteHostJson) { if jsnCfg.Tls != nil { rh.TLS = *jsnCfg.Tls } - return } // AsMapInterface returns the config as a map[string]interface{} diff --git a/ees/ees_test.go b/ees/ees_test.go index 0bfb94ef4..0de421e3b 100644 --- a/ees/ees_test.go +++ b/ees/ees_test.go @@ -198,7 +198,7 @@ func TestV1ProcessEvent(t *testing.T) { } var rply map[string]map[string]interface{} rplyExpect := map[string]map[string]interface{}{ - "SQLExporterFull": map[string]interface{}{}, + "SQLExporterFull": {}, } if err := eeS.V1ProcessEvent(cgrEv, &rply); err != nil { t.Error(err) diff --git a/ees/elastic.go b/ees/elastic.go index c9f0fa61f..7c5897c63 100644 --- a/ees/elastic.go +++ b/ees/elastic.go @@ -153,8 +153,10 @@ func (eEe *ElasticEe) ExportEvent(cgrEv *utils.CGREvent) (err error) { return } for el := eeReq.OrdNavMP[utils.MetaExp].GetFirstElement(); el != nil; el = el.Next() { - nmIt, _ := eeReq.OrdNavMP[utils.MetaExp].Field(el.Value) - valMp[strings.Join(nmIt.Path, utils.NestingSep)] = nmIt.String() + path := el.Value + nmIt, _ := eeReq.OrdNavMP[utils.MetaExp].Field(path) + path = path[:len(path)-1] // remove the last index + valMp[strings.Join(path, utils.NestingSep)] = nmIt.String() } } updateEEMetrics(eEe.dc, cgrEv.Event, utils.FirstNonEmpty(eEe.cgrCfg.EEsCfg().Exporters[eEe.cfgIdx].Timezone, diff --git a/ees/httpjsonmap.go b/ees/httpjsonmap.go index 4f6336f80..99970bfce 100644 --- a/ees/httpjsonmap.go +++ b/ees/httpjsonmap.go @@ -99,8 +99,10 @@ func (httpEE *HTTPjsonMapEE) ExportEvent(cgrEv *utils.CGREvent) (err error) { return } for el := eeReq.OrdNavMP[utils.MetaExp].GetFirstElement(); el != nil; el = el.Next() { - nmIt, _ := eeReq.OrdNavMP[utils.MetaExp].Field(el.Value) - valMp[strings.Join(nmIt.Path, utils.NestingSep)] = nmIt.String() + path := el.Value + nmIt, _ := eeReq.OrdNavMP[utils.MetaExp].Field(path) + path = path[:len(path)-1] // remove the last index + valMp[strings.Join(path, utils.NestingSep)] = nmIt.String() } if hdr, err = httpEE.composeHeader(); err != nil { return @@ -145,8 +147,10 @@ func (httpEE *HTTPjsonMapEE) composeHeader() (hdr http.Header, err error) { return } for el := eeReq.OrdNavMP[utils.MetaHdr].GetFirstElement(); el != nil; el = el.Next() { - nmIt, _ := eeReq.OrdNavMP[utils.MetaHdr].Field(el.Value) //Safe to ignore error, since the path always exists - hdr.Set(strings.Join(nmIt.Path, utils.NestingSep), nmIt.String()) + path := el.Value + nmIt, _ := eeReq.OrdNavMP[utils.MetaHdr].Field(path) //Safe to ignore error, since the path always exists + path = path[:len(path)-1] // remove the last index + hdr.Set(strings.Join(path, utils.NestingSep), nmIt.String()) } return } diff --git a/ees/httppost.go b/ees/httppost.go index 93d678dd4..b411950a1 100644 --- a/ees/httppost.go +++ b/ees/httppost.go @@ -95,8 +95,10 @@ func (httpPost *HTTPPost) ExportEvent(cgrEv *utils.CGREvent) (err error) { return } for el := eeReq.OrdNavMP[utils.MetaExp].GetFirstElement(); el != nil; el = el.Next() { - nmIt, _ := eeReq.OrdNavMP[utils.MetaExp].Field(el.Value) - urlVals.Set(strings.Join(nmIt.Path, utils.NestingSep), nmIt.String()) + path := el.Value + nmIt, _ := eeReq.OrdNavMP[utils.MetaExp].Field(path) + path = path[:len(path)-1] // remove the last index + urlVals.Set(strings.Join(path, utils.NestingSep), nmIt.String()) } if hdr, err = httpPost.composeHeader(); err != nil { return @@ -139,8 +141,10 @@ func (httpPost *HTTPPost) composeHeader() (hdr http.Header, err error) { return } for el := eeReq.OrdNavMP[utils.MetaHdr].GetFirstElement(); el != nil; el = el.Next() { - nmIt, _ := eeReq.OrdNavMP[utils.MetaHdr].Field(el.Value) - hdr.Set(strings.Join(nmIt.Path, utils.NestingSep), nmIt.String()) + path := el.Value + nmIt, _ := eeReq.OrdNavMP[utils.MetaHdr].Field(path) + path = path[:len(path)-1] // remove the last index + hdr.Set(strings.Join(path, utils.NestingSep), nmIt.String()) } return } diff --git a/ees/posterjsonmap.go b/ees/posterjsonmap.go index dd81d553c..28be1d499 100644 --- a/ees/posterjsonmap.go +++ b/ees/posterjsonmap.go @@ -110,8 +110,10 @@ func (pstrEE *PosterJSONMapEE) ExportEvent(cgrEv *utils.CGREvent) (err error) { return } for el := eeReq.OrdNavMP[utils.MetaExp].GetFirstElement(); el != nil; el = el.Next() { - nmIt, _ := eeReq.OrdNavMP[utils.MetaExp].Field(el.Value) - valMp[strings.Join(nmIt.Path, utils.NestingSep)] = nmIt.String() + path := el.Value + nmIt, _ := eeReq.OrdNavMP[utils.MetaExp].Field(path) + path = path[:len(path)-1] // remove the last index + valMp[strings.Join(path, utils.NestingSep)] = nmIt.String() } } updateEEMetrics(pstrEE.dc, cgrEv.Event, utils.FirstNonEmpty(pstrEE.cgrCfg.EEsCfg().Exporters[pstrEE.cfgIdx].Timezone, diff --git a/engine/account.go b/engine/account.go index 5e6bf0139..bb7c2c665 100644 --- a/engine/account.go +++ b/engine/account.go @@ -296,7 +296,7 @@ func (acc *Account) getBalancesForPrefix(prefix, category, tor, if b.IsExpiredAt(aTime) || (len(b.SharedGroups) == 0 && b.GetValue() <= 0 && !b.Blocker) { continue } - if sharedGroup != "" && b.SharedGroups[sharedGroup] == false { + if sharedGroup != "" && !b.SharedGroups[sharedGroup] { continue } if !b.MatchCategory(category) { @@ -304,7 +304,7 @@ func (acc *Account) getBalancesForPrefix(prefix, category, tor, } b.account = acc - if len(b.DestinationIDs) > 0 && b.DestinationIDs[utils.MetaAny] == false { + if len(b.DestinationIDs) > 0 && !b.DestinationIDs[utils.MetaAny] { for _, p := range utils.SplitPrefix(prefix, MIN_PREFIX_MATCH) { if destIDs, err := dm.GetReverseDestination(p, true, true, utils.NonTransactional); err == nil { foundResult := false @@ -944,9 +944,6 @@ func (acc *Account) AsOldStructure() interface{} { Timings []*RITiming TimingIDs string Disabled bool - precision int - account *Account - dirty bool } type Balances []*Balance type UnitsCounter struct { diff --git a/engine/account_test.go b/engine/account_test.go index 69ffb21d2..221b89974 100644 --- a/engine/account_test.go +++ b/engine/account_test.go @@ -1897,9 +1897,7 @@ func TestDebitDataMoney(t *testing.T) { utils.MetaData: {&Balance{Uuid: "testm", Value: 0, Weight: 5, DestinationIDs: utils.StringMap{"NAT": true}}}, utils.MetaMonetary: {&Balance{Value: 160}}, }} - var err error - cc, err = rifsBalance.debitCreditBalance(cd, false, false, true) - if err != nil { + if _, err := rifsBalance.debitCreditBalance(cd, false, false, true); err != nil { t.Error("Error debiting balance: ", err) } if rifsBalance.BalanceMap[utils.MetaData][0].GetValue() != 0 || diff --git a/engine/action.go b/engine/action.go index 63b991c84..564520a55 100644 --- a/engine/action.go +++ b/engine/action.go @@ -275,7 +275,7 @@ func topupResetAction(ub *Account, a *Action, acs Actions, extraData interface{} return errors.New("nil account") } if ub.BalanceMap == nil { // Init the map since otherwise will get error if nil - ub.BalanceMap = make(map[string]Balances, 0) + ub.BalanceMap = make(map[string]Balances) } c := a.Clone() genericMakeNegative(c) @@ -300,7 +300,7 @@ func debitResetAction(ub *Account, a *Action, acs Actions, extraData interface{} return errors.New("nil account") } if ub.BalanceMap == nil { // Init the map since otherwise will get error if nil - ub.BalanceMap = make(map[string]Balances, 0) + ub.BalanceMap = make(map[string]Balances) } return genericDebit(ub, a, true) } diff --git a/engine/actions_test.go b/engine/actions_test.go index f1a5cd18b..746a8bcef 100644 --- a/engine/actions_test.go +++ b/engine/actions_test.go @@ -189,7 +189,7 @@ func TestActionPlanHourMonths(t *testing.T) { nextMonth := time.Date(y, m, 1, 0, 0, 0, 0, time.Local).AddDate(0, 1, 0) if now.After(testTime) { testTime = testTime.AddDate(0, 0, 1) - y, m, d = testTime.Date() + y, m, _ = testTime.Date() } if now.After(testTime) { m = nextMonth.Month() @@ -773,7 +773,7 @@ func TestActionTriggerMatchAll(t *testing.T) { Weight: utils.Float64Pointer(1.0), DestinationIDs: utils.StringMapPointer(utils.NewStringMap("NAT")), SharedGroups: utils.StringMapPointer(utils.NewStringMap("test2")), - }, ExtraParameters: fmt.Sprintf(`{"UniqueID":"ZIP", "GroupID":"TEST", "ThresholdType":"TT"}`)} + }, ExtraParameters: `{"UniqueID":"ZIP", "GroupID":"TEST", "ThresholdType":"TT"}`} if !at.Match(a) { t.Errorf("Action trigger [%v] does not match action [%v]", at, a) } @@ -1550,6 +1550,9 @@ func TestActionTransactionBalanceType(t *testing.T) { }, } err = at.Execute(nil, nil) + if err != nil { + t.Error(err) + } acc, err := dm.GetAccount("cgrates.org:trans") if err != nil || acc == nil { t.Error("Error getting account: ", acc, err) @@ -1587,6 +1590,9 @@ func TestActionTransactionBalanceNotType(t *testing.T) { }, } err = at.Execute(nil, nil) + if err != nil { + t.Error(err) + } acc, err := dm.GetAccount("cgrates.org:trans") if err != nil || acc == nil { t.Error("Error getting account: ", acc, err) @@ -1630,6 +1636,9 @@ func TestActionWithExpireWithoutExpire(t *testing.T) { }, } err = at.Execute(nil, nil) + if err != nil { + t.Error(err) + } acc, err := dm.GetAccount("cgrates.org:exp") if err != nil || acc == nil { t.Errorf("Error getting account: %+v: %v", acc, err) @@ -1677,6 +1686,9 @@ func TestActionRemoveBalance(t *testing.T) { }, } err = at.Execute(nil, nil) + if err != nil { + t.Error(err) + } acc, err := dm.GetAccount("cgrates.org:rembal") if err != nil || acc == nil { t.Errorf("Error getting account: %+v: %v", acc, err) @@ -1730,6 +1742,9 @@ func TestActionRemoveExpiredBalance(t *testing.T) { }, } err = at.Execute(nil, nil) + if err != nil { + t.Error(err) + } acc, err := dm.GetAccount("cgrates.org:rembal2") if err != nil || acc == nil { t.Errorf("Error getting account: %+v: %v", acc, err) @@ -2356,6 +2371,9 @@ func TestActionTopUpZeroNegative(t *testing.T) { }, } err = at.Execute(nil, nil) + if err != nil { + t.Error(err) + } acc, err := dm.GetAccount("cgrates.org:zeroNegative") if err != nil || acc == nil { t.Error("Error getting account: ", acc, err) @@ -2407,6 +2425,9 @@ func TestActionSetExpiry(t *testing.T) { }, } err = at.Execute(nil, nil) + if err != nil { + t.Error(err) + } acc, err := dm.GetAccount("cgrates.org:zeroNegative") if err != nil || acc == nil { t.Error("Error getting account: ", acc, err) diff --git a/engine/balances.go b/engine/balances.go index 80222ef38..c0391ad57 100644 --- a/engine/balances.go +++ b/engine/balances.go @@ -145,15 +145,15 @@ func (b *Balance) IsActiveAt(t time.Time) bool { } func (b *Balance) MatchCategory(category string) bool { - return len(b.Categories) == 0 || b.Categories[category] == true + return len(b.Categories) == 0 || b.Categories[category] } func (b *Balance) HasDestination() bool { - return len(b.DestinationIDs) > 0 && b.DestinationIDs[utils.MetaAny] == false + return len(b.DestinationIDs) > 0 && !b.DestinationIDs[utils.MetaAny] } func (b *Balance) MatchDestination(destinationID string) bool { - return !b.HasDestination() || b.DestinationIDs[destinationID] == true + return !b.HasDestination() || b.DestinationIDs[destinationID] } func (b *Balance) MatchActionTrigger(at *ActionTrigger) bool { @@ -186,11 +186,11 @@ func (b *Balance) Clone() *Balance { } func (b *Balance) getMatchingPrefixAndDestID(dest string) (prefix, destID string) { - if len(b.DestinationIDs) != 0 && b.DestinationIDs[utils.MetaAny] == false { + if len(b.DestinationIDs) != 0 && !b.DestinationIDs[utils.MetaAny] { for _, p := range utils.SplitPrefix(dest, MIN_PREFIX_MATCH) { if destIDs, err := dm.GetReverseDestination(p, true, true, utils.NonTransactional); err == nil { for _, dID := range destIDs { - if b.DestinationIDs[dID] == true { + if b.DestinationIDs[dID] { return p, dID } } diff --git a/engine/callcost.go b/engine/callcost.go index 6013dc41e..23fd34cfc 100644 --- a/engine/callcost.go +++ b/engine/callcost.go @@ -232,7 +232,7 @@ func (cc *CallCost) MatchCCFilter(bf *BalanceFilter) bool { if bf == nil { return true } - if bf.Categories != nil && cc.Category != "" && (*bf.Categories)[cc.Category] == false { + if bf.Categories != nil && cc.Category != "" && !(*bf.Categories)[cc.Category] { return false } // match destination ids diff --git a/engine/calldesc.go b/engine/calldesc.go index 580277f71..8d16e16d1 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -643,7 +643,7 @@ func (origCD *CallDescriptor) getMaxSessionDuration(origAcc *Account) (time.Dura } // not enough credit for connect fee - if cc.negativeConnectFee == true { + if cc.negativeConnectFee { return 0, nil } diff --git a/engine/caps.go b/engine/caps.go index eb184b004..8657a3482 100644 --- a/engine/caps.go +++ b/engine/caps.go @@ -68,7 +68,6 @@ func (cR *Caps) Allocate() (err error) { // Deallocate will free a channel for the API call func (cR *Caps) Deallocate() { <-cR.aReqs - return } // NewCapsStats returns the stats for the caps diff --git a/engine/caps_test.go b/engine/caps_test.go index d7af7ec42..f575a0221 100644 --- a/engine/caps_test.go +++ b/engine/caps_test.go @@ -31,7 +31,7 @@ import ( func TestNewCaps(t *testing.T) { exp := &Caps{ strategy: utils.MetaBusy, - aReqs: make(chan struct{}, 0), + aReqs: make(chan struct{}), } cs := NewCaps(0, utils.MetaBusy) @@ -74,7 +74,7 @@ func TestCapsStats(t *testing.T) { stopChan = make(chan struct{}, 1) go func() { runtime.Gosched() - time.Sleep(100) + time.Sleep(100 * time.Nanosecond) close(stopChan) }() cr = NewCaps(10, utils.MetaBusy) diff --git a/engine/cdr.go b/engine/cdr.go index d62339ff1..86003e8d0 100644 --- a/engine/cdr.go +++ b/engine/cdr.go @@ -354,11 +354,13 @@ func (cdr *CDR) formatField(cfgFld *config.FCTemplate, groupedCDRs []*CDR, outVal = dtFld.Format(cfgFld.Layout) case utils.MetaHTTPPost: var outValByte []byte - httpAddr, err := cfgFld.Value.ParseValue(utils.EmptyString) + var httpAddr string + httpAddr, err = cfgFld.Value.ParseValue(utils.EmptyString) if err != nil { return "", err } - jsn, err := json.Marshal(cdr) + var jsn []byte + jsn, err = json.Marshal(cdr) if err != nil { return "", err } @@ -525,41 +527,41 @@ type UsageRecord struct { ExtraFields map[string]string } -func (self *UsageRecord) AsCallDescriptor(timezone string, denyNegative bool) (*CallDescriptor, error) { +func (uR *UsageRecord) AsCallDescriptor(timezone string, denyNegative bool) (*CallDescriptor, error) { var err error cd := &CallDescriptor{ - CgrID: self.GetId(), - ToR: self.ToR, - Tenant: self.Tenant, - Category: self.Category, - Subject: self.Subject, - Account: self.Account, - Destination: self.Destination, + CgrID: uR.GetId(), + ToR: uR.ToR, + Tenant: uR.Tenant, + Category: uR.Category, + Subject: uR.Subject, + Account: uR.Account, + Destination: uR.Destination, DenyNegativeAccount: denyNegative, } - timeStr := self.AnswerTime + timeStr := uR.AnswerTime if len(timeStr) == 0 { // In case of auth, answer time will not be defined, so take it out of setup one - timeStr = self.SetupTime + timeStr = uR.SetupTime } if cd.TimeStart, err = utils.ParseTimeDetectLayout(timeStr, timezone); err != nil { return nil, err } - if usage, err := utils.ParseDurationWithNanosecs(self.Usage); err != nil { + if usage, err := utils.ParseDurationWithNanosecs(uR.Usage); err != nil { return nil, err } else { cd.TimeEnd = cd.TimeStart.Add(usage) } - if self.ExtraFields != nil { + if uR.ExtraFields != nil { cd.ExtraFields = make(map[string]string) } - for k, v := range self.ExtraFields { + for k, v := range uR.ExtraFields { cd.ExtraFields[k] = v } return cd, nil } -func (self *UsageRecord) GetId() string { - return utils.Sha1(self.ToR, self.RequestType, self.Tenant, self.Category, self.Account, self.Subject, self.Destination, self.SetupTime, self.AnswerTime, self.Usage) +func (uR *UsageRecord) GetId() string { + return utils.Sha1(uR.ToR, uR.RequestType, uR.Tenant, uR.Category, uR.Account, uR.Subject, uR.Destination, uR.SetupTime, uR.AnswerTime, uR.Usage) } type ExternalCDRWithAPIOpts struct { diff --git a/engine/destinations_test.go b/engine/destinations_test.go index 1f2650410..740183157 100644 --- a/engine/destinations_test.go +++ b/engine/destinations_test.go @@ -44,6 +44,9 @@ func TestDestinationStorageStore(t *testing.T) { } result, err := dm.GetDestination(nationale.Id, true, true, utils.NonTransactional) + if err != nil { + t.Error(err) + } if nationale.containsPrefix("0257") == 0 || nationale.containsPrefix("0256") == 0 || nationale.containsPrefix("0723") == 0 { diff --git a/engine/dispatcherprfl.go b/engine/dispatcherprfl.go index 7dca7f417..7bdb5074c 100644 --- a/engine/dispatcherprfl.go +++ b/engine/dispatcherprfl.go @@ -73,7 +73,6 @@ func (dHPrfls DispatcherHostProfiles) ReorderFromIndex(idx int) { dHPrfls[i] = initConns[idx] idx++ } - return } // Shuffle will mix the connections in place @@ -81,7 +80,6 @@ func (dHPrfls DispatcherHostProfiles) Shuffle() { rand.Shuffle(len(dHPrfls), func(i, j int) { dHPrfls[i], dHPrfls[j] = dHPrfls[j], dHPrfls[i] }) - return } func (dHPrfls DispatcherHostProfiles) Clone() (cln DispatcherHostProfiles) { @@ -180,7 +178,6 @@ func (dHPrflIDs DispatcherHostIDs) ReorderFromIndex(idx int) { dHPrflIDs[i] = initConns[idx] idx++ } - return } // Shuffle will mix the connections in place @@ -188,7 +185,6 @@ func (dHPrflIDs DispatcherHostIDs) Shuffle() { rand.Shuffle(len(dHPrflIDs), func(i, j int) { dHPrflIDs[i], dHPrflIDs[j] = dHPrflIDs[j], dHPrflIDs[i] }) - return } func (dHPrflIDs DispatcherHostIDs) Clone() (cln DispatcherHostIDs) { diff --git a/engine/eventrequest.go b/engine/eventrequest.go index 8fbfcab93..7d83e14bd 100644 --- a/engine/eventrequest.go +++ b/engine/eventrequest.go @@ -141,19 +141,15 @@ func (eeR *EventRequest) SetFields(tplFlds []*config.FCTemplate) (err error) { return } var fullPath *utils.FullPath - var itmPath []string if fullPath, err = utils.GetFullFieldPath(tplFld.Path, eeR); err != nil { return } else if fullPath == nil { // no dynamic path fullPath = &utils.FullPath{ - PathItems: utils.CloneStringSlice(tplFld.GetPathItems()), // need to clone so me do not modify the template + PathSlice: utils.CloneStringSlice(tplFld.GetPathSlice()), // need to clone so me do not modify the template Path: tplFld.Path, } - itmPath = tplFld.GetPathSlice()[1:] - } else { - itmPath = fullPath.PathItems } - nMItm := &utils.DataLeaf{Data: out, Path: itmPath, NewBranch: tplFld.NewBranch, AttributeID: tplFld.AttributeID} + nMItm := &utils.DataLeaf{Data: out, NewBranch: tplFld.NewBranch, AttributeID: tplFld.AttributeID} switch tplFld.Type { case utils.MetaComposed: err = eeR.Compose(fullPath, nMItm) @@ -175,18 +171,18 @@ func (eeR *EventRequest) SetFields(tplFlds []*config.FCTemplate) (err error) { // Set implements utils.NMInterface func (eeR *EventRequest) SetAsSlice(fullPath *utils.FullPath, val *utils.DataLeaf) (err error) { - switch prfx := fullPath.PathItems[0]; prfx { + switch prfx := fullPath.PathSlice[0]; prfx { case utils.MetaUCH: return Cache.Set(utils.CacheUCH, fullPath.Path[5:], val.Data, nil, true, utils.NonTransactional) case utils.MetaOpts: - return eeR.opts.Set(fullPath.PathItems[1:], val.Data) + return eeR.opts.Set(fullPath.PathSlice[1:], val.Data) default: oNM, has := eeR.OrdNavMP[prfx] if !has { return fmt.Errorf("unsupported field prefix: <%s> when set field", prfx) } return oNM.SetAsSlice(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], + PathSlice: fullPath.PathSlice[1:], Path: fullPath.Path[len(prfx):], }, []*utils.DataNode{{Type: utils.NMDataType, Value: val}}) } @@ -365,18 +361,18 @@ func (eeR *EventRequest) ParseField( // Set sets the value at the given path // this used with full path and the processed path to not calculate them for every set func (eeR *EventRequest) Append(fullPath *utils.FullPath, val *utils.DataLeaf) (err error) { - switch prfx := fullPath.PathItems[0]; prfx { + switch prfx := fullPath.PathSlice[0]; prfx { case utils.MetaUCH: return Cache.Set(utils.CacheUCH, fullPath.Path[5:], val.Data, nil, true, utils.NonTransactional) case utils.MetaOpts: - return eeR.opts.Set(fullPath.PathItems[1:], val.Data) + return eeR.opts.Set(fullPath.PathSlice[1:], val.Data) default: oNM, has := eeR.OrdNavMP[prfx] if !has { return fmt.Errorf("unsupported field prefix: <%s> when set field", prfx) } return oNM.Append(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], + PathSlice: fullPath.PathSlice[1:], Path: fullPath.Path[len(prfx):], }, val) } @@ -385,7 +381,7 @@ func (eeR *EventRequest) Append(fullPath *utils.FullPath, val *utils.DataLeaf) ( // Set sets the value at the given path // this used with full path and the processed path to not calculate them for every set func (eeR *EventRequest) Compose(fullPath *utils.FullPath, val *utils.DataLeaf) (err error) { - switch prfx := fullPath.PathItems[0]; prfx { + switch prfx := fullPath.PathSlice[0]; prfx { case utils.MetaUCH: path := fullPath.Path[5:] var prv interface{} @@ -397,7 +393,7 @@ func (eeR *EventRequest) Compose(fullPath *utils.FullPath, val *utils.DataLeaf) return Cache.Set(utils.CacheUCH, path, prv, nil, true, utils.NonTransactional) case utils.MetaOpts: var prv interface{} - if prv, err = eeR.opts.FieldAsInterface(fullPath.PathItems[1:]); err != nil { + if prv, err = eeR.opts.FieldAsInterface(fullPath.PathSlice[1:]); err != nil { if err != utils.ErrNotFound { return } @@ -405,14 +401,14 @@ func (eeR *EventRequest) Compose(fullPath *utils.FullPath, val *utils.DataLeaf) } else { prv = utils.IfaceAsString(prv) + utils.IfaceAsString(val.Data) } - return eeR.opts.Set(fullPath.PathItems[1:], prv) + return eeR.opts.Set(fullPath.PathSlice[1:], prv) default: oNM, has := eeR.OrdNavMP[prfx] if !has { return fmt.Errorf("unsupported field prefix: <%s> when set field", prfx) } return oNM.Compose(&utils.FullPath{ - PathItems: fullPath.PathItems[1:], + PathSlice: fullPath.PathSlice[1:], Path: fullPath.Path[len(prfx):], }, val) } diff --git a/engine/filters_test.go b/engine/filters_test.go index 36a08dba2..6b9395615 100644 --- a/engine/filters_test.go +++ b/engine/filters_test.go @@ -823,8 +823,7 @@ func TestInlineFilterPassFiltersForEvent(t *testing.T) { "EmptyPtrSlice": &[]string{""}, "EmptyPtrMap": &map[string]string{"": ""}, } - var testnil *struct{} - testnil = nil + var testnil *struct{} = nil passEvent = map[string]interface{}{ "EmptyString": "", "EmptySlice": []string{}, diff --git a/engine/libcdre.go b/engine/libcdre.go index 02f21c7ba..fea7034b3 100644 --- a/engine/libcdre.go +++ b/engine/libcdre.go @@ -54,7 +54,6 @@ func writeFailedPosts(itmID string, value interface{}) { utils.Logger.Warning(fmt.Sprintf("<%s> Failed to write file <%s> because <%s>", utils.CDRs, filePath, err)) } - return } func AddFailedPost(expPath, format, module string, ev interface{}, opts map[string]interface{}) { diff --git a/engine/libroutes_test.go b/engine/libroutes_test.go index e78deb462..318150011 100644 --- a/engine/libroutes_test.go +++ b/engine/libroutes_test.go @@ -1017,7 +1017,7 @@ func TestSortedRouteAsNavigableMap(t *testing.T) { Map: map[string]*utils.DataNode{ utils.RouteID: utils.NewLeafNode("ROUTE1"), utils.RouteParameters: utils.NewLeafNode("SORTING_PARAMETER"), - utils.SortingData: &utils.DataNode{ + utils.SortingData: { Type: utils.NMMapType, Map: map[string]*utils.DataNode{ utils.Ratio: utils.NewLeafNode(6.0), @@ -1062,15 +1062,15 @@ func TestSortedRoutesAsNavigableMap(t *testing.T) { Map: map[string]*utils.DataNode{ utils.ProfileID: utils.NewLeafNode("TEST_ID1"), utils.Sorting: utils.NewLeafNode(utils.MetaWeight), - utils.CapRoutes: &utils.DataNode{ + utils.CapRoutes: { Type: utils.NMSliceType, Slice: []*utils.DataNode{ - &utils.DataNode{ + { Type: utils.NMMapType, Map: map[string]*utils.DataNode{ utils.RouteID: utils.NewLeafNode("ROUTE1"), utils.RouteParameters: utils.NewLeafNode("SORTING_PARAMETER"), - utils.SortingData: &utils.DataNode{ + utils.SortingData: { Type: utils.NMMapType, Map: map[string]*utils.DataNode{ utils.Ratio: utils.NewLeafNode(6.0), @@ -1080,12 +1080,12 @@ func TestSortedRoutesAsNavigableMap(t *testing.T) { }, }, }, - &utils.DataNode{ + { Type: utils.NMMapType, Map: map[string]*utils.DataNode{ utils.RouteID: utils.NewLeafNode("ROUTE2"), utils.RouteParameters: utils.NewLeafNode("SORTING_PARAMETER_SECOND"), - utils.SortingData: &utils.DataNode{ + utils.SortingData: { Type: utils.NMMapType, Map: map[string]*utils.DataNode{ utils.Ratio: utils.NewLeafNode(7.0), diff --git a/engine/mapevent_test.go b/engine/mapevent_test.go index f874210d7..0d3e975bf 100644 --- a/engine/mapevent_test.go +++ b/engine/mapevent_test.go @@ -299,8 +299,7 @@ func TestMapEventAsMapString(t *testing.T) { if rply := mapEv.AsMapString(mpIgnore); !reflect.DeepEqual(expected, rply) { t.Errorf("Expecting %+v, received: %+v", expected, rply) } - var mp MapEvent - mp = nil + var mp MapEvent = nil if rply := mp.AsMapString(nil); !reflect.DeepEqual(map[string]string{}, rply) { t.Errorf("Expecting %+v, received: %+v", map[string]string{}, rply) } @@ -770,10 +769,8 @@ func TestMapEventGetDurationPtrOrDefault(t *testing.T) { } func TestMapEventCloneError(t *testing.T) { - testStruct := MapEvent{} - testStruct = nil - exp := MapEvent{} - exp = nil + var testStruct MapEvent = nil + var exp MapEvent = nil result := testStruct.Clone() if !reflect.DeepEqual(result, exp) { t.Errorf("Expected: %+v, received: %+v", exp, result) diff --git a/engine/model_helpers.go b/engine/model_helpers.go index fa57e7093..5ab70e67c 100644 --- a/engine/model_helpers.go +++ b/engine/model_helpers.go @@ -338,9 +338,7 @@ func APItoModelRate(r *utils.TPRateRALs) (result RateMdls) { func APItoModelRates(rs []*utils.TPRateRALs) (result RateMdls) { for _, r := range rs { - for _, sr := range APItoModelRate(r) { - result = append(result, sr) - } + result = append(result, APItoModelRate(r)...) } return result } @@ -419,12 +417,8 @@ func APItoModelDestinationRate(d *utils.TPDestinationRate) (result DestinationRa } func APItoModelDestinationRates(drs []*utils.TPDestinationRate) (result DestinationRateMdls) { - if drs != nil { - for _, dr := range drs { - for _, sdr := range APItoModelDestinationRate(dr) { - result = append(result, sdr) - } - } + for _, dr := range drs { + result = append(result, APItoModelDestinationRate(dr)...) } return result } @@ -529,9 +523,7 @@ func APItoModelRatingPlan(rp *utils.TPRatingPlan) (result RatingPlanMdls) { func APItoModelRatingPlans(rps []*utils.TPRatingPlan) (result RatingPlanMdls) { for _, rp := range rps { - for _, srp := range APItoModelRatingPlan(rp) { - result = append(result, srp) - } + result = append(result, APItoModelRatingPlan(rp)...) } return result } @@ -611,9 +603,7 @@ func APItoModelRatingProfile(rp *utils.TPRatingProfile) (result RatingProfileMdl func APItoModelRatingProfiles(rps []*utils.TPRatingProfile) (result RatingProfileMdls) { for _, rp := range rps { - for _, srp := range APItoModelRatingProfile(rp) { - result = append(result, srp) - } + result = append(result, APItoModelRatingProfile(rp)...) } return result } @@ -686,9 +676,7 @@ func APItoModelSharedGroup(sgs *utils.TPSharedGroups) (result SharedGroupMdls) { func APItoModelSharedGroups(sgs []*utils.TPSharedGroups) (result SharedGroupMdls) { for _, sg := range sgs { - for _, ssg := range APItoModelSharedGroup(sg) { - result = append(result, ssg) - } + result = append(result, APItoModelSharedGroup(sg)...) } return result } @@ -787,9 +775,7 @@ func APItoModelAction(as *utils.TPActions) (result ActionMdls) { func APItoModelActions(as []*utils.TPActions) (result ActionMdls) { for _, a := range as { - for _, sa := range APItoModelAction(a) { - result = append(result, sa) - } + result = append(result, APItoModelAction(a)...) } return result } @@ -862,9 +848,7 @@ func APItoModelActionPlan(a *utils.TPActionPlan) (result ActionPlanMdls) { func APItoModelActionPlans(aps []*utils.TPActionPlan) (result ActionPlanMdls) { for _, ap := range aps { - for _, sap := range APItoModelActionPlan(ap) { - result = append(result, sap) - } + result = append(result, APItoModelActionPlan(ap)...) } return result } @@ -972,9 +956,7 @@ func APItoModelActionTrigger(ats *utils.TPActionTriggers) (result ActionTriggerM func APItoModelActionTriggers(ts []*utils.TPActionTriggers) (result ActionTriggerMdls) { for _, t := range ts { - for _, st := range APItoModelActionTrigger(t) { - result = append(result, st) - } + result = append(result, APItoModelActionTrigger(t)...) } return result } @@ -2147,10 +2129,7 @@ func (tps AttributeMdls) AsTPAttributes() (result []*utils.TPAttributeProfile) { if tp.Path != utils.EmptyString { filterIDs := make([]string, 0) if tp.AttributeFilterIDs != utils.EmptyString { - filterAttrSplit := strings.Split(tp.AttributeFilterIDs, utils.InfieldSep) - for _, filterAttr := range filterAttrSplit { - filterIDs = append(filterIDs, filterAttr) - } + filterIDs = append(filterIDs, strings.Split(tp.AttributeFilterIDs, utils.InfieldSep)...) } th.Attributes = append(th.Attributes, &utils.TPAttribute{ FilterIDs: filterIDs, @@ -2370,9 +2349,7 @@ func (tps ChargerMdls) AsTPChargers() (result []*utils.TPChargerProfile) { result[i] = tp result[i].FilterIDs = filterMap[tntID].AsSlice() result[i].AttributeIDs = make([]string, 0, len(attributeMap[tntID])) - for _, attributeID := range attributeMap[tntID] { - result[i].AttributeIDs = append(result[i].AttributeIDs, attributeID) - } + result[i].AttributeIDs = append(result[i].AttributeIDs, attributeMap[tntID]...) i++ } return diff --git a/engine/pstr_amqp.go b/engine/pstr_amqp.go index e70a452a6..172f6240e 100644 --- a/engine/pstr_amqp.go +++ b/engine/pstr_amqp.go @@ -66,7 +66,6 @@ func (pstr *AMQPPoster) parseOpts(dialURL map[string]interface{}) { if vals, has := dialURL[utils.ExchangeType]; has { pstr.exchangeType = utils.IfaceAsString(vals) } - return } // Post is the method being called when we need to post anything in the queue diff --git a/engine/pstr_amqpv1.go b/engine/pstr_amqpv1.go index a4943a1d8..7fc2efbc0 100644 --- a/engine/pstr_amqpv1.go +++ b/engine/pstr_amqpv1.go @@ -21,7 +21,6 @@ package engine import ( "context" "fmt" - "net" "sync" "time" @@ -146,11 +145,3 @@ func (pstr *AMQPv1Poster) newPosterSession() (s *amqpv1.Session, err error) { } return pstr.client.NewSession() } - -func (pstr *AMQPv1Poster) isRecoverableError(err error) bool { - netErr, ok := err.(net.Error) - return (ok && netErr.Temporary()) || - err == amqpv1.ErrConnClosed || - err == amqpv1.ErrLinkClosed || - err == amqpv1.ErrSessionClosed -} diff --git a/engine/rateinterval.go b/engine/rateinterval.go index ab2b55f94..1c5b35871 100644 --- a/engine/rateinterval.go +++ b/engine/rateinterval.go @@ -69,15 +69,9 @@ func (rit *RITiming) CronString() string { } else { hour, min, sec = "*", "*", "*" } - if strings.HasPrefix(hour, "0") { - hour = hour[1:] - } - if strings.HasPrefix(min, "0") { - min = min[1:] - } - if strings.HasPrefix(sec, "0") { - sec = sec[1:] - } + hour = strings.TrimPrefix(hour, "0") + min = strings.TrimPrefix(min, "0") + sec = strings.TrimPrefix(sec, "0") } if len(rit.MonthDays) == 0 { monthday = "*" diff --git a/engine/rateinterval_test.go b/engine/rateinterval_test.go index d39e995f7..d44776e09 100644 --- a/engine/rateinterval_test.go +++ b/engine/rateinterval_test.go @@ -772,8 +772,7 @@ func TestRateIntervalEqualError(t *testing.T) { testRateInterval := &RateInterval{ Weight: 2, } - testRateInterval2 := &RateInterval{} - testRateInterval2 = nil + var testRateInterval2 *RateInterval = nil result := testRateInterval.Equal(testRateInterval2) if !reflect.DeepEqual(result, false) { t.Errorf("\nExpecting: ,\n Received: <%+v>", result) @@ -809,8 +808,7 @@ func TestRateIntervalGetMaxCost(t *testing.T) { } func TestRGRateCloneNil(t *testing.T) { - testRate := &RGRate{} - testRate = nil + var testRate *RGRate = nil result := testRate.Clone() if !reflect.DeepEqual(result, testRate) { t.Errorf("\nExpecting: ,\n Received: <%+v>", result) diff --git a/engine/routes.go b/engine/routes.go index 76c312504..dc8f3fb9c 100644 --- a/engine/routes.go +++ b/engine/routes.go @@ -55,8 +55,6 @@ type RouteProfile struct { SortingParameters []string Routes []*Route Weight float64 - - cache map[string]interface{} } // RouteProfileWithAPIOpts is used in replicatorV1 for dispatcher diff --git a/engine/safevent.go b/engine/safevent.go index 76fe0b28b..f6fe866fc 100644 --- a/engine/safevent.go +++ b/engine/safevent.go @@ -101,7 +101,6 @@ func (se *SafEvent) Set(fldName string, val interface{}) { se.Lock() se.Me[fldName] = val se.Unlock() - return } // Remove will remove a field from map @@ -109,7 +108,6 @@ func (se *SafEvent) Remove(fldName string) { se.Lock() delete(se.Me, fldName) se.Unlock() - return } func (se *SafEvent) GetString(fldName string) (out string, err error) { diff --git a/engine/statmetrics_test.go b/engine/statmetrics_test.go index a839d8c73..7f5b3cf8e 100644 --- a/engine/statmetrics_test.go +++ b/engine/statmetrics_test.go @@ -292,7 +292,7 @@ func TestASRCompress(t *testing.T) { } func TestASRGetCompressFactor(t *testing.T) { - CF := make(map[string]int) + var CF map[string]int expectedCF := map[string]int{ "EVENT_1": 1, "EVENT_2": 1, @@ -511,7 +511,7 @@ func TestACDCompress(t *testing.T) { } func TestACDGetCompressFactor(t *testing.T) { - CF := make(map[string]int) + var CF map[string]int expectedCF := map[string]int{ "EVENT_1": 1, "EVENT_2": 1, @@ -970,7 +970,7 @@ func TestTCDCompress(t *testing.T) { } func TestTCDGetCompressFactor(t *testing.T) { - CF := make(map[string]int) + var CF map[string]int expectedCF := map[string]int{ "EVENT_1": 1, "EVENT_2": 1, @@ -1241,7 +1241,7 @@ func TestACCCompress(t *testing.T) { } func TestACCGetCompressFactor(t *testing.T) { - CF := make(map[string]int) + var CF map[string]int expectedCF := map[string]int{ "EVENT_1": 1, "EVENT_2": 1, @@ -1514,7 +1514,7 @@ func TestTCCCompress(t *testing.T) { } func TestTCCGetCompressFactor(t *testing.T) { - CF := make(map[string]int) + var CF map[string]int expectedCF := map[string]int{ "EVENT_1": 1, "EVENT_2": 1, @@ -1856,7 +1856,7 @@ func TestPDDCompress(t *testing.T) { } func TestPDDGetCompressFactor(t *testing.T) { - CF := make(map[string]int) + var CF map[string]int expectedCF := map[string]int{ "EVENT_1": 1, "EVENT_2": 1, @@ -2072,7 +2072,7 @@ func TestDDCCompress(t *testing.T) { } func TestDDCGetCompressFactor(t *testing.T) { - CF := make(map[string]int) + var CF map[string]int expectedCF := map[string]int{ "EVENT_1": 1, "EVENT_2": 1, @@ -2353,7 +2353,7 @@ func TestStatSumCompress(t *testing.T) { } func TestStatSumGetCompressFactor(t *testing.T) { - CF := make(map[string]int) + var CF map[string]int expectedCF := map[string]int{ "EVENT_1": 1, "EVENT_2": 1, @@ -2632,7 +2632,7 @@ func TestStatAverageCompress(t *testing.T) { } func TestStatAverageGetCompressFactor(t *testing.T) { - CF := make(map[string]int) + var CF map[string]int expectedCF := map[string]int{ "EVENT_1": 1, "EVENT_2": 1, @@ -2835,7 +2835,7 @@ func TestStatDistinctCompress(t *testing.T) { } func TestStatDistinctGetCompressFactor(t *testing.T) { - CF := make(map[string]int) + var CF map[string]int expectedCF := map[string]int{ "EVENT_1": 1, "EVENT_2": 1, diff --git a/engine/stats.go b/engine/stats.go index 760e3972f..4bdb1e4a9 100644 --- a/engine/stats.go +++ b/engine/stats.go @@ -62,7 +62,6 @@ func (sS *StatService) Shutdown() { close(sS.stopBackup) sS.storeStats() utils.Logger.Info(" service shutdown complete") - return } // runBackup will regularly store resources changed to dataDB diff --git a/engine/storage_mongo_stordb.go b/engine/storage_mongo_stordb.go index b6b6965aa..086c214c5 100644 --- a/engine/storage_mongo_stordb.go +++ b/engine/storage_mongo_stordb.go @@ -636,7 +636,7 @@ func (ms *MongoStorage) SetTPRates(tps []*utils.TPRateRALs) error { m := make(map[string]bool) return ms.query(func(sctx mongo.SessionContext) (err error) { for _, tp := range tps { - if found, _ := m[tp.ID]; !found { + if !m[tp.ID] { m[tp.ID] = true _, err := ms.getCol(utils.TBLTPRates).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}) if err != nil { @@ -659,7 +659,7 @@ func (ms *MongoStorage) SetTPDestinationRates(tps []*utils.TPDestinationRate) er m := make(map[string]bool) return ms.query(func(sctx mongo.SessionContext) (err error) { for _, tp := range tps { - if found, _ := m[tp.ID]; !found { + if !m[tp.ID] { m[tp.ID] = true _, err := ms.getCol(utils.TBLTPDestinationRates).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}) if err != nil { @@ -682,7 +682,7 @@ func (ms *MongoStorage) SetTPRatingPlans(tps []*utils.TPRatingPlan) error { m := make(map[string]bool) return ms.query(func(sctx mongo.SessionContext) (err error) { for _, tp := range tps { - if found, _ := m[tp.ID]; !found { + if !m[tp.ID] { m[tp.ID] = true _, err := ms.getCol(utils.TBLTPRatingPlans).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}) if err != nil { @@ -726,7 +726,7 @@ func (ms *MongoStorage) SetTPSharedGroups(tps []*utils.TPSharedGroups) error { m := make(map[string]bool) return ms.query(func(sctx mongo.SessionContext) (err error) { for _, tp := range tps { - if found, _ := m[tp.ID]; !found { + if !m[tp.ID] { m[tp.ID] = true _, err := ms.getCol(utils.TBLTPSharedGroups).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}) if err != nil { @@ -749,7 +749,7 @@ func (ms *MongoStorage) SetTPActions(tps []*utils.TPActions) error { m := make(map[string]bool) return ms.query(func(sctx mongo.SessionContext) (err error) { for _, tp := range tps { - if found, _ := m[tp.ID]; !found { + if !m[tp.ID] { m[tp.ID] = true if _, err := ms.getCol(utils.TBLTPActions).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}); err != nil { return err @@ -770,7 +770,7 @@ func (ms *MongoStorage) SetTPActionPlans(tps []*utils.TPActionPlan) error { m := make(map[string]bool) return ms.query(func(sctx mongo.SessionContext) (err error) { for _, tp := range tps { - if found, _ := m[tp.ID]; !found { + if !m[tp.ID] { m[tp.ID] = true if _, err := ms.getCol(utils.TBLTPActionPlans).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}); err != nil { return err @@ -791,7 +791,7 @@ func (ms *MongoStorage) SetTPActionTriggers(tps []*utils.TPActionTriggers) error m := make(map[string]bool) return ms.query(func(sctx mongo.SessionContext) (err error) { for _, tp := range tps { - if found, _ := m[tp.ID]; !found { + if !m[tp.ID] { m[tp.ID] = true if _, err := ms.getCol(utils.TBLTPActionTriggers).DeleteMany(sctx, bson.M{"tpid": tp.TPid, "id": tp.ID}); err != nil { return err diff --git a/engine/storage_mysql.go b/engine/storage_mysql.go index d2da7edea..0db0c3e27 100644 --- a/engine/storage_mysql.go +++ b/engine/storage_mysql.go @@ -61,8 +61,8 @@ func NewMySQLStorage(host, port, name, user, password string, } // SetVersions will set a slice of versions, updating existing -func (self *MySQLStorage) SetVersions(vrs Versions, overwrite bool) (err error) { - tx := self.db.Begin() +func (msqlS *MySQLStorage) SetVersions(vrs Versions, overwrite bool) (err error) { + tx := msqlS.db.Begin() if overwrite { tx.Table(utils.TBLVersions).Delete(nil) } @@ -80,22 +80,22 @@ func (self *MySQLStorage) SetVersions(vrs Versions, overwrite bool) (err error) return } -func (self *MySQLStorage) extraFieldsExistsQry(field string) string { +func (msqlS *MySQLStorage) extraFieldsExistsQry(field string) string { return fmt.Sprintf(" extra_fields LIKE '%%\"%s\":%%'", field) } -func (self *MySQLStorage) extraFieldsValueQry(field, value string) string { +func (msqlS *MySQLStorage) extraFieldsValueQry(field, value string) string { return fmt.Sprintf(" extra_fields LIKE '%%\"%s\":\"%s\"%%'", field, value) } -func (self *MySQLStorage) notExtraFieldsExistsQry(field string) string { +func (msqlS *MySQLStorage) notExtraFieldsExistsQry(field string) string { return fmt.Sprintf(" extra_fields NOT LIKE '%%\"%s\":%%'", field) } -func (self *MySQLStorage) notExtraFieldsValueQry(field, value string) string { +func (msqlS *MySQLStorage) notExtraFieldsValueQry(field, value string) string { return fmt.Sprintf(" extra_fields NOT LIKE '%%\"%s\":\"%s\"%%'", field, value) } -func (self *MySQLStorage) GetStorageType() string { +func (msqlS *MySQLStorage) GetStorageType() string { return utils.MySQL } diff --git a/engine/storage_postgres.go b/engine/storage_postgres.go index 0831ff999..97714e78c 100644 --- a/engine/storage_postgres.go +++ b/engine/storage_postgres.go @@ -58,8 +58,8 @@ type PostgresStorage struct { SQLStorage } -func (self *PostgresStorage) SetVersions(vrs Versions, overwrite bool) (err error) { - tx := self.db.Begin() +func (poS *PostgresStorage) SetVersions(vrs Versions, overwrite bool) (err error) { + tx := poS.db.Begin() if overwrite { tx.Table(utils.TBLVersions).Delete(nil) } @@ -81,22 +81,22 @@ func (self *PostgresStorage) SetVersions(vrs Versions, overwrite bool) (err erro return } -func (self *PostgresStorage) extraFieldsExistsQry(field string) string { +func (poS *PostgresStorage) extraFieldsExistsQry(field string) string { return fmt.Sprintf(" extra_fields ?'%s'", field) } -func (self *PostgresStorage) extraFieldsValueQry(field, value string) string { +func (poS *PostgresStorage) extraFieldsValueQry(field, value string) string { return fmt.Sprintf(" (extra_fields ->> '%s') = '%s'", field, value) } -func (self *PostgresStorage) notExtraFieldsExistsQry(field string) string { +func (poS *PostgresStorage) notExtraFieldsExistsQry(field string) string { return fmt.Sprintf(" NOT extra_fields ?'%s'", field) } -func (self *PostgresStorage) notExtraFieldsValueQry(field, value string) string { +func (poS *PostgresStorage) notExtraFieldsValueQry(field, value string) string { return fmt.Sprintf(" NOT (extra_fields ?'%s' AND (extra_fields ->> '%s') = '%s')", field, field, value) } -func (self *PostgresStorage) GetStorageType() string { +func (poS *PostgresStorage) GetStorageType() string { return utils.Postgres } diff --git a/engine/storage_redis.go b/engine/storage_redis.go index 0b44935c7..f9f226f45 100644 --- a/engine/storage_redis.go +++ b/engine/storage_redis.go @@ -301,7 +301,10 @@ func (rs *RedisStorage) GetRatingPlanDrv(key string) (rp *RatingPlan, err error) } func (rs *RedisStorage) SetRatingPlanDrv(rp *RatingPlan) (err error) { - result, err := rs.ms.Marshal(rp) + var result []byte + if result, err = rs.ms.Marshal(rp); err != nil { + return + } var b bytes.Buffer w := zlib.NewWriter(&b) w.Write(result) diff --git a/engine/storage_sql.go b/engine/storage_sql.go index 859229a6b..f30f2e731 100644 --- a/engine/storage_sql.go +++ b/engine/storage_sql.go @@ -184,7 +184,7 @@ func (sqls *SQLStorage) GetTpTableIds(tpid, table string, distinct utils.TPDisti for _, d := range distinct[1:] { qry += fmt.Sprintf(" OR %s LIKE '%%%s%%'", d, pagination.Search) } - qry += fmt.Sprintf(")") + qry += ")" } if pagination.Paginator != nil { if pagination.Limit != nil { // Keep Postgres compatibility by adding offset only when limit defined @@ -206,7 +206,10 @@ func (sqls *SQLStorage) GetTpTableIds(tpid, table string, distinct utils.TPDisti for rows.Next() { i++ //Keep here a reference so we know we got at least one - cols, err := rows.Columns() // Get the column names; remember to check err + cols, err := rows.Columns() // Get the column names; remember to check err + if err != nil { + return nil, err + } vals := make([]string, len(cols)) // Allocate enough values ints := make([]interface{}, len(cols)) // Make a slice of []interface{} for i := range ints { @@ -312,7 +315,7 @@ func (sqls *SQLStorage) SetTPRates(rs []*utils.TPRateRALs) error { m := make(map[string]bool) tx := sqls.db.Begin() for _, rate := range rs { - if found, _ := m[rate.ID]; !found { + if !m[rate.ID] { m[rate.ID] = true if err := tx.Where(&RateMdl{Tpid: rate.TPid, Tag: rate.ID}).Delete(RateMdl{}).Error; err != nil { tx.Rollback() @@ -337,7 +340,7 @@ func (sqls *SQLStorage) SetTPDestinationRates(drs []*utils.TPDestinationRate) er m := make(map[string]bool) tx := sqls.db.Begin() for _, dRate := range drs { - if found, _ := m[dRate.ID]; !found { + if !m[dRate.ID] { m[dRate.ID] = true if err := tx.Where(&DestinationRateMdl{Tpid: dRate.TPid, Tag: dRate.ID}).Delete(DestinationRateMdl{}).Error; err != nil { tx.Rollback() @@ -362,7 +365,7 @@ func (sqls *SQLStorage) SetTPRatingPlans(rps []*utils.TPRatingPlan) error { m := make(map[string]bool) tx := sqls.db.Begin() for _, rPlan := range rps { - if found, _ := m[rPlan.ID]; !found { + if !m[rPlan.ID] { m[rPlan.ID] = true if err := tx.Where(&RatingPlanMdl{Tpid: rPlan.TPid, Tag: rPlan.ID}).Delete(RatingPlanMdl{}).Error; err != nil { tx.Rollback() @@ -410,7 +413,7 @@ func (sqls *SQLStorage) SetTPSharedGroups(sgs []*utils.TPSharedGroups) error { m := make(map[string]bool) tx := sqls.db.Begin() for _, sGroup := range sgs { - if found, _ := m[sGroup.ID]; !found { + if !m[sGroup.ID] { m[sGroup.ID] = true if err := tx.Where(&SharedGroupMdl{Tpid: sGroup.TPid, Tag: sGroup.ID}).Delete(SharedGroupMdl{}).Error; err != nil { tx.Rollback() @@ -435,7 +438,7 @@ func (sqls *SQLStorage) SetTPActions(acts []*utils.TPActions) error { m := make(map[string]bool) tx := sqls.db.Begin() for _, a := range acts { - if found, _ := m[a.ID]; !found { + if !m[a.ID] { m[a.ID] = true if err := tx.Where(&ActionMdl{Tpid: a.TPid, Tag: a.ID}).Delete(ActionMdl{}).Error; err != nil { tx.Rollback() @@ -461,7 +464,7 @@ func (sqls *SQLStorage) SetTPActionPlans(ats []*utils.TPActionPlan) error { tx := sqls.db.Begin() for _, aPlan := range ats { - if found, _ := m[aPlan.ID]; !found { + if !m[aPlan.ID] { m[aPlan.ID] = true if err := tx.Where(&ActionPlanMdl{Tpid: aPlan.TPid, Tag: aPlan.ID}).Delete(ActionPlanMdl{}).Error; err != nil { tx.Rollback() @@ -486,7 +489,7 @@ func (sqls *SQLStorage) SetTPActionTriggers(ats []*utils.TPActionTriggers) error m := make(map[string]bool) tx := sqls.db.Begin() for _, aTrigger := range ats { - if found, _ := m[aTrigger.ID]; !found { + if !m[aTrigger.ID] { m[aTrigger.ID] = true if err := tx.Where(&ActionTriggerMdl{Tpid: aTrigger.TPid, Tag: aTrigger.ID}).Delete(ActionTriggerMdl{}).Error; err != nil { tx.Rollback() @@ -513,7 +516,7 @@ func (sqls *SQLStorage) SetTPAccountActions(aas []*utils.TPAccountActions) error tx := sqls.db.Begin() for _, aa := range aas { - if found, _ := m[aa.GetId()]; !found { + if !m[aa.GetId()] { m[aa.GetId()] = true if err := tx.Where(&AccountActionMdl{Tpid: aa.TPid, Loadid: aa.LoadId, Tenant: aa.Tenant, Account: aa.Account}).Delete(&AccountActionMdl{}).Error; err != nil { tx.Rollback() diff --git a/engine/storage_utils.go b/engine/storage_utils.go index c32790cd3..17fbfda67 100644 --- a/engine/storage_utils.go +++ b/engine/storage_utils.go @@ -40,7 +40,7 @@ func NewDataDBConn(dbType, host, port, name, user, utils.Logger.Crit("Redis db name must be an integer!") return } - if port != "" && strings.Index(host, ":") == -1 { + if port != "" && !strings.Contains(host, ":") { host += ":" + port } var isCluster bool diff --git a/engine/thresholds.go b/engine/thresholds.go index c9c965b41..8781210b0 100644 --- a/engine/thresholds.go +++ b/engine/thresholds.go @@ -156,7 +156,6 @@ func (tS *ThresholdService) Shutdown() { close(tS.stopBackup) tS.storeThresholds() utils.Logger.Info(" shutdown complete") - return } // backup will regularly store resources changed to dataDB diff --git a/engine/tpexporter.go b/engine/tpexporter.go index e0ed0206c..722521140 100644 --- a/engine/tpexporter.go +++ b/engine/tpexporter.go @@ -80,12 +80,12 @@ type TPExporter struct { exportedFiles []string } -func (self *TPExporter) Run() error { - self.removeFiles() // Make sure we clean the folder before starting with new one +func (tpExp *TPExporter) Run() error { + tpExp.removeFiles() // Make sure we clean the folder before starting with new one var withError bool toExportMap := make(map[string][]interface{}) - storDataTimings, err := self.storDb.GetTPTimings(self.tpID, "") + storDataTimings, err := tpExp.storDb.GetTPTimings(tpExp.tpID, "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpTiming)) withError = true @@ -96,7 +96,7 @@ func (self *TPExporter) Run() error { toExportMap[utils.TimingsCsv][i] = sd } - storDataDestinations, err := self.storDb.GetTPDestinations(self.tpID, "") + storDataDestinations, err := tpExp.storDb.GetTPDestinations(tpExp.tpID, "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpDestinations)) withError = true @@ -108,7 +108,7 @@ func (self *TPExporter) Run() error { } } - storDataRates, err := self.storDb.GetTPRates(self.tpID, "") + storDataRates, err := tpExp.storDb.GetTPRates(tpExp.tpID, "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpRates)) withError = true @@ -120,7 +120,7 @@ func (self *TPExporter) Run() error { } } - storDataDestinationRates, err := self.storDb.GetTPDestinationRates(self.tpID, "", nil) + storDataDestinationRates, err := tpExp.storDb.GetTPDestinationRates(tpExp.tpID, "", nil) if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpDestinationRates)) withError = true @@ -132,7 +132,7 @@ func (self *TPExporter) Run() error { } } - storDataRatingPlans, err := self.storDb.GetTPRatingPlans(self.tpID, "", nil) + storDataRatingPlans, err := tpExp.storDb.GetTPRatingPlans(tpExp.tpID, "", nil) if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpRatingPlans)) withError = true @@ -144,7 +144,7 @@ func (self *TPExporter) Run() error { } } - storDataRatingProfiles, err := self.storDb.GetTPRatingProfiles(&utils.TPRatingProfile{TPid: self.tpID}) + storDataRatingProfiles, err := tpExp.storDb.GetTPRatingProfiles(&utils.TPRatingProfile{TPid: tpExp.tpID}) if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpRatingProfiles)) withError = true @@ -156,7 +156,7 @@ func (self *TPExporter) Run() error { } } - storDataSharedGroups, err := self.storDb.GetTPSharedGroups(self.tpID, "") + storDataSharedGroups, err := tpExp.storDb.GetTPSharedGroups(tpExp.tpID, "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpSharedGroups)) withError = true @@ -169,7 +169,7 @@ func (self *TPExporter) Run() error { } } - storDataActions, err := self.storDb.GetTPActions(self.tpID, "") + storDataActions, err := tpExp.storDb.GetTPActions(tpExp.tpID, "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpActions)) withError = true @@ -181,7 +181,7 @@ func (self *TPExporter) Run() error { } } - storDataActionPlans, err := self.storDb.GetTPActionPlans(self.tpID, "") + storDataActionPlans, err := tpExp.storDb.GetTPActionPlans(tpExp.tpID, "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpActionPlans)) withError = true @@ -193,7 +193,7 @@ func (self *TPExporter) Run() error { } } - storDataActionTriggers, err := self.storDb.GetTPActionTriggers(self.tpID, "") + storDataActionTriggers, err := tpExp.storDb.GetTPActionTriggers(tpExp.tpID, "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpActionTriggers)) withError = true @@ -205,7 +205,7 @@ func (self *TPExporter) Run() error { } } - storDataAccountActions, err := self.storDb.GetTPAccountActions(&utils.TPAccountActions{TPid: self.tpID}) + storDataAccountActions, err := tpExp.storDb.GetTPAccountActions(&utils.TPAccountActions{TPid: tpExp.tpID}) if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpAccountActionsV)) withError = true @@ -215,7 +215,7 @@ func (self *TPExporter) Run() error { toExportMap[utils.AccountActionsCsv] = append(toExportMap[utils.AccountActionsCsv], sdModel) } - storDataResources, err := self.storDb.GetTPResources(self.tpID, "", "") + storDataResources, err := tpExp.storDb.GetTPResources(tpExp.tpID, "", "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpResources)) withError = true @@ -227,7 +227,7 @@ func (self *TPExporter) Run() error { } } - storDataStats, err := self.storDb.GetTPStats(self.tpID, "", "") + storDataStats, err := tpExp.storDb.GetTPStats(tpExp.tpID, "", "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpStats)) withError = true @@ -239,7 +239,7 @@ func (self *TPExporter) Run() error { } } - storDataThresholds, err := self.storDb.GetTPThresholds(self.tpID, "", "") + storDataThresholds, err := tpExp.storDb.GetTPThresholds(tpExp.tpID, "", "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpThresholds)) withError = true @@ -251,7 +251,7 @@ func (self *TPExporter) Run() error { } } - storDataFilters, err := self.storDb.GetTPFilters(self.tpID, "", "") + storDataFilters, err := tpExp.storDb.GetTPFilters(tpExp.tpID, "", "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpFilters)) withError = true @@ -263,7 +263,7 @@ func (self *TPExporter) Run() error { } } - storDataRoutes, err := self.storDb.GetTPRoutes(self.tpID, "", "") + storDataRoutes, err := tpExp.storDb.GetTPRoutes(tpExp.tpID, "", "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpRoutes)) withError = true @@ -275,7 +275,7 @@ func (self *TPExporter) Run() error { } } - storeDataAttributes, err := self.storDb.GetTPAttributes(self.tpID, "", "") + storeDataAttributes, err := tpExp.storDb.GetTPAttributes(tpExp.tpID, "", "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpAttributes)) withError = true @@ -287,7 +287,7 @@ func (self *TPExporter) Run() error { } } - storDataChargers, err := self.storDb.GetTPChargers(self.tpID, "", "") + storDataChargers, err := tpExp.storDb.GetTPChargers(tpExp.tpID, "", "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpChargers)) withError = true @@ -299,7 +299,7 @@ func (self *TPExporter) Run() error { } } - storDataDispatcherProfiles, err := self.storDb.GetTPDispatcherProfiles(self.tpID, "", "") + storDataDispatcherProfiles, err := tpExp.storDb.GetTPDispatcherProfiles(tpExp.tpID, "", "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpDispatcherProfiles)) withError = true @@ -311,7 +311,7 @@ func (self *TPExporter) Run() error { } } - storDataDispatcherHosts, err := self.storDb.GetTPDispatcherHosts(self.tpID, "", "") + storDataDispatcherHosts, err := tpExp.storDb.GetTPDispatcherHosts(tpExp.tpID, "", "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpDispatcherHosts)) withError = true @@ -320,7 +320,7 @@ func (self *TPExporter) Run() error { toExportMap[utils.DispatcherHostsCsv] = append(toExportMap[utils.DispatcherHostsCsv], APItoModelTPDispatcherHost(sd)) } - storDataRateProfiles, err := self.storDb.GetTPRateProfiles(self.tpID, "", "") + storDataRateProfiles, err := tpExp.storDb.GetTPRateProfiles(tpExp.tpID, "", "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpRateProfiles)) withError = true @@ -332,7 +332,7 @@ func (self *TPExporter) Run() error { } } - storDataActionProfiles, err := self.storDb.GetTPActionProfiles(self.tpID, "", "") + storDataActionProfiles, err := tpExp.storDb.GetTPActionProfiles(tpExp.tpID, "", "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpActionProfiles)) withError = true @@ -344,7 +344,7 @@ func (self *TPExporter) Run() error { } } - storDataAccountProfiles, err := self.storDb.GetTPAccountProfiles(self.tpID, "", "") + storDataAccountProfiles, err := tpExp.storDb.GetTPAccountProfiles(tpExp.tpID, "", "") if err != nil && err.Error() != utils.ErrNotFound.Error() { utils.Logger.Warning(fmt.Sprintf("<%s> error: %s, when getting %s from stordb for export", utils.ApierS, err, utils.TpAccountProfiles)) withError = true @@ -361,15 +361,15 @@ func (self *TPExporter) Run() error { } for fileName, storData := range toExportMap { - if err := self.writeOut(fileName, storData); err != nil { - self.removeFiles() + if err := tpExp.writeOut(fileName, storData); err != nil { + tpExp.removeFiles() return err } - self.exportedFiles = append(self.exportedFiles, fileName) + tpExp.exportedFiles = append(tpExp.exportedFiles, fileName) } - if self.compress { - if err := self.zipWritter.Close(); err != nil { + if tpExp.compress { + if err := tpExp.zipWritter.Close(); err != nil { return err } } @@ -380,18 +380,18 @@ func (self *TPExporter) Run() error { } // Some export did not end up well, remove the files here -func (self *TPExporter) removeFiles() error { - if len(self.exportPath) == 0 { +func (tpExp *TPExporter) removeFiles() error { + if len(tpExp.exportPath) == 0 { return nil } - for _, fileName := range self.exportedFiles { - os.Remove(path.Join(self.exportPath, fileName)) + for _, fileName := range tpExp.exportedFiles { + os.Remove(path.Join(tpExp.exportPath, fileName)) } return nil } // General method to write the content out to a file on path or zip archive -func (self *TPExporter) writeOut(fileName string, tpData []interface{}) error { +func (tpExp *TPExporter) writeOut(fileName string, tpData []interface{}) error { if len(tpData) == 0 { return nil } @@ -399,12 +399,12 @@ func (self *TPExporter) writeOut(fileName string, tpData []interface{}) error { var writerOut utils.CgrRecordWriter var err error - if self.compress { - if fWriter, err = self.zipWritter.Create(fileName); err != nil { + if tpExp.compress { + if fWriter, err = tpExp.zipWritter.Create(fileName); err != nil { return err } - } else if len(self.exportPath) != 0 { - if f, err := os.Create(path.Join(self.exportPath, fileName)); err != nil { + } else if len(tpExp.exportPath) != 0 { + if f, err := os.Create(path.Join(tpExp.exportPath, fileName)); err != nil { return err } else { fWriter = f @@ -415,10 +415,10 @@ func (self *TPExporter) writeOut(fileName string, tpData []interface{}) error { fWriter = new(bytes.Buffer) } - switch self.fileFormat { + switch tpExp.fileFormat { case utils.CSV: csvWriter := csv.NewWriter(fWriter) - csvWriter.Comma = self.sep + csvWriter.Comma = tpExp.sep writerOut = csvWriter default: writerOut = utils.NewCgrIORecordWriter(fWriter) @@ -436,10 +436,10 @@ func (self *TPExporter) writeOut(fileName string, tpData []interface{}) error { return nil } -func (self *TPExporter) ExportStats() *utils.ExportedTPStats { - return &utils.ExportedTPStats{ExportPath: self.exportPath, ExportedFiles: self.exportedFiles, Compressed: self.compress} +func (tpExp *TPExporter) ExportStats() *utils.ExportedTPStats { + return &utils.ExportedTPStats{ExportPath: tpExp.exportPath, ExportedFiles: tpExp.exportedFiles, Compressed: tpExp.compress} } -func (self *TPExporter) GetCacheBuffer() *bytes.Buffer { - return self.cacheBuff +func (tpExp *TPExporter) GetCacheBuffer() *bytes.Buffer { + return tpExp.cacheBuff } diff --git a/engine/tpimporter_csv.go b/engine/tpimporter_csv.go index d8d2ac2ee..4b25139b1 100644 --- a/engine/tpimporter_csv.go +++ b/engine/tpimporter_csv.go @@ -65,16 +65,16 @@ var fileHandlers = map[string]func(*TPCSVImporter, string) error{ utils.AccountProfilesCsv: (*TPCSVImporter).importAccountProfiles, } -func (self *TPCSVImporter) Run() error { - self.csvr = NewFileCSVStorage(self.Sep, self.DirPath) - files, _ := os.ReadDir(self.DirPath) +func (tpImp *TPCSVImporter) Run() error { + tpImp.csvr = NewFileCSVStorage(tpImp.Sep, tpImp.DirPath) + files, _ := os.ReadDir(tpImp.DirPath) var withErrors bool for _, f := range files { fHandler, hasName := fileHandlers[f.Name()] if !hasName { continue } - if err := fHandler(self, f.Name()); err != nil { + if err := fHandler(tpImp, f.Name()); err != nil { withErrors = true utils.Logger.Err(fmt.Sprintf(" Importing file: %s, got error: %s", f.Name(), err.Error())) } @@ -86,310 +86,310 @@ func (self *TPCSVImporter) Run() error { } // Handler importing timings from file, saved row by row to storDb -func (self *TPCSVImporter) importTimings(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importTimings(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - tps, err := self.csvr.GetTPTimings(self.TPid, "") + tps, err := tpImp.csvr.GetTPTimings(tpImp.TPid, "") if err != nil { return err } for i := 0; i < len(tps); i++ { - tps[i].TPid = self.TPid + tps[i].TPid = tpImp.TPid } - return self.StorDb.SetTPTimings(tps) + return tpImp.StorDb.SetTPTimings(tps) } -func (self *TPCSVImporter) importDestinations(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importDestinations(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - tps, err := self.csvr.GetTPDestinations(self.TPid, "") + tps, err := tpImp.csvr.GetTPDestinations(tpImp.TPid, "") if err != nil { return err } for i := 0; i < len(tps); i++ { - tps[i].TPid = self.TPid + tps[i].TPid = tpImp.TPid } - return self.StorDb.SetTPDestinations(tps) + return tpImp.StorDb.SetTPDestinations(tps) } -func (self *TPCSVImporter) importRates(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importRates(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - tps, err := self.csvr.GetTPRates(self.TPid, "") + tps, err := tpImp.csvr.GetTPRates(tpImp.TPid, "") if err != nil { return err } for i := 0; i < len(tps); i++ { - tps[i].TPid = self.TPid + tps[i].TPid = tpImp.TPid } - return self.StorDb.SetTPRates(tps) + return tpImp.StorDb.SetTPRates(tps) } -func (self *TPCSVImporter) importDestinationRates(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importDestinationRates(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - tps, err := self.csvr.GetTPDestinationRates(self.TPid, "", nil) + tps, err := tpImp.csvr.GetTPDestinationRates(tpImp.TPid, "", nil) if err != nil { return err } for i := 0; i < len(tps); i++ { - tps[i].TPid = self.TPid + tps[i].TPid = tpImp.TPid } - return self.StorDb.SetTPDestinationRates(tps) + return tpImp.StorDb.SetTPDestinationRates(tps) } -func (self *TPCSVImporter) importRatingPlans(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importRatingPlans(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - tps, err := self.csvr.GetTPRatingPlans(self.TPid, "", nil) + tps, err := tpImp.csvr.GetTPRatingPlans(tpImp.TPid, "", nil) if err != nil { return err } for i := 0; i < len(tps); i++ { - tps[i].TPid = self.TPid + tps[i].TPid = tpImp.TPid } - return self.StorDb.SetTPRatingPlans(tps) + return tpImp.StorDb.SetTPRatingPlans(tps) } -func (self *TPCSVImporter) importRatingProfiles(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importRatingProfiles(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - tps, err := self.csvr.GetTPRatingProfiles(&utils.TPRatingProfile{TPid: self.TPid}) + tps, err := tpImp.csvr.GetTPRatingProfiles(&utils.TPRatingProfile{TPid: tpImp.TPid}) if err != nil { return err } loadId := utils.CSVLoad //Autogenerate rating profile id - if self.ImportId != "" { - loadId += "_" + self.ImportId + if tpImp.ImportId != "" { + loadId += "_" + tpImp.ImportId } for i := 0; i < len(tps); i++ { - tps[i].TPid = self.TPid + tps[i].TPid = tpImp.TPid tps[i].LoadId = loadId } - return self.StorDb.SetTPRatingProfiles(tps) + return tpImp.StorDb.SetTPRatingProfiles(tps) } -func (self *TPCSVImporter) importSharedGroups(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importSharedGroups(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - tps, err := self.csvr.GetTPSharedGroups(self.TPid, "") + tps, err := tpImp.csvr.GetTPSharedGroups(tpImp.TPid, "") if err != nil { return err } for i := 0; i < len(tps); i++ { - tps[i].TPid = self.TPid + tps[i].TPid = tpImp.TPid } - return self.StorDb.SetTPSharedGroups(tps) + return tpImp.StorDb.SetTPSharedGroups(tps) } -func (self *TPCSVImporter) importActions(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importActions(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - tps, err := self.csvr.GetTPActions(self.TPid, "") + tps, err := tpImp.csvr.GetTPActions(tpImp.TPid, "") if err != nil { return err } for i := 0; i < len(tps); i++ { - tps[i].TPid = self.TPid + tps[i].TPid = tpImp.TPid } - return self.StorDb.SetTPActions(tps) + return tpImp.StorDb.SetTPActions(tps) } -func (self *TPCSVImporter) importActionTimings(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importActionTimings(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - tps, err := self.csvr.GetTPActionPlans(self.TPid, "") + tps, err := tpImp.csvr.GetTPActionPlans(tpImp.TPid, "") if err != nil { return err } for i := 0; i < len(tps); i++ { - tps[i].TPid = self.TPid + tps[i].TPid = tpImp.TPid } - return self.StorDb.SetTPActionPlans(tps) + return tpImp.StorDb.SetTPActionPlans(tps) } -func (self *TPCSVImporter) importActionTriggers(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importActionTriggers(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - tps, err := self.csvr.GetTPActionTriggers(self.TPid, "") + tps, err := tpImp.csvr.GetTPActionTriggers(tpImp.TPid, "") if err != nil { return err } for i := 0; i < len(tps); i++ { - tps[i].TPid = self.TPid + tps[i].TPid = tpImp.TPid } - return self.StorDb.SetTPActionTriggers(tps) + return tpImp.StorDb.SetTPActionTriggers(tps) } -func (self *TPCSVImporter) importAccountActions(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importAccountActions(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - tps, err := self.csvr.GetTPAccountActions(&utils.TPAccountActions{TPid: self.TPid}) + tps, err := tpImp.csvr.GetTPAccountActions(&utils.TPAccountActions{TPid: tpImp.TPid}) if err != nil { return err } loadId := utils.CSVLoad //Autogenerate rating profile id - if self.ImportId != "" { - loadId += "_" + self.ImportId + if tpImp.ImportId != "" { + loadId += "_" + tpImp.ImportId } for i := 0; i < len(tps); i++ { - tps[i].TPid = self.TPid + tps[i].TPid = tpImp.TPid tps[i].LoadId = loadId } - return self.StorDb.SetTPAccountActions(tps) + return tpImp.StorDb.SetTPAccountActions(tps) } -func (self *TPCSVImporter) importResources(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importResources(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - rls, err := self.csvr.GetTPResources(self.TPid, "", "") + rls, err := tpImp.csvr.GetTPResources(tpImp.TPid, "", "") if err != nil { return err } - return self.StorDb.SetTPResources(rls) + return tpImp.StorDb.SetTPResources(rls) } -func (self *TPCSVImporter) importStats(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importStats(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - sts, err := self.csvr.GetTPStats(self.TPid, "", "") + sts, err := tpImp.csvr.GetTPStats(tpImp.TPid, "", "") if err != nil { return err } - return self.StorDb.SetTPStats(sts) + return tpImp.StorDb.SetTPStats(sts) } -func (self *TPCSVImporter) importThresholds(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importThresholds(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - sts, err := self.csvr.GetTPThresholds(self.TPid, "", "") + sts, err := tpImp.csvr.GetTPThresholds(tpImp.TPid, "", "") if err != nil { return err } - return self.StorDb.SetTPThresholds(sts) + return tpImp.StorDb.SetTPThresholds(sts) } -func (self *TPCSVImporter) importFilters(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importFilters(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - sts, err := self.csvr.GetTPFilters(self.TPid, "", "") + sts, err := tpImp.csvr.GetTPFilters(tpImp.TPid, "", "") if err != nil { return err } - return self.StorDb.SetTPFilters(sts) + return tpImp.StorDb.SetTPFilters(sts) } -func (self *TPCSVImporter) importRoutes(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importRoutes(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - rls, err := self.csvr.GetTPRoutes(self.TPid, "", "") + rls, err := tpImp.csvr.GetTPRoutes(tpImp.TPid, "", "") if err != nil { return err } - return self.StorDb.SetTPRoutes(rls) + return tpImp.StorDb.SetTPRoutes(rls) } -func (self *TPCSVImporter) importAttributeProfiles(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importAttributeProfiles(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - rls, err := self.csvr.GetTPAttributes(self.TPid, "", "") + rls, err := tpImp.csvr.GetTPAttributes(tpImp.TPid, "", "") if err != nil { return err } - return self.StorDb.SetTPAttributes(rls) + return tpImp.StorDb.SetTPAttributes(rls) } -func (self *TPCSVImporter) importChargerProfiles(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importChargerProfiles(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - rls, err := self.csvr.GetTPChargers(self.TPid, "", "") + rls, err := tpImp.csvr.GetTPChargers(tpImp.TPid, "", "") if err != nil { return err } - return self.StorDb.SetTPChargers(rls) + return tpImp.StorDb.SetTPChargers(rls) } -func (self *TPCSVImporter) importDispatcherProfiles(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importDispatcherProfiles(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - dpps, err := self.csvr.GetTPDispatcherProfiles(self.TPid, "", "") + dpps, err := tpImp.csvr.GetTPDispatcherProfiles(tpImp.TPid, "", "") if err != nil { return err } - return self.StorDb.SetTPDispatcherProfiles(dpps) + return tpImp.StorDb.SetTPDispatcherProfiles(dpps) } -func (self *TPCSVImporter) importDispatcherHosts(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importDispatcherHosts(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - dpps, err := self.csvr.GetTPDispatcherHosts(self.TPid, "", "") + dpps, err := tpImp.csvr.GetTPDispatcherHosts(tpImp.TPid, "", "") if err != nil { return err } - return self.StorDb.SetTPDispatcherHosts(dpps) + return tpImp.StorDb.SetTPDispatcherHosts(dpps) } -func (self *TPCSVImporter) importRateProfiles(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importRateProfiles(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - rpps, err := self.csvr.GetTPRateProfiles(self.TPid, "", "") + rpps, err := tpImp.csvr.GetTPRateProfiles(tpImp.TPid, "", "") if err != nil { return err } - return self.StorDb.SetTPRateProfiles(rpps) + return tpImp.StorDb.SetTPRateProfiles(rpps) } -func (self *TPCSVImporter) importActionProfiles(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importActionProfiles(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - rpps, err := self.csvr.GetTPActionProfiles(self.TPid, "", "") + rpps, err := tpImp.csvr.GetTPActionProfiles(tpImp.TPid, "", "") if err != nil { return err } - return self.StorDb.SetTPActionProfiles(rpps) + return tpImp.StorDb.SetTPActionProfiles(rpps) } -func (self *TPCSVImporter) importAccountProfiles(fn string) error { - if self.Verbose { +func (tpImp *TPCSVImporter) importAccountProfiles(fn string) error { + if tpImp.Verbose { log.Printf("Processing file: <%s> ", fn) } - rpps, err := self.csvr.GetTPAccountProfiles(self.TPid, "", "") + rpps, err := tpImp.csvr.GetTPAccountProfiles(tpImp.TPid, "", "") if err != nil { return err } - return self.StorDb.SetTPAccountProfiles(rpps) + return tpImp.StorDb.SetTPAccountProfiles(rpps) } diff --git a/engine/z_datamanager_it_test.go b/engine/z_datamanager_it_test.go index 7dba1462f..150b5f868 100644 --- a/engine/z_datamanager_it_test.go +++ b/engine/z_datamanager_it_test.go @@ -32,8 +32,7 @@ import ( ) var ( - dm2 *DataManager - dataMngConfigDIR string + dm2 *DataManager sTestsDMit = []func(t *testing.T){ testDMitDataFlush, diff --git a/engine/z_libcdre_it_test.go b/engine/z_libcdre_it_test.go index 9677cb747..634e59e72 100644 --- a/engine/z_libcdre_it_test.go +++ b/engine/z_libcdre_it_test.go @@ -101,7 +101,7 @@ func TestWriteToFile(t *testing.T) { //wrong path *reading exportEvent = &ExportEvents{} filePath = "/tmp/engine/libcdre_test/wrongpath.txt" - if rcv, err = NewExportEventsFromFile(filePath); err == nil || err.Error() != "open /tmp/engine/libcdre_test/wrongpath.txt: no such file or directory" { + if _, err = NewExportEventsFromFile(filePath); err == nil || err.Error() != "open /tmp/engine/libcdre_test/wrongpath.txt: no such file or directory" { t.Errorf("Expecting: 'open /tmp/engine/libcdre_test/wrongpath.txt: no such file or directory',\nReceived: '%+v'", err) } //wrong path *writing diff --git a/engine/z_stordb_it_test.go b/engine/z_stordb_it_test.go index 40d5ad781..f22652d4d 100644 --- a/engine/z_stordb_it_test.go +++ b/engine/z_stordb_it_test.go @@ -1015,8 +1015,8 @@ func testStorDBitCRUDTpDestinations(t *testing.T) { } pfrOk := true for i := range rcv[0].Prefixes { - found1, _ := prfs[rcv[0].Prefixes[i]] - found2, _ := prfs[rcv[1].Prefixes[i]] + found1 := prfs[rcv[0].Prefixes[i]] + found2 := prfs[rcv[1].Prefixes[i]] if !found1 && !found2 { pfrOk = false } @@ -1045,8 +1045,8 @@ func testStorDBitCRUDTpDestinations(t *testing.T) { } pfrOk := true for i := range rcv[0].Prefixes { - found1, _ := prfs[rcv[0].Prefixes[i]] - found2, _ := prfs[rcv[1].Prefixes[i]] + found1 := prfs[rcv[0].Prefixes[i]] + found2 := prfs[rcv[1].Prefixes[i]] if !found1 && !found2 { pfrOk = false } diff --git a/ers/amqp.go b/ers/amqp.go index 7015af813..4c5c99dc1 100644 --- a/ers/amqp.go +++ b/ers/amqp.go @@ -200,7 +200,7 @@ func (rdr *AMQPER) processMessage(msg []byte) (err error) { if err = agReq.SetFields(rdr.Config().Fields); err != nil { return } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) rdr.rdrEvents <- &erEvent{ cgrEvent: cgrEv, rdrCfg: rdr.Config(), diff --git a/ers/amqpv1.go b/ers/amqpv1.go index 539d22e7d..9510585f6 100644 --- a/ers/amqpv1.go +++ b/ers/amqpv1.go @@ -175,7 +175,7 @@ func (rdr *AMQPv1ER) processMessage(msg []byte) (err error) { if err = agReq.SetFields(rdr.Config().Fields); err != nil { return } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) rdr.rdrEvents <- &erEvent{ cgrEvent: cgrEv, rdrCfg: rdr.Config(), diff --git a/ers/filecsv.go b/ers/filecsv.go index 2837e4a8f..61a024310 100644 --- a/ers/filecsv.go +++ b/ers/filecsv.go @@ -184,7 +184,7 @@ func (rdr *CSVFileER) processFile(fPath, fName string) (err error) { utils.ERs, absPath, rowNr, err.Error())) return } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) rdr.rdrEvents <- &erEvent{ cgrEvent: cgrEv, rdrCfg: rdr.Config(), diff --git a/ers/filefwv.go b/ers/filefwv.go index f0e7ade78..115c4c957 100644 --- a/ers/filefwv.go +++ b/ers/filefwv.go @@ -140,7 +140,7 @@ func (rdr *FWVFileER) processFile(fPath, fName string) (err error) { rowNr := 0 // This counts the rows in the file, not really number of CDRs evsPosted := 0 timeStart := time.Now() - reqVars := &utils.DataNode{Type:utils.NMMapType,Map:map[string]*utils.DataNode{utils.FileName: utils.NewLeafNode(fName)}} + reqVars := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{utils.FileName: utils.NewLeafNode(fName)}} for { var hasHeader, hasTrailer bool @@ -217,7 +217,7 @@ func (rdr *FWVFileER) processFile(fPath, fName string) (err error) { return } rdr.offset += rdr.lineLen // increase the offset - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) rdr.rdrEvents <- &erEvent{ cgrEvent: cgrEv, rdrCfg: rdr.Config(), @@ -305,7 +305,7 @@ func (rdr *FWVFileER) processTrailer(file *os.File, rowNr, evsPosted int, absPat utils.ERs, absPath, rowNr, err.Error())) return err } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) rdr.rdrEvents <- &erEvent{ cgrEvent: cgrEv, rdrCfg: rdr.Config(), @@ -347,7 +347,7 @@ func (rdr *FWVFileER) createHeaderMap(record string, rowNr, evsPosted int, absPa return err } rdr.offset += rdr.headerOffset // increase the offset - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) rdr.rdrEvents <- &erEvent{ cgrEvent: cgrEv, rdrCfg: rdr.Config(), diff --git a/ers/filejson.go b/ers/filejson.go index 6c9c3df98..c68463d1a 100644 --- a/ers/filejson.go +++ b/ers/filejson.go @@ -166,7 +166,7 @@ func (rdr *JSONFileER) processFile(fPath, fName string) (err error) { utils.ERs, absPath, err.Error())) return } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) rdr.rdrEvents <- &erEvent{ cgrEvent: cgrEv, rdrCfg: rdr.Config(), diff --git a/ers/filexml.go b/ers/filexml.go index 01be446fa..a05420e9d 100644 --- a/ers/filexml.go +++ b/ers/filexml.go @@ -163,7 +163,7 @@ func (rdr *XMLFileER) processFile(fPath, fName string) (err error) { utils.ERs, absPath, rowNr, err.Error())) continue } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) rdr.rdrEvents <- &erEvent{ cgrEvent: cgrEv, rdrCfg: rdr.Config(), diff --git a/ers/flatstore.go b/ers/flatstore.go index cdf5c58ff..8c5d53f31 100644 --- a/ers/flatstore.go +++ b/ers/flatstore.go @@ -214,7 +214,7 @@ func (rdr *FlatstoreER) processFile(fPath, fName string) (err error) { return } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) rdr.rdrEvents <- &erEvent{ cgrEvent: cgrEv, rdrCfg: rdr.Config(), diff --git a/ers/kafka.go b/ers/kafka.go index ef583c643..0e5ed13b8 100644 --- a/ers/kafka.go +++ b/ers/kafka.go @@ -172,7 +172,7 @@ func (rdr *KafkaER) processMessage(msg []byte) (err error) { if err = agReq.SetFields(rdr.Config().Fields); err != nil { return } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) rdr.rdrEvents <- &erEvent{ cgrEvent: cgrEv, rdrCfg: rdr.Config(), diff --git a/ers/partial_csv.go b/ers/partial_csv.go index 3111c8ca6..a40dd4121 100644 --- a/ers/partial_csv.go +++ b/ers/partial_csv.go @@ -216,7 +216,7 @@ func (rdr *PartialCSVFileER) processFile(fPath, fName string) (err error) { cgrID := utils.Sha1(orgID, orgHost) // take Partial field from NavigableMap partial, _ := agReq.CGRRequest.FieldAsString([]string{utils.Partial}) - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) if val, has := rdr.cache.Get(cgrID); !has { if utils.IsSliceMember([]string{"false", utils.EmptyString}, partial) { // complete CDR rdr.rdrEvents <- &erEvent{ diff --git a/ers/s3.go b/ers/s3.go index 91095f21d..db95aa690 100644 --- a/ers/s3.go +++ b/ers/s3.go @@ -129,7 +129,7 @@ func (rdr *S3ER) processMessage(body []byte) (err error) { if err = agReq.SetFields(rdr.Config().Fields); err != nil { return } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) rdr.rdrEvents <- &erEvent{ cgrEvent: cgrEv, rdrCfg: rdr.Config(), diff --git a/ers/sql.go b/ers/sql.go index adf0fed55..f00db6b7e 100644 --- a/ers/sql.go +++ b/ers/sql.go @@ -249,7 +249,7 @@ func (rdr *SQLEventReader) processMessage(msg map[string]interface{}) (err error if err = agReq.SetFields(rdr.Config().Fields); err != nil { return } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) rdr.rdrEvents <- &erEvent{ cgrEvent: cgrEv, rdrCfg: rdr.Config(), diff --git a/ers/sqs.go b/ers/sqs.go index b077e456d..5c80f6b8f 100644 --- a/ers/sqs.go +++ b/ers/sqs.go @@ -115,7 +115,7 @@ func (rdr *SQSER) processMessage(body []byte) (err error) { if err = agReq.SetFields(rdr.Config().Fields); err != nil { return } - cgrEv := config.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) + cgrEv := utils.NMAsCGREvent(agReq.CGRRequest, agReq.Tenant, utils.NestingSep, agReq.Opts) rdr.rdrEvents <- &erEvent{ cgrEvent: cgrEv, rdrCfg: rdr.Config(), diff --git a/packages/debian/changelog b/packages/debian/changelog index f4756b26b..9204fac5b 100644 --- a/packages/debian/changelog +++ b/packages/debian/changelog @@ -153,6 +153,7 @@ cgrates (0.11.0~dev) UNRELEASED; urgency=medium * [Templates] Added support for Length Field in case of NMSlice * [Templates] Added support for multiple indexes * [AgentS] Added ~*req prefix for freeswitch extra_fields + * [AgentS] Changed NavigableMap with DataNode for speed improvements -- DanB Wed, 19 Feb 2020 13:25:52 +0200 diff --git a/utils/cgrevent.go b/utils/cgrevent.go index e45e6f98d..716342692 100644 --- a/utils/cgrevent.go +++ b/utils/cgrevent.go @@ -19,6 +19,7 @@ along with this program. If not, see package utils import ( + "strings" "time" ) @@ -240,3 +241,36 @@ type CGREventWithEeIDs struct { EeIDs []string *CGREvent } + +// NMAsCGREvent builds a CGREvent considering Time as time.Now() +// and Event as linear map[string]interface{} with joined paths +// treats particular case when the value of map is []*NMItem - used in agents/AgentRequest +func NMAsCGREvent(nM *OrderedNavigableMap, tnt string, pathSep string, opts MapStorage) (cgrEv *CGREvent) { + if nM == nil { + return + } + el := nM.GetFirstElement() + if el == nil { + return + } + cgrEv = &CGREvent{ + Tenant: tnt, + ID: UUIDSha1Prefix(), + Time: TimePointer(time.Now()), + Event: make(map[string]interface{}), + APIOpts: opts, + } + for ; el != nil; el = el.Next() { + path := el.Value + val, _ := nM.Field(path) // this should never return error cause we get the path from the order + if val.AttributeID != "" { + continue + } + path = path[:len(path)-1] // remove the last index + opath := strings.Join(path, NestingSep) + if _, has := cgrEv.Event[opath]; !has { + cgrEv.Event[opath] = val.Data // first item which is not an attribute will become the value + } + } + return +} diff --git a/utils/cgrevent_test.go b/utils/cgrevent_test.go index 19566dbee..fb7fd1448 100644 --- a/utils/cgrevent_test.go +++ b/utils/cgrevent_test.go @@ -527,3 +527,95 @@ func TestCGREventAsDataProvider(t *testing.T) { t.Errorf("\nExpected: <%+v>, \nReceived: <%+v>", expected, received) } } + +func TestNMAsCGREvent(t *testing.T) { + if cgrEv := NMAsCGREvent(nil, "cgrates.org", + NestingSep, nil); cgrEv != nil { + t.Errorf("expecting: %+v, \nreceived: %+v", ToJSON(nil), ToJSON(cgrEv.Event)) + } + + nM := NewOrderedNavigableMap() + if cgrEv := NMAsCGREvent(nM, "cgrates.org", + NestingSep, nil); cgrEv != nil { + t.Errorf("expecting: %+v, \nreceived: %+v", ToJSON(nil), ToJSON(cgrEv.Event)) + } + + path := []string{"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"} + if err := nM.SetAsSlice(&FullPath{Path: strings.Join(path, NestingSep), PathSlice: path}, []*DataNode{ + {Type: NMDataType, Value: &DataLeaf{ + Data: "Val1", + }}}); err != nil { + t.Error(err) + } + + path = []string{"FirstLevel2", "SecondLevel2", "Field2"} + if err := nM.SetAsSlice(&FullPath{Path: strings.Join(path, NestingSep), PathSlice: path}, []*DataNode{ + {Type: NMDataType, Value: &DataLeaf{ + Data: "attrVal1", + AttributeID: "attribute1", + }}, + {Type: NMDataType, Value: &DataLeaf{ + Data: "Value2", + }}}); err != nil { + t.Error(err) + } + + path = []string{"FirstLevel2", "Field3"} + if err := nM.SetAsSlice(&FullPath{Path: strings.Join(path, NestingSep), PathSlice: path}, []*DataNode{ + {Type: NMDataType, Value: &DataLeaf{ + Data: "Value3", + }}}); err != nil { + t.Error(err) + } + + path = []string{"FirstLevel2", "Field5"} + if err := nM.SetAsSlice(&FullPath{Path: strings.Join(path, NestingSep), PathSlice: path}, []*DataNode{ + {Type: NMDataType, Value: &DataLeaf{ + Data: "Value5", + }}, + {Type: NMDataType, Value: &DataLeaf{ + Data: "attrVal5", + AttributeID: "attribute5", + }}}); err != nil { + t.Error(err) + } + + path = []string{"FirstLevel2", "Field6"} + if err := nM.SetAsSlice(&FullPath{Path: strings.Join(path, NestingSep), PathSlice: path}, []*DataNode{ + {Type: NMDataType, Value: &DataLeaf{ + Data: "Value6", + NewBranch: true, + }}, + {Type: NMDataType, Value: &DataLeaf{ + Data: "attrVal6", + AttributeID: "attribute6", + }}}); err != nil { + t.Error(err) + } + + path = []string{"Field4"} + if err := nM.SetAsSlice(&FullPath{Path: strings.Join(path, NestingSep), PathSlice: path}, []*DataNode{ + {Type: NMDataType, Value: &DataLeaf{ + Data: "Val4", + }}, + {Type: NMDataType, Value: &DataLeaf{ + Data: "attrVal2", + 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", + NestingSep, MapStorage{}); cgrEv.Tenant != "cgrates.org" || + cgrEv.Time == nil || + !reflect.DeepEqual(eEv, cgrEv.Event) { + t.Errorf("expecting: %+v, \nreceived: %+v", ToJSON(eEv), ToJSON(cgrEv.Event)) + } +} diff --git a/utils/datanode.go b/utils/datanode.go index 056485da8..f8b4e346d 100644 --- a/utils/datanode.go +++ b/utils/datanode.go @@ -26,40 +26,44 @@ import ( // CompilePathSlice returns the path as a slice accepted by DataNode structure // field1[field2][index], field3 // will become: -// field1.field2.index.field3 +// field1 field2 index field3 func CompilePathSlice(spath []string) (path []string) { - path = make([]string, 0, len(spath)) + path = make([]string, 0, len(spath)) // in most cases the length will be the same for _, p := range spath { idxStart := strings.Index(p, IdxStart) - if idxStart == -1 || !strings.HasSuffix(p, IdxEnd) { - path = append(path, p) + if idxStart == -1 || !strings.HasSuffix(p, IdxEnd) { // no index in current path + path = append(path, p) // append the path as it is continue } - path = append(path, p[:idxStart]) - path = append(path, strings.Split(p[idxStart+1:len(p)-1], IdxCombination)...) + path = append(path, p[:idxStart]) // append first part of path + path = append(path, strings.Split(p[idxStart+1:len(p)-1], IdxCombination)...) // append the indexes } return } + +// CompilePath returns the path as a slice func CompilePath(spath string) (path []string) { return CompilePathSlice(strings.Split(spath, NestingSep)) } +// NewDataNode using the compiled path creates a node func NewDataNode(path []string) (n *DataNode) { n = new(DataNode) if len(path) == 0 { // is most probably a leaf - return + return // so return it as it is } - obj := NewDataNode(path[1:]) - if path[0] == "0" { // only support the 0 index when creating new array - n.Type = NMSliceType + obj := NewDataNode(path[1:]) // create the next node + if path[0] == "0" { // only support the 0 index when creating new array + n.Type = NMSliceType // is a slice so put the first element as the obj node n.Slice = []*DataNode{obj} return } - n.Type = NMMapType // consider it a map otherwise - n.Map = map[string]*DataNode{path[0]: obj} + n.Type = NMMapType // consider it a map otherwise + n.Map = map[string]*DataNode{path[0]: obj} // and the first element from path is the key in map return } +// NewLeafNode creates a leaf node with given value func NewLeafNode(val interface{}) *DataNode { return &DataNode{ Type: NMDataType, @@ -79,22 +83,19 @@ type DataNode struct { // DataLeaf is an item in the DataNode type DataLeaf struct { - Data interface{} // value of the element - Path []string // path in map - NewBranch bool - AttributeID string - // Config *FCTemplate // so we can store additional configuration + Data interface{} // value of the element + // the config of the leaf + NewBranch bool `json:",omitempty"` + AttributeID string `json:",omitempty"` } +// String returs the value of the leaf as string func (dl *DataLeaf) String() string { return IfaceAsString(dl.Data) } -// Field returns the value found at path -// the path equivalent for: -// field1[field2][index].field3 -// should be of following form: -// field1.field2.index.field3 +// Field returns the DataLeaf found at path +// if at the end of the path is not a DataLeaf return an error func (n *DataNode) Field(path []string) (*DataLeaf, error) { switch n.Type { // based on current type return the value case NMDataType: @@ -103,19 +104,19 @@ func (n *DataNode) Field(path []string) (*DataLeaf, error) { } return n.Value, nil case NMMapType: - if len(path) == 0 { + if len(path) == 0 { // do not return in this function the n.Map return nil, ErrWrongPath } node, has := n.Map[path[0]] - if !has { + if !has { // not found in map return nil, ErrNotFound } return node.Field(path[1:]) // let the next node handle the value case NMSliceType: - if len(path) == 0 { + if len(path) == 0 { // do not return in this function the n.Slice return nil, ErrWrongPath } - if path[0] == Length { + if path[0] == Length { // special case for slice to return the Length of the slice return &DataLeaf{Data: len(n.Slice)}, nil } idx, err := strconv.Atoi(path[0]) // convert the path to index @@ -128,15 +129,21 @@ func (n *DataNode) Field(path []string) (*DataLeaf, error) { if idx < 0 || idx >= len(n.Slice) { // check if the index is in range [0,len(slice)) return nil, ErrNotFound } - return n.Slice[idx].Field(path[1:]) + return n.Slice[idx].Field(path[1:]) // let the next node handle the value } // this is possible if the node was created but no value was assigned to it return nil, ErrWrongPath } +// FieldAsInterface will compile the given path +// and return the node value at the end of the path +// this function is used most probably by filters so expect the path to not be compiled func (n *DataNode) FieldAsInterface(path []string) (interface{}, error) { return n.fieldAsInterface(CompilePathSlice(path)) } + +// fieldAsInterface return ill the node value at the end of the path +// but will not compile the path func (n *DataNode) fieldAsInterface(path []string) (interface{}, error) { switch n.Type { // based on current type return the value case NMDataType: @@ -145,19 +152,19 @@ func (n *DataNode) fieldAsInterface(path []string) (interface{}, error) { } return n.Value.Data, nil case NMMapType: - if len(path) == 0 { + if len(path) == 0 { // last element form path so return the n.Map return n.Map, nil } node, has := n.Map[path[0]] - if !has { + if !has { // not found in map return nil, ErrNotFound } return node.fieldAsInterface(path[1:]) // let the next node handle the value case NMSliceType: - if len(path) == 0 { + if len(path) == 0 { // last element form path so return the n.Slice return n.Slice, nil } - if path[0] == Length { + if path[0] == Length { // special case for slice to return the Length of the slice return len(n.Slice), nil } idx, err := strconv.Atoi(path[0]) // convert the path to index @@ -170,7 +177,7 @@ func (n *DataNode) fieldAsInterface(path []string) (interface{}, error) { if idx < 0 || idx >= len(n.Slice) { // check if the index is in range [0,len(slice)) return nil, ErrNotFound } - return n.Slice[idx].fieldAsInterface(path[1:]) + return n.Slice[idx].fieldAsInterface(path[1:]) // let the next node handle the value } // this is possible if the node was created but no value was assigned to it return nil, ErrWrongPath @@ -184,7 +191,7 @@ func (n *DataNode) Set(path []string, val interface{}) (addedNew bool, err error case map[string]*DataNode: n.Type = NMMapType n.Map = v - case []*DataNode: + case []*DataNode: // need this to not parse the node path for each element in slice n.Type = NMSliceType n.Slice = v case *DataLeaf: @@ -203,8 +210,8 @@ func (n *DataNode) Set(path []string, val interface{}) (addedNew bool, err error } return } - switch n.Type { - case NMDataType: + switch n.Type { // the path has more elements so parse the nodes based on type + case NMDataType: // node is an leaf but the path expects a slice or a map return false, ErrWrongPath case NMMapType: node, has := n.Map[path[0]] @@ -215,24 +222,25 @@ func (n *DataNode) Set(path []string, val interface{}) (addedNew bool, err error addedNew, err = node.Set(path[1:], val) // set the value in the node return addedNew || !has, err case NMSliceType: - idx, err := strconv.Atoi(path[0]) + idx, err := strconv.Atoi(path[0]) // convert the path to int if err != nil { return false, err } if idx == len(n.Slice) { // special case when the index is the length so append - node := NewDataNode(path[1:]) + node := NewDataNode(path[1:]) // create the node n.Slice = append(n.Slice, node) - _, err = node.Set(path[1:], val) + _, err = node.Set(path[1:], val) // set the value in the node return true, err } - if idx < 0 { // in case the index is negative add the slice lenght - idx += len(n.Slice) - path[0] = strconv.Itoa(idx) // update the slice to reflect on orderNavMap - } + // try dynamic path instead + // if idx < 0 { // in case the index is negative add the slice lenght + // idx += len(n.Slice) + // path[0] = strconv.Itoa(idx) // update the slice to reflect on orderNavMap + // } if idx < 0 || idx >= len(n.Slice) { // check if the index is in range [0,len(slice)) return false, ErrNotFound } - return n.Slice[idx].Set(path[1:], val) + return n.Slice[idx].Set(path[1:], val) // set the value in the next node } // this is possible if the node was created but no value was assigned to it return false, ErrWrongPath @@ -255,7 +263,7 @@ func (n *DataNode) Remove(path []string) error { n.Value = nil return nil } - switch n.Type { + switch n.Type { // the path has more elements so parse the nodes based on type case NMDataType: // no remove for data type return ErrWrongPath case NMMapType: @@ -263,26 +271,26 @@ func (n *DataNode) Remove(path []string) error { if !has { // the element doesn't exist so ignore return nil } - err := node.Remove(path[1:]) - if node.IsEmpty() { // remove the element if empty + err := node.Remove(path[1:]) // remove the element in next path + if node.IsEmpty() { // remove the current element if empty delete(n.Map, path[0]) } return err case NMSliceType: - idx, err := strconv.Atoi(path[0]) + idx, err := strconv.Atoi(path[0]) // convert the path to int if err != nil { return err // the only error is when we expect an index but is not int } - if idx < 0 { + if idx < 0 { // in case the index is negative add the slice lenght idx += len(n.Slice) path[0] = strconv.Itoa(idx) // update the path for OrdNavMap } if idx < 0 || idx >= len(n.Slice) { // the index is not in range so ignore return nil } - err = n.Slice[idx].Remove(path[1:]) - if n.Slice[idx].IsEmpty() { // remove the element if empty - n.Slice = append(n.Slice[:idx], n.Slice[idx+1:]...) + err = n.Slice[idx].Remove(path[1:]) // remove the element in next path + if n.Slice[idx].IsEmpty() { // remove the current element if empty + n.Slice = append(n.Slice[:idx], n.Slice[idx+1:]...) // slow but needed } return err } @@ -295,10 +303,10 @@ func (n *DataNode) Remove(path []string) error { func (n *DataNode) Append(path []string, val *DataLeaf) (idx int, err error) { if len(path) == 0 { // the path is empty so overwrite curent node data switch n.Type { - case NMMapType: + case NMMapType: // append only works for slice return -1, ErrWrongPath case NMDataType: - if n.Value != nil && n.Value.Data != nil { + if n.Value != nil && n.Value.Data != nil { // it has alerady data so can not append return -1, ErrWrongPath } // is empty so make a slice to be compatible with append @@ -306,14 +314,14 @@ func (n *DataNode) Append(path []string, val *DataLeaf) (idx int, err error) { n.Value = nil n.Slice = []*DataNode{{Type: NMDataType, Value: val}} return 0, nil - default: + default: // is a slice so append the leaf as a DataNode n.Type = NMSliceType n.Slice = append(n.Slice, &DataNode{Type: NMDataType, Value: val}) return len(n.Slice) - 1, nil } } - switch n.Type { - case NMDataType: + switch n.Type { // the path has more elements so parse the nodes based on type + case NMDataType: // node is an leaf but the path expects a slice or a map return -1, ErrWrongPath case NMMapType: node, has := n.Map[path[0]] @@ -321,9 +329,9 @@ func (n *DataNode) Append(path []string, val *DataLeaf) (idx int, err error) { node = NewDataNode(path[1:]) n.Map[path[0]] = node } - return node.Append(path[1:], val) // set the value in the node + return node.Append(path[1:], val) // append the value in the next node case NMSliceType: - idx, err := strconv.Atoi(path[0]) + idx, err := strconv.Atoi(path[0]) // convert the path to int if err != nil { return -1, err } @@ -332,25 +340,26 @@ func (n *DataNode) Append(path []string, val *DataLeaf) (idx int, err error) { n.Slice = append(n.Slice, node) return node.Append(path[1:], val) } - if idx < 0 { // in case the index is negative add the slice lenght - idx += len(n.Slice) - path[0] = strconv.Itoa(idx) // update the slice to reflect on orderNavMap - } + // try dynamic path instead + // if idx < 0 { // in case the index is negative add the slice lenght + // idx += len(n.Slice) + // path[0] = strconv.Itoa(idx) // update the slice to reflect on orderNavMap + // } if idx < 0 || idx >= len(n.Slice) { // check if the index is in range [0,len(slice)) return -1, ErrNotFound } - return n.Slice[idx].Append(path[1:], val) + return n.Slice[idx].Append(path[1:], val) // append the value in the next node } // this is possible if the node was created but no value was assigned to it return -1, ErrWrongPath } -// Compose will set the value at de specified path +// Compose will string compose the value at de specified path with the given value // the path should be in the same format as the path given to Field func (n *DataNode) Compose(path []string, val *DataLeaf) (err error) { if len(path) == 0 { // the path is empty so overwrite curent node data switch n.Type { - case NMMapType: + case NMMapType: // compose only works for slice and dataType return ErrWrongPath case NMDataType: if n.Value == nil || n.Value.Data == nil { @@ -360,19 +369,19 @@ func (n *DataNode) Compose(path []string, val *DataLeaf) (err error) { n.Slice = []*DataNode{{Type: NMDataType, Value: val}} return } - n.Value.Data = n.Value.String() + val.String() - default: - if len(n.Slice) == 0 { + n.Value.Data = n.Value.String() + val.String() // has already data so do a simple compose + default: // is a slice + if len(n.Slice) == 0 { // empty so add the first element n.Type = NMSliceType n.Slice = []*DataNode{{Type: NMDataType, Value: val}} return } - n.Slice[len(n.Slice)-1].Value.Data = n.Slice[len(n.Slice)-1].Value.String() + val.String() + n.Slice[len(n.Slice)-1].Value.Data = n.Slice[len(n.Slice)-1].Value.String() + val.String() // compose the last element from slice } return } - switch n.Type { - case NMDataType: + switch n.Type { // the path has more elements so parse the nodes based on type + case NMDataType: // node is an leaf but the path expects a slice or a map return ErrWrongPath case NMMapType: node, has := n.Map[path[0]] @@ -380,9 +389,9 @@ func (n *DataNode) Compose(path []string, val *DataLeaf) (err error) { node = NewDataNode(path[1:]) n.Map[path[0]] = node } - return node.Compose(path[1:], val) // set the value in the node + return node.Compose(path[1:], val) // compose the value in the next node case NMSliceType: - idx, err := strconv.Atoi(path[0]) + idx, err := strconv.Atoi(path[0]) // convert the path to int if err != nil { return err } @@ -391,14 +400,15 @@ func (n *DataNode) Compose(path []string, val *DataLeaf) (err error) { n.Slice = append(n.Slice, node) return node.Compose(path[1:], val) } - if idx < 0 { // in case the index is negative add the slice lenght - idx += len(n.Slice) - path[0] = strconv.Itoa(idx) // update the slice to reflect on orderNavMap - } + // try dynamic path instead + // if idx < 0 { // in case the index is negative add the slice lenght + // idx += len(n.Slice) + // path[0] = strconv.Itoa(idx) // update the slice to reflect on orderNavMap + // } if idx < 0 || idx >= len(n.Slice) { // check if the index is in range [0,len(slice)) return ErrNotFound } - return n.Slice[idx].Compose(path[1:], val) + return n.Slice[idx].Compose(path[1:], val) // compose the value in the next node } // this is possible if the node was created but no value was assigned to it return ErrWrongPath diff --git a/utils/dataprovider_test.go b/utils/dataprovider_test.go index ba386895b..1a6cfe99b 100644 --- a/utils/dataprovider_test.go +++ b/utils/dataprovider_test.go @@ -83,7 +83,7 @@ func TestAppendNavMapVal(t *testing.T) { "Field3": {Type: NMMapType, Map: map[string]*DataNode{"Field4": NewLeafNode("Val")}}, "Field5": {Type: NMSliceType, Slice: []*DataNode{NewLeafNode(10), NewLeafNode(101), NewLeafNode(18)}}, }} - if err := onm.Append(&FullPath{Path: "Field5", PathItems: []string{"Field5"}}, NewLeafNode(18).Value); err != nil { + if err := onm.Append(&FullPath{Path: "Field5", PathSlice: []string{"Field5"}}, NewLeafNode(18).Value); err != nil { t.Error(err) } else if !reflect.DeepEqual(expected, onm.nm) { t.Errorf("Expected %v ,received: %v", expected, onm.nm) @@ -101,14 +101,14 @@ func TestComposeNavMapVal(t *testing.T) { "Field5": {Type: NMSliceType, Slice: []*DataNode{NewLeafNode(10), NewLeafNode(101)}}, }} onm.nm = nm - if err := onm.Compose(&FullPath{Path: "Field4", PathItems: []string{"Field4", "10"}}, NewLeafNode(18).Value); err != ErrNotFound { + if err := onm.Compose(&FullPath{Path: "Field4", PathSlice: []string{"Field4", "10"}}, NewLeafNode(18).Value); err != ErrNotFound { t.Error(err) } expected := &DataNode{Type: NMMapType, Map: map[string]*DataNode{ "Field4": {Type: NMSliceType, Slice: []*DataNode{}}, "Field5": {Type: NMSliceType, Slice: []*DataNode{NewLeafNode(10), NewLeafNode("10118")}}, }} - if err := onm.Compose(&FullPath{Path: "Field5", PathItems: []string{"Field5"}}, NewLeafNode(18).Value); err != nil { + if err := onm.Compose(&FullPath{Path: "Field5", PathSlice: []string{"Field5"}}, NewLeafNode(18).Value); err != nil { t.Error(err) } else if !reflect.DeepEqual(expected, nm) { t.Errorf("Expected %v ,received: %v", expected, nm) @@ -119,7 +119,7 @@ func TestComposeNavMapVal(t *testing.T) { "Field5": {Type: NMSliceType, Slice: []*DataNode{NewLeafNode(10), NewLeafNode("10118")}}, "Field6": {Type: NMSliceType, Slice: []*DataNode{NewLeafNode(10)}}, }} - if err := onm.Compose(&FullPath{Path: "Field6", PathItems: []string{"Field6"}}, NewLeafNode(10).Value); err != nil { + if err := onm.Compose(&FullPath{Path: "Field6", PathSlice: []string{"Field6"}}, NewLeafNode(10).Value); err != nil { t.Error(err) } else if !reflect.DeepEqual(expected, nm) { t.Errorf("Expected %v ,received: %v", expected, nm) diff --git a/utils/orderednavigablemap.go b/utils/orderednavigablemap.go index cd784c2e7..878c59605 100644 --- a/utils/orderednavigablemap.go +++ b/utils/orderednavigablemap.go @@ -24,7 +24,7 @@ import ( "strings" ) -// NewOrderedNavigableMap initializates a structure of OrderedNavigableMap with a NavigableMap2 +// NewOrderedNavigableMap initializates a structure of OrderedNavigableMap with a DataNode func NewOrderedNavigableMap() *OrderedNavigableMap { return &OrderedNavigableMap{ nm: &DataNode{Type: NMMapType, Map: make(map[string]*DataNode)}, @@ -33,7 +33,7 @@ func NewOrderedNavigableMap() *OrderedNavigableMap { } } -// OrderedNavigableMap is the same as NavigableMap2 but keeps the order of fields +// OrderedNavigableMap is the same as DataNode but keeps the order of fields type OrderedNavigableMap struct { nm *DataNode orderIdx *PathItemList @@ -65,80 +65,74 @@ func (onm *OrderedNavigableMap) Empty() bool { return onm.nm.IsEmpty() } +func (onm *OrderedNavigableMap) removeRef(path string) { + for idxPath, slcIdx := range onm.orderRef { //remove the references from order + if strings.HasPrefix(idxPath, path) { + for _, el := range slcIdx { + onm.orderIdx.Remove(el) + } + delete(onm.orderRef, idxPath) + } + } +} + // Remove removes the item for the given path and updates the order func (onm *OrderedNavigableMap) Remove(fullPath *FullPath) (err error) { if fullPath.Path == EmptyString { return ErrWrongPath } - fullPath.PathItems = CloneStringSlice(fullPath.PathItems) - if err = onm.nm.Remove(fullPath.PathItems); err != nil { + // fullPath.PathSlice = CloneStringSlice(fullPath.PathSlice) // clone the items to not modify the templates + if err = onm.nm.Remove(fullPath.PathSlice); err != nil { // remove them from DataNode return } - - for idxPath, slcIdx := range onm.orderRef { - if strings.HasPrefix(idxPath, fullPath.Path) { - for _, el := range slcIdx { - onm.orderIdx.Remove(el) - } - delete(onm.orderRef, idxPath) - } - } + onm.removeRef(fullPath.Path) return } // Set sets the value at the given path // this used with full path and the processed path to not calculate them for every set +// used in tests func (onm *OrderedNavigableMap) Set(fullPath *FullPath, val interface{}) (err error) { - if fullPath == nil || len(fullPath.PathItems) == 0 { + if fullPath == nil || len(fullPath.PathSlice) == 0 { return ErrWrongPath } - var addedNew bool - if addedNew, err = onm.nm.Set(fullPath.PathItems, val); err != nil { + var addedNew bool // determine if the node was created or only overwriten + if addedNew, err = onm.nm.Set(fullPath.PathSlice, val); err != nil { return } + // update the order reference path := stripIdxFromLastPathElm(fullPath.Path) _, hasRef := onm.orderRef[path] - if addedNew || !hasRef { - onm.orderRef[path] = append(onm.orderRef[path], onm.orderIdx.PushBack(fullPath.PathItems)) - } else { + if addedNew || !hasRef { // the element is new so append to order + onm.orderRef[path] = append(onm.orderRef[path], onm.orderIdx.PushBack(fullPath.PathSlice)) + } else { // move element in the back of order list onm.orderIdx.MoveToBack(onm.orderRef[path][len(onm.orderRef[path])-1]) } return } -// Set sets the value at the given path +// SetAsSlice sets the slice of nodes at the given path // this used with full path and the processed path to not calculate them for every set +// this is used by agent request to overwrite the slice at path func (onm *OrderedNavigableMap) SetAsSlice(fullPath *FullPath, vals []*DataNode) (err error) { - if fullPath == nil || len(fullPath.PathItems) == 0 { + if fullPath == nil || len(fullPath.PathSlice) == 0 { return ErrWrongPath } var addedNew bool - if addedNew, err = onm.nm.Set(fullPath.PathItems, vals); err != nil { + if addedNew, err = onm.nm.Set(fullPath.PathSlice, vals); err != nil { return } - pathItmsSet := make([][]string, len(vals)) - + pathItmsSet := make([][]string, len(vals)) // prepare the path for order update for i := range vals { - pathItms := CloneStringSlice(fullPath.PathItems) - pathItms = append(pathItms, strconv.Itoa(i)) - pathItmsSet[i] = pathItms + pathItmsSet[i] = append(CloneStringSlice(fullPath.PathSlice), strconv.Itoa(i)) // clone the slice as we will append an index } path := stripIdxFromLastPathElm(fullPath.Path) if !addedNew { // cleanup old references since the value is being overwritten - for idxPath, slcIdx := range onm.orderRef { - if !strings.HasPrefix(idxPath, path) { - continue - } - for _, el := range slcIdx { - onm.orderIdx.Remove(el) - } - delete(onm.orderRef, idxPath) - } - + onm.removeRef(path) } - for _, pathItms := range pathItmsSet { + for _, pathItms := range pathItmsSet { // add the path in order list onm.orderRef[path] = append(onm.orderRef[path], onm.orderIdx.PushBack(pathItms)) } return @@ -147,8 +141,7 @@ func (onm *OrderedNavigableMap) SetAsSlice(fullPath *FullPath, vals []*DataNode) // FieldAsString returns the value from path as string func (onm *OrderedNavigableMap) FieldAsString(fldPath []string) (str string, err error) { var val interface{} - val, err = onm.FieldAsInterface(fldPath) - if err != nil { + if val, err = onm.FieldAsInterface(fldPath); err != nil { return } return IfaceAsString(val), nil @@ -199,34 +192,40 @@ func (onm *OrderedNavigableMap) OrderedFieldsAsStrings() (flds []string) { return } -// Set sets the value at the given path +// Append appends the leaf at the given path the end must be a slice // this used with full path and the processed path to not calculate them for every set func (onm *OrderedNavigableMap) Append(fullPath *FullPath, val *DataLeaf) (err error) { - if fullPath == nil || len(fullPath.PathItems) == 0 { + if fullPath == nil || len(fullPath.PathSlice) == 0 { return ErrWrongPath } var idx int - if idx, err = onm.nm.Append(fullPath.PathItems, val); err != nil { + if idx, err = onm.nm.Append(fullPath.PathSlice, val); err != nil { return } - - onm.orderRef[fullPath.Path] = append(onm.orderRef[fullPath.Path], onm.orderIdx.PushBack(append(fullPath.PathItems, strconv.Itoa(idx)))) + // add the path to order + onm.orderRef[fullPath.Path] = append(onm.orderRef[fullPath.Path], + onm.orderIdx.PushBack( + append(CloneStringSlice(fullPath.PathSlice), // clone the slice as we will append an index + strconv.Itoa(idx)))) return } -// Set sets the value at the given path +// Compose comose the value of the leaf at the given path // this used with full path and the processed path to not calculate them for every set func (onm *OrderedNavigableMap) Compose(fullPath *FullPath, val *DataLeaf) (err error) { - if fullPath == nil || len(fullPath.PathItems) == 0 { + if fullPath == nil || len(fullPath.PathSlice) == 0 { return ErrWrongPath } - if err = onm.nm.Compose(fullPath.PathItems, val); err != nil { + if err = onm.nm.Compose(fullPath.PathSlice, val); err != nil { return } - if _, hasRef := onm.orderRef[fullPath.Path]; !hasRef { - onm.orderRef[fullPath.Path] = append(onm.orderRef[fullPath.Path], onm.orderIdx.PushBack(append(fullPath.PathItems, "0"))) - } else { + if _, hasRef := onm.orderRef[fullPath.Path]; !hasRef { // the element is new so append to order + onm.orderRef[fullPath.Path] = append(onm.orderRef[fullPath.Path], + onm.orderIdx.PushBack( + append(CloneStringSlice(fullPath.PathSlice), // clone the slice as we will append an index + "0"))) + } else { // move element in the back of order list onm.orderIdx.MoveToBack(onm.orderRef[fullPath.Path][len(onm.orderRef[fullPath.Path])-1]) } return diff --git a/utils/orderednavigablemap_test.go b/utils/orderednavigablemap_test.go index d59ebb98c..e38dffec1 100644 --- a/utils/orderednavigablemap_test.go +++ b/utils/orderednavigablemap_test.go @@ -28,7 +28,7 @@ func TestOrderedNavigableMap(t *testing.T) { onm.Set(&FullPath{ Path: "Field1", - PathItems: []string{"Field1"}, + PathSlice: []string{"Field1"}, }, NewLeafNode(10)) expOrder := [][]string{{"Field1"}} if !reflect.DeepEqual(expOrder, onm.GetOrder()) { @@ -37,7 +37,7 @@ func TestOrderedNavigableMap(t *testing.T) { onm.Set(&FullPath{ Path: "Field2[0]", - PathItems: []string{"Field2", "0"}, + PathSlice: []string{"Field2", "0"}, }, NewLeafNode("1001")) expOrder = [][]string{ {"Field1"}, @@ -49,7 +49,7 @@ func TestOrderedNavigableMap(t *testing.T) { onm.Set(&FullPath{ Path: "Field2[1].Account[0]", - PathItems: []string{"Field2", "1", "Account", "0"}, + PathSlice: []string{"Field2", "1", "Account", "0"}, }, NewLeafNode(10)) expOrder = [][]string{ {"Field1"}, @@ -62,7 +62,7 @@ func TestOrderedNavigableMap(t *testing.T) { onm.Set(&FullPath{ Path: "Field2[1].Account[1]", - PathItems: []string{"Field2", "1", "Account", "1"}, + PathSlice: []string{"Field2", "1", "Account", "1"}, }, NewLeafNode(11)) expOrder = [][]string{ {"Field1"}, @@ -76,7 +76,7 @@ func TestOrderedNavigableMap(t *testing.T) { onm.Set(&FullPath{ Path: "Field2[2]", - PathItems: []string{"Field2", "2"}, + PathSlice: []string{"Field2", "2"}, }, NewLeafNode(111)) expOrder = [][]string{ {"Field1"}, @@ -91,7 +91,7 @@ func TestOrderedNavigableMap(t *testing.T) { onm.Set(&FullPath{ Path: "Field3.Field4.Field5", - PathItems: []string{"Field3", "Field4", "Field5"}, + PathSlice: []string{"Field3", "Field4", "Field5"}, }, NewLeafNode(5)) expOrder = [][]string{ {"Field1"}, @@ -133,7 +133,7 @@ func TestOrderedNavigableMap(t *testing.T) { // sliceDeNM exp := []*DataNode{NewLeafNode("500"), NewLeafNode("502")} path := []string{"Field2"} - if err := onm.SetAsSlice(&FullPath{Path: path[0], PathItems: path}, exp); err != nil { + if err := onm.SetAsSlice(&FullPath{Path: path[0], PathSlice: path}, exp); err != nil { t.Error(err) } path = []string{"Field2"} @@ -231,11 +231,11 @@ func TestOrderedNavigableMapEmpty(t *testing.T) { func TestOrderedNavigableMapGetSet(t *testing.T) { nm := NewOrderedNavigableMap() nm.Set(&FullPath{ - PathItems: []string{"Account", "0"}, + PathSlice: []string{"Account", "0"}, Path: "Account", }, NewLeafNode(1001)) nm.Set(&FullPath{ - PathItems: []string{"Account", "1"}, + PathSlice: []string{"Account", "1"}, Path: "Account", }, NewLeafNode("account_on_new_branch")) @@ -280,7 +280,7 @@ func TestOrderedNavigableMapGetSet(t *testing.T) { } path = []string{"Field2", "2"} - if err := nm.Set(&FullPath{Path: strings.Join(path, NestingSep), PathItems: path}, NewLeafNode("500")); err != nil { + if err := nm.Set(&FullPath{Path: strings.Join(path, NestingSep), PathSlice: path}, NewLeafNode("500")); err != nil { t.Error(err) } if val, err := nm.Field(path); err != nil { @@ -290,7 +290,7 @@ func TestOrderedNavigableMapGetSet(t *testing.T) { } path = []string{"Field2", "1", "Account"} - if err := nm.Set(&FullPath{Path: strings.Join(path, NestingSep), PathItems: path}, NewLeafNode("5")); err != nil { + if err := nm.Set(&FullPath{Path: strings.Join(path, NestingSep), PathSlice: path}, NewLeafNode("5")); err != nil { t.Error(err) } path = []string{"Field2", "1", "Account"} @@ -350,19 +350,19 @@ func TestOrderedNavigableMapFieldAsString(t *testing.T) { func TestOrderedNavigableMapGetOrder(t *testing.T) { nm := NewOrderedNavigableMap() nm.Set(&FullPath{ - PathItems: []string{"Field1", "Field2", "0"}, + PathSlice: []string{"Field1", "Field2", "0"}, Path: "Field1.Field2[0]", }, NewLeafNode("1003")) nm.Set(&FullPath{ - PathItems: []string{"Field1", "Field2", "1"}, + PathSlice: []string{"Field1", "Field2", "1"}, Path: "Field1.Field2[1]", }, NewLeafNode("Val")) nm.Set(&FullPath{ - PathItems: []string{"Field3", "Field4", "Field5", "0"}, + PathSlice: []string{"Field3", "Field4", "Field5", "0"}, Path: "Field3.Field4.Field5", }, NewLeafNode("1001")) nm.Set(&FullPath{ - PathItems: []string{"Field1", "Field2", "2"}, + PathSlice: []string{"Field1", "Field2", "2"}, Path: "Field1.Field2[2]", }, NewLeafNode(101)) expected := [][]string{ @@ -386,7 +386,7 @@ func TestOrderedNavigableMapSet(t *testing.T) { path := []string{"Field1", "0"} if err := nm.Set(&FullPath{ - PathItems: path, + PathSlice: path, Path: strings.Join(path, NestingSep), }, NewLeafNode("1001")); err != nil { t.Error(err) @@ -400,20 +400,20 @@ func TestOrderedNavigableMapSet(t *testing.T) { t.Errorf("Expected %s ,received: %s", order, nm.GetOrder()) } if err := nm.Set(&FullPath{ - PathItems: []string{"Field1", "0", ""}, + PathSlice: []string{"Field1", "0", ""}, Path: "Field1[0]", }, NewLeafNode("1001")); err != ErrWrongPath { t.Error(err) } if err := nm.SetAsSlice(&FullPath{ - PathItems: []string{"Field1", "0", ""}, + PathSlice: []string{"Field1", "0", ""}, Path: "Field1[0]", }, []*DataNode{}); err != ErrWrongPath { t.Error(err) } if err := nm.SetAsSlice(&FullPath{ - PathItems: []string{"Field1", "10"}, + PathSlice: []string{"Field1", "10"}, Path: "Field[10]", }, []*DataNode{}); err != ErrNotFound { t.Error(err) @@ -422,7 +422,7 @@ func TestOrderedNavigableMapSet(t *testing.T) { nMap = &DataNode{Type: NMMapType, Map: map[string]*DataNode{"Field1": {Type: NMSliceType, Slice: []*DataNode{NewLeafNode("1002")}}}} order = [][]string{path} if err := nm.Set(&FullPath{ - PathItems: path, + PathSlice: path, Path: strings.Join(path, NestingSep), }, NewLeafNode("1002")); err != nil { t.Error(err) @@ -440,7 +440,7 @@ func TestOrderedNavigableMapSet(t *testing.T) { }} order = append(order, path) if err := nm.Set(&FullPath{ - PathItems: path, + PathSlice: path, Path: strings.Join(path, NestingSep), }, NewLeafNode("1002")); err != nil { t.Error(err) @@ -458,7 +458,7 @@ func TestOrderedNavigableMapSet(t *testing.T) { }} order = append(order, path) if err := nm.Set(&FullPath{ - PathItems: path, + PathSlice: path, Path: strings.Join(path, NestingSep), }, NewLeafNode("1003")); err != nil { t.Error(err) @@ -478,7 +478,7 @@ func TestOrderedNavigableMapSet(t *testing.T) { }} order = append(order, []string{"Field3", "0"}, []string{"Field3", "1"}) if err := nm.SetAsSlice(&FullPath{ - PathItems: path, + PathSlice: path, Path: strings.Join(path, NestingSep), }, obj.Slice); err != nil { t.Error(err) @@ -503,7 +503,7 @@ func TestOrderedNavigableMapSet(t *testing.T) { {"Field1", "1"}, } if err := nm.SetAsSlice(&FullPath{ - PathItems: []string{"Field1"}, + PathSlice: []string{"Field1"}, Path: "Field1", }, obj.Slice); err != nil { t.Error(err) @@ -514,63 +514,64 @@ func TestOrderedNavigableMapSet(t *testing.T) { if !reflect.DeepEqual(nm.GetOrder(), order) { t.Errorf("Expected %s ,received: %s", order, nm.GetOrder()) } - obj = &DataNode{Type: NMSliceType, Slice: []*DataNode{NewLeafNode("1005"), NewLeafNode("1006")}} - nMap = &DataNode{Type: NMMapType, Map: map[string]*DataNode{ - "Field1": {Type: NMSliceType, Slice: []*DataNode{NewLeafNode("1005"), NewLeafNode("1006")}}, - "Field2": NewLeafNode("1002"), - "Field3": {Type: NMSliceType, Slice: []*DataNode{NewLeafNode("1004"), NewLeafNode("1007")}}, - }} - order = [][]string{ - {"Field2"}, - {"Field3", "0"}, - {"Field1", "0"}, - {"Field1", "1"}, - {"Field3", "1"}, - } - if err := nm.Set(&FullPath{ - PathItems: []string{"Field3", "-1"}, - Path: "Field3[-1]", - }, NewLeafNode("1007")); err != nil { - t.Error(err) - } - if !reflect.DeepEqual(nm.nm, nMap) { - t.Errorf("Expected %s ,received: %s", ToJSON(nMap), ToJSON(nm)) - } - if !reflect.DeepEqual(nm.GetOrder(), order) { - t.Errorf("Expected %s ,received: %s", ToJSON(order), ToJSON(nm.GetOrder())) - } + // try dynamic path + // obj = &DataNode{Type: NMSliceType, Slice: []*DataNode{NewLeafNode("1005"), NewLeafNode("1006")}} + // nMap = &DataNode{Type: NMMapType, Map: map[string]*DataNode{ + // "Field1": {Type: NMSliceType, Slice: []*DataNode{NewLeafNode("1005"), NewLeafNode("1006")}}, + // "Field2": NewLeafNode("1002"), + // "Field3": {Type: NMSliceType, Slice: []*DataNode{NewLeafNode("1004"), NewLeafNode("1007")}}, + // }} + // order = [][]string{ + // {"Field2"}, + // {"Field3", "0"}, + // {"Field1", "0"}, + // {"Field1", "1"}, + // {"Field3", "1"}, + // } + // if err := nm.Set(&FullPath{ + // PathSlice: []string{"Field3", "-1"}, + // Path: "Field3[-1]", + // }, NewLeafNode("1007")); err != nil { + // t.Error(err) + // } + // if !reflect.DeepEqual(nm.nm, nMap) { + // t.Errorf("Expected %s ,received: %s", ToJSON(nMap), ToJSON(nm)) + // } + // if !reflect.DeepEqual(nm.GetOrder(), order) { + // t.Errorf("Expected %s ,received: %s", ToJSON(order), ToJSON(nm.GetOrder())) + // } } func TestOrderedNavigableMapRemove(t *testing.T) { nm := NewOrderedNavigableMap() nm.Set(&FullPath{ - PathItems: []string{"Field2"}, + PathSlice: []string{"Field2"}, Path: "Field2", }, NewLeafNode("1003")) nm.Set(&FullPath{ - PathItems: []string{"Field3", "Field4"}, + PathSlice: []string{"Field3", "Field4"}, Path: "Field3.Field4", }, NewLeafNode("Val")) nm.Set(&FullPath{ - PathItems: []string{"Field1"}, + PathSlice: []string{"Field1"}, Path: "Field1", }, NewLeafNode("1001")) nm.SetAsSlice(&FullPath{ - PathItems: []string{"Field5"}, + PathSlice: []string{"Field5"}, Path: "Field5", }, []*DataNode{NewLeafNode(10), NewLeafNode(101)}) if err := nm.Remove(&FullPath{}); err != ErrWrongPath { t.Error(err) } - if err := nm.Remove(&FullPath{PathItems: []string{}}); err != ErrWrongPath { + if err := nm.Remove(&FullPath{PathSlice: []string{}}); err != ErrWrongPath { t.Error(err) } - if err := nm.Remove(&FullPath{PathItems: []string{"field"}, Path: "field"}); err != nil { + if err := nm.Remove(&FullPath{PathSlice: []string{"field"}, Path: "field"}); err != nil { t.Error(err) } - if err := nm.Remove(&FullPath{PathItems: []string{"-1", ""}}); err != ErrWrongPath { + if err := nm.Remove(&FullPath{PathSlice: []string{"-1", ""}}); err != ErrWrongPath { t.Error(err) } nMap := &DataNode{Type: NMMapType, Map: map[string]*DataNode{ @@ -604,7 +605,7 @@ func TestOrderedNavigableMapRemove(t *testing.T) { {"Field5", "1"}, } - if err := nm.Remove(&FullPath{PathItems: []string{"Field2"}, Path: "Field2"}); err != nil { + if err := nm.Remove(&FullPath{PathSlice: []string{"Field2"}, Path: "Field2"}); err != nil { t.Error(err) } if !reflect.DeepEqual(nm.nm, nMap) { @@ -622,7 +623,7 @@ func TestOrderedNavigableMapRemove(t *testing.T) { {"Field1"}, } - if err := nm.Remove(&FullPath{PathItems: []string{"Field5"}, Path: "Field5"}); err != nil { + if err := nm.Remove(&FullPath{PathSlice: []string{"Field5"}, Path: "Field5"}); err != nil { t.Error(err) } if !reflect.DeepEqual(nm.nm, nMap) { @@ -631,7 +632,7 @@ func TestOrderedNavigableMapRemove(t *testing.T) { if !reflect.DeepEqual(nm.GetOrder(), order) { t.Errorf("Expected %s ,received: %s", order, nm.GetOrder()) } - if err := nm.Remove(&FullPath{PathItems: []string{"Field1", "0", ""}}); err != ErrWrongPath { + if err := nm.Remove(&FullPath{PathSlice: []string{"Field1", "0", ""}}); err != ErrWrongPath { t.Error(err) } } @@ -802,19 +803,19 @@ func BenchmarkNavigableMapField(b *testing.B) { func TestOrderedNavigableMapRemoveAll(t *testing.T) { nm := NewOrderedNavigableMap() nm.Set(&FullPath{ - PathItems: []string{"Field2"}, + PathSlice: []string{"Field2"}, Path: "Field2", }, NewLeafNode("1003")) nm.Set(&FullPath{ - PathItems: []string{"Field3", "Field4"}, + PathSlice: []string{"Field3", "Field4"}, Path: "Field3.Field4", }, NewLeafNode("Val")) nm.Set(&FullPath{ - PathItems: []string{"Field1"}, + PathSlice: []string{"Field1"}, Path: "Field1", }, NewLeafNode("1001")) nm.SetAsSlice(&FullPath{ - PathItems: []string{"Field5"}, + PathSlice: []string{"Field5"}, Path: "Field5", }, []*DataNode{NewLeafNode(10), NewLeafNode(101)}) expected := NewOrderedNavigableMap() @@ -831,7 +832,7 @@ func TestOrderedNavigableMapRemove2(t *testing.T) { }}, } expErr := `strconv.Atoi: parsing "nan": invalid syntax` - if err := nm.Remove(&FullPath{PathItems: []string{"Field1", "nan", ""}, Path: "Field1[nan]"}); err == nil || err.Error() != expErr { + if err := nm.Remove(&FullPath{PathSlice: []string{"Field1", "nan", ""}, Path: "Field1[nan]"}); err == nil || err.Error() != expErr { t.Errorf("Expected error: %s,received: %v", expErr, err) } } @@ -839,23 +840,23 @@ func TestOrderedNavigableMapRemove2(t *testing.T) { func TestOrderedNavigableMapOrderedFields(t *testing.T) { nm := NewOrderedNavigableMap() nm.Set(&FullPath{ - PathItems: []string{"Field1", "Field2", "0"}, + PathSlice: []string{"Field1", "Field2", "0"}, Path: "Field1.Field2[0]", }, NewLeafNode("1003")) nm.Set(&FullPath{ - PathItems: []string{"Field1", "Field3", "0"}, + PathSlice: []string{"Field1", "Field3", "0"}, Path: "Field1.Field3[0]", }, NewLeafNode("1004")) nm.Set(&FullPath{ - PathItems: []string{"Field5"}, + PathSlice: []string{"Field5"}, Path: "Field5", }, NewLeafNode("1005")) nm.Set(&FullPath{ - PathItems: []string{"Field6"}, + PathSlice: []string{"Field6"}, Path: "Field6", }, NewLeafNode("1006")) nm.Remove(&FullPath{ - PathItems: []string{"Field5"}, + PathSlice: []string{"Field5"}, Path: "Field5", }) exp := []interface{}{"1003", "1004", "1006"} diff --git a/utils/pathitem.go b/utils/pathitem.go index 2f8458762..26b1a7349 100644 --- a/utils/pathitem.go +++ b/utils/pathitem.go @@ -38,13 +38,13 @@ func stripIdxFromLastPathElm(path string) string { func NewFullPath(path string) *FullPath { return &FullPath{ Path: path, - PathItems: CompilePath(path), + PathSlice: CompilePath(path), } } // FullPath is the path to the item with all the needed fields type FullPath struct { - PathItems []string + PathSlice []string Path string } @@ -68,15 +68,6 @@ func GetPathIndex(spath string) (opath string, idx *int) { return opath, &idxVal } -func GetPathWithoutIndex(spath string) (opath string) { - idxStart := strings.LastIndex(spath, IdxStart) - if idxStart == -1 || !strings.HasSuffix(spath, IdxEnd) { - return spath - } - opath = spath[:idxStart] - return -} - // GetPathIndexString returns the path and index as string if index present // path[index]=>path,index // path=>path,nil diff --git a/utils/pathitem_test.go b/utils/pathitem_test.go index 0664257ad..b02268e1e 100644 --- a/utils/pathitem_test.go +++ b/utils/pathitem_test.go @@ -53,20 +53,9 @@ func TestStripIdxFromLastPathElm(t *testing.T) { } } -func TestGetPathWithoutIndex(t *testing.T) { - expected := "field" - if rply := GetPathWithoutIndex("field[index]"); expected != rply { - t.Errorf("Expected: %s, received: %s", expected, rply) - } - expected = "field[index" - if rply := GetPathWithoutIndex("field[index"); expected != rply { - t.Errorf("Expected: %s, received: %s", expected, rply) - } -} - func TestNewFullPath(t *testing.T) { expected := &FullPath{ - PathItems: []string{"test", "path"}, + PathSlice: []string{"test", "path"}, Path: "test.path", } if rcv := NewFullPath("test.path"); !reflect.DeepEqual(rcv, expected) { diff --git a/config/navigablemap.go b/utils/xmlelement.go similarity index 54% rename from config/navigablemap.go rename to utils/xmlelement.go index e1ee933dd..dfb0525d4 100644 --- a/config/navigablemap.go +++ b/utils/xmlelement.go @@ -16,14 +16,11 @@ You should have received a copy of the GNU General Public License along with this program. If not, see */ -package config +package utils import ( "encoding/xml" "strings" - "time" - - "github.com/cgrates/cgrates/utils" ) // XMLElement is specially crafted to be automatically marshalled by encoding/xml @@ -36,7 +33,7 @@ type XMLElement struct { // NMAsXMLElements returns the values as []*XMLElement which can be later marshaled // considers each value returned by .Values() in the form of []*NMItem, otherwise errors -func NMAsXMLElements(nm *utils.OrderedNavigableMap) (ents []*XMLElement, err error) { +func NMAsXMLElements(nm *OrderedNavigableMap) (ents []*XMLElement, err error) { pathIdx := make(map[string]*XMLElement) // Keep the index of elements based on path for el := nm.GetFirstElement(); el != nil; el = el.Next() { path := el.Value @@ -44,14 +41,15 @@ func NMAsXMLElements(nm *utils.OrderedNavigableMap) (ents []*XMLElement, err err if nmItm.NewBranch { pathIdx = make(map[string]*XMLElement) // reset cache so we can start having other elements with same path } - val := utils.IfaceAsString(nmItm.Data) + path = path[:len(path)-1] // remove the last index + val := nmItm.String() var pathCached bool - for i := len(nmItm.Path); i > 0; i-- { + for i := len(path); i > 0; i-- { var cachedElm *XMLElement - if cachedElm, pathCached = pathIdx[strings.Join(nmItm.Path[:i], "")]; !pathCached { + if cachedElm, pathCached = pathIdx[strings.Join(path[:i], "")]; !pathCached { continue } - if i == len(nmItm.Path) { // lastElmnt, overwrite value or add attribute + if i == len(path) { // lastElmnt, overwrite value or add attribute if nmItm.AttributeID != "" { cachedElm.Attributes = append(cachedElm.Attributes, &xml.Attr{ @@ -65,9 +63,9 @@ func NMAsXMLElements(nm *utils.OrderedNavigableMap) (ents []*XMLElement, err err } // create elements in reverse order so we can append already created var newElm *XMLElement - for j := len(nmItm.Path); j > i; j-- { - elm := &XMLElement{XMLName: xml.Name{Local: nmItm.Path[j-1]}} - pathIdx[strings.Join(nmItm.Path[:j], "")] = elm + for j := len(path); j > i; j-- { + elm := &XMLElement{XMLName: xml.Name{Local: path[j-1]}} + pathIdx[strings.Join(path[:j], "")] = elm if newElm == nil { if nmItm.AttributeID != "" { elm.Attributes = append(elm.Attributes, @@ -88,9 +86,9 @@ func NMAsXMLElements(nm *utils.OrderedNavigableMap) (ents []*XMLElement, err err } if !pathCached { // not an update but new element to be created var newElm *XMLElement - for i := len(nmItm.Path); i > 0; i-- { - elm := &XMLElement{XMLName: xml.Name{Local: nmItm.Path[i-1]}} - pathIdx[strings.Join(nmItm.Path[:i], "")] = elm + for i := len(path); i > 0; i-- { + elm := &XMLElement{XMLName: xml.Name{Local: path[i-1]}} + pathIdx[strings.Join(path[:i], "")] = elm if newElm == nil { // last element, create data inside if nmItm.AttributeID != "" { elm.Attributes = append(elm.Attributes, @@ -112,55 +110,3 @@ func NMAsXMLElements(nm *utils.OrderedNavigableMap) (ents []*XMLElement, err err } return } - -// NMAsCGREvent builds a CGREvent considering Time as time.Now() -// and Event as linear map[string]interface{} with joined paths -// treats particular case when the value of map is []*NMItem - used in agents/AgentRequest -func NMAsCGREvent(nM *utils.OrderedNavigableMap, tnt string, pathSep string, opts utils.MapStorage) (cgrEv *utils.CGREvent) { - if nM == nil { - return - } - el := nM.GetFirstElement() - if el == nil { - return - } - cgrEv = &utils.CGREvent{ - Tenant: tnt, - ID: utils.UUIDSha1Prefix(), - Time: utils.TimePointer(time.Now()), - Event: make(map[string]interface{}), - APIOpts: opts, - } - for ; el != nil; el = el.Next() { - val, _ := nM.Field(el.Value) // this should never return error cause we get the path from the order - opath := utils.GetPathWithoutIndex(strings.Join(val.Path, utils.NestingSep)) - if val.AttributeID != "" { - continue - } - if _, has := cgrEv.Event[opath]; !has { - cgrEv.Event[opath] = val.Data // first item which is not an attribute will become the value - } - } - return -} - -// NMAsMapInterface builds a linear map[string]interface{} with joined paths -// treats particular case when the value of map is []*NMItem - used in agents/AgentRequest -func NMAsMapInterface(nM *utils.OrderedNavigableMap, pathSep string) (mp map[string]interface{}) { - mp = make(map[string]interface{}) - el := nM.GetFirstElement() - if el == nil { - return - } - for ; el != nil; el = el.Next() { - val, _ := nM.Field(el.Value) // this should never return error cause we get the path from the order - opath := utils.GetPathWithoutIndex(strings.Join(val.Path, utils.NestingSep)) - if val.AttributeID != "" { - continue - } - if _, has := mp[opath]; !has { - mp[opath] = val.Data // first item which is not an attribute will become the value - } - } - return -} diff --git a/utils/xmlelement_test.go b/utils/xmlelement_test.go new file mode 100644 index 000000000..1dd0f8dc0 --- /dev/null +++ b/utils/xmlelement_test.go @@ -0,0 +1,284 @@ +/* +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 +*/ +package utils + +import ( + "encoding/xml" + "math/rand" + "reflect" + "strings" + "testing" +) + +func TestNMAsXMLElementsConfigEmptyID(t *testing.T) { + nM := NewOrderedNavigableMap() + order := [][]string{ + {"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"}, + {"FirstLevel2", "FirestLevel3", "Field3"}, + {"FirstLevel2", "FirestLevel3", "Field5"}, + } + if err := nM.SetAsSlice(&FullPath{Path: strings.Join(order[0], NestingSep), PathSlice: order[0]}, []*DataNode{ + {Type: NMDataType, Value: &DataLeaf{ + Data: "Val1"}}}); err != nil { + t.Error(err) + } + if err := nM.SetAsSlice(&FullPath{Path: strings.Join(order[1], NestingSep), PathSlice: order[1]}, []*DataNode{ + {Type: NMDataType, Value: &DataLeaf{ + Data: "Value3"}}}); err != nil { + t.Error(err) + } + if err := nM.SetAsSlice(&FullPath{Path: strings.Join(order[2], NestingSep), PathSlice: order[2]}, []*DataNode{ + {Type: NMDataType, Value: &DataLeaf{ + Data: "Value5", + AttributeID: "attribute5"}}, + {Type: NMDataType, Value: &DataLeaf{ + Data: "attrVal5", + AttributeID: "attribute5"}}}); err != nil { + t.Error(err) + } + if _, err := NMAsXMLElements(nM); err != nil { + t.Error(err) + } +} + +func TestNMAsXMLElements(t *testing.T) { + nM := NewOrderedNavigableMap() + order := [][]string{ + {"FirstLevel2", "SecondLevel2", "Field2"}, + {"FirstLevel", "SecondLevel", "ThirdLevel", "Fld1"}, + {"FirstLevel2", "Field3"}, + {"FirstLevel2", "Field5"}, + {"Field4"}, + {"FirstLevel2", "Field6"}, + } + if err := nM.SetAsSlice(&FullPath{Path: strings.Join(order[0], NestingSep), PathSlice: order[0]}, []*DataNode{ + {Type: NMDataType, Value: &DataLeaf{ + Data: "attrVal1", + AttributeID: "attribute1"}}, + {Type: NMDataType, Value: &DataLeaf{ + Data: "Value2"}}}); err != nil { + t.Error(err) + } + if err := nM.SetAsSlice(&FullPath{Path: strings.Join(order[1], NestingSep), PathSlice: order[1]}, []*DataNode{ + {Type: NMDataType, Value: &DataLeaf{ + Data: "Val1"}}}); err != nil { + t.Error(err) + } + if err := nM.SetAsSlice(&FullPath{Path: strings.Join(order[2], NestingSep), PathSlice: order[2]}, []*DataNode{ + {Type: NMDataType, Value: &DataLeaf{ + Data: "Value3"}}}); err != nil { + t.Error(err) + } + if err := nM.SetAsSlice(&FullPath{Path: strings.Join(order[3], NestingSep), PathSlice: order[3]}, []*DataNode{ + {Type: NMDataType, Value: &DataLeaf{ + Data: "Value5"}}, + {Type: NMDataType, Value: &DataLeaf{ + Data: "attrVal5", + AttributeID: "attribute5"}}}); err != nil { + t.Error(err) + } + if err := nM.SetAsSlice(&FullPath{Path: strings.Join(order[4], NestingSep), PathSlice: order[4]}, []*DataNode{ + {Type: NMDataType, Value: &DataLeaf{ + Data: "Val4"}}, + {Type: NMDataType, Value: &DataLeaf{ + Data: "attrVal2", + AttributeID: "attribute2"}}}); err != nil { + t.Error(err) + } + if err := nM.SetAsSlice(&FullPath{Path: strings.Join(order[5], NestingSep), PathSlice: order[5]}, []*DataNode{ + {Type: NMDataType, Value: &DataLeaf{ + Data: "Value6", + NewBranch: true}}, + {Type: NMDataType, Value: &DataLeaf{ + Data: "attrVal6", + AttributeID: "attribute6"}}}); err != nil { + t.Error(err) + } + + eXMLElmnts := []*XMLElement{ + { + XMLName: xml.Name{Local: order[0][0]}, + Elements: []*XMLElement{ + { + XMLName: xml.Name{Local: order[0][1]}, + Elements: []*XMLElement{ + { + XMLName: xml.Name{Local: order[0][2]}, + Attributes: []*xml.Attr{ + { + Name: xml.Name{Local: "attribute1"}, + Value: "attrVal1", + }, + }, + Value: "Value2", + }, + }, + }, + { + XMLName: xml.Name{Local: "Field3"}, + Value: "Value3", + }, + { + XMLName: xml.Name{Local: order[3][1]}, + Attributes: []*xml.Attr{ + { + Name: xml.Name{Local: "attribute5"}, + Value: "attrVal5", + }, + }, + Value: "Value5", + }, + }, + }, + { + XMLName: xml.Name{Local: order[1][0]}, + Elements: []*XMLElement{ + { + XMLName: xml.Name{Local: order[1][1]}, + Elements: []*XMLElement{ + { + XMLName: xml.Name{Local: order[1][2]}, + Elements: []*XMLElement{ + { + XMLName: xml.Name{Local: "Fld1"}, + Value: "Val1", + }, + }, + }, + }, + }, + }, + }, + { + XMLName: xml.Name{Local: order[4][0]}, + Attributes: []*xml.Attr{ + { + Name: xml.Name{Local: "attribute2"}, + Value: "attrVal2", + }, + }, + Value: "Val4", + }, + { + XMLName: xml.Name{Local: order[5][0]}, + Elements: []*XMLElement{ + { + XMLName: xml.Name{Local: order[5][1]}, + Attributes: []*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", ToJSON(eXMLElmnts), 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)) + } +} + +/* +goos: linux +goarch: amd64 +pkg: github.com/cgrates/cgrates/config +BenchmarkOrderdNavigableMapSet2-16 1738 6463443 ns/op +BenchmarkOrderdNavigableMapSet2-16 1792 6536313 ns/op +BenchmarkOrderdNavigableMapSet2-16 1744 6554331 ns/op +BenchmarkNavigableMapOld1Set-16 2980 3831743 ns/op +BenchmarkNavigableMapOld1Set-16 2758 3789885 ns/op +BenchmarkNavigableMapOld1Set-16 2916 3741273 ns/op +PASS +ok github.com/cgrates/cgrates/config 71.065s +*/ +var generator = rand.New(rand.NewSource(42)) +var gen = generateRandomTemplate(10_000) + +type benchData struct { + path []string + strPath string + data string +} + +func generateRandomPath() (out []string) { + size := generator.Intn(16) + 1 + out = make([]string, size) + for i := 0; i < size; i++ { + out[i] = Sha1(GenUUID()) + } + return +} +func generateRandomTemplate(size int) (out []benchData) { + out = make([]benchData, size) + for i := 0; i < size; i++ { + out[i].path = generateRandomPath() + out[i].data = UUIDSha1Prefix() + out[i].strPath = strings.Join(out[i].path, NestingSep) + } + return +} + +func BenchmarkOrderdNavigableMapSet2(b *testing.B) { + nm := NewOrderedNavigableMap() + b.ResetTimer() + for n := 0; n < b.N; n++ { + for _, data := range gen { + if err := nm.Set(&FullPath{PathSlice: data.path, Path: data.strPath}, data.data); err != nil { + b.Log(err, data.path) + } + } + } +} + +// func BenchmarkNavigableMapOld1Set(b *testing.B) { +// nm := NewNavigableMap(nil) +// b.ResetTimer() +// for n := 0; n < b.N; n++ { +// for _, data := range gen { +// nm.Set(data.path, data.data, false, true) +// } +// } +// }