From 5fcd7dcb5796405741685810cdcbd4b881fde5e9 Mon Sep 17 00:00:00 2001 From: TeoV Date: Fri, 15 Mar 2019 15:59:51 +0200 Subject: [PATCH] Add ExternalAttributeProfile + unit tests --- apier/v2/attributes.go | 21 ++---- engine/libattributes.go | 44 +++++++++++++ engine/libattributes_test.go | 122 +++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 16 deletions(-) create mode 100644 engine/libattributes_test.go diff --git a/apier/v2/attributes.go b/apier/v2/attributes.go index c1d66635f..3e8e17a7a 100644 --- a/apier/v2/attributes.go +++ b/apier/v2/attributes.go @@ -18,34 +18,23 @@ along with this program. If not, see package v2 -/* import ( "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" ) //SetAttributeProfile add/update a new Attribute Profile -func (apierV1 *ApierV2) SetAttributeProfile(alsPrf *engine.AttributeProfile, reply *string) error { - if missing := utils.MissingStructFields(alsPrf, []string{"Tenant", "ID"}); len(missing) != 0 { +func (apierV1 *ApierV2) SetAttributeProfile(extAlsPrf *engine.ExternalAttributeProfile, reply *string) error { + if missing := utils.MissingStructFields(extAlsPrf, []string{"Tenant", "ID"}); len(missing) != 0 { return utils.NewErrMandatoryIeMissing(missing...) } - if len(alsPrf.Attributes) != 0 { - for _, attr := range alsPrf.Attributes { - for _, sub := range attr.Substitute { - if sub.Rules == "" { - return utils.NewErrMandatoryIeMissing("Rules") - } - if err := sub.Compile(); err != nil { - return utils.NewErrServerError(err) - } - } - } + alsPrf, err := extAlsPrf.ConvertExtToAttrPrf() + if err != nil { + return utils.APIErrorHandler(err) } - if err := apierV1.DataManager.SetAttributeProfile(alsPrf, true); err != nil { return utils.APIErrorHandler(err) } *reply = utils.OK return nil } -*/ diff --git a/engine/libattributes.go b/engine/libattributes.go index dc9aeb3cf..bdef8c2bd 100644 --- a/engine/libattributes.go +++ b/engine/libattributes.go @@ -67,3 +67,47 @@ type AttributeProfiles []*AttributeProfile func (aps AttributeProfiles) Sort() { sort.Slice(aps, func(i, j int) bool { return aps[i].Weight > aps[j].Weight }) } + +type ExternalAttribute struct { + FilterIDs []string + FieldName string + Substitute string +} + +type ExternalAttributeProfile struct { + Tenant string + ID string + Contexts []string // bind this AttributeProfile to multiple contexts + FilterIDs []string + ActivationInterval *utils.ActivationInterval // Activation interval + Attributes []*ExternalAttribute + Blocker bool // blocker flag to stop processing on multiple runs + Weight float64 +} + +func (ext *ExternalAttributeProfile) ConvertExtToAttrPrf() (attr *AttributeProfile, err error) { + attr = new(AttributeProfile) + if len(ext.Attributes) == 0 { + return nil, utils.NewErrMandatoryIeMissing("Attributes") + } + attr.Attributes = make([]*Attribute, len(ext.Attributes)) + for i, extAttr := range ext.Attributes { + if len(extAttr.Substitute) == 0 { + return nil, utils.NewErrMandatoryIeMissing("Substitute") + } + attr.Attributes[i] = new(Attribute) + if attr.Attributes[i].Substitute, err = config.NewRSRParsers(extAttr.Substitute, true, utils.INFIELD_SEP); err != nil { + return nil, err + } + attr.Attributes[i].FilterIDs = extAttr.FilterIDs + attr.Attributes[i].FieldName = extAttr.FieldName + } + attr.Tenant = ext.Tenant + attr.ID = ext.ID + attr.Contexts = ext.Contexts + attr.FilterIDs = ext.FilterIDs + attr.ActivationInterval = ext.ActivationInterval + attr.Blocker = ext.Blocker + attr.Weight = ext.Weight + return +} diff --git a/engine/libattributes_test.go b/engine/libattributes_test.go new file mode 100644 index 000000000..a682e1b89 --- /dev/null +++ b/engine/libattributes_test.go @@ -0,0 +1,122 @@ +/* +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 engine + +import ( + "reflect" + "testing" + "time" + + "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/utils" +) + +func TestConvertExternalToProfile(t *testing.T) { + external := &ExternalAttributeProfile{ + Tenant: "cgrates.org", + ID: "ATTR_ID", + Contexts: []string{utils.MetaSessionS, utils.MetaCDRs}, + FilterIDs: []string{"FLTR_ACNT_dan", "FLTR_DST_DE"}, + ActivationInterval: &utils.ActivationInterval{ + ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), + ExpiryTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), + }, + Attributes: []*ExternalAttribute{ + &ExternalAttribute{ + FieldName: "Account", + Substitute: "1001", + }, + }, + Weight: 20, + } + + expAttr := &AttributeProfile{ + Tenant: "cgrates.org", + ID: "ATTR_ID", + Contexts: []string{utils.MetaSessionS, utils.MetaCDRs}, + FilterIDs: []string{"FLTR_ACNT_dan", "FLTR_DST_DE"}, + ActivationInterval: &utils.ActivationInterval{ + ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), + ExpiryTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), + }, + Attributes: []*Attribute{ + { + FieldName: "Account", + Substitute: config.NewRSRParsersMustCompile("1001", true, utils.INFIELD_SEP), + }, + }, + Weight: 20, + } + + rcv, err := external.ConvertExtToAttrPrf() + if err != nil { + t.Error(err) + } + rcv.Compile() + + if !reflect.DeepEqual(expAttr, rcv) { + t.Errorf("Expecting : %+v, received: %+v", expAttr, rcv) + } +} + +func TestConvertExternalToProfileMissing(t *testing.T) { + external := &ExternalAttributeProfile{ + Tenant: "cgrates.org", + ID: "ATTR_ID", + Contexts: []string{utils.MetaSessionS, utils.MetaCDRs}, + FilterIDs: []string{"FLTR_ACNT_dan", "FLTR_DST_DE"}, + ActivationInterval: &utils.ActivationInterval{ + ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), + ExpiryTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), + }, + Attributes: []*ExternalAttribute{}, + Weight: 20, + } + + _, err := external.ConvertExtToAttrPrf() + if err == nil || err.Error() != "MANDATORY_IE_MISSING: [Attributes]" { + t.Error(err) + } + +} + +func TestConvertExternalToProfileMissing2(t *testing.T) { + external := &ExternalAttributeProfile{ + Tenant: "cgrates.org", + ID: "ATTR_ID", + Contexts: []string{utils.MetaSessionS, utils.MetaCDRs}, + FilterIDs: []string{"FLTR_ACNT_dan", "FLTR_DST_DE"}, + ActivationInterval: &utils.ActivationInterval{ + ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), + ExpiryTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), + }, + Attributes: []*ExternalAttribute{ + &ExternalAttribute{ + FieldName: "Account", + }, + }, + Weight: 20, + } + + _, err := external.ConvertExtToAttrPrf() + if err == nil || err.Error() != "MANDATORY_IE_MISSING: [Substitute]" { + t.Error(err) + } + +}