Update empty xml_root_path sanity check case.

Also added tests for it.

Added comment to the *HierarchyPath.AsString() function,
addressing the issue of not being able to retrieve the
element when the root path is equal to the path that
is being processed.
This commit is contained in:
ionutboangiu
2023-10-13 10:38:37 -04:00
committed by Dan Christian Bogos
parent 950c5279a6
commit 0bc94857ca
3 changed files with 72 additions and 8 deletions

View File

@@ -515,21 +515,24 @@ func (cfg *CGRConfig) checkConfigSanity() error {
}
// The following sanity check prevents a "slice bounds out of range" panic.
if rdr.Type == utils.MetaFileXML && !utils.IsSliceMember([]string{utils.META_NONE, utils.META_CONSTANT,
utils.META_FILLER, utils.MetaRemoteHost}, field.Type) && len(field.Value) != 0 {
if rdr.Type == utils.MetaFileXML && len(field.Value) != 0 &&
!utils.IsSliceMember([]string{utils.META_NONE, utils.META_CONSTANT}, field.Type) {
// Retrieve the number of elements of the parser rule with the fewest elements.
// Find the minimum rule length for dynamic RSRParser within the field value.
minRuleLength := math.MaxInt
for _, rule := range field.Value {
if ruleLen := len(strings.Split(rule.AttrName(), utils.NestingSep)); minRuleLength > ruleLen {
minRuleLength = ruleLen
for _, parser := range field.Value {
if !strings.HasPrefix(parser.Rules, utils.DynamicDataPrefix) {
continue
}
ruleLen := len(strings.Split(parser.Rules, utils.NestingSep))
minRuleLength = min(minRuleLength, ruleLen)
}
if len(rdr.XmlRootPath) >= minRuleLength {
// If a dynamic RSRParser is found, verify xml_root_path length against minRuleLength.
if minRuleLength != math.MaxInt && len(rdr.XmlRootPath) >= minRuleLength {
return fmt.Errorf("<%s> %s for reader %s at %s",
utils.ERs,
"len of xml_root_path elements cannot be equal to or exceed the number of value rule elements",
"xml_root_path length exceeds value rule elements",
rdr.ID, field.Tag)
}
}

View File

@@ -873,3 +873,58 @@ func TestConfigSanityFilterS(t *testing.T) {
cfg.filterSCfg.ResourceSConns = []string{}
}
func TestConfigSanityERsXmlRootPath(t *testing.T) {
cfg, err := NewCGRConfigFromJsonStringWithDefaults(`{
"ers": {
"enabled": true,
"sessions_conns": [],
"readers": [
{
"id": "*default",
"type": "*file_xml",
"source_path": "/tmp",
"processed_path": "/tmp",
"flags": ["*dryrun"],
"xml_root_path": "A.B",
"fields":[
{"tag": "VariableFld", "path": "*cgreq.VariableFld", "type": "*variable", "value": "~*req.A.B.Value1", "mandatory": true},
{"tag": "ComposedFld", "path": "*cgreq.ComposedFld", "type": "*composed", "value": "~*req.A.B.Value2", "mandatory": true},
{"tag": "ComposedFld", "path": "*cgreq.ComposedFld", "type": "*composed", "value": "_", "mandatory": true},
{"tag": "ComposedFld", "path": "*cgreq.ComposedFld", "type": "*composed", "value": "~*req.A.B.Value3", "mandatory": true},
{"tag": "ConstantFld", "path": "*cgreq.ConstantFld", "type": "*constant", "value": "Value4", "mandatory": true},
{"tag": "UsageDiffFld", "path": "*cgreq.UsageDiffFld", "type": "*usage_difference", "value": "~*req.A.B.Value5;~*req.A.B.Value6", "mandatory": true},
{"tag": "NoneFld", "path": "*cgreq.NoneFld", "type": "*none", "mandatory": true},
{"tag": "FillerFld", "path": "*cgreq.FillerFld", "type": "*filler", "width": 5, "mandatory": true}
]
}
]
}}`)
if err != nil {
t.Fatal(err)
}
err = cfg.checkConfigSanity()
if err != nil {
t.Fatal(err)
}
cfg.ERsCfg().Readers[0].XmlRootPath = utils.ParseHierarchyPath("", utils.EmptyString)
err = cfg.checkConfigSanity()
if err != nil {
t.Fatal(err)
}
cfg.ERsCfg().Readers[0].XmlRootPath = utils.ParseHierarchyPath("A.B.Value1", utils.EmptyString)
err = cfg.checkConfigSanity()
if err != nil {
t.Fatal(err)
}
experr := `<ERs> xml_root_path length exceeds value rule elements for reader *default at VariableFld`
cfg.ERsCfg().Readers[0].XmlRootPath = utils.ParseHierarchyPath("A.B.C.D", utils.EmptyString)
err = cfg.checkConfigSanity()
if err == nil || err.Error() != experr {
t.Errorf("expected: %s, received: %s", experr, err)
}
}

View File

@@ -650,6 +650,12 @@ func (hP HierarchyPath) AsString(sep string, prefix bool) string {
if prefix {
strHP.WriteString(sep)
}
// TODO: Since this function can convert both the full and the relative HierarchyPath to a string, with
// prefix telling us which is which (true -> full path, false -> relative path), we should consider
// returning the '.' character when prefix == false. Currently, because we are returning an empty string
// if the path we are currently parsing is equal to the root path, when we attempt to retrieve the element
// we receive the error "expr expression is nil".
if len(hP) == 0 {
return strHP.String()
}