diff --git a/engine/storage_test.go b/engine/storage_test.go index 805ffe4f8..5c7b8d77f 100644 --- a/engine/storage_test.go +++ b/engine/storage_test.go @@ -20,6 +20,7 @@ package engine import ( "bytes" "reflect" + "slices" "sort" "strings" "testing" @@ -652,3 +653,554 @@ func TestIDBGetTpIds(t *testing.T) { t.Errorf("expected %v,received %v", utils.ToJSON(val), utils.ToJSON(exp)) } } + +func TestIDBTpResources(t *testing.T) { + cfg := config.NewDefaultCGRConfig() + storDB := NewInternalDB(nil, nil, false, cfg.StorDbCfg().Items) + // READ + if _, err := storDB.GetTPResources("TP1", utils.EmptyString, utils.EmptyString); err != utils.ErrNotFound { + t.Error(err) + } + //WRITE + var snd = []*utils.TPResourceProfile{ + { + TPid: "TP1", + ID: "RP1", + Weight: 10.8, + FilterIDs: []string{"FILTR_RES_1"}, + ThresholdIDs: []string{"TH1"}, + Stored: true, + }, + { + TPid: "TP1", + ID: "RP2", + Weight: 20.6, + ThresholdIDs: []string{"TH2"}, + FilterIDs: []string{"FLTR_RES_2"}, + Blocker: true, + Stored: false, + }, + } + if err := storDB.SetTPResources(snd); err != nil { + t.Error(err) + } + // READ + if rcv, err := storDB.GetTPResources("TP1", utils.EmptyString, utils.EmptyString); err != nil { + t.Error(err) + } else if sort.Slice(rcv, func(a, b int) bool { + return rcv[a].ID < rcv[b].ID + }); !slices.Equal(snd, rcv) { + t.Errorf("Expecting: %+v, received: %+v ", utils.ToJSON(snd), utils.ToJSON(rcv)) + } + // UPDATE + snd[0].Weight = 2.1 + snd[1].Weight = 8.1 + if err := storDB.SetTPResources(snd); err != nil { + t.Error(err) + } + // READ + if rcv, err := storDB.GetTPResources("TP1", utils.EmptyString, utils.EmptyString); err != nil { + t.Error(err) + } else if sort.Slice(rcv, func(a, b int) bool { + return rcv[a].ID < rcv[b].ID + }); rcv[0].Weight != snd[0].Weight { + t.Errorf("Expecting: %+v, received: %+v ", utils.ToJSON(snd[0]), utils.ToJSON(rcv[0])) + } + //tpIDs + expIds := []string{":RP1", ":RP2"} + if tpIds, err := storDB.GetTpTableIds("TP1", utils.TBLTPResources, utils.TPDistinctIds{utils.TenantCfg, utils.IDCfg}, nil, &utils.PaginatorWithSearch{}); err != nil { + t.Error(err) + } else if slices.Sort(tpIds); !slices.Equal(tpIds, expIds) { + t.Errorf("Expected %v,Received %v", expIds, tpIds) + } + // REMOVE + if err := storDB.RemTpData("", "TP1", nil); err != nil { + t.Error(err) + } + // READ + if _, err := storDB.GetTPResources("TP1", utils.EmptyString, utils.EmptyString); err != utils.ErrNotFound { + t.Error(err) + } +} + +func TestIDBTpStats(t *testing.T) { + cfg := config.NewDefaultCGRConfig() + storDB := NewInternalDB(nil, nil, false, cfg.StorDbCfg().Items) + + // READ + if _, err := storDB.GetTPStats("TP1", utils.EmptyString, utils.EmptyString); err != utils.ErrNotFound { + t.Error(err) + } + //WRITE + eTPs := []*utils.TPStatProfile{ + { + TPid: "TP1", + Tenant: "cgrates.org", + ID: "Stats1", + FilterIDs: []string{"FLTR_1"}, + QueueLength: 100, + TTL: "1s", + Metrics: []*utils.MetricWithFilters{ + { + MetricID: utils.MetaASR, + }, + }, + ThresholdIDs: []string{"*none"}, + Weight: 20.0, + Stored: true, + MinItems: 1, + }, + } + + if err := storDB.SetTPStats(eTPs); err != nil { + t.Error(err) + } + // READ + if rcv, err := storDB.GetTPStats("TP1", utils.EmptyString, utils.EmptyString); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eTPs[0], rcv[0]) { + t.Errorf("Expecting: %+v,\n received: %+v", utils.ToJSON(eTPs[0]), utils.ToJSON(rcv[0])) + } + + // UPDATE + eTPs[0].Metrics = []*utils.MetricWithFilters{ + { + MetricID: utils.MetaACD, + }, + } + if err := storDB.SetTPStats(eTPs); err != nil { + t.Error(err) + } + // READ + if rcv, err := storDB.GetTPStats("TP1", utils.EmptyString, utils.EmptyString); err != nil { + t.Error(err) + } else if eTPs[0].Metrics[0].MetricID != rcv[0].Metrics[0].MetricID { + t.Errorf("Expecting: %+v,\n received: %+v", utils.ToJSON(eTPs[0]), utils.ToJSON(rcv[0])) + } + + // REMOVE + if err := storDB.RemTpData(utils.TBLTPStats, "TP1", nil); err != nil { + t.Error(err) + } + // READ + if ids, err := storDB.GetTPStats("TP1", utils.EmptyString, utils.EmptyString); err != utils.ErrNotFound { + t.Error(err) + t.Error(utils.ToJSON(ids)) + } +} + +func TestIDBTPThresholds(t *testing.T) { + + storDB := NewInternalDB(nil, nil, false, config.CgrConfig().StorDbCfg().Items) + //READ + if _, err := storDB.GetTPThresholds("TH1", utils.EmptyString, utils.EmptyString); err != utils.ErrNotFound { + t.Error(err) + } + + //WRITE + tpThresholds := []*utils.TPThresholdProfile{ + { + TPid: "TP1", + Tenant: "cgrates.org", + ID: "Th1", + FilterIDs: []string{"*string:~*req.Account:1002", "*string:~*req.DryRun:*default"}, + MaxHits: -1, + MinSleep: "1s", + Blocker: true, + Weight: 10, + ActionIDs: []string{"ACT_TOPUP_RST"}, + Async: true, + }, + { + TPid: "TP1", + Tenant: "cgrates.org", + ID: "Th2", + FilterIDs: []string{"*string:~*req.Destination:10"}, + MaxHits: -1, + MinSleep: "1s", + Blocker: true, + Weight: 20, + ActionIDs: []string{"ACT_LOG_WARNING"}, + Async: true, + }, + } + if err := storDB.SetTPThresholds(tpThresholds); err != nil { + t.Errorf("Unable to set TPThresholds") + } + + //READ + if rcv, err := storDB.GetTPThresholds(tpThresholds[0].TPid, utils.EmptyString, utils.EmptyString); err != nil { + t.Error(err) + } else if sort.Slice(rcv, func(i, j int) bool { + return rcv[i].ID < rcv[j].ID + }); !slices.Equal(rcv, tpThresholds) { + t.Errorf("Expecting: %+v , Received: %+v", utils.ToJSON(tpThresholds), utils.ToJSON(rcv)) + } + + //UPDATE + tpThresholds[0].FilterIDs = []string{"*string:~*req.Destination:101"} + tpThresholds[1].FilterIDs = []string{"*string:~*req.Destination:101"} + if err := storDB.SetTPThresholds(tpThresholds); err != nil { + t.Errorf("Unable to set TPThresholds") + } + + //READ + if rcv, err := storDB.GetTPThresholds(tpThresholds[0].TPid, utils.EmptyString, utils.EmptyString); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(tpThresholds[0], rcv[0]) && + !reflect.DeepEqual(tpThresholds[0], rcv[1]) { + t.Errorf("Expecting:\n%+v\nReceived:\n%+v\n||\n%+v", + utils.ToJSON(tpThresholds[0]), utils.ToJSON(rcv[0]), utils.ToJSON(rcv[1])) + } + + //REMOVE and READ + if err := storDB.RemTpData(utils.EmptyString, tpThresholds[0].TPid, nil); err != nil { + t.Error(err) + } else if _, err := storDB.GetTPRoutes(tpThresholds[0].TPid, utils.EmptyString, utils.EmptyString); err != utils.ErrNotFound { + t.Error(err) + } +} + +func TestIDBTPFilters(t *testing.T) { + storDB := NewInternalDB(nil, nil, false, config.CgrConfig().StorDbCfg().Items) + //READ + if _, err := storDB.GetTPFilters("TP1", utils.EmptyString, utils.EmptyString); err != utils.ErrNotFound { + t.Error(err) + } + + //WRITE + tpFilters := []*utils.TPFilterProfile{ + { + TPid: "TP1", + Tenant: "cgrates.org", + ID: "Filter1", + Filters: []*utils.TPFilter{ + { + Type: utils.MetaString, + Element: "Account", + Values: []string{"1001", "1002"}, + }, + }, + }, + { + TPid: "TP1", + Tenant: "cgrates.org", + ID: "Filter2", + Filters: []*utils.TPFilter{ + { + Type: utils.MetaPrefix, + Element: "Destination", + Values: []string{"10"}, + }, + }, + }, + } + if err := storDB.SetTPFilters(tpFilters); err != nil { + t.Errorf("Unable to set TPFilters") + } + + //READ + if rcv, err := storDB.GetTPFilters(tpFilters[0].TPid, utils.EmptyString, utils.EmptyString); err != nil { + t.Error(err) + } else if sort.Slice(rcv, func(i, j int) bool { + return rcv[i].ID < rcv[j].ID + }); !slices.Equal(rcv, tpFilters) { + t.Errorf("Expecting: %+v , Received: %+v", utils.ToJSON(tpFilters), utils.ToJSON(rcv)) + } + + //UPDATE and WRITE + tpFilters[1].Filters[0].Element = "Account" + if err := storDB.SetTPFilters(tpFilters); err != nil { + t.Errorf("Unable to set TPFilters") + } + + //READ + if rcv, err := storDB.GetTPFilters(tpFilters[0].TPid, utils.EmptyString, utils.EmptyString); err != nil { + t.Error(err) + } else if sort.Slice(rcv, func(i, j int) bool { + return rcv[i].ID < rcv[j].ID + }); rcv[1].Filters[0].Element != tpFilters[1].Filters[0].Element { + t.Errorf("Expecting: %+v , Received: %+v", utils.ToJSON(tpFilters[1]), utils.ToJSON(rcv[1])) + } + + //REMOVE and READ + if err := storDB.RemTpData(utils.EmptyString, tpFilters[0].TPid, nil); err != nil { + t.Error(err) + } else if _, err := storDB.GetTPFilters(tpFilters[0].TPid, utils.EmptyString, utils.EmptyString); err != utils.ErrNotFound { + t.Error(err) + } +} + +func TestIDTPRoutes(t *testing.T) { + storDB := NewInternalDB(nil, nil, false, config.CgrConfig().StorDbCfg().Items) + //READ + if _, err := storDB.GetTPRoutes("TP1", utils.EmptyString, utils.EmptyString); err != utils.ErrNotFound { + t.Error(err) + } + //WRITE + tpRoutes := []*utils.TPRouteProfile{ + { + TPid: "TP1", + Tenant: "cgrates.org", + ID: "SUPL_1", + FilterIDs: []string{"*string:~*req.Accout:1007"}, + Sorting: "*lowest_cost", + Routes: []*utils.TPRoute{ + { + ID: "supplier1", + FilterIDs: []string{"FLTR_1"}, + AccountIDs: []string{"Acc1", "Acc2"}, + RatingPlanIDs: []string{"RPL_1"}, + ResourceIDs: []string{"ResGroup1"}, + StatIDs: []string{"Stat1"}, + Weight: 10, + Blocker: false, + RouteParameters: "SortingParam1", + }, + }, + Weight: 20, + }, + { + TPid: "TP1", + Tenant: "cgrates.org", + ID: "SUPL_2", + FilterIDs: []string{"*string:~*req.Destination:100"}, + Sorting: "*lowest_cost", + Routes: []*utils.TPRoute{ + { + ID: "supplier1", + FilterIDs: []string{"FLTR_1"}, + AccountIDs: []string{"Acc1", "Acc2"}, + RatingPlanIDs: []string{"RPL_1"}, + ResourceIDs: []string{"ResGroup1"}, + StatIDs: []string{"Stat1"}, + Weight: 10, + Blocker: false, + RouteParameters: "SortingParam2", + }, + }, + Weight: 10, + }, + } + if err := storDB.SetTPRoutes(tpRoutes); err != nil { + t.Errorf("Unable to set TPRoutes") + } + + //READ + if rcv, err := storDB.GetTPRoutes(tpRoutes[0].TPid, utils.EmptyString, utils.EmptyString); err != nil { + t.Error(err) + } else if sort.Slice(rcv, func(i, j int) bool { + return rcv[i].ID < rcv[j].ID + }); !slices.Equal(rcv, tpRoutes) { + t.Errorf("Expecting: %v Received: %+v", utils.ToJSON(tpRoutes), utils.ToJSON(rcv)) + } + + //UPDATE + tpRoutes[0].Sorting = "*higher_cost" + if err := storDB.SetTPRoutes(tpRoutes); err != nil { + t.Errorf("Unable to set TPRoutes") + } + //READ + if rcv, err := storDB.GetTPRoutes(tpRoutes[0].TPid, utils.EmptyString, utils.EmptyString); err != nil { + t.Error(err) + } else if sort.Slice(rcv, func(i, j int) bool { + return rcv[i].ID < rcv[j].ID + }); tpRoutes[0].Sorting != rcv[0].Sorting { + t.Errorf("Expecting: %v Received: %+v", utils.ToJSON(tpRoutes[0]), utils.ToJSON(rcv[0])) + } + + //REMOVE and READ + if err := storDB.RemTpData(utils.EmptyString, tpRoutes[0].TPid, nil); err != nil { + t.Error(err) + } else if _, err := storDB.GetTPRoutes(tpRoutes[0].TPid, utils.EmptyString, utils.EmptyString); err != utils.ErrNotFound { + t.Error(err) + } +} + +func TestIDBTPAttributes(t *testing.T) { + storDB := NewInternalDB(nil, nil, false, config.CgrConfig().StorDbCfg().Items) + //READ + if _, err := storDB.GetTPAttributes("TP_ID", utils.EmptyString, utils.EmptyString); err != utils.ErrNotFound { + t.Error(err) + } + + //WRITE + tpAProfile := []*utils.TPAttributeProfile{ + { + TPid: "TP_ID", + Tenant: "cgrates.org", + ID: "APROFILE_ID1", + Attributes: []*utils.TPAttribute{ + { + Type: utils.MetaString, + Path: utils.MetaReq + utils.NestingSep + utils.AccountField + utils.InInFieldSep, + Value: "101", + FilterIDs: []string{"*string:~*req.Account:101"}, + }, + { + Type: utils.MetaString, + Path: utils.MetaReq + utils.NestingSep + utils.AccountField + utils.InInFieldSep, + Value: "108", + FilterIDs: []string{"*string:~*req.Account:102"}, + }, + }, + }, + { + TPid: "TP_ID", + Tenant: "cgrates.org", + ID: "APROFILE_ID2", + Attributes: []*utils.TPAttribute{ + { + Type: utils.MetaString, + Path: utils.MetaReq + utils.NestingSep + utils.Destination + utils.InInFieldSep, + Value: "12", + FilterIDs: []string{"*string:~*req.Destination:11"}, + }, + { + Type: utils.MetaString, + Path: utils.MetaReq + utils.NestingSep + utils.Destination + utils.InInFieldSep, + Value: "13", + FilterIDs: []string{"*string:~*req.Destination:10"}, + }, + }, + }, + } + if err := storDB.SetTPAttributes(tpAProfile); err != nil { + t.Errorf("Unable to set TPAttributeProfile:%s", err) + } + + //READ + if rcv, err := storDB.GetTPAttributes(tpAProfile[0].TPid, utils.EmptyString, utils.EmptyString); err != nil { + t.Error(err) + } else if sort.Slice(rcv, func(i, j int) bool { + return rcv[i].ID < rcv[j].ID + }); !slices.Equal(rcv, tpAProfile) { + t.Errorf("Expected %v, Received %v", utils.ToJSON(rcv), utils.ToJSON(tpAProfile)) + } + + //UPDATE + tpAProfile[0].Attributes[0].Value = "107" + if err := storDB.SetTPAttributes(tpAProfile); err != nil { + t.Error(err) + } + + //READ + if rcv, err := storDB.GetTPAttributes(tpAProfile[0].TPid, utils.EmptyString, utils.EmptyString); err != nil { + t.Error(err) + } else if sort.Slice(rcv, func(i, j int) bool { + return rcv[i].ID < rcv[j].ID + }); tpAProfile[0].Attributes[0].Value != rcv[0].Attributes[0].Value { + t.Errorf("Expected %v, Received %v", utils.ToJSON(rcv[0]), utils.ToJSON(tpAProfile[0])) + } + + //REMOVE and READ + if err := storDB.RemTpData(utils.EmptyString, tpAProfile[0].TPid, nil); err != nil { + t.Error(err) + } else if _, err := storDB.GetTPAttributes(tpAProfile[0].TPid, utils.EmptyString, utils.EmptyString); err != utils.ErrNotFound { + t.Error(err) + } +} + +func TestIDBRemTpData(t *testing.T) { + storDB := NewInternalDB(nil, nil, false, config.CgrConfig().StorDbCfg().Items) + tpAccActions := []*utils.TPAccountActions{ + { + TPid: "TP1", + LoadId: "ID", + Tenant: "cgrates.org", + Account: "1001", + ActionPlanId: "PREPAID_10", + AllowNegative: true, + Disabled: false, + }, + } + if err := storDB.SetTPAccountActions(tpAccActions); err != nil { + t.Error(err) + } + tpRatingProfiles := []*utils.TPRatingProfile{ + { + TPid: "TP1", + LoadId: "TEST_LOADID", + Tenant: "cgrates.org", + Category: "call", + Subject: "*any", + }, + } + if err := storDB.SetTPRatingProfiles(tpRatingProfiles); err != nil { + t.Error(err) + } + + if err := storDB.RemTpData(utils.TBLTPAccountActions, tpAccActions[0].TPid, map[string]string{"tenant": "cgrates.org"}); err != nil { + t.Error(err) + } + + if err := storDB.RemTpData(utils.TBLTPRatingProfiles, tpRatingProfiles[0].TPid, map[string]string{"category": "call"}); err != nil { + t.Error(err) + } +} + +func TestIDBTpSharedGroups(t *testing.T) { + storDB := NewInternalDB(nil, nil, false, config.CgrConfig().StorDbCfg().Items) + // READ + if _, err := storDB.GetTPSharedGroups("TP1", ""); err != utils.ErrNotFound { + t.Error(err) + } + // WRITE + var snd = []*utils.TPSharedGroups{ + { + TPid: "TP1", + ID: "1", + SharedGroups: []*utils.TPSharedGroup{ + { + Account: "test", + Strategy: "*lowest_cost", + RatingSubject: "test", + }, + }, + }, + { + TPid: "TP1", + ID: "2", + SharedGroups: []*utils.TPSharedGroup{ + { + Account: "test", + Strategy: "*lowest_cost", + RatingSubject: "test", + }, + }, + }, + } + if err := storDB.SetTPSharedGroups(snd); err != nil { + t.Error(err) + } + // READ + if rcv, err := storDB.GetTPSharedGroups("TP1", ""); err != nil { + t.Error(err) + } else if sort.Slice(rcv, func(i, j int) bool { + return rcv[i].ID < rcv[j].ID + }); !slices.Equal(rcv, snd) { + t.Errorf("Expected %v, Received %v", utils.ToJSON(rcv), utils.ToJSON(snd)) + } + // UPDATE + snd[0].SharedGroups[0].Strategy = "*highest_cost" + + if err := storDB.SetTPSharedGroups(snd); err != nil { + t.Error(err) + } + // READ + if rcv, err := storDB.GetTPSharedGroups("TP1", ""); err != nil { + t.Error(err) + } else if sort.Slice(rcv, func(i, j int) bool { + return rcv[i].ID < rcv[j].ID + }); snd[0].SharedGroups[0].Strategy != rcv[0].SharedGroups[0].Strategy { + t.Errorf("Expected %v, Received %v", utils.ToJSON(rcv[0]), utils.ToJSON(snd[0])) + } + // REMOVE + if err := storDB.RemTpData("", "TP1", nil); err != nil { + t.Error(err) + } + // READ + if _, err := storDB.GetTPSharedGroups("TP1", ""); err != utils.ErrNotFound { + t.Error(err) + } +}