diff --git a/apier/v1/filter_indexes.go b/apier/v1/filter_indexes.go index 465269515..03700106b 100644 --- a/apier/v1/filter_indexes.go +++ b/apier/v1/filter_indexes.go @@ -209,7 +209,7 @@ func (api *APIerSv1) ComputeFilterIndexes(args utils.ArgsComputeFilterIndexes, r //ThresholdProfile Indexes var thdsIndexers *engine.FilterIndexer if args.ThresholdS { - thdsIndexers, err = api.computeThresholdIndexes(args.Tenant, nil, transactionID) + thdsIndexers, err = engine.ComputeThresholdIndexes(api.DataManager, args.Tenant, nil, transactionID) if err != nil && err != utils.ErrNotFound { return utils.APIErrorHandler(err) } @@ -314,7 +314,7 @@ func (api *APIerSv1) ComputeFilterIndexes(args utils.ArgsComputeFilterIndexes, r func (api *APIerSv1) ComputeFilterIndexIDs(args utils.ArgsComputeFilterIndexIDs, reply *string) (err error) { transactionID := utils.GenUUID() //ThresholdProfile Indexes - thdsIndexers, err := api.computeThresholdIndexes(args.Tenant, &args.ThresholdIDs, transactionID) + thdsIndexers, err := engine.ComputeThresholdIndexes(api.DataManager, args.Tenant, &args.ThresholdIDs, transactionID) if err != nil && err != utils.ErrNotFound { return utils.APIErrorHandler(err) } @@ -460,83 +460,6 @@ func (api *APIerSv1) ComputeFilterIndexIDs(args utils.ArgsComputeFilterIndexIDs, return nil } -func (api *APIerSv1) computeThresholdIndexes(tenant string, thIDs *[]string, - transactionID string) (filterIndexer *engine.FilterIndexer, err error) { - var thresholdIDs []string - var thdsIndexers *engine.FilterIndexer - if thIDs == nil { - ids, err := api.DataManager.DataDB().GetKeysForPrefix(utils.ThresholdProfilePrefix) - if err != nil { - return nil, err - } - for _, id := range ids { - thresholdIDs = append(thresholdIDs, strings.Split(id, utils.CONCATENATED_KEY_SEP)[1]) - } - // this will be on ComputeIndexes that contains empty indexes - thdsIndexers = engine.NewFilterIndexer(api.DataManager, utils.ThresholdProfilePrefix, tenant) - } else { - // this will be on ComputeIndexesIDs that contains the old indexes from the next getter - var oldIDx map[string]utils.StringMap - if oldIDx, err = api.DataManager.GetFilterIndexes(utils.PrefixToIndexCache[utils.ThresholdProfilePrefix], - tenant, utils.EmptyString, nil); err != nil || oldIDx == nil { - thdsIndexers = engine.NewFilterIndexer(api.DataManager, utils.ThresholdProfilePrefix, tenant) - } else { - thdsIndexers = engine.NewFilterIndexerWithIndexes(api.DataManager, utils.ThresholdProfilePrefix, tenant, oldIDx) - } - thresholdIDs = *thIDs - transactionID = utils.NonTransactional - } - for _, id := range thresholdIDs { - th, err := api.DataManager.GetThresholdProfile(tenant, id, true, false, utils.NonTransactional) - if err != nil { - return nil, err - } - fltrIDs := make([]string, len(th.FilterIDs)) - for i, fltrID := range th.FilterIDs { - fltrIDs[i] = fltrID - } - if len(fltrIDs) == 0 { - fltrIDs = []string{utils.META_NONE} - } - for _, fltrID := range fltrIDs { - var fltr *engine.Filter - if fltrID == utils.META_NONE { - fltr = &engine.Filter{ - Tenant: th.Tenant, - ID: th.ID, - Rules: []*engine.FilterRule{ - { - Type: utils.META_NONE, - Element: utils.META_ANY, - Values: []string{utils.META_ANY}, - }, - }, - } - } else if fltr, err = engine.GetFilter(api.DataManager, th.Tenant, fltrID, - true, false, utils.NonTransactional); err != nil { - if err == utils.ErrNotFound { - err = fmt.Errorf("broken reference to filter: %+v for threshold: %+v", - fltrID, th) - } - return nil, err - } - thdsIndexers.IndexTPFilter(engine.FilterToTPFilter(fltr), th.ID) - } - } - - if transactionID == utils.NonTransactional { - if err := thdsIndexers.StoreIndexes(true, transactionID); err != nil { - return nil, err - } - return nil, nil - } else { - if err := thdsIndexers.StoreIndexes(false, transactionID); err != nil { - return nil, err - } - } - return thdsIndexers, nil -} - func (api *APIerSv1) computeAttributeIndexes(tenant, context string, attrIDs *[]string, transactionID string) (filterIndexer *engine.FilterIndexer, err error) { var attributeIDs []string diff --git a/engine/datamanager.go b/engine/datamanager.go index a61b11e1c..edd8f5d03 100644 --- a/engine/datamanager.go +++ b/engine/datamanager.go @@ -788,12 +788,20 @@ func (dm *DataManager) SetThresholdProfile(th *ThresholdProfile, withIndex bool) th.Tenant).RemoveItemFromIndex(th.Tenant, th.ID, oldTh.FilterIDs); err != nil { return } + if err = removeReverseFilterIndexForFilter(dm, utils.CacheThresholdFilterIndexes, utils.EmptyString, + th.Tenant, th.ID, th.FilterIDs); err != nil { + return + } } } if err := createAndIndex(utils.ThresholdProfilePrefix, th.Tenant, utils.EmptyString, th.ID, th.FilterIDs, dm); err != nil { return err } + if err = addReverseFilterIndexForFilter(dm, utils.CacheThresholdFilterIndexes, utils.EmptyString, + th.Tenant, th.ID, th.FilterIDs); err != nil { + return + } } if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaThresholdProfiles]; itm.Replicate { if err = replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, @@ -824,6 +832,10 @@ func (dm *DataManager) RemoveThresholdProfile(tenant, id, tenant).RemoveItemFromIndex(tenant, id, oldTh.FilterIDs); err != nil { return } + if err = removeReverseFilterIndexForFilter(dm, utils.CacheThresholdFilterIndexes, utils.EmptyString, + oldTh.Tenant, oldTh.ID, oldTh.FilterIDs); err != nil { + return + } } if itm := config.CgrConfig().DataDbCfg().Items[utils.MetaThresholdProfiles]; itm.Replicate { replicate(dm.connMgr, config.CgrConfig().DataDbCfg().RplConns, diff --git a/engine/filter_indexes.go b/engine/filter_indexes.go index ae7f8e037..673242613 100644 --- a/engine/filter_indexes.go +++ b/engine/filter_indexes.go @@ -25,10 +25,87 @@ import ( "github.com/cgrates/cgrates/utils" ) +func ComputeThresholdIndexes(dm *DataManager, tenant string, thIDs *[]string, + transactionID string) (filterIndexer *FilterIndexer, err error) { + var thresholdIDs []string + var thdsIndexers *FilterIndexer + if thIDs == nil { + ids, err := dm.DataDB().GetKeysForPrefix(utils.ThresholdProfilePrefix) + if err != nil { + return nil, err + } + for _, id := range ids { + thresholdIDs = append(thresholdIDs, strings.Split(id, utils.CONCATENATED_KEY_SEP)[1]) + } + // this will be on ComputeIndexes that contains empty indexes + thdsIndexers = NewFilterIndexer(dm, utils.ThresholdProfilePrefix, tenant) + } else { + // this will be on ComputeIndexesIDs that contains the old indexes from the next getter + var oldIDx map[string]utils.StringMap + if oldIDx, err = dm.GetFilterIndexes(utils.PrefixToIndexCache[utils.ThresholdProfilePrefix], + tenant, utils.EmptyString, nil); err != nil || oldIDx == nil { + thdsIndexers = NewFilterIndexer(dm, utils.ThresholdProfilePrefix, tenant) + } else { + thdsIndexers = NewFilterIndexerWithIndexes(dm, utils.ThresholdProfilePrefix, tenant, oldIDx) + } + thresholdIDs = *thIDs + transactionID = utils.NonTransactional + } + for _, id := range thresholdIDs { + th, err := dm.GetThresholdProfile(tenant, id, true, false, utils.NonTransactional) + if err != nil { + return nil, err + } + fltrIDs := make([]string, len(th.FilterIDs)) + for i, fltrID := range th.FilterIDs { + fltrIDs[i] = fltrID + } + if len(fltrIDs) == 0 { + fltrIDs = []string{utils.META_NONE} + } + for _, fltrID := range fltrIDs { + var fltr *Filter + if fltrID == utils.META_NONE { + fltr = &Filter{ + Tenant: th.Tenant, + ID: th.ID, + Rules: []*FilterRule{ + { + Type: utils.META_NONE, + Element: utils.META_ANY, + Values: []string{utils.META_ANY}, + }, + }, + } + } else if fltr, err = GetFilter(dm, th.Tenant, fltrID, + true, false, utils.NonTransactional); err != nil { + if err == utils.ErrNotFound { + err = fmt.Errorf("broken reference to filter: %+v for threshold: %+v", + fltrID, th) + } + return nil, err + } + thdsIndexers.IndexTPFilter(FilterToTPFilter(fltr), th.ID) + } + } + + if transactionID == utils.NonTransactional { + if err := thdsIndexers.StoreIndexes(true, transactionID); err != nil { + return nil, err + } + return nil, nil + } else { + if err := thdsIndexers.StoreIndexes(false, transactionID); err != nil { + return nil, err + } + } + return thdsIndexers, nil +} + func ComputeChargerIndexes(dm *DataManager, tenant string, cppIDs *[]string, - transactionID string) (cppIndexes *FilterIndexer, err error) { + transactionID string) (filterIndexer *FilterIndexer, err error) { var chargerIDs []string - //var cppIndexes *FilterIndexer + var cppIndexes *FilterIndexer if cppIDs == nil { ids, err := dm.DataDB().GetKeysForPrefix(utils.ChargerProfilePrefix) if err != nil { diff --git a/engine/libindex.go b/engine/libindex.go index e85b4a75a..e0656b3cf 100644 --- a/engine/libindex.go +++ b/engine/libindex.go @@ -116,6 +116,7 @@ func UpdateFilterIndexes(dm *DataManager, tnt string, oldFltr *Filter, newFltr * err = nil // if the error is NOT_FOUND, it means that no indexes were found for this filter, so no need to update return } + removeIndexKeys := removeRules.Slice() for idxItmType, index := range rcvIndexes { @@ -132,6 +133,18 @@ func UpdateFilterIndexes(dm *DataManager, tnt string, oldFltr *Filter, newFltr * utils.NonTransactional); err != nil { return err } + case utils.CacheThresholdFilterIndexes: + // remove the indexes from this filter for this partition + if err = removeFilterIndexesForFilter(dm, idxItmType, utils.CacheThresholdProfiles, + tnt, removeIndexKeys, index); err != nil { + return + } + // we removed the old reverse indexes, now we have to compute the new ones + thresholdIDs := index.Slice() + if _, err = ComputeThresholdIndexes(dm, newFltr.Tenant, &thresholdIDs, + utils.NonTransactional); err != nil { + return err + } } } return nil @@ -190,6 +203,9 @@ func addReverseFilterIndexForFilter(dm *DataManager, idxItmType, ctx, tnt, idxItmType: make(map[string]bool), // not found in database any reverse, we declare them to add in the next steps } } + if indexes[idxItmType] == nil { + indexes[idxItmType] = make(utils.StringMap) + } indexes[idxItmType].Copy(map[string]bool{ itemID: true, }) diff --git a/general_tests/filter_indexes_cases_it_test.go b/general_tests/filter_indexes_cases_it_test.go index e1df98933..8bccc98c3 100644 --- a/general_tests/filter_indexes_cases_it_test.go +++ b/general_tests/filter_indexes_cases_it_test.go @@ -27,6 +27,7 @@ import ( "reflect" "sort" "testing" + "time" v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" @@ -104,6 +105,7 @@ var ( testFilterIndexesCasesGetIndexesAnyContextChanged, testFilterIndexesCasesGetIndexesSessionsContextChanged, + // CHARGERS testFilterIndexesCasesSetIndexedFilter, testFilterIndexesCasesSetChargerWithFltr, testFilterIndexesCasesGetChargerIndexes, @@ -115,6 +117,17 @@ var ( testFilterIndexesCasesGetIndexesAfterRemove, testFilterIndexesCasesGetReverseIndexesAfterRemove, + // THRESHOLDS + testFilterIndexesCasesSetThresholdWithFltr, + testFilterIndexesCasesGetThresholdsIndexes, + testFilterIndexesCasesOverwriteFilterForThresholds, + testFilterIndexesCasesGetThresholdsIndexesChanged, + + testFilterIndexesCasesGetReverseFilterIndexes2, + testFilterIndexesCasesRemoveThresholdsProfile, + testFilterIndexesCasesGetIndexesAfterRemove2, + testFilterIndexesCasesGetReverseIndexesAfterRemove2, + testFilterIndexesCasesStopEngine, } ) @@ -768,6 +781,346 @@ func testFilterIndexesCasesGetReverseIndexesAfterRemove(t *testing.T) { } } +func testFilterIndexesCasesSetThresholdWithFltr(t *testing.T) { + tPrfl1 := &engine.ThresholdWithCache{ + ThresholdProfile: &engine.ThresholdProfile{ + Tenant: "cgrates.org", + ID: "TEST_PROFILE1", + FilterIDs: []string{"FLTR_Charger"}, + MaxHits: 1, + MinSleep: time.Duration(5 * time.Minute), + Blocker: false, + Weight: 10.0, + Async: true, + }, + } + tPrfl2 := &engine.ThresholdWithCache{ + ThresholdProfile: &engine.ThresholdProfile{ + Tenant: "cgrates.org", + ID: "TEST_PROFILE2", + FilterIDs: []string{ + "FLTR_Charger4564", + "FLTR_Charger", + "FLTR_Charger12312", + }, + 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), + }, + MaxHits: 1, + MinSleep: time.Duration(5 * time.Minute), + Blocker: false, + Weight: 20.0, + Async: true, + }, + } + tPrfl3 := &engine.ThresholdWithCache{ + ThresholdProfile: &engine.ThresholdProfile{ + Tenant: "cgrates.org", + ID: "TEST_PROFILE3", + FilterIDs: []string{ + "FLTR_Charger12312", + "*prefix:~*req.Cost:4", + "FLTR_Charger", + }, + 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), + }, + MaxHits: 1, + MinSleep: time.Duration(5 * time.Minute), + Blocker: false, + Weight: 40.0, + Async: true, + }, + } + tPrfl4 := &engine.ThresholdWithCache{ + ThresholdProfile: &engine.ThresholdProfile{ + Tenant: "cgrates.org", + ID: "TEST_PROFILE4", + FilterIDs: []string{}, + MaxHits: 1, + MinSleep: time.Duration(5 * time.Minute), + Blocker: false, + Weight: 5.0, + Async: true, + }, + } + var result string + if err := fIdxCasesRPC.Call(utils.APIerSv1SetThresholdProfile, tPrfl1, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + if err := fIdxCasesRPC.Call(utils.APIerSv1SetThresholdProfile, tPrfl2, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + if err := fIdxCasesRPC.Call(utils.APIerSv1SetThresholdProfile, tPrfl3, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + if err := fIdxCasesRPC.Call(utils.APIerSv1SetThresholdProfile, tPrfl4, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } +} + +func testFilterIndexesCasesGetThresholdsIndexes(t *testing.T) { + arg := &v1.AttrGetFilterIndexes{ + Tenant: "cgrates.org", + ItemType: utils.MetaThresholds, + } + expectedIndexes := []string{ + // TEST_PROFILE1" + "*string:~*req.Account:12345:TEST_PROFILE1", + // TEST_PROFILE2" + "*string:~*req.Account:12345:TEST_PROFILE2", + "*string:~*req.RequestType:*none:TEST_PROFILE2", + "*string:~*req.Destination:1443:TEST_PROFILE2", + "*prefix:~*req.SetupTime:2022:TEST_PROFILE2", + // TEST_PROFILE3" + "*string:~*req.Account:12345:TEST_PROFILE3", + "*prefix:~*req.Cost:4:TEST_PROFILE3", + "*string:~*req.Destination:1443:TEST_PROFILE3", + "*prefix:~*req.SetupTime:2022:TEST_PROFILE3", + // TEST_PROFILE4" + "*none:*any:*any:TEST_PROFILE4", + } + sort.Strings(expectedIndexes) + var reply []string + if err := fIdxCasesRPC.Call(utils.APIerSv1GetFilterIndexes, arg, &reply); err != nil { + t.Error(err) + } else if sort.Strings(reply); !reflect.DeepEqual(expectedIndexes, reply) { + t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(expectedIndexes), utils.ToJSON(reply)) + } +} + +func testFilterIndexesCasesOverwriteFilterForThresholds(t *testing.T) { + filter1 = &v1.FilterWithCache{ + Filter: &engine.Filter{ + Tenant: "cgrates.org", + ID: "FLTR_Charger", + Rules: []*engine.FilterRule{ + { + Type: utils.MetaPrefix, + Element: "~*req.CostRefunded", + Values: []string{"12345"}, + }, + { + Type: utils.MetaString, + Element: "~*req.ToR", + Values: []string{"*voice"}, + }, + { + Type: utils.MetaLessOrEqual, + Element: "~*req.ProcessRuns", + Values: []string{"1"}, + }, + }, + }, + } + filter2 := &v1.FilterWithCache{ + Filter: &engine.Filter{ + Tenant: "cgrates.org", + ID: "FLTR_Charger4564", + Rules: []*engine.FilterRule{ + { + Type: utils.MetaString, + Element: "~*req.Increment", + Values: []string{"1s"}, + }, + }, + }, + } + var result string + if err := fIdxCasesRPC.Call(utils.APIerSv1SetFilter, filter1, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + if err := fIdxCasesRPC.Call(utils.APIerSv1SetFilter, filter2, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } +} + +func testFilterIndexesCasesGetThresholdsIndexesChanged(t *testing.T) { + arg := &v1.AttrGetFilterIndexes{ + Tenant: "cgrates.org", + ItemType: utils.MetaThresholds, + } + expectedIndexes := []string{ + // TEST_PROFILE1" + "*string:~*req.ToR:*voice:TEST_PROFILE1", + "*prefix:~*req.CostRefunded:12345:TEST_PROFILE1", + // TEST_PROFILE2" + "*string:~*req.ToR:*voice:TEST_PROFILE2", + "*prefix:~*req.CostRefunded:12345:TEST_PROFILE2", + "*string:~*req.Increment:1s:TEST_PROFILE2", + "*string:~*req.Destination:1443:TEST_PROFILE2", + "*prefix:~*req.SetupTime:2022:TEST_PROFILE2", + // TEST_PROFILE3" + "*string:~*req.ToR:*voice:TEST_PROFILE3", + "*prefix:~*req.CostRefunded:12345:TEST_PROFILE3", + "*prefix:~*req.Cost:4:TEST_PROFILE3", + "*string:~*req.Destination:1443:TEST_PROFILE3", + "*prefix:~*req.SetupTime:2022:TEST_PROFILE3", + // TEST_PROFILE4" + "*none:*any:*any:TEST_PROFILE4", + } + sort.Strings(expectedIndexes) + var reply []string + if err := fIdxCasesRPC.Call(utils.APIerSv1GetFilterIndexes, arg, &reply); err != nil { + t.Error(err) + } else if sort.Strings(reply); !reflect.DeepEqual(expectedIndexes, reply) { + t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(expectedIndexes), utils.ToJSON(reply)) + } +} + +func testFilterIndexesCasesGetReverseFilterIndexes2(t *testing.T) { + arg := &v1.AttrGetFilterIndexes{ + Tenant: "cgrates.org:FLTR_Charger", + ItemType: utils.CacheReverseFilterIndexes, + } + expectedIndexes := []string{ + "*threshold_filter_indexes:TEST_PROFILE1", + "*threshold_filter_indexes:TEST_PROFILE2", + "*threshold_filter_indexes:TEST_PROFILE3", + "*charger_filter_indexes:ChrgerIndexable", + } + sort.Strings(expectedIndexes) + var reply []string + if err := fIdxCasesRPC.Call(utils.APIerSv1GetFilterIndexes, arg, &reply); err != nil { + t.Error(err) + } else if sort.Strings(reply); !reflect.DeepEqual(expectedIndexes, reply) { + t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(expectedIndexes), utils.ToJSON(reply)) + } + + arg = &v1.AttrGetFilterIndexes{ + Tenant: "cgrates.org:FLTR_Charger4564", + ItemType: utils.CacheReverseFilterIndexes, + } + expectedIndexes = []string{ + "*threshold_filter_indexes:TEST_PROFILE2", + "*charger_filter_indexes:ChrgerIndexable", + } + sort.Strings(expectedIndexes) + if err := fIdxCasesRPC.Call(utils.APIerSv1GetFilterIndexes, arg, &reply); err != nil { + t.Error(err) + } else if sort.Strings(reply); !reflect.DeepEqual(expectedIndexes, reply) { + t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(expectedIndexes), utils.ToJSON(reply)) + } + + arg = &v1.AttrGetFilterIndexes{ + Tenant: "cgrates.org:FLTR_Charger12312", + ItemType: utils.CacheReverseFilterIndexes, + } + expectedIndexes = []string{ + "*threshold_filter_indexes:TEST_PROFILE2", + "*threshold_filter_indexes:TEST_PROFILE3", + "*charger_filter_indexes:ChrgerIndexable", + } + sort.Strings(expectedIndexes) + if err := fIdxCasesRPC.Call(utils.APIerSv1GetFilterIndexes, arg, &reply); err != nil { + t.Error(err) + } else if sort.Strings(reply); !reflect.DeepEqual(expectedIndexes, reply) { + t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(expectedIndexes), utils.ToJSON(reply)) + } +} + +func testFilterIndexesCasesRemoveThresholdsProfile(t *testing.T) { + var resp string + if err := fIdxCasesRPC.Call(utils.APIerSv1RemoveThresholdProfile, + &utils.TenantIDWithCache{Tenant: "cgrates.org", ID: "TEST_PROFILE1"}, &resp); err != nil { + t.Error(err) + } else if resp != utils.OK { + t.Error("Unexpected reply returned", resp) + } + if err := fIdxCasesRPC.Call(utils.APIerSv1RemoveThresholdProfile, + &utils.TenantIDWithCache{Tenant: "cgrates.org", ID: "TEST_PROFILE3"}, &resp); err != nil { + t.Error(err) + } else if resp != utils.OK { + t.Error("Unexpected reply returned", resp) + } +} + +func testFilterIndexesCasesGetIndexesAfterRemove2(t *testing.T) { + arg := &v1.AttrGetFilterIndexes{ + Tenant: "cgrates.org", + ItemType: utils.MetaThresholds, + } + expectedIndexes := []string{ + // TEST_PROFILE2" + "*string:~*req.ToR:*voice:TEST_PROFILE2", + "*prefix:~*req.CostRefunded:12345:TEST_PROFILE2", + "*string:~*req.Increment:1s:TEST_PROFILE2", + "*string:~*req.Destination:1443:TEST_PROFILE2", + "*prefix:~*req.SetupTime:2022:TEST_PROFILE2", + // TEST_PROFILE4" + "*none:*any:*any:TEST_PROFILE4", + } + sort.Strings(expectedIndexes) + var reply []string + if err := fIdxCasesRPC.Call(utils.APIerSv1GetFilterIndexes, arg, &reply); err != nil { + t.Error(err) + } else if sort.Strings(reply); !reflect.DeepEqual(expectedIndexes, reply) { + t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(expectedIndexes), utils.ToJSON(reply)) + } +} + +func testFilterIndexesCasesGetReverseIndexesAfterRemove2(t *testing.T) { + arg := &v1.AttrGetFilterIndexes{ + Tenant: "cgrates.org:FLTR_Charger", + ItemType: utils.CacheReverseFilterIndexes, + } + expectedIndexes := []string{ + "*threshold_filter_indexes:TEST_PROFILE2", + "*charger_filter_indexes:ChrgerIndexable", + } + sort.Strings(expectedIndexes) + var reply []string + if err := fIdxCasesRPC.Call(utils.APIerSv1GetFilterIndexes, arg, &reply); err != nil { + t.Error(err) + } else if sort.Strings(reply); !reflect.DeepEqual(expectedIndexes, reply) { + t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(expectedIndexes), utils.ToJSON(reply)) + } + + arg = &v1.AttrGetFilterIndexes{ + Tenant: "cgrates.org:FLTR_Charger4564", + ItemType: utils.CacheReverseFilterIndexes, + } + expectedIndexes = []string{ + "*threshold_filter_indexes:TEST_PROFILE2", + "*charger_filter_indexes:ChrgerIndexable", + } + sort.Strings(expectedIndexes) + if err := fIdxCasesRPC.Call(utils.APIerSv1GetFilterIndexes, arg, &reply); err != nil { + t.Error(err) + } else if sort.Strings(reply); !reflect.DeepEqual(expectedIndexes, reply) { + t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(expectedIndexes), utils.ToJSON(reply)) + } + + arg = &v1.AttrGetFilterIndexes{ + Tenant: "cgrates.org:FLTR_Charger12312", + ItemType: utils.CacheReverseFilterIndexes, + } + expectedIndexes = []string{ + "*threshold_filter_indexes:TEST_PROFILE2", + "*charger_filter_indexes:ChrgerIndexable", + } + sort.Strings(expectedIndexes) + if err := fIdxCasesRPC.Call(utils.APIerSv1GetFilterIndexes, arg, &reply); err != nil { + t.Error(err) + } else if sort.Strings(reply); !reflect.DeepEqual(expectedIndexes, reply) { + t.Errorf("Expecting: %+v, received: %+v", utils.ToJSON(expectedIndexes), utils.ToJSON(reply)) + } +} + func testFilterIndexesCasesStopEngine(t *testing.T) { if err := engine.KillEngine(100); err != nil { t.Error(err)