Files
cgrates/resources/resources_it_test.go

831 lines
23 KiB
Go

//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 <https://www.gnu.org/licenses/>
*/
package resources
import (
"io"
"net/http"
"net/http/httptest"
"os"
"path"
"reflect"
"sort"
"testing"
"time"
"github.com/cgrates/birpc"
"github.com/cgrates/birpc/context"
"github.com/cgrates/cgrates/utils"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/engine"
)
var (
rsSrv *httptest.Server
rsBody []byte
rsCfgPath string
rsCfg *config.CGRConfig
rsRPC *birpc.Client
rsConfigDIR string //run tests for specific configuration
sTestsRs = []func(t *testing.T){
testResourceSInitCfg,
testResourceSInitDataDB,
testResourceSStartEngine,
testResourceSRPCConn,
testResourceSGetResourceBeforeSet,
testResourceSGetResourceProfileBeforeSet,
testResourceSSetResourceProfiles,
testResourceSGetResourceAfterSet,
testResourceSGetResourceWithConfigAfterSet,
testResourceSGetResourceProfileIDs,
testResourceSGetResourceProfiles,
testResourceSGetResourceProfilesCount,
testResourceSGetResourcesForEvent,
testResourceSAllocateResources,
testResourceSAuthorizeResourcesBeforeRelease,
testResourceSReleaseResources,
testResourceSAuthorizeResourcesAfterRelease,
testResourceSRemoveResourceProfiles,
testResourceSGetResourceProfilesAfterRemove,
testResourceSPing,
testResourceSGetResourceProfilesWithPrefix,
testResourceSKillEngine,
// check threshold behaviour after allocation/release of resources
testResourceSInitCfg,
testResourceSInitDataDB,
testResourceSStartEngine,
testResourceSRPCConn,
testResourceSStartServer,
testResourceSSetActionProfile,
testResourceSSetThresholdProfile,
testResourceSSetResourceProfile,
testResourceSCheckThresholdAfterResourceAllocate,
testResourceSCheckThresholdAfterResourceRelease,
testResourceSStopServer,
testResourceSKillEngine,
}
)
func TestResourceSIT(t *testing.T) {
switch *utils.DBType {
case utils.MetaInternal:
rsConfigDIR = "resources_internal"
if err := os.MkdirAll("/tmp/internal_db/db", 0755); err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
if err := os.RemoveAll("/tmp/internal_db"); err != nil {
t.Error(err)
}
})
case utils.MetaMongo:
rsConfigDIR = "resources_mongo"
case utils.MetaRedis:
rsConfigDIR = "resources_redis"
case utils.MetaMySQL:
rsConfigDIR = "resources_mysql"
case utils.MetaPostgres:
rsConfigDIR = "resources_postgres"
default:
t.Fatal("Unknown Database type")
}
for _, stest := range sTestsRs {
t.Run(rsConfigDIR, stest)
}
}
func testResourceSInitCfg(t *testing.T) {
var err error
rsCfgPath = path.Join(*utils.DataDir, "conf", "samples", rsConfigDIR)
rsCfg, err = config.NewCGRConfigFromPath(context.Background(), rsCfgPath)
if err != nil {
t.Error(err)
}
}
func testResourceSInitDataDB(t *testing.T) {
if err := engine.InitDB(rsCfg); err != nil {
t.Fatal(err)
}
}
// Start CGR Engine
func testResourceSStartEngine(t *testing.T) {
if _, err := engine.StopStartEngine(rsCfgPath, *utils.WaitRater); err != nil {
t.Fatal(err)
}
}
func testResourceSRPCConn(t *testing.T) {
rsRPC = engine.NewRPCClient(t, rsCfg.ListenCfg(), *utils.Encoding)
}
// Kill the engine when it is about to be finished
func testResourceSKillEngine(t *testing.T) {
if err := engine.KillEngine(100); err != nil {
t.Error(err)
}
}
func testResourceSGetResourceBeforeSet(t *testing.T) { // cache it with not found
var rplyRes *utils.Resource
if err := rsRPC.Call(context.Background(), utils.ResourceSv1GetResource,
&utils.TenantIDWithAPIOpts{
TenantID: &utils.TenantID{
Tenant: "cgrates.org",
ID: "ResGroup1",
}}, &rplyRes); err == nil || err.Error() != utils.ErrNotFound.Error() {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err)
}
}
func testResourceSGetResourceProfileBeforeSet(t *testing.T) { // cache it with not found
var rplyRes *[]*utils.ResourceProfile
var args *utils.ArgsItemIDs
if err := rsRPC.Call(context.Background(), utils.AdminSv1GetResourceProfiles,
args, &rplyRes); err == nil || err.Error() != utils.ErrNotFound.Error() {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err)
}
}
func testResourceSSetResourceProfiles(t *testing.T) {
rsPrf1 := &utils.ResourceProfileWithAPIOpts{
ResourceProfile: &utils.ResourceProfile{
Tenant: "cgrates.org",
ID: "ResGroup1",
FilterIDs: []string{"*string:~*req.Account:1001"},
Limit: 10,
AllocationMessage: "Approved",
Weights: utils.DynamicWeights{
{
Weight: 20,
}},
ThresholdIDs: []string{utils.MetaNone},
},
}
var reply string
if err := rsRPC.Call(context.Background(), utils.AdminSv1SetResourceProfile,
rsPrf1, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error("Unexpected reply returned", reply)
}
rsPrf2 := &utils.ResourceProfileWithAPIOpts{
ResourceProfile: &utils.ResourceProfile{
Tenant: "cgrates.org",
ID: "ResGroup2",
FilterIDs: []string{"*string:~*req.Account:1001"},
Limit: 10,
AllocationMessage: "Approved",
Weights: utils.DynamicWeights{
{
Weight: 10,
}},
ThresholdIDs: []string{utils.MetaNone},
},
}
if err := rsRPC.Call(context.Background(), utils.AdminSv1SetResourceProfile,
rsPrf2, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error("Unexpected reply returned", reply)
}
}
func testResourceSGetResourceAfterSet(t *testing.T) {
var rplyRes utils.Resource
var rplyResPrf utils.ResourceProfile
expRes := utils.Resource{
Tenant: "cgrates.org",
ID: "ResGroup1",
Usages: make(map[string]*utils.ResourceUsage),
}
expResPrf := utils.ResourceProfile{
Tenant: "cgrates.org",
ID: "ResGroup1",
FilterIDs: []string{"*string:~*req.Account:1001"},
Limit: 10,
AllocationMessage: "Approved",
Weights: utils.DynamicWeights{
{
Weight: 20,
}},
ThresholdIDs: []string{utils.MetaNone},
}
if err := rsRPC.Call(context.Background(), utils.ResourceSv1GetResource,
&utils.TenantIDWithAPIOpts{
TenantID: &utils.TenantID{
Tenant: "cgrates.org",
ID: "ResGroup1"}}, &rplyRes); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rplyRes, expRes) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>",
utils.ToJSON(expRes), utils.ToJSON(rplyRes))
}
if err := rsRPC.Call(context.Background(), utils.AdminSv1GetResourceProfile,
utils.TenantID{
Tenant: "cgrates.org",
ID: "ResGroup1",
}, &rplyResPrf); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rplyResPrf, expResPrf) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>",
utils.ToJSON(expResPrf), utils.ToJSON(rplyResPrf))
}
expRes = utils.Resource{
Tenant: "cgrates.org",
ID: "ResGroup2",
Usages: make(map[string]*utils.ResourceUsage),
}
expResPrf = utils.ResourceProfile{
Tenant: "cgrates.org",
ID: "ResGroup2",
FilterIDs: []string{"*string:~*req.Account:1001"},
Limit: 10,
AllocationMessage: "Approved",
Weights: utils.DynamicWeights{
{
Weight: 10,
}},
ThresholdIDs: []string{utils.MetaNone},
}
if err := rsRPC.Call(context.Background(), utils.ResourceSv1GetResource,
&utils.TenantIDWithAPIOpts{
TenantID: &utils.TenantID{
Tenant: "cgrates.org",
ID: "ResGroup2"}}, &rplyRes); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rplyRes, expRes) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>",
utils.ToJSON(expRes), utils.ToJSON(rplyRes))
}
if err := rsRPC.Call(context.Background(), utils.AdminSv1GetResourceProfile,
utils.TenantID{
Tenant: "cgrates.org",
ID: "ResGroup2",
}, &rplyResPrf); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rplyResPrf, expResPrf) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>",
utils.ToJSON(expResPrf), utils.ToJSON(rplyResPrf))
}
}
func testResourceSGetResourceWithConfigAfterSet(t *testing.T) {
var rplyRes utils.ResourceWithConfig
expRes := utils.ResourceWithConfig{
Resource: &utils.Resource{
Tenant: "cgrates.org",
ID: "ResGroup2",
Usages: make(map[string]*utils.ResourceUsage),
},
Config: &utils.ResourceProfile{
Tenant: "cgrates.org",
ID: "ResGroup2",
FilterIDs: []string{"*string:~*req.Account:1001"},
Limit: 10,
AllocationMessage: "Approved",
Weights: utils.DynamicWeights{
{
Weight: 10,
}},
ThresholdIDs: []string{utils.MetaNone},
},
}
if err := rsRPC.Call(context.Background(), utils.ResourceSv1GetResourceWithConfig,
&utils.TenantIDWithAPIOpts{
TenantID: &utils.TenantID{
Tenant: "cgrates.org",
ID: "ResGroup2"}}, &rplyRes); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(rplyRes, expRes) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>",
utils.ToJSON(expRes), utils.ToJSON(rplyRes))
}
}
func testResourceSGetResourceProfileIDs(t *testing.T) {
var reply []string
exp := []string{"ResGroup1", "ResGroup2"}
if err := rsRPC.Call(context.Background(), utils.AdminSv1GetResourceProfileIDs,
&utils.ArgsItemIDs{
Tenant: "cgrates.org",
}, &reply); err != nil {
t.Error(err)
} else {
sort.Strings(reply)
if !reflect.DeepEqual(reply, exp) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", exp, reply)
}
}
}
func testResourceSGetResourceProfiles(t *testing.T) {
var rplyRes []*utils.ResourceProfile
var args *utils.ArgsItemIDs
exp := []*utils.ResourceProfile{
{
Tenant: "cgrates.org",
ID: "ResGroup1",
FilterIDs: []string{"*string:~*req.Account:1001"},
Limit: 10,
AllocationMessage: "Approved",
Weights: utils.DynamicWeights{
{
Weight: 20,
}},
ThresholdIDs: []string{utils.MetaNone},
},
{
Tenant: "cgrates.org",
ID: "ResGroup2",
FilterIDs: []string{"*string:~*req.Account:1001"},
Limit: 10,
AllocationMessage: "Approved",
Weights: utils.DynamicWeights{
{
Weight: 10,
}},
ThresholdIDs: []string{utils.MetaNone},
},
}
if err := rsRPC.Call(context.Background(), utils.AdminSv1GetResourceProfiles,
args, &rplyRes); err != nil {
t.Error(err)
}
sort.Slice(rplyRes, func(i int, j int) bool {
return rplyRes[i].ID < rplyRes[j].ID
})
if !reflect.DeepEqual(rplyRes, exp) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", exp, rplyRes)
}
}
func testResourceSGetResourceProfilesCount(t *testing.T) {
var reply int
if err := rsRPC.Call(context.Background(), utils.AdminSv1GetResourceProfilesCount,
&utils.TenantWithAPIOpts{Tenant: "cgrates.org"}, &reply); err != nil {
t.Error(err)
} else if reply != 2 {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", 2, reply)
}
}
func testResourceSGetResourcesForEvent(t *testing.T) {
args := &utils.CGREvent{
Event: map[string]any{
utils.AccountField: "1001",
},
ID: "EventTest",
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "RU_Test",
utils.OptsResourcesUnits: 2,
},
}
exp := Resources{
{
Resource: &utils.Resource{
Tenant: "cgrates.org",
ID: "ResGroup1",
Usages: make(map[string]*utils.ResourceUsage),
},
},
{
Resource: &utils.Resource{
Tenant: "cgrates.org",
ID: "ResGroup2",
Usages: make(map[string]*utils.ResourceUsage),
},
},
}
var reply Resources
if err := rsRPC.Call(context.Background(), utils.ResourceSv1GetResourcesForEvent,
args, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(reply, exp) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>",
utils.ToJSON(exp), utils.ToJSON(reply))
}
}
func testResourceSAllocateResources(t *testing.T) {
args := &utils.CGREvent{
Event: map[string]any{
utils.AccountField: "1001",
},
ID: "EventTest",
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "RU_Test",
utils.OptsResourcesUnits: 6,
utils.OptsResourcesUsageTTL: time.Minute,
},
}
var reply string
if err := rsRPC.Call(context.Background(), utils.ResourceSv1AllocateResources,
args, &reply); err != nil {
t.Error(err)
} else if reply != "Approved" {
t.Error("Unexpected reply returned:", reply)
}
}
func testResourceSAuthorizeResourcesBeforeRelease(t *testing.T) {
args := &utils.CGREvent{
Event: map[string]any{
utils.AccountField: "1001",
},
ID: "EventTest",
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "RU_Test",
utils.OptsResourcesUnits: 7,
utils.OptsResourcesUsageTTL: time.Minute,
},
}
var reply string
if err := rsRPC.Call(context.Background(), utils.ResourceSv1AuthorizeResources,
args, &reply); err == nil || err.Error() != utils.ErrResourceUnauthorized.Error() {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrResourceUnauthorized, err)
}
}
func testResourceSReleaseResources(t *testing.T) {
args := &utils.CGREvent{
Event: map[string]any{
utils.AccountField: "1001",
},
ID: "EventTest",
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "RU_Test",
utils.OptsResourcesUnits: 4,
utils.OptsResourcesUsageTTL: time.Minute,
},
}
var reply string
if err := rsRPC.Call(context.Background(), utils.ResourceSv1ReleaseResources,
args, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error("Unexpected reply returned:", reply)
}
}
func testResourceSAuthorizeResourcesAfterRelease(t *testing.T) {
args := &utils.CGREvent{
Event: map[string]any{
utils.AccountField: "1001",
},
ID: "EventTest",
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "RU_Test",
utils.OptsResourcesUnits: 7,
utils.OptsResourcesUsageTTL: time.Minute,
},
}
var reply string
if err := rsRPC.Call(context.Background(), utils.ResourceSv1AuthorizeResources,
args, &reply); err != nil {
t.Error(err)
} else if reply != "Approved" {
t.Error("Unexpected reply returned:", reply)
}
}
func testResourceSRemoveResourceProfiles(t *testing.T) {
var reply string
if err := rsRPC.Call(context.Background(), utils.AdminSv1RemoveResourceProfile,
&utils.TenantIDWithAPIOpts{TenantID: &utils.TenantID{
Tenant: "cgrates.org",
ID: "ResGroup1",
}}, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error("Unexpected reply returned:", reply)
}
if err := rsRPC.Call(context.Background(), utils.AdminSv1RemoveResourceProfile,
&utils.TenantIDWithAPIOpts{TenantID: &utils.TenantID{
Tenant: "cgrates.org",
ID: "ResGroup2",
}}, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error("Unexpected reply returned:", reply)
}
}
func testResourceSGetResourceProfilesAfterRemove(t *testing.T) {
var rplyResPrf utils.ResourceProfile
if err := rsRPC.Call(context.Background(), utils.AdminSv1GetResourceProfile,
utils.TenantID{
Tenant: "cgrates.org",
ID: "ResGroup1",
}, &rplyResPrf); err.Error() != utils.ErrNotFound.Error() {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err)
}
if err := rsRPC.Call(context.Background(), utils.AdminSv1GetResourceProfile,
utils.TenantID{
Tenant: "cgrates.org",
ID: "ResGroup2",
}, &rplyResPrf); err.Error() != utils.ErrNotFound.Error() {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", utils.ErrNotFound, err)
}
}
func testResourceSPing(t *testing.T) {
var reply string
if err := rsRPC.Call(context.Background(), utils.ResourceSv1Ping,
new(utils.CGREvent), &reply); err != nil {
t.Error(err)
} else if reply != utils.Pong {
t.Error("Unexpected reply returned:", reply)
}
}
func testResourceSStartServer(t *testing.T) {
rsSrv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var err error
rsBody, err = io.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusNotFound)
}
r.Body.Close()
}))
}
func testResourceSStopServer(t *testing.T) {
rsSrv.Close()
}
func testResourceSSetActionProfile(t *testing.T) {
actPrf := &utils.ActionProfileWithAPIOpts{
ActionProfile: &utils.ActionProfile{
Tenant: "cgrates.org",
ID: "actPrfID",
Actions: []*utils.APAction{
{
ID: "actID",
Type: utils.MetaHTTPPost,
Diktats: []*utils.APDiktat{
{
ID: "HttpsPost",
Opts: map[string]any{
"*url": rsSrv.URL,
},
},
},
TTL: time.Duration(time.Minute),
},
},
},
}
var reply *string
if err := rsRPC.Call(context.Background(), utils.AdminSv1SetActionProfile,
actPrf, &reply); err != nil {
t.Error(err)
}
}
func testResourceSSetThresholdProfile(t *testing.T) {
thPrf := &engine.ThresholdProfileWithAPIOpts{
ThresholdProfile: &engine.ThresholdProfile{
Tenant: "cgrates.org",
FilterIDs: []string{"*string:~*opts.*eventType:ResourceUpdate"},
ID: "THD_1",
MaxHits: -1,
ActionProfileIDs: []string{"actPrfID"},
},
}
var reply string
if err := rsRPC.Call(context.Background(), utils.AdminSv1SetThresholdProfile,
thPrf, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error("Unexpected reply returned", reply)
}
args := &utils.TenantID{
Tenant: "cgrates.org",
ID: "THD_1",
}
var result *engine.ThresholdProfile
if err := rsRPC.Call(context.Background(), utils.AdminSv1GetThresholdProfile,
args, &result); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(result, thPrf.ThresholdProfile) {
t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>",
utils.ToJSON(thPrf.ThresholdProfile), utils.ToJSON(result))
}
}
func testResourceSSetResourceProfile(t *testing.T) {
rsPrf := &utils.ResourceProfile{
Tenant: "cgrates.org",
ID: "RES_1",
FilterIDs: []string{"*string:~*req.Account:1001"},
AllocationMessage: "Approved",
Limit: 10,
ThresholdIDs: []string{"THD_1"},
}
var reply string
if err := rsRPC.Call(context.Background(), utils.AdminSv1SetResourceProfile,
rsPrf, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error("Unexpected reply returned", reply)
}
var result *utils.ResourceProfile
if err := rsRPC.Call(context.Background(), utils.AdminSv1GetResourceProfile,
&utils.TenantID{Tenant: "cgrates.org", ID: rsPrf.ID}, &result); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(result, rsPrf) {
t.Errorf("expected: %+v, received: %+v",
utils.ToJSON(rsPrf), utils.ToJSON(result))
}
}
func testResourceSCheckThresholdAfterResourceAllocate(t *testing.T) {
var reply string
argsRU := &utils.CGREvent{
Tenant: "cgrates.org",
ID: "EV_1",
Event: map[string]any{
utils.AccountField: "1001",
},
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "RU_1",
utils.OptsResourcesUnits: 1,
},
}
expBody := `{"*opts":{"*actProfileIDs":["actPrfID"],"*eventType":"ResourceUpdate","*resUnits":1,"*resUsageID":"RU_1","*thdProfileIDs":["THD_1"]},"*req":{"EventType":"ResourceUpdate","ResourceID":"RES_1","Usage":1}}`
if err := rsRPC.Call(context.Background(), utils.ResourceSv1AllocateResources,
argsRU, &reply); err != nil {
t.Error(err)
} else if reply != "Approved" {
t.Error("Unexpected reply returned", reply)
}
if expBody != string(rsBody) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", expBody, string(rsBody))
}
args := &utils.TenantID{
Tenant: "cgrates.org",
ID: "THD_1",
}
var result *engine.Threshold
if err := rsRPC.Call(context.Background(), utils.ThresholdSv1GetThreshold,
args, &result); err != nil {
t.Error(err)
} else if result.Hits != 1 {
t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", 1, result.Hits)
}
}
func testResourceSCheckThresholdAfterResourceRelease(t *testing.T) {
argsRU := &utils.CGREvent{
Tenant: "cgrates.org",
ID: "EV_1",
Event: map[string]any{
utils.AccountField: "1001",
},
APIOpts: map[string]any{
utils.OptsResourcesUsageID: "RU_1",
},
}
var reply string
if err := rsRPC.Call(context.Background(), utils.ResourceSv1ReleaseResources,
argsRU, &reply); err != nil {
t.Error(err)
}
args := &utils.TenantID{
Tenant: "cgrates.org",
ID: "THD_1",
}
var result *engine.Threshold
if err := rsRPC.Call(context.Background(), utils.ThresholdSv1GetThreshold,
args, &result); err != nil {
t.Error(err)
} else if result.Hits != 2 {
t.Errorf("\nexpected: <%+v>, \nreceived: <%+v>", 2, result.Hits)
}
}
func testResourceSGetResourceProfilesWithPrefix(t *testing.T) {
rsPrf1 := &utils.ResourceProfileWithAPIOpts{
ResourceProfile: &utils.ResourceProfile{
Tenant: "cgrates.org",
ID: "PrefixResGroup1",
FilterIDs: []string{"*string:~*req.Account:1001"},
Limit: 10,
AllocationMessage: "Approved",
Weights: utils.DynamicWeights{
{
Weight: 20,
}},
ThresholdIDs: []string{utils.MetaNone},
},
}
var reply string
if err := rsRPC.Call(context.Background(), utils.AdminSv1SetResourceProfile,
rsPrf1, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error("Unexpected reply returned", reply)
}
rsPrf2 := &utils.ResourceProfileWithAPIOpts{
ResourceProfile: &utils.ResourceProfile{
Tenant: "cgrates.org",
ID: "ResGroup2",
FilterIDs: []string{"*string:~*req.Account:1001"},
Limit: 10,
AllocationMessage: "Approved",
Weights: utils.DynamicWeights{
{
Weight: 10,
}},
ThresholdIDs: []string{utils.MetaNone},
},
}
if err := rsRPC.Call(context.Background(), utils.AdminSv1SetResourceProfile,
rsPrf2, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error("Unexpected reply returned", reply)
}
var rplyRes []*utils.ResourceProfile
args := &utils.ArgsItemIDs{
ItemsPrefix: "PrefixRes",
}
exp := []*utils.ResourceProfile{
{
Tenant: "cgrates.org",
ID: "PrefixResGroup1",
FilterIDs: []string{"*string:~*req.Account:1001"},
Limit: 10,
AllocationMessage: "Approved",
Weights: utils.DynamicWeights{
{
Weight: 20,
}},
ThresholdIDs: []string{utils.MetaNone},
},
}
if err := rsRPC.Call(context.Background(), utils.AdminSv1GetResourceProfiles,
args, &rplyRes); err != nil {
t.Error(err)
}
if !reflect.DeepEqual(rplyRes, exp) {
t.Errorf("expected: <%+v>, \nreceived: <%+v>", exp, rplyRes)
}
}