//go:build integration // +build integration /* Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments Copyright (C) ITsysCOM GmbH This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see */ package general_tests import ( "bufio" "fmt" "os" "path" "path/filepath" "reflect" "sort" "strconv" "testing" "time" "github.com/cgrates/birpc/context" v1 "github.com/cgrates/cgrates/apier/v1" v2 "github.com/cgrates/cgrates/apier/v2" "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" ) func TestOfflineInternal(t *testing.T) { // run with sudo paths := []string{ path.Join(*utils.DataDir, "conf", "samples", "offline_internal"), // dump -1 path.Join(*utils.DataDir, "conf", "samples", "offline_internal_ms"), // dump ms path.Join(*utils.DataDir, "conf", "samples", "offline_internal_rewrite"), // dump -1 and rewrite -1 path.Join(*utils.DataDir, "conf", "samples", "offline_internal_rewrite_ms"), // dump -1 and rewrite ms path.Join(*utils.DataDir, "conf", "samples", "offline_internal_ms_rewrite"), // dump ms and rewrite -1 path.Join(*utils.DataDir, "conf", "samples", "offline_internal_ms_rewrite_ms"), // dump ms and rewrite ms path.Join(*utils.DataDir, "conf", "samples", "offline_internal_limit"), // dump -1 and limit passed path.Join(*utils.DataDir, "conf", "samples", "offline_internal_ms_limit"), // dump ms and limit passed path.Join(*utils.DataDir, "conf", "samples", "offline_internal_rewrite_limit"), // dump -1 and rewrite -1 and limit passed path.Join(*utils.DataDir, "conf", "samples", "offline_internal_rewrite_ms_limit"), // dump -1 and rewrite ms and limit passed path.Join(*utils.DataDir, "conf", "samples", "offline_internal_ms_rewrite_limit"), // dump ms and rewrite -1 and limit passed path.Join(*utils.DataDir, "conf", "samples", "offline_internal_ms_rewrite_ms_limit"), // dump ms and rewrite ms and limit passed } for i, pth := range paths { if err := os.MkdirAll(config.NewDefaultCGRConfig().DataDbCfg().Opts.InternalDBDumpPath, 0755); err != nil { t.Fatal(err) } if err := os.MkdirAll(config.NewDefaultCGRConfig().StorDbCfg().Opts.InternalDBDumpPath, 0755); err != nil { t.Fatal(err) } t.Run("OfflineInternal"+strconv.Itoa(i), func(t *testing.T) { ng := engine.TestEngine{ ConfigPath: pth, GracefulShutdown: true, } client, cfg := ng.Run(t) time.Sleep(100 * time.Millisecond) t.Run("LoadTariffs", func(t *testing.T) { attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*utils.DataDir, "tariffplans", "testit")} var loadInst utils.LoadInstance if err := client.Call(context.Background(), utils.APIerSv2LoadTariffPlanFromFolder, attrs, &loadInst); err != nil { t.Error(err) } time.Sleep(100 * time.Millisecond) }) t.Run("ExportDataDB", func(t *testing.T) { // exports Attributes, Chargers, Dispatchers, DispatcherHosts, Filters, Resources, Stats, Routes, Thresholds, Rankings, Trends var reply string if err := client.Call(context.Background(), utils.APIerSv1ExportToFolder, utils.ArgExportToFolder{Path: "/tmp/ExportPath1"}, &reply); err != nil { t.Error(err) } else if reply != utils.OK { t.Errorf("Expected: <%v>, received: <%v>", utils.OK, reply) } }) var acnts []*engine.Account t.Run("GetAccounts", func(t *testing.T) { if err := client.Call(context.Background(), utils.APIerSv2GetAccounts, &utils.AttrGetAccounts{ Tenant: "cgrates.org", }, &acnts); err != nil { t.Errorf("APIerSv2GetAccounts failed unexpectedly: %v", err) } if len(acnts) != 2 { t.Fatalf("APIerSv2GetAccounts len(acnts)=%v, want 2", len(acnts)) } sort.Slice(acnts, func(i, j int) bool { return acnts[i].ID > acnts[j].ID }) }) ratingPl := new(engine.RatingPlan) ratingPl2 := new(engine.RatingPlan) ratingPl3 := new(engine.RatingPlan) ratingPl4 := new(engine.RatingPlan) ratingPl5 := new(engine.RatingPlan) ratingPl6 := new(engine.RatingPlan) ratingPl7 := new(engine.RatingPlan) ratingPl8 := new(engine.RatingPlan) ratingPl9 := new(engine.RatingPlan) ratingPl10 := new(engine.RatingPlan) ratingPl11 := new(engine.RatingPlan) t.Run("GetRatingPlans", func(t *testing.T) { rplnId := "RP_TESTIT1" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, ratingPl); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } rplnId = "RP_SPECIAL_1002" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, ratingPl2); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } rplnId = "RP_RETAIL1" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, ratingPl3); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } rplnId = "RP_ANY2CNT" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, ratingPl4); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } rplnId = "RP_ANY1CNT" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, ratingPl5); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } rplnId = "RP_TEST" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, ratingPl6); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } rplnId = "RP_MOBILE" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, ratingPl7); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } rplnId = "RP_LOCAL" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, ratingPl8); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } rplnId = "RP_FREE" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, ratingPl9); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } rplnId = "RP_ANY2CNT_SEC" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, ratingPl10); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } rplnId = "RP_ANY1CNT_SEC" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, ratingPl11); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } }) var rProf engine.RatingProfile t.Run("GetRatingProfile", func(t *testing.T) { if err := client.Call(context.Background(), utils.APIerSv1GetRatingProfile, &utils.AttrGetRatingProfile{ Tenant: "cgrates.org", Category: "free", Subject: "RP_FREE", }, &rProf); err != nil { t.Error(err) } }) var dests []*engine.Destination t.Run("GetDestinations", func(t *testing.T) { attrs := &v2.AttrGetDestinations{DestinationIDs: []string{}} if err := client.Call(context.Background(), utils.APIerSv2GetDestinations, attrs, &dests); err != nil { t.Error("Got error on APIerSv2.GetDestinations: ", err.Error()) } }) var rdID1, rdID2, rdID3, rdID4, rdID5, rdID6, rdID7 []string t.Run("GetReverseDestination", func(t *testing.T) { checkRD := func(t *testing.T, dst string) (rpl []string) { if err := client.Call(context.Background(), utils.APIerSv1GetReverseDestination, utils.StringPointer(dst), &rpl); err != nil { t.Errorf("Error dst <%s>, <%v>", dst, err) } return } rdID1 = checkRD(t, "1001") rdID2 = checkRD(t, "1002") rdID3 = checkRD(t, "+49151") rdID4 = checkRD(t, "077") rdID5 = checkRD(t, "10") rdID6 = checkRD(t, "+246") rdID7 = checkRD(t, "+135") }) var actsMp map[string]engine.Actions t.Run("GetActions", func(t *testing.T) { if err := client.Call(context.Background(), utils.APIerSv2GetActions, &v2.AttrGetActions{}, &actsMp); err != nil { t.Error(err) } }) var atr engine.ActionTriggers t.Run("GetActionTriggers", func(t *testing.T) { var reply string if err := client.Call(context.Background(), utils.APIerSv1SetActionTrigger, engine.AttrSetActionTrigger{ GroupID: "GroupID", UniqueID: "ID", ActionTrigger: map[string]any{ utils.ThresholdType: "THR", utils.ThresholdValue: 10, utils.Recurrent: false, utils.Executed: false, utils.MinSleep: time.Second, utils.ExpirationDate: time.Now(), utils.ActivationDate: time.Now(), utils.BalanceID: "*default", utils.BalanceType: "*call", utils.BalanceDestinationIds: []any{"DST1", "DST2"}, utils.BalanceWeight: 10, utils.BalanceExpirationDate: time.Now(), utils.BalanceTimingTags: []string{"*asap"}, utils.BalanceCategories: []string{utils.Call}, utils.BalanceSharedGroups: []string{"SHRGroup"}, utils.BalanceBlocker: true, utils.ActionsID: "ACT1", utils.MinQueuedItems: 5, }, }, &reply); err != nil { t.Error(err) } else if reply != utils.OK { t.Errorf("Calling v1.SetActionTrigger got: %v", reply) } if err := client.Call(context.Background(), utils.APIerSv1GetActionTriggers, &v1.AttrGetActionTriggers{GroupIDs: []string{}}, &atr); err != nil { t.Error(err) } }) var aps []*engine.ActionPlan t.Run("GetActionPlan", func(t *testing.T) { var reply string atms1 := &engine.AttrSetActionPlan{ Id: "ATMS_1", ActionPlan: []*engine.AttrActionPlan{ { ActionsId: "ACTION_TOPUP_RESET_SMS", MonthDays: "1", Time: "00:00:00", Weight: 20.0}, }, } if err := client.Call(context.Background(), utils.APIerSv1SetActionPlan, &atms1, &reply); err != nil { t.Error("Got error on APIerSv1.SetActionPlan: ", err.Error()) } else if reply != utils.OK { t.Errorf("Unexpected reply returned: %s", reply) } if err := client.Call(context.Background(), utils.APIerSv1GetActionPlan, &v1.AttrGetActionPlan{ID: "ATMS_1"}, &aps); err != nil { t.Error(err) } }) t.Run("EngineShutdown", func(t *testing.T) { if err := engine.KillEngine(100); err != nil { t.Error(err) } }) t.Run("CountDataDBFiles", func(t *testing.T) { var dirs, files int if err := filepath.Walk(cfg.DataDbCfg().Opts.InternalDBDumpPath, func(_ string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { dirs++ } else { files++ } return nil }); err != nil { t.Error(err) } else if dirs != 43 { t.Errorf("expected <%d> directories, received <%d>", 43, dirs) } else if i > 6 && (files != 29 && files != 30) { // depends if rewriting is scheduled or not by the time we shutdown t.Errorf("expected 29 or 30 files, received <%d>", files) } else if i < 6 && files != 28 { t.Errorf("expected <%d> files, received <%d>", 28, files) } }) t.Run("CountStorDBFiles", func(t *testing.T) { var dirs, files int if err := filepath.Walk(cfg.StorDbCfg().Opts.InternalDBDumpPath, func(_ string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { dirs++ } else { files++ } return nil }); err != nil { t.Error(err) } else if dirs != 28 { t.Errorf("expected <%d> directories, received <%d>", 28, dirs) } else if files != 1 { t.Errorf("expected <%d> files, received <%d>", 1, files) } }) ng.PreserveDataDB = true ng.PreserveStorDB = true client, cfg = ng.Run(t) time.Sleep(100 * time.Millisecond) t.Run("ExportDataDB2", func(t *testing.T) { var reply string if err := client.Call(context.Background(), utils.APIerSv1ExportToFolder, utils.ArgExportToFolder{Path: "/tmp/ExportPath2"}, &reply); err != nil { t.Error(err) } else if reply != utils.OK { t.Errorf("Expected: <%v>, received: <%v>", utils.OK, reply) } }) t.Run("CompareExports", func(t *testing.T) { readLines := func(filePath string) ([]string, error) { file, err := os.Open(filePath) if err != nil { return nil, fmt.Errorf("error opening file %s: %v", filePath, err) } defer file.Close() var lines []string scanner := bufio.NewScanner(file) for scanner.Scan() { lines = append(lines, scanner.Text()) } if err := scanner.Err(); err != nil { return nil, fmt.Errorf("error reading file %s: %v", filePath, err) } sort.Strings(lines) return lines, nil } if err := filepath.Walk("/tmp/ExportPath1", func(path1 string, info1 os.FileInfo, err1 error) error { if err1 != nil { return err1 } relPath, err := filepath.Rel("/tmp/ExportPath1", path1) // save path that comes after /tmp/ExportPath1 if err != nil { return fmt.Errorf("error calculating relative path: %v", err) } path2 := filepath.Join("/tmp/ExportPath2", relPath) if _, err := os.Stat(path2); err != nil { return err } if info1.Mode().IsRegular() { lines1, err := readLines(path1) if err != nil { return err } lines2, err := readLines(path2) if err != nil { return err } if len(lines1) != len(lines2) { return fmt.Errorf("Line count doesnt match: <%v> \n\n<%v>", lines1, lines2) } for i := 0; i < len(lines1); i++ { if lines1[i] != lines2[i] { return fmt.Errorf("Files differ: %v <%v> \nand \n%v <%v>", path1, lines1[i], path2, lines2[i]) } } } return nil }); err != nil { t.Error(err) } }) t.Run("GetAccounts2", func(t *testing.T) { var acnts2 []*engine.Account if err := client.Call(context.Background(), utils.APIerSv2GetAccounts, &utils.AttrGetAccounts{ Tenant: "cgrates.org", }, &acnts2); err != nil { t.Errorf("APIerSv2GetAccounts failed unexpectedly: %v", err) } if len(acnts2) != 2 { t.Fatalf("APIerSv2GetAccounts len(acnts)=%v, want 2", len(acnts)) } sort.Slice(acnts2, func(i, j int) bool { return acnts2[i].ID > acnts2[j].ID }) if !reflect.DeepEqual(acnts2, acnts) { t.Errorf("Expected accounts to be the same. Before shutdown \n<%v>\nAfter rebooting <%v>", utils.ToJSON(acnts), utils.ToJSON(acnts2)) } }) t.Run("GetRatingPlans2", func(t *testing.T) { restoreRply := new(engine.RatingPlan) rplnId := "RP_TESTIT1" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, restoreRply); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } for rateId := range restoreRply.Ratings { if !reflect.DeepEqual(restoreRply.Ratings[rateId], ratingPl.Ratings[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply.Ratings[rateId], ratingPl.Ratings[rateId]) } } for rateId := range restoreRply.DestinationRates { if !reflect.DeepEqual(restoreRply.DestinationRates[rateId], ratingPl.DestinationRates[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply.DestinationRates[rateId], ratingPl.DestinationRates[rateId]) } } restoreRply2 := new(engine.RatingPlan) rplnId = "RP_SPECIAL_1002" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, restoreRply2); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } for rateId := range restoreRply2.Ratings { if !reflect.DeepEqual(restoreRply2.Ratings[rateId], ratingPl2.Ratings[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply2.Ratings[rateId], ratingPl2.Ratings[rateId]) } } for rateId := range restoreRply2.DestinationRates { if !reflect.DeepEqual(restoreRply2.DestinationRates[rateId], ratingPl2.DestinationRates[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply2.DestinationRates[rateId], ratingPl2.DestinationRates[rateId]) } } restoreRply3 := new(engine.RatingPlan) rplnId = "RP_RETAIL1" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, restoreRply3); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } for rateId := range restoreRply3.Ratings { if !reflect.DeepEqual(restoreRply3.Ratings[rateId], ratingPl3.Ratings[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply3.Ratings[rateId], ratingPl3.Ratings[rateId]) } } for rateId := range restoreRply3.DestinationRates { if !reflect.DeepEqual(restoreRply3.DestinationRates[rateId], ratingPl3.DestinationRates[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply3.DestinationRates[rateId], ratingPl3.DestinationRates[rateId]) } } restoreRply4 := new(engine.RatingPlan) rplnId = "RP_ANY2CNT" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, restoreRply4); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } for rateId := range restoreRply4.Ratings { if !reflect.DeepEqual(restoreRply4.Ratings[rateId], ratingPl4.Ratings[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply4.Ratings[rateId], ratingPl4.Ratings[rateId]) } } for rateId := range restoreRply4.DestinationRates { if !reflect.DeepEqual(restoreRply4.DestinationRates[rateId], ratingPl4.DestinationRates[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply4.DestinationRates[rateId], ratingPl4.DestinationRates[rateId]) } } restoreRply5 := new(engine.RatingPlan) rplnId = "RP_ANY1CNT" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, restoreRply5); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } for rateId := range restoreRply5.Ratings { if !reflect.DeepEqual(restoreRply5.Ratings[rateId], ratingPl5.Ratings[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply5.Ratings[rateId], ratingPl5.Ratings[rateId]) } } for rateId := range restoreRply5.DestinationRates { if !reflect.DeepEqual(restoreRply5.DestinationRates[rateId], ratingPl5.DestinationRates[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply5.DestinationRates[rateId], ratingPl5.DestinationRates[rateId]) } } restoreRply6 := new(engine.RatingPlan) rplnId = "RP_TEST" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, restoreRply6); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } for rateId := range restoreRply6.Ratings { if !reflect.DeepEqual(restoreRply6.Ratings[rateId], ratingPl6.Ratings[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply6.Ratings[rateId], ratingPl6.Ratings[rateId]) } } for rateId := range restoreRply6.DestinationRates { if !reflect.DeepEqual(restoreRply6.DestinationRates[rateId], ratingPl6.DestinationRates[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply6.DestinationRates[rateId], ratingPl6.DestinationRates[rateId]) } } restoreRply7 := new(engine.RatingPlan) rplnId = "RP_MOBILE" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, restoreRply7); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } for rateId := range restoreRply7.Ratings { if !reflect.DeepEqual(restoreRply7.Ratings[rateId], ratingPl7.Ratings[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply7.Ratings[rateId], ratingPl7.Ratings[rateId]) } } for rateId := range restoreRply7.DestinationRates { if !reflect.DeepEqual(restoreRply7.DestinationRates[rateId], ratingPl7.DestinationRates[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply7.DestinationRates[rateId], ratingPl7.DestinationRates[rateId]) } } restoreRply8 := new(engine.RatingPlan) rplnId = "RP_LOCAL" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, restoreRply8); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } for rateId := range restoreRply8.Ratings { if !reflect.DeepEqual(restoreRply8.Ratings[rateId], ratingPl8.Ratings[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply8.Ratings[rateId], ratingPl8.Ratings[rateId]) } } for rateId := range restoreRply8.DestinationRates { if !reflect.DeepEqual(restoreRply8.DestinationRates[rateId], ratingPl8.DestinationRates[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply8.DestinationRates[rateId], ratingPl8.DestinationRates[rateId]) } } restoreRply9 := new(engine.RatingPlan) rplnId = "RP_FREE" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, restoreRply9); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } for rateId := range restoreRply9.Ratings { if !reflect.DeepEqual(restoreRply9.Ratings[rateId], ratingPl9.Ratings[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply9.Ratings[rateId], ratingPl9.Ratings[rateId]) } } for rateId := range restoreRply9.DestinationRates { if !reflect.DeepEqual(restoreRply9.DestinationRates[rateId], ratingPl9.DestinationRates[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply9.DestinationRates[rateId], ratingPl9.DestinationRates[rateId]) } } restoreRply10 := new(engine.RatingPlan) rplnId = "RP_ANY2CNT_SEC" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, restoreRply10); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } for rateId := range restoreRply10.Ratings { if !reflect.DeepEqual(restoreRply10.Ratings[rateId], ratingPl10.Ratings[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply10.Ratings[rateId], ratingPl10.Ratings[rateId]) } } for rateId := range restoreRply10.DestinationRates { if !reflect.DeepEqual(restoreRply10.DestinationRates[rateId], ratingPl10.DestinationRates[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply10.DestinationRates[rateId], ratingPl10.DestinationRates[rateId]) } } restoreRply11 := new(engine.RatingPlan) rplnId = "RP_ANY1CNT_SEC" if err := client.Call(context.Background(), utils.APIerSv1GetRatingPlan, &rplnId, restoreRply11); err != nil { t.Error("Got error on APIerSv1.GetRatingPlan: ", err.Error()) } for rateId := range restoreRply11.Ratings { if !reflect.DeepEqual(restoreRply11.Ratings[rateId], ratingPl11.Ratings[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply11.Ratings[rateId], ratingPl11.Ratings[rateId]) } } for rateId := range restoreRply11.DestinationRates { if !reflect.DeepEqual(restoreRply11.DestinationRates[rateId], ratingPl11.DestinationRates[rateId]) { t.Errorf("expected <%+v>, \nreceived <%+v>", restoreRply11.DestinationRates[rateId], ratingPl11.DestinationRates[rateId]) } } }) t.Run("GetRatingProfiles2", func(t *testing.T) { var rcvRprof engine.RatingProfile if err := client.Call(context.Background(), utils.APIerSv1GetRatingProfile, &utils.AttrGetRatingProfile{ Tenant: "cgrates.org", Category: "free", Subject: "RP_FREE", }, &rcvRprof); err != nil { t.Error(err) } if !reflect.DeepEqual(rcvRprof, rProf) { t.Errorf("expected <%+v>, \nreceived <%+v>", rProf, rcvRprof) } }) t.Run("GetDestinations2", func(t *testing.T) { sort.Slice(dests, func(i, j int) bool { return dests[i].Id < dests[j].Id }) var rcv []*engine.Destination attrs := &v2.AttrGetDestinations{DestinationIDs: []string{}} if err := client.Call(context.Background(), utils.APIerSv2GetDestinations, attrs, &rcv); err != nil { t.Error("Got error on APIerSv2.GetDestinations: ", err.Error()) } sort.Slice(rcv, func(i, j int) bool { return rcv[i].Id < rcv[j].Id }) if !reflect.DeepEqual(dests, rcv) { t.Errorf("expected <%+v>, \nreceived <%+v>", dests, rcv) } }) t.Run("GetReverseDestination2", func(t *testing.T) { checkRD := func(t *testing.T, dst string) (rpl []string) { if err := client.Call(context.Background(), utils.APIerSv1GetReverseDestination, utils.StringPointer(dst), &rpl); err != nil { t.Errorf("Error dst <%s>, <%v>", dst, err) } return } rcvRdID1 := checkRD(t, "1001") rcvRdID2 := checkRD(t, "1002") rcvRdID3 := checkRD(t, "+49151") rcvRdID4 := checkRD(t, "077") rcvRdID5 := checkRD(t, "10") rcvRdID6 := checkRD(t, "+246") rcvRdID7 := checkRD(t, "+135") if !reflect.DeepEqual(rdID1, rcvRdID1) { t.Errorf("expected <%+v>, \nreceived <%+v>", rdID1, rcvRdID1) } if !reflect.DeepEqual(rdID2, rcvRdID2) { t.Errorf("expected <%+v>, \nreceived <%+v>", rdID2, rcvRdID2) } if !reflect.DeepEqual(rdID3, rcvRdID3) { t.Errorf("expected <%+v>, \nreceived <%+v>", rdID3, rcvRdID3) } if !reflect.DeepEqual(rdID4, rcvRdID4) { t.Errorf("expected <%+v>, \nreceived <%+v>", rdID4, rcvRdID4) } if !reflect.DeepEqual(rdID5, rcvRdID5) { t.Errorf("expected <%+v>, \nreceived <%+v>", rdID5, rcvRdID5) } if !reflect.DeepEqual(rdID6, rcvRdID6) { t.Errorf("expected <%+v>, \nreceived <%+v>", rdID6, rcvRdID6) } if !reflect.DeepEqual(rdID7, rcvRdID7) { t.Errorf("expected <%+v>, \nreceived <%+v>", rdID7, rcvRdID7) } }) t.Run("GetActions2", func(t *testing.T) { var rcv map[string]engine.Actions if err := client.Call(context.Background(), utils.APIerSv2GetActions, &v2.AttrGetActions{}, &rcv); err != nil { t.Error(err) } if len(actsMp) != len(rcv) { t.Errorf("Length of expected <%v>, doesnt match <%v>", len(actsMp), len(rcv)) } for id, acts := range actsMp { if len(acts) != len(rcv[id]) { t.Errorf("Length of expected <%v>, doesnt match <%v>", len(acts), len(rcv[id])) } for i, act := range acts { if rcv[id][i].Balance.Blocker == nil { rcv[id][i].Balance.Blocker = utils.BoolPointer(false) } if rcv[id][i].Balance.Disabled == nil { rcv[id][i].Balance.Disabled = utils.BoolPointer(false) } if rcv[id][i].Balance.ExpirationDate == nil { rcv[id][i].Balance.ExpirationDate = act.Balance.ExpirationDate } if !reflect.DeepEqual(utils.ToJSON(act), utils.ToJSON(rcv[id][i])) { t.Errorf("expected <%+v>, \nreceived <%+v>", utils.ToJSON(act), utils.ToJSON(rcv[id][i])) } } } }) t.Run("GetActionTriggers2", func(t *testing.T) { var rcv engine.ActionTriggers if err := client.Call(context.Background(), utils.APIerSv1GetActionTriggers, &v1.AttrGetActionTriggers{GroupIDs: []string{}}, &rcv); err != nil { t.Error(err) } if !reflect.DeepEqual(atr, rcv) { t.Errorf("expected <%+v>, \nreceived <%+v>", atr, rcv) } }) t.Run("GetActionPlan2", func(t *testing.T) { var rcv []*engine.ActionPlan if err := client.Call(context.Background(), utils.APIerSv1GetActionPlan, &v1.AttrGetActionPlan{ID: "ATMS_1"}, &rcv); err != nil { t.Error(err) } if len(aps) != 1 || len(rcv) != 1 { t.Errorf("expected aps len 1, got <%v>, expected rcv len 1, got <%v>", len(aps), len(rcv)) } if !reflect.DeepEqual(aps[0].Id, rcv[0].Id) { t.Errorf("expected <%+v>, \nreceived <%+v>", aps[0].Id, rcv[0].Id) } for id, actts := range aps[0].ActionTimings { if !reflect.DeepEqual(actts.ActionsID, rcv[0].ActionTimings[id].ActionsID) { t.Errorf("expected <%+v>, \nreceived <%+v>", actts.ActionsID, rcv[0].ActionTimings[id].ActionsID) } if !reflect.DeepEqual(actts.Uuid, rcv[0].ActionTimings[id].Uuid) { t.Errorf("expected <%+v>, \nreceived <%+v>", actts.Uuid, rcv[0].ActionTimings[id].Uuid) } if !reflect.DeepEqual(actts.ExtraData, rcv[0].ActionTimings[id].ExtraData) { t.Errorf("expected <%+v>, \nreceived <%+v>", actts.ExtraData, rcv[0].ActionTimings[id].ExtraData) } if !reflect.DeepEqual(actts.Weight, rcv[0].ActionTimings[id].Weight) { t.Errorf("expected <%+v>, \nreceived <%+v>", actts.Weight, rcv[0].ActionTimings[id].Weight) } } }) if err := os.RemoveAll("/var/lib/cgrates/internal_db"); err != nil { t.Error(err) } if err := os.RemoveAll("/tmp/ExportPath1"); err != nil { t.Error(err) } if err := os.RemoveAll("/tmp/ExportPath2"); err != nil { t.Error(err) } }) } }