Update AttributeProfile struct

This commit is contained in:
TeoV
2018-01-25 18:15:53 +02:00
committed by Dan Christian Bogos
parent e3083471b1
commit b6bbc65e49
15 changed files with 287 additions and 304 deletions

View File

@@ -73,6 +73,7 @@ func (alS *AttributeService) matchingAttributeProfilesForEvent(ev *utils.CGREven
lockIDs := utils.PrefixSliceItems(aPrflIDs.Slice(), utils.AttributeFilterIndexes)
guardian.Guardian.GuardIDs(config.CgrConfig().LockingTimeout, lockIDs...)
defer guardian.Guardian.UnguardIDs(lockIDs...)
//utils.Logger.Debug(fmt.Sprintf("ID %+v", aPrflIDs))
for apID := range aPrflIDs {
aPrfl, err := alS.dm.GetAttributeProfile(ev.Tenant, apID, false, utils.NonTransactional)
if err != nil {
@@ -105,6 +106,7 @@ func (alS *AttributeService) matchingAttributeProfilesForEvent(ev *utils.CGREven
i++
}
aPrfls.Sort()
utils.Logger.Debug(fmt.Sprintf("aPrfls %+v", utils.ToJSON(aPrfls)))
return
}
@@ -150,7 +152,7 @@ func (alS *AttributeService) processEvent(ev *utils.CGREvent) (rply *AttrSProces
return nil, err
}
rply = &AttrSProcessEventReply{MatchedProfile: attrPrf.ID, CGREvent: ev.Clone()}
for fldName, intialMp := range attrPrf.Attributes {
for fldName, intialMp := range attrPrf.attributes {
initEvValIf, has := ev.Event[fldName]
if !has { // we don't have initial in event, try append
if anyInitial, has := intialMp[utils.ANY]; has && anyInitial.Append {
@@ -159,14 +161,14 @@ func (alS *AttributeService) processEvent(ev *utils.CGREvent) (rply *AttrSProces
}
continue
}
initEvVal, cast := utils.CastFieldIfToString(initEvValIf)
if !cast {
utils.Logger.Warning(
fmt.Sprintf("<%s> ev: %s, cannot cast field: %+v to string",
utils.AttributeS, ev, fldName))
continue
}
attrVal, has := intialMp[initEvVal]
// initEvVal, cast := utils.CastFieldIfToString(initEvValIf)
// if !cast {
// utils.Logger.Warning(
// fmt.Sprintf("<%s> ev: %s, cannot cast field: %+v to string",
// utils.AttributeS, ev, fldName))
// continue
// }
attrVal, has := intialMp[initEvValIf]
if !has {
attrVal, has = intialMp[utils.ANY]
}
@@ -187,7 +189,7 @@ func (alS *AttributeService) processEvent(ev *utils.CGREvent) (rply *AttrSProces
}
func (alS *AttributeService) V1GetAttributeForEvent(ev *utils.CGREvent,
extattrPrf *ExternalAttributeProfile) (err error) {
attrPrfl *AttributeProfile) (err error) {
attrPrf, err := alS.attributeProfileForEvent(ev)
if err != nil {
if err != utils.ErrNotFound {
@@ -195,8 +197,7 @@ func (alS *AttributeService) V1GetAttributeForEvent(ev *utils.CGREvent,
}
return err
}
eattrPrfl := NewExternalAttributeProfileFromAttributeProfile(attrPrf)
*extattrPrf = *eattrPrfl
*attrPrfl = *attrPrf
return
}

View File

@@ -21,106 +21,10 @@ package engine
import (
"reflect"
"testing"
"time"
"github.com/cgrates/cgrates/utils"
)
func TestExternalAttributeProfileAsAttributeProfile(t *testing.T) {
extAttr := &ExternalAttributeProfile{
Tenant: "cgrates.org",
ID: "ALS1",
Contexts: []string{"con1"},
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{
&Attribute{
FieldName: "FL1",
Initial: "In1",
Substitute: "Al1",
Append: true,
},
},
Weight: 20,
}
attrMap := make(map[string]map[string]*Attribute)
attrMap["FL1"] = make(map[string]*Attribute)
attrMap["FL1"]["In1"] = &Attribute{
FieldName: "FL1",
Initial: "In1",
Substitute: "Al1",
Append: true,
}
expected := &AttributeProfile{
Tenant: "cgrates.org",
ID: "ALS1",
Contexts: []string{"con1"},
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: attrMap,
Weight: 20,
}
rcv := extAttr.AsAttributeProfile()
if !reflect.DeepEqual(expected, rcv) {
t.Errorf("Expecting : %+v, received: %+v", utils.ToJSON(expected), utils.ToJSON(rcv))
}
}
func TestNewExternalAttributeProfileFromAttributeProfile(t *testing.T) {
attrMap := make(map[string]map[string]*Attribute)
attrMap["FL1"] = make(map[string]*Attribute)
attrMap["FL1"]["In1"] = &Attribute{
FieldName: "FL1",
Initial: "In1",
Substitute: "Al1",
Append: true,
}
attrPrf := &AttributeProfile{
Tenant: "cgrates.org",
ID: "ALS1",
Contexts: []string{"con1"},
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: attrMap,
Weight: 20,
}
expected := &ExternalAttributeProfile{
Tenant: "cgrates.org",
ID: "ALS1",
Contexts: []string{"con1"},
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{
&Attribute{
FieldName: "FL1",
Initial: "In1",
Substitute: "Al1",
Append: true,
},
},
Weight: 20,
}
rcv := NewExternalAttributeProfileFromAttributeProfile(attrPrf)
if !reflect.DeepEqual(expected, rcv) {
t.Errorf("Expecting : %+v, received: %+v", utils.ToJSON(expected), utils.ToJSON(rcv))
}
}
func TestAttrSProcessEventReplyDigest(t *testing.T) {
eRpl := &AttrSProcessEventReply{
MatchedProfile: "ATTR_1",

View File

@@ -40,20 +40,20 @@ func TestPopulateAttrService(t *testing.T) {
data, _ := NewMapStorage()
dmAtr = NewDataManager(data)
context := utils.MetaRating
attrMap := make(map[string]map[string]*Attribute)
attrMap["FL1"] = make(map[string]*Attribute)
attrMap["FL1"]["In1"] = &Attribute{
FieldName: "FL1",
Initial: "In1",
Substitute: "Al1",
Append: true,
}
//Need clone because time.Now add extra information and DeepEqual don't like
var cloneExpTime time.Time
expTime := time.Now().Add(time.Duration(20 * time.Minute))
if err := utils.Clone(expTime, &cloneExpTime); err != nil {
t.Error(err)
}
mapSubstitutes := make(map[string]map[interface{}]*Attribute)
mapSubstitutes["FL1"] = make(map[interface{}]*Attribute)
mapSubstitutes["FL1"]["In1"] = &Attribute{
FieldName: "FL1",
Initial: "In1",
Substitute: "Al1",
Append: true,
}
atrPs = AttributeProfiles{
&AttributeProfile{
Tenant: "cgrates.org",
@@ -64,8 +64,16 @@ func TestPopulateAttrService(t *testing.T) {
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
ExpiryTime: cloneExpTime,
},
Attributes: attrMap,
Attributes: []*Attribute{
&Attribute{
FieldName: "FL1",
Initial: "In1",
Substitute: "Al1",
Append: true,
},
},
Weight: 20,
attributes: mapSubstitutes,
},
&AttributeProfile{
Tenant: "cgrates.org",
@@ -76,8 +84,16 @@ func TestPopulateAttrService(t *testing.T) {
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
ExpiryTime: cloneExpTime,
},
Attributes: attrMap,
Attributes: []*Attribute{
&Attribute{
FieldName: "FL1",
Initial: "In1",
Substitute: "Al1",
Append: true,
},
},
Weight: 20,
attributes: mapSubstitutes,
},
}
x, err := NewRequestFilter(MetaString, "attributeprofile1", []string{"Attribute"})
@@ -145,7 +161,7 @@ func TestAttributeMatchingAttributeProfilesForEvent(t *testing.T) {
t.Errorf("Error: %+v", err)
}
if !reflect.DeepEqual(atrPs[0], atrpl[0]) && !reflect.DeepEqual(atrPs[0], atrpl[1]) {
t.Errorf("Expecting: %+v, received: %+v ", atrPs[0], atrpl[0])
t.Errorf("Expecting: %+v, received: %+v ", utils.ToJSON(atrPs[0]), utils.ToJSON(atrpl[0]))
} else if !reflect.DeepEqual(atrPs[1], atrpl[1]) && !reflect.DeepEqual(atrPs[1], atrpl[0]) {
t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(atrPs), utils.ToJSON(atrpl))
}
@@ -168,7 +184,7 @@ func TestAttributeProfileForEvent(t *testing.T) {
t.Errorf("Error: %+v", err)
}
if !reflect.DeepEqual(atrPs[0], atrpl) && !reflect.DeepEqual(atrPs[1], atrpl) {
t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(atrPs[0]), utils.ToJSON(atrpl))
t.Errorf("Expecting: %+v, received: %+v", atrPs[0], atrpl)
}
}

View File

@@ -1165,6 +1165,16 @@ func (dm *DataManager) GetAttributeProfile(tenant, id string, skipCache bool, tr
}
return nil, err
}
for _, attr := range alsPrf.Attributes {
alsPrf.attributes = make(map[string]map[interface{}]*Attribute)
alsPrf.attributes[attr.FieldName] = make(map[interface{}]*Attribute)
alsPrf.attributes[attr.FieldName][attr.Initial] = &Attribute{
FieldName: attr.FieldName,
Initial: attr.Initial,
Substitute: attr.Substitute,
Append: attr.Append,
}
}
cache.Set(key, alsPrf, cacheCommit(transactionID), transactionID)
return
}

View File

@@ -26,8 +26,8 @@ import (
type Attribute struct {
FieldName string
Initial string
Substitute string
Initial interface{}
Substitute interface{}
Append bool
}
@@ -36,8 +36,9 @@ type AttributeProfile struct {
ID string
Contexts []string // bind this AttributeProfile to multiple contexts
FilterIDs []string
ActivationInterval *utils.ActivationInterval // Activation interval
Attributes map[string]map[string]*Attribute // map[FieldName][InitialValue]*Attribute
ActivationInterval *utils.ActivationInterval // Activation interval
attributes map[string]map[interface{}]*Attribute // map[FieldName][InitialValue]*Attribute
Attributes []*Attribute
Weight float64
}
@@ -52,53 +53,3 @@ type AttributeProfiles []*AttributeProfile
func (aps AttributeProfiles) Sort() {
sort.Slice(aps, func(i, j int) bool { return aps[i].Weight > aps[j].Weight })
}
type ExternalAttributeProfile struct {
Tenant string
ID string
Contexts []string // bind this AttributeProfile to multiple context
FilterIDs []string
ActivationInterval *utils.ActivationInterval // Activation interval
Attributes []*Attribute
Weight float64
}
func (eap *ExternalAttributeProfile) AsAttributeProfile() *AttributeProfile {
alsPrf := &AttributeProfile{
Tenant: eap.Tenant,
ID: eap.ID,
Contexts: eap.Contexts,
FilterIDs: eap.FilterIDs,
ActivationInterval: eap.ActivationInterval,
Weight: eap.Weight,
}
alsMap := make(map[string]map[string]*Attribute)
for _, als := range eap.Attributes {
alsMap[als.FieldName] = make(map[string]*Attribute)
alsMap[als.FieldName][als.Initial] = als
}
alsPrf.Attributes = alsMap
return alsPrf
}
func NewExternalAttributeProfileFromAttributeProfile(alsPrf *AttributeProfile) *ExternalAttributeProfile {
extals := &ExternalAttributeProfile{
Tenant: alsPrf.Tenant,
ID: alsPrf.ID,
Contexts: alsPrf.Contexts,
ActivationInterval: alsPrf.ActivationInterval,
FilterIDs: alsPrf.FilterIDs,
Weight: alsPrf.Weight,
}
for key, val := range alsPrf.Attributes {
for key2, val2 := range val {
extals.Attributes = append(extals.Attributes, &Attribute{
FieldName: key,
Initial: key2,
Substitute: val2.Substitute,
Append: val2.Append,
})
}
}
return extals
}

View File

@@ -2773,12 +2773,11 @@ func APItoModelTPAttribute(th *utils.TPAttributeProfile) (mdls TPAttributes) {
func APItoAttributeProfile(tpTH *utils.TPAttributeProfile, timezone string) (th *AttributeProfile, err error) {
th = &AttributeProfile{
Tenant: tpTH.Tenant,
ID: tpTH.ID,
Weight: tpTH.Weight,
FilterIDs: []string{},
Contexts: []string{},
Attributes: make(map[string]map[string]*Attribute, len(tpTH.Attributes)),
Tenant: tpTH.Tenant,
ID: tpTH.ID,
Weight: tpTH.Weight,
FilterIDs: []string{},
Contexts: []string{},
}
for _, fli := range tpTH.FilterIDs {
th.FilterIDs = append(th.FilterIDs, fli)
@@ -2787,10 +2786,15 @@ func APItoAttributeProfile(tpTH *utils.TPAttributeProfile, timezone string) (th
th.Contexts = append(th.Contexts, context)
}
for _, reqAttr := range tpTH.Attributes {
if _, has := th.Attributes[reqAttr.FieldName]; !has {
th.Attributes[reqAttr.FieldName] = make(map[string]*Attribute)
}
th.Attributes[reqAttr.FieldName][reqAttr.Initial] = &Attribute{
th.Attributes = append(th.Attributes, &Attribute{
Append: reqAttr.Append,
FieldName: reqAttr.FieldName,
Initial: reqAttr.Initial,
Substitute: reqAttr.Substitute,
})
th.attributes = make(map[string]map[interface{}]*Attribute)
th.attributes[reqAttr.FieldName] = make(map[interface{}]*Attribute)
th.attributes[reqAttr.FieldName][reqAttr.Initial] = &Attribute{
FieldName: reqAttr.FieldName,
Initial: reqAttr.Initial,
Substitute: reqAttr.Substitute,

View File

@@ -1175,9 +1175,9 @@ func TestAPItoAttributeProfile(t *testing.T) {
},
Weight: 20,
}
attrMap := make(map[string]map[string]*Attribute)
attrMap["FL1"] = make(map[string]*Attribute)
attrMap["FL1"]["In1"] = &Attribute{
mapSubstitutes := make(map[string]map[interface{}]*Attribute)
mapSubstitutes["FL1"] = make(map[interface{}]*Attribute)
mapSubstitutes["FL1"]["In1"] = &Attribute{
FieldName: "FL1",
Initial: "In1",
Substitute: "Al1",
@@ -1191,8 +1191,16 @@ func TestAPItoAttributeProfile(t *testing.T) {
ActivationInterval: &utils.ActivationInterval{
ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC),
},
Attributes: attrMap,
Attributes: []*Attribute{
&Attribute{
FieldName: "FL1",
Initial: "In1",
Substitute: "Al1",
Append: true,
},
},
Weight: 20,
attributes: mapSubstitutes,
}
if rcv, err := APItoAttributeProfile(tpAlsPrf, "UTC"); err != nil {
t.Error(err)

View File

@@ -86,6 +86,8 @@ var sTestsOnStorIT = []func(t *testing.T){
testOnStorITTestThresholdFilterIndexes,
testOnStorITTestAttributeProfileFilterIndexes,
testOnStorITTestThresholdInlineFilterIndexing,
testOnStorITFlush,
testOnStorITTestAttributeSubstituteIface,
//testOnStorITCacheActionTriggers,
//testOnStorITCacheAlias,
//testOnStorITCacheReverseAlias,
@@ -113,7 +115,7 @@ func TestOnStorITRedis(t *testing.T) {
}
func TestOnStorITMongoConnect(t *testing.T) {
sleepDelay = 500 * time.Millisecond
sleepDelay = 50 * time.Millisecond
cdrsMongoCfgPath := path.Join(*dataDir, "conf", "samples", "cdrsv2mongo")
mgoITCfg, err := config.NewCGRConfigFromFolder(cdrsMongoCfgPath)
if err != nil {
@@ -761,10 +763,10 @@ func testOnStorITRatingPlan(t *testing.T) {
StartTime: "00:00:00",
},
}
time.Sleep(sleepDelay)
if err := onStor.SetRatingPlan(rp, utils.NonTransactional); err != nil {
t.Error(err)
}
time.Sleep(sleepDelay)
//get from cache
if rcv, err := onStor.GetRatingPlan(rp.Id, false, utils.NonTransactional); err != nil {
t.Error(err)
@@ -839,10 +841,10 @@ func testOnStorITRatingProfile(t *testing.T) {
CdrStatQueueIds: []string{},
},
}
time.Sleep(sleepDelay)
if err := onStor.SetRatingProfile(rpf, utils.NonTransactional); err != nil {
t.Error(err)
}
time.Sleep(sleepDelay)
//get from cache
if rcv, err := onStor.GetRatingProfile(rpf.Id, false,
utils.NonTransactional); err != nil {
@@ -1232,11 +1234,11 @@ func testOnStorITActions(t *testing.T) {
},
},
}
time.Sleep(sleepDelay)
if err := onStor.SetActions(acts[0].Id,
acts, utils.NonTransactional); err != nil {
t.Error(err)
}
time.Sleep(sleepDelay)
//get from cache
if rcv, err := onStor.GetActions(acts[0].Id,
false, utils.NonTransactional); err != nil {
@@ -1801,10 +1803,10 @@ func testOnStorITResourceProfile(t *testing.T) {
}
//update
rL.Thresholds = []string{"TH1", "TH2"}
time.Sleep(sleepDelay)
if err := onStor.SetResourceProfile(rL, false); err != nil {
t.Error(err)
}
time.Sleep(sleepDelay)
//get from cache
if rcv, err := onStor.GetResourceProfile(rL.Tenant, rL.ID,
false, utils.NonTransactional); err != nil {
@@ -1877,10 +1879,10 @@ func testOnStorITResource(t *testing.T) {
}
//update
res.TTLIdx = []string{"RU1", "RU2"}
time.Sleep(sleepDelay)
if err := onStor.SetResource(res); err != nil {
t.Error(err)
}
time.Sleep(sleepDelay)
//get from cache
if rcv, err := onStor.GetResource("cgrates.org", "RL1",
false, utils.NonTransactional); err != nil {
@@ -1947,10 +1949,10 @@ func testOnStorITTiming(t *testing.T) {
}
//update
tmg.MonthDays = utils.MonthDays{1, 2, 3, 4, 5, 6, 7}
time.Sleep(sleepDelay)
if err := onStor.SetTiming(tmg); err != nil {
t.Error(err)
}
time.Sleep(sleepDelay)
//get from cache
if rcv, err := onStor.GetTiming(tmg.ID, false, utils.NonTransactional); err != nil {
t.Error(err)
@@ -2054,10 +2056,10 @@ func testOnStorITStatQueueProfile(t *testing.T) {
}
//update
sq.Thresholds = []string{"TH1", "TH2"}
time.Sleep(sleepDelay)
if err := onStor.SetStatQueueProfile(sq, false); err != nil {
t.Error(err)
}
time.Sleep(sleepDelay)
//get from cache
if rcv, err := onStor.GetStatQueueProfile(sq.Tenant,
sq.ID, false, utils.NonTransactional); err != nil {
@@ -2150,10 +2152,10 @@ func testOnStorITStatQueue(t *testing.T) {
},
},
}
time.Sleep(sleepDelay)
if err := onStor.SetStatQueue(sq); err != nil {
t.Error(err)
}
time.Sleep(sleepDelay)
//get from cache
if rcv, err := onStor.GetStatQueue(sq.Tenant,
sq.ID, false, utils.NonTransactional); err != nil {
@@ -2243,10 +2245,10 @@ func testOnStorITThresholdProfile(t *testing.T) {
}
//update
th.ActionIDs = []string{"Action1", "Action2"}
time.Sleep(sleepDelay)
if err := onStor.SetThresholdProfile(th, true); err != nil {
t.Error(err)
}
time.Sleep(sleepDelay)
//get from cache
if rcv, err := onStor.GetThresholdProfile(th.Tenant, th.ID,
false, utils.NonTransactional); err != nil {
@@ -2313,10 +2315,10 @@ func testOnStorITThreshold(t *testing.T) {
}
//update
th.Hits = 20
time.Sleep(sleepDelay)
if err := onStor.SetThreshold(th); err != nil {
t.Error(err)
}
time.Sleep(sleepDelay)
//get from cache
if rcv, err := onStor.GetThreshold("cgrates.org", "TH1",
false, utils.NonTransactional); err != nil {
@@ -2402,10 +2404,10 @@ func testOnStorITFilter(t *testing.T) {
Values: []string{"10", "20"},
},
}
time.Sleep(sleepDelay)
if err := onStor.SetFilter(fp); err != nil {
t.Error(err)
}
time.Sleep(sleepDelay)
//get from cache
if rcv, err := onStor.GetFilter("cgrates.org", "Filter1",
false, utils.NonTransactional); err != nil {
@@ -2509,10 +2511,10 @@ func testOnStorITSupplierProfile(t *testing.T) {
SupplierParameters: "param2",
},
}
time.Sleep(sleepDelay)
if err := onStor.SetSupplierProfile(splProfile, false); err != nil {
t.Error(err)
}
time.Sleep(sleepDelay)
//get from cache
if rcv, err := onStor.GetSupplierProfile("cgrates.org", "SPRF_1",
false, utils.NonTransactional); err != nil {
@@ -2544,8 +2546,8 @@ func testOnStorITSupplierProfile(t *testing.T) {
}
func testOnStorITAttributeProfile(t *testing.T) {
mapSubstitutes := make(map[string]map[string]*Attribute)
mapSubstitutes["FN1"] = make(map[string]*Attribute)
mapSubstitutes := make(map[string]map[interface{}]*Attribute)
mapSubstitutes["FN1"] = make(map[interface{}]*Attribute)
mapSubstitutes["FN1"]["Init1"] = &Attribute{
FieldName: "FN1",
Initial: "Init1",
@@ -2559,9 +2561,17 @@ func testOnStorITAttributeProfile(t *testing.T) {
ActivationInterval: &utils.ActivationInterval{
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
},
Contexts: []string{"con1"},
Attributes: mapSubstitutes,
Contexts: []string{"con1"},
Attributes: []*Attribute{
&Attribute{
FieldName: "FN1",
Initial: "Init1",
Substitute: "Val1",
Append: true,
},
},
Weight: 20,
attributes: mapSubstitutes,
}
if _, rcvErr := onStor.GetAttributeProfile("cgrates.org", "AttrPrf1",
false, utils.NonTransactional); rcvErr != nil && rcvErr != utils.ErrNotFound {
@@ -2591,11 +2601,11 @@ func testOnStorITAttributeProfile(t *testing.T) {
t.Errorf("Expected : %+v, but received %+v", expectedT, itm)
}
//update
time.Sleep(sleepDelay)
attrProfile.Contexts = []string{"con1", "con2", "con3"}
if err := onStor.SetAttributeProfile(attrProfile, false); err != nil {
t.Error(err)
}
time.Sleep(sleepDelay)
//get from cache
if rcv, err := onStor.GetAttributeProfile("cgrates.org", "AttrPrf1",
false, utils.NonTransactional); err != nil {
@@ -2892,14 +2902,6 @@ func testOnStorITTestAttributeProfileFilterIndexes(t *testing.T) {
if err := onStor.SetFilter(fp); err != nil {
t.Error(err)
}
mapSubstitutes := make(map[string]map[string]*Attribute)
mapSubstitutes["FN1"] = make(map[string]*Attribute)
mapSubstitutes["FN1"]["Init1"] = &Attribute{
FieldName: "FN1",
Initial: "Init1",
Substitute: "Val1",
Append: true,
}
attrProfile := &AttributeProfile{
Tenant: "cgrates.org",
ID: "AttrPrf",
@@ -2907,9 +2909,16 @@ func testOnStorITTestAttributeProfileFilterIndexes(t *testing.T) {
ActivationInterval: &utils.ActivationInterval{
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
},
Contexts: []string{"con1", "con2"},
Attributes: mapSubstitutes,
Weight: 20,
Contexts: []string{"con1", "con2"},
Attributes: []*Attribute{
&Attribute{
FieldName: "FN1",
Initial: "Init1",
Substitute: "Val1",
Append: true,
},
},
Weight: 20,
}
//Set AttributeProfile with 2 contexts ( con1 , con2)
if err := onStor.SetAttributeProfile(attrProfile, true); err != nil {
@@ -3137,3 +3146,121 @@ func testOnStorITTestThresholdInlineFilterIndexing(t *testing.T) {
t.Error(err)
}
}
func testOnStorITTestAttributeSubstituteIface(t *testing.T) {
//set Substitue with type string
mapSubstitutes := make(map[string]map[interface{}]*Attribute)
mapSubstitutes["FN1"] = make(map[interface{}]*Attribute)
mapSubstitutes["FN1"]["Init1"] = &Attribute{
FieldName: "FN1",
Initial: "Init1",
Substitute: "Val1",
Append: true,
}
attrProfile := &AttributeProfile{
Tenant: "cgrates.org",
ID: "AttrPrf1",
FilterIDs: []string{"FLTR_ACNT_dan", "FLTR_DST_DE"},
ActivationInterval: &utils.ActivationInterval{
ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC),
},
Contexts: []string{"con1"},
Attributes: []*Attribute{
&Attribute{
FieldName: "FN1",
Initial: "Init1",
Substitute: "Val1",
Append: true,
},
},
Weight: 20,
attributes: mapSubstitutes,
}
if _, rcvErr := onStor.GetAttributeProfile("cgrates.org", "AttrPrf1",
false, utils.NonTransactional); rcvErr != nil && rcvErr != utils.ErrNotFound {
t.Error(rcvErr)
}
if err := onStor.SetAttributeProfile(attrProfile, false); err != nil {
t.Error(err)
}
//check cache
if rcv, err := onStor.GetAttributeProfile("cgrates.org", "AttrPrf1",
false, utils.NonTransactional); err != nil {
t.Error(err)
} else if !(reflect.DeepEqual(attrProfile, rcv)) {
t.Errorf("Expecting: %v, received: %v", attrProfile, rcv)
}
//check database
if rcv, err := onStor.GetAttributeProfile("cgrates.org", "AttrPrf1",
true, utils.NonTransactional); err != nil {
t.Error(err)
} else if !(reflect.DeepEqual(attrProfile, rcv)) {
t.Errorf("Expecting: %v, received: %v", attrProfile, rcv)
}
//set Substitue with type float
mapSubstitutes["FN1"]["Init1"] = &Attribute{
FieldName: "FN1",
Initial: "Init1",
Substitute: 123.5,
Append: true,
}
attrProfile.Attributes = []*Attribute{
&Attribute{
FieldName: "FN1",
Initial: "Init1",
Substitute: 123.5,
Append: true,
},
}
if err := onStor.SetAttributeProfile(attrProfile, false); err != nil {
t.Error(err)
}
attrProfile.attributes = mapSubstitutes
//check cache
if rcv, err := onStor.GetAttributeProfile("cgrates.org", "AttrPrf1",
false, utils.NonTransactional); err != nil {
t.Error(err)
} else if !(reflect.DeepEqual(attrProfile, rcv)) {
t.Errorf("Expecting: %v, received: %v", utils.ToJSON(attrProfile), utils.ToJSON(rcv))
}
//check database
if rcv, err := onStor.GetAttributeProfile("cgrates.org", "AttrPrf1",
true, utils.NonTransactional); err != nil {
t.Error(err)
} else if !(reflect.DeepEqual(attrProfile, rcv)) {
t.Errorf("Expecting: %v, received: %v", utils.ToJSON(attrProfile), utils.ToJSON(rcv))
}
//set Substitue with type bool
mapSubstitutes["FN1"]["Init1"] = &Attribute{
FieldName: "FN1",
Initial: "Init1",
Substitute: true,
Append: true,
}
attrProfile.Attributes = []*Attribute{
&Attribute{
FieldName: "FN1",
Initial: "Init1",
Substitute: true,
Append: true,
},
}
if err := onStor.SetAttributeProfile(attrProfile, false); err != nil {
t.Error(err)
}
attrProfile.attributes = mapSubstitutes
//check cache
if rcv, err := onStor.GetAttributeProfile("cgrates.org", "AttrPrf1",
false, utils.NonTransactional); err != nil {
t.Error(err)
} else if !(reflect.DeepEqual(attrProfile, rcv)) {
t.Errorf("Expecting: %v, received: %v", utils.ToJSON(attrProfile), utils.ToJSON(rcv))
}
//check database
if rcv, err := onStor.GetAttributeProfile("cgrates.org", "AttrPrf1",
true, utils.NonTransactional); err != nil {
t.Error(err)
} else if !(reflect.DeepEqual(attrProfile, rcv)) {
t.Errorf("Expecting: %v, received: %v", utils.ToJSON(attrProfile), utils.ToJSON(rcv))
}
}