From 0d318cc8b946fd2f07d690dbe66e12f9de8a662c Mon Sep 17 00:00:00 2001 From: TeoV Date: Fri, 13 Jul 2018 07:21:29 -0400 Subject: [PATCH] Update test in apier/v1 and model_helpers in engine --- apier/v1/filterindexecache_it_test.go | 38 +++--- apier/v1/resourcesv1_it_test.go | 49 +------- apier/v1/thresholds_it_test.go | 48 +------- engine/loader_csv_test.go | 25 +++- engine/model_helpers.go | 162 ++++++++++++++++++++------ engine/model_helpers_test.go | 51 ++++++-- loaders/loader_test.go | 4 +- 7 files changed, 210 insertions(+), 167 deletions(-) diff --git a/apier/v1/filterindexecache_it_test.go b/apier/v1/filterindexecache_it_test.go index 9436485c1..43cd2b5b0 100644 --- a/apier/v1/filterindexecache_it_test.go +++ b/apier/v1/filterindexecache_it_test.go @@ -287,7 +287,6 @@ func testV1FIdxCaGetThresholdFromTP(t *testing.T) { //test to make sure indexes are made as expected idx := map[string]utils.StringMap{ "THD_ACNT_BALANCE_1": { - "*default:*any:*any": true, "*string:Account:1001": true, "*string:Account:1002": true, "*string:EventType:BalanceUpdate": true}} @@ -358,10 +357,9 @@ func testV1FIdxCaUpdateThresholdProfile(t *testing.T) { var thIDs []string eIDs := []string{} //Testing ProcessEvent on set thresholdprofile after update making sure there are no hits - if err := tFIdxCaRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &thIDs); err != nil { + if err := tFIdxCaRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &thIDs); err == nil || + err.Error() != utils.ErrNotFound.Error() { t.Error(err) - } else if !reflect.DeepEqual(thIDs, eIDs) { - t.Errorf("Expecting : %+v, received: %+v", eIDs, thIDs) } //matches thresholdprofile after update tEv2 := &engine.ArgsProcessEvent{ @@ -428,7 +426,6 @@ func testV1FIdxCaUpdateThresholdProfileFromTP(t *testing.T) { } time.Sleep(100 * time.Millisecond) reply.FilterIDs = []string{"TestFilter3"} - reply.ActivationInterval = &utils.ActivationInterval{ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC)} if err := tFIdxCaRpc.Call("ApierV1.SetThresholdProfile", reply, &result); err != nil { t.Error(err) @@ -444,12 +441,10 @@ func testV1FIdxCaUpdateThresholdProfileFromTP(t *testing.T) { utils.Account: "1002", utils.EventType: utils.BalanceUpdate}}} var thIDs []string - eIDs := []string{} //Testing ProcessEvent on set thresholdprofile using apier - if err := tFIdxCaRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &thIDs); err != nil { + if err := tFIdxCaRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &thIDs); err == nil || + err.Error() != utils.ErrNotFound.Error() { t.Error(err) - } else if !reflect.DeepEqual(thIDs, eIDs) { - t.Errorf("Expecting : %s, received: %s", eIDs, thIDs) } tEv2 := &engine.ArgsProcessEvent{ CGREvent: utils.CGREvent{ @@ -458,7 +453,7 @@ func testV1FIdxCaUpdateThresholdProfileFromTP(t *testing.T) { Event: map[string]interface{}{ utils.Account: "1003", utils.EventType: utils.BalanceUpdate}}} - eIDs = []string{"THD_ACNT_BALANCE_1"} + eIDs := []string{"THD_ACNT_BALANCE_1"} //Testing ProcessEvent on set thresholdprofile using apier if err := tFIdxCaRpc.Call(utils.ThresholdSv1ProcessEvent, tEv2, &thIDs); err != nil { t.Error(err) @@ -537,16 +532,13 @@ func testV1FIdxCaRemoveThresholdProfile(t *testing.T) { err.Error() != utils.ErrNotFound.Error() { t.Error(err) } - eIDs = []string{} - if err := tFIdxCaRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &thIDs); err != nil { + if err := tFIdxCaRpc.Call(utils.ThresholdSv1ProcessEvent, tEv, &thIDs); err == nil || + err.Error() != utils.ErrNotFound.Error() { t.Error(err) - } else if !reflect.DeepEqual(thIDs, eIDs) { - t.Errorf("Expecting : %s, received: %s", eIDs, thIDs) } - if err := tFIdxCaRpc.Call(utils.ThresholdSv1ProcessEvent, tEv2, &thIDs); err != nil { + if err := tFIdxCaRpc.Call(utils.ThresholdSv1ProcessEvent, tEv2, &thIDs); err == nil || + err.Error() != utils.ErrNotFound.Error() { t.Error(err) - } else if !reflect.DeepEqual(thIDs, eIDs) { - t.Errorf("Expecting : %s, received: %s", eIDs, thIDs) } //test to make sure indexes are made as expected fldNameVal2 := map[string]string{"THD_ACNT_BALANCE_1": "", "TEST_PROFILE1": ""} @@ -744,7 +736,7 @@ func testV1FIdxCaUpdateStatQueueProfile(t *testing.T) { &engine.FilterRule{ FieldName: utils.Account, Type: "*string", - Values: []string{"1002"}, + Values: []string{"1003"}, }, &engine.FilterRule{ FieldName: utils.EventType, @@ -789,13 +781,13 @@ func testV1FIdxCaUpdateStatQueueProfile(t *testing.T) { t.Error("Unexpected reply returned", result) } var reply []string - expected := []string{"Stats1"} + expected := []string{"TEST_PROFILE1"} tEv := &utils.CGREvent{ Tenant: "cgrates.org", ID: "event1", Event: map[string]interface{}{ utils.EventType: utils.BalanceUpdate, - utils.Account: "1002", + utils.Account: "1003", }} if err := tFIdxCaRpc.Call(utils.StatSv1ProcessEvent, tEv, &reply); err != nil { t.Error(err) @@ -805,7 +797,7 @@ func testV1FIdxCaUpdateStatQueueProfile(t *testing.T) { fldNameVal := map[string]string{"TEST_PROFILE1": ""} expectedRevIDX := map[string]utils.StringMap{ - "TEST_PROFILE1": {"*string:Account:1002": true, + "TEST_PROFILE1": {"*string:Account:1003": true, "*string:EventType:BalanceUpdate": true}} if indexes, err = onStor.GetFilterReverseIndexes( utils.PrefixToRevIndexCache[utils.StatQueueProfilePrefix], "cgrates.org", @@ -895,7 +887,7 @@ func testV1FIdxCaRemoveStatQueueProfile(t *testing.T) { ID: "event1", Event: map[string]interface{}{ utils.EventType: utils.BalanceUpdate, - utils.Account: "1002", + utils.Account: "1003", }} if err := tFIdxCaRpc.Call(utils.StatSv1ProcessEvent, tEv, &reply); err != nil { t.Error(err) @@ -1488,7 +1480,7 @@ func testV1FIdxCaGetResourceProfileFromTP(t *testing.T) { t.Error("Unexpected reply returned", reply) } idx := map[string]utils.StringMap{ - "ResGroup1": {"*default:*any:*any": true, + "ResGroup1": { "*prefix:Destination:10": true, "*prefix:Destination:20": true, "*string:Account:1001": true, diff --git a/apier/v1/resourcesv1_it_test.go b/apier/v1/resourcesv1_it_test.go index 895e9d0af..8eecdbdbb 100644 --- a/apier/v1/resourcesv1_it_test.go +++ b/apier/v1/resourcesv1_it_test.go @@ -582,8 +582,8 @@ func testV1RsGetResourceProfileBeforeSet(t *testing.T) { func testV1RsSetResourceProfile(t *testing.T) { rlsConfig = &engine.ResourceProfile{ Tenant: "cgrates.org", - ID: "RCFG1", - FilterIDs: []string{"FLTR_RES_RCFG1"}, + ID: "RES_GR_TEST", + FilterIDs: []string{"*string:Account:1001"}, ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), @@ -594,29 +594,10 @@ func testV1RsSetResourceProfile(t *testing.T) { Blocker: true, Stored: true, Weight: 20, - ThresholdIDs: []string{"Val1", "Val2"}, - } - filter = &engine.Filter{ - Tenant: "cgrates.org", - ID: "FLTR_RES_RCFG1", - Rules: []*engine.FilterRule{ - &engine.FilterRule{ - FieldName: "*string", - Type: "Account", - Values: []string{"dan"}, - }, - }, - ActivationInterval: &utils.ActivationInterval{ - ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - }, + ThresholdIDs: []string{"Val1"}, } var result string - if err := rlsV1Rpc.Call("ApierV1.SetFilter", filter, &result); err != nil { - t.Error(err) - } else if result != utils.OK { - t.Error("Unexpected reply returned", result) - } + if err := rlsV1Rpc.Call("ApierV1.SetResourceProfile", rlsConfig, &result); err != nil { t.Error(err) } else if result != utils.OK { @@ -636,27 +617,7 @@ func testV1RsGetResourceProfileAfterSet(t *testing.T) { func testV1RsUpdateResourceProfile(t *testing.T) { var result string - rlsConfig.FilterIDs = []string{"FLTR_RES_RCFG1", "FLTR_RES_RCFG2"} - filter = &engine.Filter{ - Tenant: "cgrates.org", - ID: "FLTR_RES_RCFG2", - Rules: []*engine.FilterRule{ - &engine.FilterRule{ - FieldName: "*string", - Type: "Account", - Values: []string{"1001", "1002"}, - }, - }, - ActivationInterval: &utils.ActivationInterval{ - ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - }, - } - if err := rlsV1Rpc.Call("ApierV1.SetFilter", filter, &result); err != nil { - t.Error(err) - } else if result != utils.OK { - t.Error("Unexpected reply returned", result) - } + rlsConfig.FilterIDs = []string{"*string:Account:1001", "*prefix:DST:10"} if err := rlsV1Rpc.Call("ApierV1.SetResourceProfile", rlsConfig, &result); err != nil { t.Error(err) } else if result != utils.OK { diff --git a/apier/v1/thresholds_it_test.go b/apier/v1/thresholds_it_test.go index 0c38401bc..60e9b5755 100644 --- a/apier/v1/thresholds_it_test.go +++ b/apier/v1/thresholds_it_test.go @@ -346,28 +346,7 @@ func testV1TSGetThresholdsAfterRestart(t *testing.T) { func testV1TSSetThresholdProfile(t *testing.T) { var reply *engine.ThresholdProfile - filter = &engine.Filter{ - Tenant: "cgrates.org", - ID: "TestFilter", - Rules: []*engine.FilterRule{ - &engine.FilterRule{ - FieldName: "*string", - Type: "Account", - Values: []string{"1001", "1002"}, - }, - }, - ActivationInterval: &utils.ActivationInterval{ - ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - }, - } - var result string - if err := tSv1Rpc.Call("ApierV1.SetFilter", filter, &result); err != nil { - t.Error(err) - } else if result != utils.OK { - t.Error("Unexpected reply returned", result) - } if err := tSv1Rpc.Call("ApierV1.GetThresholdProfile", &utils.TenantID{Tenant: "cgrates.org", ID: "THD_Test"}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() { @@ -376,7 +355,7 @@ func testV1TSSetThresholdProfile(t *testing.T) { tPrfl = &engine.ThresholdProfile{ Tenant: "cgrates.org", ID: "THD_Test", - FilterIDs: []string{"TestFilter"}, + FilterIDs: []string{"*string:Account:1001"}, 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), @@ -385,7 +364,7 @@ func testV1TSSetThresholdProfile(t *testing.T) { MinSleep: time.Duration(5 * time.Minute), Blocker: false, Weight: 20.0, - ActionIDs: []string{"ACT_1", "ACT_2"}, + ActionIDs: []string{"ACT_1"}, Async: true, } if err := tSv1Rpc.Call("ApierV1.SetThresholdProfile", tPrfl, &result); err != nil { @@ -403,28 +382,7 @@ func testV1TSSetThresholdProfile(t *testing.T) { func testV1TSUpdateThresholdProfile(t *testing.T) { var result string - filter = &engine.Filter{ - Tenant: "cgrates.org", - ID: "TestFilter2", - Rules: []*engine.FilterRule{ - &engine.FilterRule{ - FieldName: "*prefix", - Type: "Destination", - Values: []string{"10", "20"}, - }, - }, - ActivationInterval: &utils.ActivationInterval{ - ActivationTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - ExpiryTime: time.Date(2014, 7, 14, 14, 25, 0, 0, time.UTC), - }, - } - - if err := tSv1Rpc.Call("ApierV1.SetFilter", filter, &result); err != nil { - t.Error(err) - } else if result != utils.OK { - t.Error("Unexpected reply returned", result) - } - tPrfl.FilterIDs = []string{"TestFilter", "TestFilter2"} + tPrfl.FilterIDs = []string{"*string:Account:1001", "*prefix:DST:10"} if err := tSv1Rpc.Call("ApierV1.SetThresholdProfile", tPrfl, &result); err != nil { t.Error(err) } else if result != utils.OK { diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 98e8e8ca7..6c3f31397 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -279,7 +279,7 @@ cgrates.org,TestStats2,,,,,*sum;*average,Cost,true,true,20,2, thresholds = ` #Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],MaxHits[4],MinHits[5],MinSleep[6],Blocker[7],Weight[8],ActionIDs[9],Async[10] -cgrates.org,Threshold1,FLTR_1;FLTR_ACNT_dan,2014-07-29T15:00:00Z,12,10,1s,true,10,THRESH1;THRESH2,true +cgrates.org,Threshold1,FLTR_1;FLTR_ACNT_dan,2014-07-29T15:00:00Z,12,10,1s,true,10,THRESH1,true ` filters = ` @@ -1597,14 +1597,31 @@ func TestLoadThresholdProfiles(t *testing.T) { MinSleep: "1s", Blocker: true, Weight: 10, - ActionIDs: []string{"THRESH1", "THRESH2"}, + ActionIDs: []string{"THRESH1"}, Async: true, }, } + revTH := &utils.TPThreshold{ + TPid: testTPID, + Tenant: "cgrates.org", + ID: "Threshold1", + FilterIDs: []string{"FLTR_1", "FLTR_ACNT_dan"}, + ActivationInterval: &utils.TPActivationInterval{ + ActivationTime: "2014-07-29T15:00:00Z", + }, + MaxHits: 12, + MinHits: 10, + MinSleep: "1s", + Blocker: true, + Weight: 10, + ActionIDs: []string{"THRESH1"}, + Async: true, + } thkey := utils.TenantID{Tenant: "cgrates.org", ID: "Threshold1"} if len(csvr.thProfiles) != len(eThresholds) { t.Errorf("Failed to load ThresholdProfiles: %s", utils.ToIJSON(csvr.thProfiles)) - } else if !reflect.DeepEqual(eThresholds[thkey], csvr.thProfiles[thkey]) { + } else if !reflect.DeepEqual(eThresholds[thkey], csvr.thProfiles[thkey]) && + !reflect.DeepEqual(revTH, csvr.thProfiles[thkey]) { t.Errorf("Expecting: %+v, received: %+v", eThresholds[thkey], csvr.thProfiles[thkey]) } } @@ -1761,7 +1778,7 @@ func TestLoadAttributeProfiles(t *testing.T) { t.Errorf("Expecting: %+v, received: %+v", eAttrProfiles[resKey].Tenant, csvr.attributeProfiles[resKey].Tenant) } else if !reflect.DeepEqual(eAttrProfiles[resKey].ID, csvr.attributeProfiles[resKey].ID) { t.Errorf("Expecting: %+v, received: %+v", eAttrProfiles[resKey].ID, csvr.attributeProfiles[resKey].ID) - } else if !reflect.DeepEqual(eAttrProfiles[resKey].Contexts, csvr.attributeProfiles[resKey].Contexts) { + } else if len(eAttrProfiles[resKey].Contexts) != len(csvr.attributeProfiles[resKey].Contexts) { t.Errorf("Expecting: %+v, received: %+v", eAttrProfiles[resKey].Contexts, csvr.attributeProfiles[resKey].Contexts) } else if !reflect.DeepEqual(eAttrProfiles[resKey].FilterIDs, csvr.attributeProfiles[resKey].FilterIDs) { t.Errorf("Expecting: %+v, received: %+v", eAttrProfiles[resKey].FilterIDs, csvr.attributeProfiles[resKey].FilterIDs) diff --git a/engine/model_helpers.go b/engine/model_helpers.go index e22d2f408..e1fc90d57 100644 --- a/engine/model_helpers.go +++ b/engine/model_helpers.go @@ -1821,6 +1821,8 @@ type TpResources []*TpResource func (tps TpResources) AsTPResources() (result []*utils.TPResource) { mrl := make(map[string]*utils.TPResource) + filterMap := make(map[string]utils.StringMap) + thresholdMap := make(map[string]utils.StringMap) for _, tp := range tps { rl, found := mrl[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] if !found { @@ -1857,19 +1859,41 @@ func (tps TpResources) AsTPResources() (result []*utils.TPResource) { } } if tp.ThresholdIDs != "" { + if _, has := thresholdMap[(&utils.TenantID{Tenant: tp.Tenant, + ID: tp.ID}).TenantID()]; !has { + thresholdMap[(&utils.TenantID{Tenant: tp.Tenant, + ID: tp.ID}).TenantID()] = make(utils.StringMap) + } trshSplt := strings.Split(tp.ThresholdIDs, utils.INFIELD_SEP) - rl.ThresholdIDs = append(rl.ThresholdIDs, trshSplt...) + for _, trsh := range trshSplt { + thresholdMap[(&utils.TenantID{Tenant: tp.Tenant, + ID: tp.ID}).TenantID()][trsh] = true + } } if tp.FilterIDs != "" { - trshSplt := strings.Split(tp.FilterIDs, utils.INFIELD_SEP) - rl.FilterIDs = append(rl.FilterIDs, trshSplt...) + if _, has := filterMap[(&utils.TenantID{Tenant: tp.Tenant, + ID: tp.ID}).TenantID()]; !has { + filterMap[(&utils.TenantID{Tenant: tp.Tenant, + ID: tp.ID}).TenantID()] = make(utils.StringMap) + } + filterSplit := strings.Split(tp.FilterIDs, utils.INFIELD_SEP) + for _, filter := range filterSplit { + filterMap[(&utils.TenantID{Tenant: tp.Tenant, + ID: tp.ID}).TenantID()][filter] = true + } } mrl[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = rl } result = make([]*utils.TPResource, len(mrl)) i := 0 - for _, rl := range mrl { + for tntID, rl := range mrl { result[i] = rl + for filter := range filterMap[tntID] { + result[i].FilterIDs = append(result[i].FilterIDs, filter) + } + for threshold := range thresholdMap[tntID] { + result[i].ThresholdIDs = append(result[i].ThresholdIDs, threshold) + } i++ } return @@ -1949,9 +1973,9 @@ type TpStatsS []*TpStats //to be modify func (tps TpStatsS) AsTPStats() (result []*utils.TPStats) { - filtermap := make(map[string]map[string]bool) + filterMap := make(map[string]utils.StringMap) metricmap := make(map[string]map[string]*utils.MetricWithParams) - thresholdmap := make(map[string]map[string]bool) + thresholdMap := make(map[string]utils.StringMap) mst := make(map[string]*utils.TPStats) for _, tp := range tps { st, found := mst[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] @@ -1999,14 +2023,14 @@ func (tps TpStatsS) AsTPStats() (result []*utils.TPStats) { } } if tp.ThresholdIDs != "" { - if _, has := thresholdmap[(&utils.TenantID{Tenant: tp.Tenant, + if _, has := thresholdMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()]; !has { - thresholdmap[(&utils.TenantID{Tenant: tp.Tenant, - ID: tp.ID}).TenantID()] = make(map[string]bool) + thresholdMap[(&utils.TenantID{Tenant: tp.Tenant, + ID: tp.ID}).TenantID()] = make(utils.StringMap) } trshSplt := strings.Split(tp.ThresholdIDs, utils.INFIELD_SEP) for _, trsh := range trshSplt { - thresholdmap[(&utils.TenantID{Tenant: tp.Tenant, + thresholdMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()][trsh] = true } } @@ -2024,32 +2048,34 @@ func (tps TpStatsS) AsTPStats() (result []*utils.TPStats) { } } if tp.FilterIDs != "" { - if _, has := filtermap[(&utils.TenantID{Tenant: tp.Tenant, + if _, has := filterMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()]; !has { - filtermap[(&utils.TenantID{Tenant: tp.Tenant, - ID: tp.ID}).TenantID()] = make(map[string]bool) + filterMap[(&utils.TenantID{Tenant: tp.Tenant, + ID: tp.ID}).TenantID()] = make(utils.StringMap) } filterSplit := strings.Split(tp.FilterIDs, utils.INFIELD_SEP) for _, filter := range filterSplit { - filtermap[(&utils.TenantID{Tenant: tp.Tenant, + filterMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()][filter] = true } } mst[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = st } + result = make([]*utils.TPStats, len(mst)) + i := 0 for tntID, st := range mst { - for filterdata, _ := range filtermap[tntID] { - st.FilterIDs = append(st.FilterIDs, filterdata) + result[i] = st + for filter := range filterMap[tntID] { + result[i].FilterIDs = append(result[i].FilterIDs, filter) } - - for trsh, _ := range thresholdmap[tntID] { - st.ThresholdIDs = append(st.ThresholdIDs, trsh) + for threshold := range thresholdMap[tntID] { + result[i].ThresholdIDs = append(result[i].ThresholdIDs, threshold) } - for metricdata, _ := range metricmap[tntID] { - st.Metrics = append(st.Metrics, metricmap[tntID][metricdata]) + for metricdata := range metricmap[tntID] { + result[i].Metrics = append(result[i].Metrics, metricmap[tntID][metricdata]) } - result = append(result, st) + i++ } return } @@ -2145,6 +2171,8 @@ type TpThresholdS []*TpThreshold func (tps TpThresholdS) AsTPThreshold() (result []*utils.TPThreshold) { mst := make(map[string]*utils.TPThreshold) + filterMap := make(map[string]utils.StringMap) + actionMap := make(map[string]utils.StringMap) for _, tp := range tps { th, found := mst[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] if !found { @@ -2160,8 +2188,13 @@ func (tps TpThresholdS) AsTPThreshold() (result []*utils.TPThreshold) { } } if tp.ActionIDs != "" { + if _, has := actionMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()]; !has { + actionMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = make(utils.StringMap) + } actionSplit := strings.Split(tp.ActionIDs, utils.INFIELD_SEP) - th.ActionIDs = append(th.ActionIDs, actionSplit...) + for _, action := range actionSplit { + actionMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()][action] = true + } } if tp.Weight != 0 { th.Weight = tp.Weight @@ -2177,16 +2210,27 @@ func (tps TpThresholdS) AsTPThreshold() (result []*utils.TPThreshold) { } } if tp.FilterIDs != "" { + if _, has := filterMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()]; !has { + filterMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = make(utils.StringMap) + } filterSplit := strings.Split(tp.FilterIDs, utils.INFIELD_SEP) - th.FilterIDs = append(th.FilterIDs, filterSplit...) + for _, filter := range filterSplit { + filterMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()][filter] = true + } } mst[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = th } result = make([]*utils.TPThreshold, len(mst)) i := 0 - for _, th := range mst { + for tntID, th := range mst { result[i] = th + for filter := range filterMap[tntID] { + result[i].FilterIDs = append(result[i].FilterIDs, filter) + } + for action := range actionMap[tntID] { + result[i].ActionIDs = append(result[i].ActionIDs, action) + } i++ } return @@ -2420,9 +2464,10 @@ func FilterToTPFilter(f *Filter) (tpFltr *utils.TPFilterProfile) { type TpSuppliers []*TpSupplier func (tps TpSuppliers) AsTPSuppliers() (result []*utils.TPSupplierProfile) { - filtermap := make(map[string]map[string]bool) + filtermap := make(map[string]utils.StringMap) mst := make(map[string]*utils.TPSupplierProfile) suppliersMap := make(map[string]map[string]*utils.TPSupplier) + sortingParameterMap := make(map[string]utils.StringMap) for _, tp := range tps { th, found := mst[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] if !found { @@ -2472,8 +2517,13 @@ func (tps TpSuppliers) AsTPSuppliers() (result []*utils.TPSupplierProfile) { suppliersMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()][tp.SupplierID] = sup } if tp.SortingParameters != "" { - sortingParameterSplit := strings.Split(tp.SortingParameters, utils.INFIELD_SEP) - th.SortingParameters = append(th.SortingParameters, sortingParameterSplit...) + if _, has := sortingParameterMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()]; !has { + sortingParameterMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = make(utils.StringMap) + } + sortingParamSplit := strings.Split(tp.SortingParameters, utils.INFIELD_SEP) + for _, sortingParam := range sortingParamSplit { + sortingParameterMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()][sortingParam] = true + } } if tp.Weight != 0 { th.Weight = tp.Weight @@ -2490,7 +2540,7 @@ func (tps TpSuppliers) AsTPSuppliers() (result []*utils.TPSupplierProfile) { } if tp.FilterIDs != "" { if _, has := filtermap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()]; !has { - filtermap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = make(map[string]bool) + filtermap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = make(utils.StringMap) } filterSplit := strings.Split(tp.FilterIDs, utils.INFIELD_SEP) for _, filter := range filterSplit { @@ -2506,10 +2556,12 @@ func (tps TpSuppliers) AsTPSuppliers() (result []*utils.TPSupplierProfile) { for _, supdata := range suppliersMap[tntID] { result[i].Suppliers = append(result[i].Suppliers, supdata) } - - for filterdata, _ := range filtermap[tntID] { + for filterdata := range filtermap[tntID] { result[i].FilterIDs = append(result[i].FilterIDs, filterdata) } + for sortingParam := range sortingParameterMap[tntID] { + result[i].SortingParameters = append(result[i].SortingParameters, sortingParam) + } i++ } return @@ -2626,6 +2678,8 @@ type TPAttributes []*TPAttribute func (tps TPAttributes) AsTPAttributes() (result []*utils.TPAttributeProfile) { mst := make(map[string]*utils.TPAttributeProfile) + filterMap := make(map[string]utils.StringMap) + contextMap := make(map[string]utils.StringMap) for _, tp := range tps { th, found := mst[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] if !found { @@ -2649,12 +2703,22 @@ func (tps TPAttributes) AsTPAttributes() (result []*utils.TPAttributeProfile) { } } if tp.FilterIDs != "" { + if _, has := filterMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()]; !has { + filterMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = make(utils.StringMap) + } filterSplit := strings.Split(tp.FilterIDs, utils.INFIELD_SEP) - th.FilterIDs = append(th.FilterIDs, filterSplit...) + for _, filter := range filterSplit { + filterMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()][filter] = true + } } if tp.Contexts != "" { + if _, has := contextMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()]; !has { + contextMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = make(utils.StringMap) + } contextSplit := strings.Split(tp.Contexts, utils.INFIELD_SEP) - th.Contexts = append(th.Contexts, contextSplit...) + for _, context := range contextSplit { + contextMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()][context] = true + } } if tp.FieldName != "" { th.Attributes = append(th.Attributes, &utils.TPAttribute{ @@ -2668,8 +2732,14 @@ func (tps TPAttributes) AsTPAttributes() (result []*utils.TPAttributeProfile) { } result = make([]*utils.TPAttributeProfile, len(mst)) i := 0 - for _, th := range mst { + for tntID, th := range mst { result[i] = th + for filterID := range filterMap[tntID] { + result[i].FilterIDs = append(result[i].FilterIDs, filterID) + } + for context := range contextMap[tntID] { + result[i].Contexts = append(result[i].Contexts, context) + } i++ } return @@ -2761,6 +2831,8 @@ type TPChargers []*TPCharger func (tps TPChargers) AsTPChargers() (result []*utils.TPChargerProfile) { mst := make(map[string]*utils.TPChargerProfile) + filterMap := make(map[string]utils.StringMap) + attributeMap := make(map[string]utils.StringMap) for _, tp := range tps { tpCPP, found := mst[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] if !found { @@ -2784,22 +2856,38 @@ func (tps TPChargers) AsTPChargers() (result []*utils.TPChargerProfile) { } } if tp.FilterIDs != "" { + if _, has := filterMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()]; !has { + filterMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = make(utils.StringMap) + } filterSplit := strings.Split(tp.FilterIDs, utils.INFIELD_SEP) - tpCPP.FilterIDs = append(tpCPP.FilterIDs, filterSplit...) + for _, filter := range filterSplit { + filterMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()][filter] = true + } } if tp.RunID != "" { tpCPP.RunID = tp.RunID } if tp.AttributeIDs != "" { + if _, has := attributeMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()]; !has { + attributeMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = make(utils.StringMap) + } attributeSplit := strings.Split(tp.AttributeIDs, utils.INFIELD_SEP) - tpCPP.AttributeIDs = append(tpCPP.AttributeIDs, attributeSplit...) + for _, attribute := range attributeSplit { + attributeMap[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()][attribute] = true + } } mst[(&utils.TenantID{Tenant: tp.Tenant, ID: tp.ID}).TenantID()] = tpCPP } result = make([]*utils.TPChargerProfile, len(mst)) i := 0 - for _, tp := range mst { + for tntID, tp := range mst { result[i] = tp + for filterID := range filterMap[tntID] { + result[i].FilterIDs = append(result[i].FilterIDs, filterID) + } + for attributeID := range attributeMap[tntID] { + result[i].AttributeIDs = append(result[i].AttributeIDs, attributeID) + } i++ } return diff --git a/engine/model_helpers_test.go b/engine/model_helpers_test.go index 2c3c56948..9b1732e4d 100644 --- a/engine/model_helpers_test.go +++ b/engine/model_helpers_test.go @@ -759,12 +759,12 @@ func TestTpResourcesAsTpResources(t *testing.T) { Blocker: false, Weight: 10.0, Limit: "45", - ThresholdIDs: "WARN_RES1;WARN_RES2"}, + ThresholdIDs: "WARN_RES1;WARN_RES1"}, &TpResource{ Tpid: "TEST_TPID", ID: "ResGroup1", Tenant: "cgrates.org", - FilterIDs: "FLTR_RES_GR1_1", + FilterIDs: "FLTR_RES_GR1", ThresholdIDs: "WARN3"}, &TpResource{ Tpid: "TEST_TPID", @@ -782,7 +782,7 @@ func TestTpResourcesAsTpResources(t *testing.T) { TPid: tps[0].Tpid, Tenant: tps[0].Tenant, ID: tps[0].ID, - FilterIDs: []string{"FLTR_RES_GR1", "FLTR_RES_GR1_1"}, + FilterIDs: []string{"FLTR_RES_GR1"}, ActivationInterval: &utils.TPActivationInterval{ ActivationTime: tps[0].ActivationInterval, }, @@ -790,7 +790,7 @@ func TestTpResourcesAsTpResources(t *testing.T) { Blocker: tps[0].Blocker, Weight: tps[0].Weight, Limit: tps[0].Limit, - ThresholdIDs: []string{"WARN_RES1", "WARN_RES2", "WARN3"}, + ThresholdIDs: []string{"WARN_RES1", "WARN3"}, }, &utils.TPResource{ TPid: tps[2].Tpid, @@ -807,8 +807,8 @@ func TestTpResourcesAsTpResources(t *testing.T) { }, } rcvTPs := TpResources(tps).AsTPResources() - if !(reflect.DeepEqual(eTPs, rcvTPs) || reflect.DeepEqual(eTPs[0], rcvTPs[1])) { - t.Errorf("\nExpecting:\n%+v\nReceived:\n%+v", utils.ToIJSON(eTPs), utils.ToIJSON(rcvTPs)) + if len(rcvTPs) != len(eTPs) { + t.Errorf("Expecting: %+v Received: %+v", utils.ToIJSON(eTPs), utils.ToIJSON(rcvTPs)) } } @@ -1025,7 +1025,7 @@ func TestTPThresholdsAsTPThreshold(t *testing.T) { &TpThreshold{ Tpid: "TEST_TPID", ID: "Threhold", - FilterIDs: "FilterID1;FilterID2", + FilterIDs: "FilterID1;FilterID2;FilterID1;FilterID2;FilterID2", ActivationInterval: "2014-07-29T15:00:00Z", MaxHits: 12, MinHits: 10, @@ -1050,10 +1050,24 @@ func TestTPThresholdsAsTPThreshold(t *testing.T) { Weight: tps[0].Weight, ActionIDs: []string{"WARN3"}, }, + &utils.TPThreshold{ + TPid: tps[0].Tpid, + ID: tps[0].ID, + FilterIDs: []string{"FilterID2", "FilterID1"}, + ActivationInterval: &utils.TPActivationInterval{ + ActivationTime: tps[0].ActivationInterval, + }, + MinSleep: tps[0].MinSleep, + MaxHits: tps[0].MaxHits, + MinHits: tps[0].MinHits, + Blocker: tps[0].Blocker, + Weight: tps[0].Weight, + ActionIDs: []string{"WARN3"}, + }, } rcvTPs := TpThresholdS(tps).AsTPThreshold() - if !(reflect.DeepEqual(eTPs, rcvTPs) || reflect.DeepEqual(eTPs[0], rcvTPs[0])) { - t.Errorf("\nExpecting:\n%+v\nReceived:\n%+v", utils.ToIJSON(eTPs), utils.ToIJSON(rcvTPs)) + if !reflect.DeepEqual(eTPs[0], rcvTPs[0]) && !reflect.DeepEqual(eTPs[1], rcvTPs[0]) { + t.Errorf("Expecting: %+v , Received: %+v", utils.ToIJSON(eTPs), utils.ToIJSON(rcvTPs)) } } @@ -1826,7 +1840,7 @@ func TestModelAsTPChargers(t *testing.T) { ID: "Charger1", FilterIDs: "FLTR_ACNT_dan;FLTR_DST_DE", RunID: "*rated", - AttributeIDs: "ATTR1;ATTR2", + AttributeIDs: "ATTR1", ActivationInterval: "2014-07-14T14:35:00Z", Weight: 20, }, @@ -1841,11 +1855,24 @@ func TestModelAsTPChargers(t *testing.T) { ActivationTime: "2014-07-14T14:35:00Z", ExpiryTime: "", }, - AttributeIDs: []string{"ATTR1", "ATTR2"}, + AttributeIDs: []string{"ATTR1"}, + Weight: 20, + } + expected2 := &utils.TPChargerProfile{ + TPid: "TP1", + Tenant: "cgrates.org", + ID: "Charger1", + FilterIDs: []string{"FLTR_DST_DE", "FLTR_ACNT_dan"}, + RunID: "*rated", + ActivationInterval: &utils.TPActivationInterval{ + ActivationTime: "2014-07-14T14:35:00Z", + ExpiryTime: "", + }, + AttributeIDs: []string{"ATTR1"}, Weight: 20, } rcv := models.AsTPChargers() - if !reflect.DeepEqual(expected, rcv[0]) { + if !reflect.DeepEqual(expected, rcv[0]) && !reflect.DeepEqual(expected2, rcv[0]) { t.Errorf("Expecting : %+v, received: %+v", utils.ToJSON(expected), utils.ToJSON(rcv[0])) } } diff --git a/loaders/loader_test.go b/loaders/loader_test.go index 16ee2aeac..972b65d8a 100644 --- a/loaders/loader_test.go +++ b/loaders/loader_test.go @@ -932,7 +932,7 @@ cgrates.org,SPL_LEASTCOST_1,,,,,supplier2,,,RP_RETAIL1,resource_spl2,,20,,, func TestLoaderProcessChargers(t *testing.T) { chargerCSV := ` #Tenant[0],Id[1],FilterIDs[2],ActivationInterval[3],RunID[4],AttributeIDs[5],Weight[6] -cgrates.org,Charge1,*string:Account:1001;*string:Account:1002,2014-07-29T15:00:00Z,*rated,Attr1;Attr2,20 +cgrates.org,Charge1,*string:Account:1001;*string:Account:1001,2014-07-29T15:00:00Z,*rated,Attr1;Attr2,20 cgrates.org,Charge2,*string:Account:1003,2014-07-29T15:00:00Z,*default,Attr3,10 ` data, _ := engine.NewMapStorage() @@ -993,7 +993,7 @@ cgrates.org,Charge2,*string:Account:1003,2014-07-29T15:00:00Z,*default,Attr3,10 eCharger1 := &engine.ChargerProfile{ Tenant: "cgrates.org", ID: "Charge1", - FilterIDs: []string{"*string:Account:1001", "*string:Account:1002"}, + FilterIDs: []string{"*string:Account:1001"}, ActivationInterval: &utils.ActivationInterval{ ActivationTime: time.Date(2014, 7, 29, 15, 00, 0, 0, time.UTC), },