diff --git a/config/fctemplate.go b/config/fctemplate.go index 38d9da4fa..d0bec162a 100755 --- a/config/fctemplate.go +++ b/config/fctemplate.go @@ -143,7 +143,7 @@ func InflateTemplates(fcts []*FCTemplate, msgTpls map[string][]*FCTemplate) ([]* if !has { return nil, fmt.Errorf("no template with id: <%s>", tplID) } else if len(refTpl) == 0 { - continue + return nil, fmt.Errorf("empty template with id: <%s>", tplID) } wrkSlice := make([]*FCTemplate, len(refTpl)+len(fcts[i:])-1) // so we can cover tpls[i+1:] copy(wrkSlice[:len(refTpl)], refTpl) // copy fields out of referenced template diff --git a/config/fctemplate_test.go b/config/fctemplate_test.go index 442b74d62..3912d70b4 100755 --- a/config/fctemplate_test.go +++ b/config/fctemplate_test.go @@ -85,3 +85,207 @@ func TestFCTemplatesFromFCTemplatesJsonCfg(t *testing.T) { t.Errorf("expected: %s ,received: %s", utils.ToJSON(expected), utils.ToJSON(rcv)) } } + +func TestFCTemplateInflate1(t *testing.T) { + fcTmp1 := []*FCTemplate{ + &FCTemplate{ + Tag: "Tenant", + Type: "*composed", + FieldId: "Tenant", + Filters: []string{"Filter1", "Filter2"}, + Value: NewRSRParsersMustCompile("cgrates.org", true), + }, + &FCTemplate{ + Tag: "RunID", + Type: "*composed", + FieldId: "RunID", + Filters: []string{"Filter1_1", "Filter2_2"}, + Value: NewRSRParsersMustCompile("SampleValue", true), + }, + &FCTemplate{ + Tag: "TmpMap", + Type: "*template", + Filters: []string{"Filter1_1", "Filter2_2"}, + Value: NewRSRParsersMustCompile("TmpMap", true), + }, + } + fcTmpMp := map[string][]*FCTemplate{ + "TmpMap": []*FCTemplate{ + &FCTemplate{ + Tag: "Elem1", + Type: "*composed", + FieldId: "Elem1", + Filters: []string{"Filter1", "Filter2"}, + Value: NewRSRParsersMustCompile("Elem1", true), + }, + &FCTemplate{ + Tag: "Elem2", + Type: "*composed", + FieldId: "Elem2", + Filters: []string{"Filter1_1", "Filter2_2"}, + Value: NewRSRParsersMustCompile("Elem2", true), + }, + }, + "TmpMap2": []*FCTemplate{ + &FCTemplate{ + Tag: "Elem2.1", + Type: "*composed", + FieldId: "Elem2.1", + Filters: []string{"Filter1", "Filter2"}, + Value: NewRSRParsersMustCompile("Elem2.1", true), + }, + &FCTemplate{ + Tag: "Elem2.2", + Type: "*composed", + FieldId: "Elem2.2", + Filters: []string{"Filter1_1", "Filter2_2"}, + Value: NewRSRParsersMustCompile("Elem2.2", true), + }, + }, + } + expFC := []*FCTemplate{ + &FCTemplate{ + Tag: "Tenant", + Type: "*composed", + FieldId: "Tenant", + Filters: []string{"Filter1", "Filter2"}, + Value: NewRSRParsersMustCompile("cgrates.org", true), + }, + &FCTemplate{ + Tag: "RunID", + Type: "*composed", + FieldId: "RunID", + Filters: []string{"Filter1_1", "Filter2_2"}, + Value: NewRSRParsersMustCompile("SampleValue", true), + }, + &FCTemplate{ + Tag: "Elem1", + Type: "*composed", + FieldId: "Elem1", + Filters: []string{"Filter1", "Filter2"}, + Value: NewRSRParsersMustCompile("Elem1", true), + }, + &FCTemplate{ + Tag: "Elem2", + Type: "*composed", + FieldId: "Elem2", + Filters: []string{"Filter1_1", "Filter2_2"}, + Value: NewRSRParsersMustCompile("Elem2", true), + }, + } + if rcv, err := InflateTemplates(fcTmp1, fcTmpMp); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expFC, rcv) { + t.Errorf("expected: %s ,received: %s", utils.ToJSON(expFC), utils.ToJSON(rcv)) + } +} + +func TestFCTemplateInflate2(t *testing.T) { + fcTmp1 := []*FCTemplate{ + &FCTemplate{ + Tag: "Tenant", + Type: "*composed", + FieldId: "Tenant", + Filters: []string{"Filter1", "Filter2"}, + Value: NewRSRParsersMustCompile("cgrates.org", true), + }, + &FCTemplate{ + Tag: "RunID", + Type: "*composed", + FieldId: "RunID", + Filters: []string{"Filter1_1", "Filter2_2"}, + Value: NewRSRParsersMustCompile("SampleValue", true), + }, + &FCTemplate{ + Tag: "TmpMap3", + Type: "*template", + Filters: []string{"Filter1_1", "Filter2_2"}, + Value: NewRSRParsersMustCompile("TmpMap3", true), + }, + } + fcTmpMp := map[string][]*FCTemplate{ + "TmpMap": []*FCTemplate{ + &FCTemplate{ + Tag: "Elem1", + Type: "*composed", + FieldId: "Elem1", + Filters: []string{"Filter1", "Filter2"}, + Value: NewRSRParsersMustCompile("Elem1", true), + }, + &FCTemplate{ + Tag: "Elem2", + Type: "*composed", + FieldId: "Elem2", + Filters: []string{"Filter1_1", "Filter2_2"}, + Value: NewRSRParsersMustCompile("Elem2", true), + }, + }, + "TmpMap2": []*FCTemplate{ + &FCTemplate{ + Tag: "Elem2.1", + Type: "*composed", + FieldId: "Elem2.1", + Filters: []string{"Filter1", "Filter2"}, + Value: NewRSRParsersMustCompile("Elem2.1", true), + }, + &FCTemplate{ + Tag: "Elem2.2", + Type: "*composed", + FieldId: "Elem2.2", + Filters: []string{"Filter1_1", "Filter2_2"}, + Value: NewRSRParsersMustCompile("Elem2.2", true), + }, + }, + } + if _, err := InflateTemplates(fcTmp1, fcTmpMp); err.Error() != "no template with id: " { + t.Error(err) + } +} + +func TestFCTemplateInflate3(t *testing.T) { + fcTmp1 := []*FCTemplate{ + &FCTemplate{ + Tag: "Tenant", + Type: "*composed", + FieldId: "Tenant", + Filters: []string{"Filter1", "Filter2"}, + Value: NewRSRParsersMustCompile("cgrates.org", true), + }, + &FCTemplate{ + Tag: "RunID", + Type: "*composed", + FieldId: "RunID", + Filters: []string{"Filter1_1", "Filter2_2"}, + Value: NewRSRParsersMustCompile("SampleValue", true), + }, + &FCTemplate{ + Tag: "TmpMap", + Type: "*template", + Filters: []string{"Filter1_1", "Filter2_2"}, + Value: NewRSRParsersMustCompile("TmpMap", true), + }, + } + fcTmpMp := map[string][]*FCTemplate{ + "TmpMap": []*FCTemplate{}, + "TmpMap2": []*FCTemplate{ + &FCTemplate{ + Tag: "Elem2.1", + Type: "*composed", + FieldId: "Elem2.1", + Filters: []string{"Filter1", "Filter2"}, + Value: NewRSRParsersMustCompile("Elem2.1", true), + }, + &FCTemplate{ + Tag: "Elem2.2", + Type: "*composed", + FieldId: "Elem2.2", + Filters: []string{"Filter1_1", "Filter2_2"}, + Value: NewRSRParsersMustCompile("Elem2.2", true), + }, + }, + } + if _, err := InflateTemplates(fcTmp1, fcTmpMp); err == nil || + err.Error() != "empty template with id: " { + t.Error(err) + } +} diff --git a/engine/ratingprofile.go b/engine/ratingprofile.go index 79f7abb7d..cb524714e 100644 --- a/engine/ratingprofile.go +++ b/engine/ratingprofile.go @@ -172,13 +172,13 @@ func (rpf *RatingProfile) GetRatingPlansForPrefix(cd *CallDescriptor) (err error } else { for _, p := range utils.SplitPrefix(cd.Destination, MIN_PREFIX_MATCH) { if destIDs, err := dm.DataDB().GetReverseDestination(p, false, utils.NonTransactional); err == nil { - var bestWeight float64 + var bestWeight *float64 for _, dID := range destIDs { if _, ok := rpl.DestinationRates[dID]; ok { ril := rpl.RateIntervalList(dID) currentWeight := ril.GetWeight() - if currentWeight > bestWeight { - bestWeight = currentWeight + if bestWeight == nil || currentWeight > *bestWeight { + bestWeight = utils.Float64Pointer(currentWeight) rps = ril prefix = p destinationId = dID