From 99526ddde29c132af4dd4ac0d595893af9ece5e5 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Tue, 23 Mar 2021 13:26:13 +0200 Subject: [PATCH] Added nil check when creating EventCost DataProvider. Fixes #2764 --- engine/cdr.go | 30 ++++++++++++++---------------- engine/eventcost.go | 3 --- engine/eventcost_test.go | 22 ++++++++++++++++------ 3 files changed, 30 insertions(+), 25 deletions(-) diff --git a/engine/cdr.go b/engine/cdr.go index b1863df2c..46e045c41 100644 --- a/engine/cdr.go +++ b/engine/cdr.go @@ -143,10 +143,7 @@ func (cdr *CDR) FormatCost(shiftDecimals, roundDecimals int) string { // FieldAsString is used to retrieve fields as string, primary fields are const labeled func (cdr *CDR) FieldAsString(rsrPrs *config.RSRParser) (parsed string, err error) { parsed, err = rsrPrs.ParseDataProviderWithInterfaces( - utils.MapStorage{ - utils.MetaReq: cdr.AsMapStringIface(), - utils.MetaEC: cdr.CostDetails, - }) + cdr.AsMapStorage()) if err != nil { return } @@ -156,10 +153,7 @@ func (cdr *CDR) FieldAsString(rsrPrs *config.RSRParser) (parsed string, err erro // FieldsAsString concatenates values of multiple fields defined in template, used eg in CDR templates func (cdr *CDR) FieldsAsString(rsrFlds config.RSRParsers) string { outVal, err := rsrFlds.ParseDataProvider( - utils.MapStorage{ - utils.MetaReq: cdr.AsMapStringIface(), - utils.MetaEC: cdr.CostDetails, - }) + cdr.AsMapStorage()) if err != nil { return "" } @@ -205,6 +199,16 @@ func (cdr *CDR) Clone() *CDR { return cln } +func (cdr *CDR) AsMapStorage() (mp utils.MapStorage) { + mp = utils.MapStorage{ + utils.MetaReq: cdr.AsMapStringIface(), + } + if cdr.CostDetails != nil { + mp[utils.MetaEC] = cdr.CostDetails + } + return +} + func (cdr *CDR) AsMapStringIface() (mp map[string]interface{}) { mp = make(map[string]interface{}) for fld, val := range cdr.ExtraFields { @@ -283,10 +287,7 @@ func (cdr *CDR) combimedCdrFieldVal(cfgCdrFld *config.FCTemplate, groupCDRs []*C if cdr.CGRID != grpCDR.CGRID { continue // We only care about cdrs with same primary cdr behind } - if pass, err := filterS.Pass(grpCDR.Tenant, cfgCdrFld.Filters, utils.MapStorage{ - utils.MetaReq: grpCDR.AsMapStringIface(), - utils.MetaEC: grpCDR.CostDetails, - }); err != nil { + if pass, err := filterS.Pass(grpCDR.Tenant, cfgCdrFld.Filters, grpCDR.AsMapStorage()); err != nil { return utils.EmptyString, err } else if !pass { continue @@ -391,10 +392,7 @@ func (cdr *CDR) formatField(cfgFld *config.FCTemplate, groupedCDRs []*CDR, // ExportRecord is a []string to keep it compatible with encoding/csv Writer func (cdr *CDR) AsExportRecord(exportFields []*config.FCTemplate, groupedCDRs []*CDR, filterS *FilterS) (expRecord []string, err error) { - nM := utils.MapStorage{ - utils.MetaReq: cdr.AsMapStringIface(), - utils.MetaEC: cdr.CostDetails, - } + nM := cdr.AsMapStorage() for _, cfgFld := range exportFields { if !strings.HasPrefix(cfgFld.Path, utils.MetaExp+utils.NestingSep) { continue diff --git a/engine/eventcost.go b/engine/eventcost.go index e6e781739..71308788d 100644 --- a/engine/eventcost.go +++ b/engine/eventcost.go @@ -955,9 +955,6 @@ func (ec *EventCost) Trim(atUsage time.Duration) (srplusEC *EventCost, err error // FieldAsInterface func to implement DataProvider func (ec *EventCost) FieldAsInterface(fldPath []string) (val interface{}, err error) { - if len(fldPath) == 0 { - return nil, utils.ErrNotFound - } if ec.cache == nil { ec.cache = utils.MapStorage{} // fix gob deserialization } diff --git a/engine/eventcost_test.go b/engine/eventcost_test.go index 9b5649c3b..725b7f853 100644 --- a/engine/eventcost_test.go +++ b/engine/eventcost_test.go @@ -2655,12 +2655,6 @@ func TestInitCache(t *testing.T) { func TestEventCostFieldAsInterface(t *testing.T) { eventCost := &EventCost{} eventCost.initCache() - // empty check - if rcv, err := eventCost.FieldAsInterface([]string{}); err != utils.ErrNotFound { - t.Errorf("Expecting: %+v, received: %+v", utils.ErrNotFound, err) - } else if rcv != nil { - t.Errorf("Expecting: nil, received: %+v", rcv) - } // item found in cache eventCost.cache = utils.MapStorage{"test": nil} if rcv, err := eventCost.FieldAsInterface([]string{"test"}); err == nil || err != utils.ErrNotFound { @@ -3791,3 +3785,19 @@ func TestECAsDataProvider2(t *testing.T) { t.Errorf("Unexpected error:%v", err) } } + +func TestECFieldAsInterfaceNilEventCost(t *testing.T) { + dft := config.NewDefaultCGRConfig() + cdr, err := NewMapEvent(map[string]interface{}{}).AsCDR(dft, "cgrates.org", "UTC") + if err != nil { + t.Fatal(err) + } + nM := cdr.AsMapStorage() + if _, err := nM.FieldAsInterface([]string{"*ec", "Charges[0]", "Increments[0]", "Accounting", "Balance", "ID"}); err == nil || err.Error() != utils.ErrNotFound.Error() { + t.Fatalf("Expected error:%s, received: %v", utils.ErrNotFound.Error(), err) + } + + if _, err := nM.FieldAsInterface([]string{"*req", "CostDetails", "Charges[0]", "Increments[0]", "Accounting", "Balance", "ID"}); err == nil || err.Error() != utils.ErrNotFound.Error() { + t.Fatalf("Expected error:%s, received: %v", utils.ErrNotFound.Error(), err) + } +}