mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
2733 lines
72 KiB
Go
2733 lines
72 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 apis
|
|
|
|
import (
|
|
"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 (
|
|
ratePrfCfgPath string
|
|
ratePrfCfg *config.CGRConfig
|
|
rateSRPC *birpc.Client
|
|
ratePrfConfigDIR string //run tests for specific configuration
|
|
|
|
sTestsRatePrf = []func(t *testing.T){
|
|
testRateSInitCfg,
|
|
testRateSInitDataDb,
|
|
|
|
testRateSStartEngine,
|
|
testRateSRPCConn,
|
|
testGetRateProfileBeforeSet,
|
|
testGetRateProfilesBeforeSet,
|
|
testRateSetRateProfile,
|
|
testRateGetRateProfileIDs,
|
|
testRateGetRateProfiles,
|
|
testRateGetRateCount,
|
|
testGetRateProfileBeforeSet2,
|
|
testRateSetRateProfile2,
|
|
testRateGetRateIDs2,
|
|
testRateGetRateProfiles2,
|
|
testRateGetRateCount2,
|
|
testRateRemoveRateProfile,
|
|
testRateGetRateProfileIDs,
|
|
testRateGetRateCount,
|
|
testRateSetRateProfile3,
|
|
testRateSetAttributeProfileBrokenReference,
|
|
testRateRemoveRateProfileRates,
|
|
testRateSetRateProfileRates,
|
|
testRateSetRateProfilesWithPrefix,
|
|
// here we will tests better the create,read,update and delte for the rates inside of a RateProfile
|
|
testRateProfileWithMultipleRates,
|
|
testRateProfileRateIDsAndCount,
|
|
testRateProfileUpdateRates,
|
|
testRateProfileRemoveMultipleRates,
|
|
testRateProfileSetMultipleRatesInProfile,
|
|
testRateProfileUpdateProfileRatesOverwrite,
|
|
testRateProfilesForEventMatchingEvents,
|
|
testRateProfileRatesForEventMatchingEvents,
|
|
|
|
// pagination tests
|
|
testRateSPaginateSetRateProfile,
|
|
testRateSPaginateGetRateProfile1,
|
|
testRateSPaginateGetRateProfile2,
|
|
testRateSPaginateGetRateProfile3,
|
|
testRateSKillEngine,
|
|
}
|
|
)
|
|
|
|
func TestRateSIT(t *testing.T) {
|
|
switch *utils.DBType {
|
|
case utils.MetaInternal:
|
|
ratePrfConfigDIR = "rates_internal"
|
|
case utils.MetaMongo:
|
|
ratePrfConfigDIR = "rates_mongo"
|
|
case utils.MetaRedis:
|
|
ratePrfConfigDIR = "rates_redis"
|
|
case utils.MetaMySQL:
|
|
ratePrfConfigDIR = "rates_mysql"
|
|
case utils.MetaPostgres:
|
|
ratePrfConfigDIR = "rates_postgres"
|
|
default:
|
|
t.Fatal("Unknown Database type")
|
|
}
|
|
for _, stest := range sTestsRatePrf {
|
|
t.Run(ratePrfConfigDIR, stest)
|
|
}
|
|
}
|
|
|
|
func testRateSInitCfg(t *testing.T) {
|
|
var err error
|
|
ratePrfCfgPath = path.Join(*utils.DataDir, "conf", "samples", ratePrfConfigDIR)
|
|
ratePrfCfg, err = config.NewCGRConfigFromPath(context.Background(), ratePrfCfgPath)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func testRateSInitDataDb(t *testing.T) {
|
|
if err := engine.InitDB(ratePrfCfg); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// Start CGR Engine
|
|
func testRateSStartEngine(t *testing.T) {
|
|
if _, err := engine.StopStartEngine(ratePrfCfgPath, *utils.WaitRater); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func testRateSRPCConn(t *testing.T) {
|
|
rateSRPC = engine.NewRPCClient(t, ratePrfCfg.ListenCfg(), *utils.Encoding)
|
|
}
|
|
|
|
func testGetRateProfileBeforeSet(t *testing.T) {
|
|
var reply *utils.RateProfile
|
|
var err error
|
|
if err = rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
&utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST",
|
|
},
|
|
}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func testGetRateProfilesBeforeSet(t *testing.T) {
|
|
var reply []*utils.RateProfile
|
|
var args *utils.ArgsItemIDs
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfiles,
|
|
args, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
func testRateSetRateProfile(t *testing.T) {
|
|
ratePrf := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var reply string
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error(err)
|
|
}
|
|
|
|
expectedRate := &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
FilterIDs: nil,
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
FilterIDs: nil,
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: nil,
|
|
RecurrentFee: nil,
|
|
Unit: nil,
|
|
Increment: nil,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var result *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
&utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST",
|
|
},
|
|
}, &result); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(result, expectedRate) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expectedRate), utils.ToJSON(result))
|
|
}
|
|
}
|
|
|
|
func testRateGetRateProfileIDs(t *testing.T) {
|
|
var reply []string
|
|
args := &utils.ArgsItemIDs{
|
|
Tenant: "cgrates.org",
|
|
}
|
|
expected := []string{"TEST_RATE_IT_TEST"}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfileIDs,
|
|
args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if len(reply) != len(expected) {
|
|
t.Errorf("Expected %+v \n, received %+v", expected, reply)
|
|
}
|
|
}
|
|
|
|
func testRateGetRateProfiles(t *testing.T) {
|
|
var reply []*utils.RateProfile
|
|
args := &utils.ArgsItemIDs{
|
|
Tenant: "cgrates.org",
|
|
}
|
|
expected := []*utils.RateProfile{
|
|
{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
FilterIDs: nil,
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
FilterIDs: nil,
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: nil,
|
|
RecurrentFee: nil,
|
|
Unit: nil,
|
|
Increment: nil,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfiles,
|
|
args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(reply, expected) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expected), utils.ToJSON(reply))
|
|
}
|
|
}
|
|
|
|
func testRateGetRateCount(t *testing.T) {
|
|
var reply int
|
|
args := &utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
},
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfilesCount,
|
|
args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != 1 {
|
|
t.Errorf("Expected %+v \n, received %+v", 1, reply)
|
|
}
|
|
}
|
|
|
|
func testGetRateProfileBeforeSet2(t *testing.T) {
|
|
var reply *utils.TenantIDWithAPIOpts
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
&utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_SECOND",
|
|
},
|
|
}, &reply); err == nil || err.Error() != utils.ErrNotFound.Error() {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func testRateSetRateProfile2(t *testing.T) {
|
|
ratePrf := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_SECOND",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var reply string
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error(err)
|
|
}
|
|
|
|
expectedRate := &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_SECOND",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
FilterIDs: nil,
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
FilterIDs: nil,
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: nil,
|
|
RecurrentFee: nil,
|
|
Unit: nil,
|
|
Increment: nil,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var result *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
&utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_SECOND",
|
|
},
|
|
}, &result); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(result, expectedRate) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expectedRate), utils.ToJSON(result))
|
|
}
|
|
}
|
|
|
|
func testRateGetRateIDs2(t *testing.T) {
|
|
var reply []string
|
|
args := &utils.ArgsItemIDs{
|
|
Tenant: "cgrates.org",
|
|
}
|
|
expected := []string{"TEST_RATE_IT_TEST", "TEST_RATE_IT_TEST_SECOND"}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfileIDs,
|
|
args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if len(reply) != len(expected) {
|
|
t.Errorf("Expected %+v \n, received %+v", expected, reply)
|
|
}
|
|
}
|
|
|
|
func testRateGetRateProfiles2(t *testing.T) {
|
|
var reply []*utils.RateProfile
|
|
args := &utils.ArgsItemIDs{
|
|
Tenant: "cgrates.org",
|
|
}
|
|
expected := []*utils.RateProfile{
|
|
{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
FilterIDs: nil,
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
FilterIDs: nil,
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: nil,
|
|
RecurrentFee: nil,
|
|
Unit: nil,
|
|
Increment: nil,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_SECOND",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
FilterIDs: nil,
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfiles,
|
|
args, &reply); err != nil {
|
|
t.Error(err)
|
|
}
|
|
sort.Slice(reply, func(i, j int) bool {
|
|
return reply[i].ID < reply[j].ID
|
|
})
|
|
if !reflect.DeepEqual(reply, expected) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expected), utils.ToJSON(reply))
|
|
}
|
|
}
|
|
|
|
func testRateGetRateCount2(t *testing.T) {
|
|
var reply int
|
|
args := &utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
},
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfilesCount,
|
|
args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != 2 {
|
|
t.Errorf("Expected %+v \n, received %+v", 2, reply)
|
|
}
|
|
}
|
|
|
|
func testRateRemoveRateProfile(t *testing.T) {
|
|
var reply string
|
|
args := &utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
ID: "TEST_RATE_IT_TEST_SECOND",
|
|
Tenant: utils.CGRateSorg,
|
|
},
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1RemoveRateProfile,
|
|
args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.OK, reply)
|
|
}
|
|
|
|
//nothing to get from db
|
|
var result *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
&utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_SECOND",
|
|
},
|
|
}, &result); err == nil || err.Error() != utils.ErrNotFound.Error() {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ErrNotFound, err)
|
|
}
|
|
}
|
|
|
|
func testRateGetRateProfilesAfterRemove(t *testing.T) {
|
|
var reply []*utils.RateProfile
|
|
args := &utils.ArgsItemIDs{
|
|
Tenant: "cgrates.org",
|
|
}
|
|
expected := []*utils.RateProfile{
|
|
{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfiles,
|
|
args, &reply); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if !reflect.DeepEqual(reply, expected) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expected), utils.ToJSON(reply))
|
|
}
|
|
}
|
|
|
|
func testRateSetAttributeProfileBrokenReference(t *testing.T) {
|
|
ratePrf := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_SECOND",
|
|
FilterIDs: []string{"invalid_filter_format", "*string:~*opts.*context:*sessions"},
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var reply string
|
|
expectedErr := "SERVER_ERROR: broken reference to filter: <invalid_filter_format> for item with ID: cgrates.org:TEST_RATE_IT_TEST_SECOND"
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf, &reply); err == nil || err.Error() != expectedErr {
|
|
t.Errorf("Expected %+v \n, received %+v", expectedErr, err)
|
|
}
|
|
}
|
|
|
|
func testRateSetRateProfile3(t *testing.T) {
|
|
ratePrf := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_THIRD",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_MONTH": {
|
|
ID: "RT_MONTH",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var reply string
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error(err)
|
|
}
|
|
|
|
expectedRate := &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_THIRD",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
FilterIDs: nil,
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_MONTH": {
|
|
ID: "RT_MONTH",
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var result *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
&utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_THIRD",
|
|
},
|
|
}, &result); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(result, expectedRate) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expectedRate), utils.ToJSON(result))
|
|
}
|
|
}
|
|
|
|
func testRateRemoveRateProfileRates(t *testing.T) {
|
|
var reply string
|
|
args := &utils.RemoveRPrfRates{
|
|
ID: "TEST_RATE_IT_TEST_THIRD",
|
|
Tenant: utils.CGRateSorg,
|
|
RateIDs: []string{"RT_WEEK"},
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1RemoveRateProfileRates,
|
|
args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.OK, reply)
|
|
}
|
|
|
|
expectedRate := &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_THIRD",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
FilterIDs: nil,
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_MONTH": {
|
|
ID: "RT_MONTH",
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var result *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
&utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_THIRD",
|
|
},
|
|
}, &result); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(result, expectedRate) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expectedRate), utils.ToJSON(result))
|
|
}
|
|
|
|
// as we removed our RT_WEEK, we will add it back to our profile
|
|
argsRate := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_THIRD",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
// RT_WEEK wich we added back we added back
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.MetaRateSOverwrite: true,
|
|
},
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
argsRate, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Errorf("UNexpected reply returned: %v", reply)
|
|
}
|
|
}
|
|
|
|
func testRateSetRateProfileRates(t *testing.T) {
|
|
argsRate := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_THIRD",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
// RT_MONTH rate will be updated
|
|
"RT_MONTH": {
|
|
ID: "RT_MONTH",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
FilterIDs: []string{"*exists:~*req.Destination:"},
|
|
Weight: 25,
|
|
},
|
|
},
|
|
ActivationTimes: "* 10 * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(4, 1),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(1, 0),
|
|
},
|
|
},
|
|
},
|
|
// RT_CHRISTMAS will be added as a new rate into our profile
|
|
"RT_CHRISTMAS": {
|
|
ID: "RT_CHRISTMAS",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 10,
|
|
},
|
|
},
|
|
ActivationTimes: "1 * * * *",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
RecurrentFee: utils.NewDecimal(2, 1),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
Increment: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var result *string
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
argsRate, &result); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(result, utils.StringPointer("OK")) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON("OK"), utils.ToJSON(result))
|
|
}
|
|
|
|
expectedRate := &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_THIRD",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
// RT_WEEK that remains the same
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
// RT_MONTH that was updated
|
|
"RT_MONTH": {
|
|
ID: "RT_MONTH",
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
FilterIDs: []string{"*exists:~*req.Destination:"},
|
|
Weight: 25,
|
|
},
|
|
},
|
|
ActivationTimes: "* 10 * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(4, 1),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(1, 0),
|
|
},
|
|
},
|
|
},
|
|
// RT_YEAR that was uadded as a new rate
|
|
"RT_CHRISTMAS": {
|
|
ID: "RT_CHRISTMAS",
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
Weight: 10,
|
|
},
|
|
},
|
|
ActivationTimes: "1 * * * *",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
Increment: utils.NewDecimal(0, 0),
|
|
RecurrentFee: utils.NewDecimal(2, 1),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var result2 *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
&utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "TEST_RATE_IT_TEST_THIRD",
|
|
},
|
|
}, &result2); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(result2, expectedRate) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expectedRate), utils.ToJSON(result2))
|
|
}
|
|
}
|
|
|
|
func testRateSetRateProfilesWithPrefix(t *testing.T) {
|
|
ratePrf := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "PrefixTEST_RATE_IT_TEST",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var reply string
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error(err)
|
|
}
|
|
|
|
expectedRate := &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "PrefixTEST_RATE_IT_TEST",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var result *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
&utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "PrefixTEST_RATE_IT_TEST",
|
|
},
|
|
}, &result); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(result, expectedRate) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expectedRate), utils.ToJSON(result))
|
|
}
|
|
|
|
var reply2 []*utils.RateProfile
|
|
args := &utils.ArgsItemIDs{
|
|
Tenant: "cgrates.org",
|
|
ItemsPrefix: "PrefixTEST",
|
|
}
|
|
expected := []*utils.RateProfile{
|
|
{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "PrefixTEST_RATE_IT_TEST",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
FilterIDs: nil,
|
|
Weight: 0,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfiles,
|
|
args, &reply2); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(reply2, expected) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expected), utils.ToJSON(reply2))
|
|
}
|
|
}
|
|
|
|
func testRateProfileWithMultipleRates(t *testing.T) {
|
|
ratePrf := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "MultipleRates",
|
|
FilterIDs: []string{"*exists:~*req.CGRID:", "*prefix:~*req.Destination:12354"},
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 100,
|
|
},
|
|
},
|
|
MinCost: utils.NewDecimal(2, 1),
|
|
MaxCost: utils.NewDecimal(20244, 3),
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_MONDAY": {
|
|
ID: "RT_MONDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 50,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 0",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(33, 2),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(60*time.Second), 0),
|
|
FixedFee: utils.NewDecimal(1, 1),
|
|
Increment: utils.NewDecimal(int64(time.Minute), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_THUESDAY": {
|
|
ID: "RT_THUESDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 40,
|
|
},
|
|
},
|
|
FilterIDs: []string{"*string:~*opts.*rates:true"},
|
|
ActivationTimes: "* * * * 1",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(20, 2),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(45*time.Second), 0),
|
|
FixedFee: utils.NewDecimal(0, 0),
|
|
Increment: utils.NewDecimal(int64(time.Minute), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_WEDNESDAY": {
|
|
ID: "RT_WEDNESDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 30,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 2",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(1, 1),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(45*time.Second), 0),
|
|
FixedFee: utils.NewDecimal(2, 3),
|
|
Increment: utils.NewDecimal(int64(time.Minute), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_THURSDAY": {
|
|
ID: "RT_THURSDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 20,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 3",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(2, 1),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(time.Minute), 0),
|
|
FixedFee: utils.NewDecimal(1, 3),
|
|
Increment: utils.NewDecimal(int64(time.Minute), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_FRIDAY": {
|
|
ID: "RT_FRIDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 10,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 4",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(5, 1),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(time.Minute+30*time.Second), 0),
|
|
FixedFee: utils.NewDecimal(21, 3),
|
|
Increment: utils.NewDecimal(int64(time.Minute), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
ratePrf1 := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "rt1",
|
|
FilterIDs: []string{"*exists:~*req.CGRID:", "*prefix:~*req.Destination:12354"},
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 100,
|
|
},
|
|
},
|
|
MinCost: utils.NewDecimal(2, 1),
|
|
MaxCost: utils.NewDecimal(20244, 3),
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_1": {
|
|
ID: "RT_MONDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 50,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 0",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(33, 2),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(60*time.Second), 0),
|
|
FixedFee: utils.NewDecimal(1, 1),
|
|
Increment: utils.NewDecimal(int64(time.Minute), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_2": {
|
|
ID: "RT_THUESDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 40,
|
|
},
|
|
},
|
|
FilterIDs: []string{"*string:~*opts.*rates:true"},
|
|
ActivationTimes: "* * * * 1",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(20, 2),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(45*time.Second), 0),
|
|
FixedFee: utils.NewDecimal(0, 0),
|
|
Increment: utils.NewDecimal(int64(time.Minute), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var reply string
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error(err)
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf1, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error(err)
|
|
}
|
|
|
|
// as we created our profile, count the rates
|
|
var result *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
&utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "MultipleRates",
|
|
},
|
|
}, &result); err != nil {
|
|
t.Error(err)
|
|
} else if len(result.Rates) != 5 {
|
|
t.Errorf("Unexpected reply returned")
|
|
}
|
|
}
|
|
|
|
func testRateProfileRateIDsAndCount(t *testing.T) {
|
|
// we will get all the rates from MultipleRates rate profile with the prefix RT_T
|
|
expected := []string{"RT_THUESDAY", "RT_THURSDAY"}
|
|
var result []string
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfileRateIDs,
|
|
&utils.ArgsSubItemIDs{
|
|
Tenant: "cgrates.org",
|
|
ProfileID: "MultipleRates",
|
|
ItemsPrefix: "RT_T",
|
|
}, &result); err != nil {
|
|
t.Error(err)
|
|
} else {
|
|
sort.Slice(expected, func(i, j int) bool {
|
|
return expected[i] < expected[j]
|
|
})
|
|
sort.Slice(expected, func(i, j int) bool {
|
|
return result[i] < result[j]
|
|
})
|
|
if !reflect.DeepEqual(expected, result) {
|
|
t.Errorf("Expected %v, received %v", expected, result)
|
|
}
|
|
|
|
}
|
|
|
|
// we will count all the rates from MultipleRates rate profile. The prefix is missing, so it will count all the rates
|
|
var reply int
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfileRatesCount,
|
|
&utils.ArgsSubItemIDs{
|
|
Tenant: "cgrates.org",
|
|
ProfileID: "MultipleRates",
|
|
}, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != 5 {
|
|
t.Errorf("Unexpected reply returned: %v", reply)
|
|
}
|
|
|
|
// now list all the rates
|
|
var replyRts []*utils.Rate
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfileRates,
|
|
&utils.ArgsSubItemIDs{
|
|
Tenant: "cgrates.org",
|
|
ProfileID: "MultipleRates",
|
|
ItemsPrefix: "RT_",
|
|
}, &replyRts); err != nil {
|
|
t.Error(err)
|
|
} else if len(replyRts) != 5 { //RT_MONDAY, RT_THUESDAY, RT_WEDNESDAY, RT_THURSDAY AND RT_FRIDAY
|
|
t.Errorf("Unexpected reply returned: %v", reply)
|
|
}
|
|
}
|
|
|
|
func testRateProfileUpdateRates(t *testing.T) {
|
|
argsRate := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "MultipleRates",
|
|
FilterIDs: []string{"*exists:~*req.CGRID:", "*prefix:~*req.Destination:12354"},
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 100,
|
|
},
|
|
},
|
|
MinCost: utils.NewDecimal(2, 1),
|
|
MaxCost: utils.NewDecimal(20244, 3),
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
// RT_MMONDAY Modified the interval rates
|
|
"RT_MONDAY": {
|
|
ID: "RT_MONDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
FilterIDs: []string{"*lt:~*req.*usage:6"},
|
|
ActivationTimes: "* 12 * * 0",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
Increment: utils.NewDecimal(int64(2*time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(2*time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(2*time.Minute), 0),
|
|
},
|
|
},
|
|
Blocker: true,
|
|
},
|
|
// on rate_friday we will modify just the activationTimes and one intervalRate, in all weekend
|
|
"RT_FRIDAY": {
|
|
ID: "RT_FRIDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 10,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 4-6",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(5, 1),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var result *string
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
argsRate, &result); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(result, utils.StringPointer("OK")) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON("OK"), utils.ToJSON(result))
|
|
}
|
|
|
|
// so, RT_MONDAY, RT_FRIDAY were updated
|
|
// RT_THURSDAY, RT_WEDNESDAY AND RATE_THUESDAY are the same
|
|
expectedRate := &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "MultipleRates",
|
|
FilterIDs: []string{"*exists:~*req.CGRID:", "*prefix:~*req.Destination:12354"},
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
Weight: 100,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
MinCost: utils.NewDecimal(2, 1),
|
|
MaxCost: utils.NewDecimal(20244, 3),
|
|
Rates: map[string]*utils.Rate{
|
|
// RT_WEEK that remains the same
|
|
"RT_MONDAY": {
|
|
ID: "RT_MONDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
FilterIDs: []string{"*lt:~*req.*usage:6"},
|
|
ActivationTimes: "* 12 * * 0",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
Increment: utils.NewDecimal(int64(2*time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(2*time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(2*time.Minute), 0),
|
|
},
|
|
},
|
|
Blocker: true,
|
|
},
|
|
"RT_THUESDAY": {
|
|
ID: "RT_THUESDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 40,
|
|
},
|
|
},
|
|
FilterIDs: []string{"*string:~*opts.*rates:true"},
|
|
ActivationTimes: "* * * * 1",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(20, 2),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(45*time.Second), 0),
|
|
FixedFee: utils.NewDecimal(0, 0),
|
|
Increment: utils.NewDecimal(int64(time.Minute), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_WEDNESDAY": {
|
|
ID: "RT_WEDNESDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 30,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 2",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(1, 1),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(45*time.Second), 0),
|
|
FixedFee: utils.NewDecimal(2, 3),
|
|
Increment: utils.NewDecimal(int64(time.Minute), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_THURSDAY": {
|
|
ID: "RT_THURSDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 20,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 3",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(2, 1),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(time.Minute), 0),
|
|
FixedFee: utils.NewDecimal(1, 3),
|
|
Increment: utils.NewDecimal(int64(time.Minute), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_FRIDAY": {
|
|
ID: "RT_FRIDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 10,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 4-6",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(5, 1),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var result2 *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
&utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "MultipleRates",
|
|
},
|
|
}, &result2); err != nil {
|
|
t.Error(err)
|
|
} else if *utils.DBType != utils.MetaMySQL && *utils.DBType != utils.MetaPostgres {
|
|
if !reflect.DeepEqual(result2, expectedRate) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expectedRate), utils.ToJSON(result2))
|
|
}
|
|
} else if *utils.DBType == utils.MetaMySQL || *utils.DBType == utils.MetaPostgres {
|
|
expectedRate.Rates["RT_THUESDAY"].IntervalRates[0].FixedFee = utils.NewDecimal(2, 1)
|
|
if !reflect.DeepEqual(result2, expectedRate) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expectedRate), utils.ToJSON(result2))
|
|
}
|
|
}
|
|
}
|
|
|
|
func testRateProfileRemoveMultipleRates(t *testing.T) {
|
|
// RT_MONDAY,RT_THURSDAY,RT_WEDNESDAY will be removed from our profile, se there are 2 remain rates
|
|
var reply string
|
|
args := &utils.RemoveRPrfRates{
|
|
ID: "MultipleRates",
|
|
Tenant: utils.CGRateSorg,
|
|
RateIDs: []string{"RT_MONDAY", "RT_THURSDAY", "RT_WEDNESDAY"},
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1RemoveRateProfileRates,
|
|
args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.OK, reply)
|
|
}
|
|
|
|
expectedRate := &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "MultipleRates",
|
|
FilterIDs: []string{"*exists:~*req.CGRID:", "*prefix:~*req.Destination:12354"},
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
Weight: 100,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
MinCost: utils.NewDecimal(2, 1),
|
|
MaxCost: utils.NewDecimal(20244, 3),
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_THUESDAY": {
|
|
ID: "RT_THUESDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 40,
|
|
},
|
|
},
|
|
FilterIDs: []string{"*string:~*opts.*rates:true"},
|
|
ActivationTimes: "* * * * 1",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(20, 2),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(45*time.Second), 0),
|
|
FixedFee: utils.NewDecimal(0, 0),
|
|
Increment: utils.NewDecimal(int64(time.Minute), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_FRIDAY": {
|
|
ID: "RT_FRIDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 10,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 4-6",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(5, 1),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var result2 *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
&utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "MultipleRates",
|
|
},
|
|
}, &result2); err != nil {
|
|
t.Error(err)
|
|
} else if *utils.DBType != utils.MetaMySQL && *utils.DBType != utils.MetaPostgres {
|
|
if !reflect.DeepEqual(result2, expectedRate) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expectedRate), utils.ToJSON(result2))
|
|
}
|
|
} else if *utils.DBType == utils.MetaMySQL || *utils.DBType == utils.MetaPostgres {
|
|
expectedRate.Rates["RT_THUESDAY"].IntervalRates[0].FixedFee = utils.NewDecimal(2, 1)
|
|
if !reflect.DeepEqual(result2, expectedRate) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expectedRate), utils.ToJSON(result2))
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func testRateProfileSetMultipleRatesInProfile(t *testing.T) {
|
|
// now we will set more rates instead of updating them
|
|
argsRate := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "MultipleRates",
|
|
FilterIDs: []string{"*exists:~*req.CGRID:", "*prefix:~*req.Destination:12354"},
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 100,
|
|
},
|
|
},
|
|
MinCost: utils.NewDecimal(2, 1),
|
|
MaxCost: utils.NewDecimal(20244, 3),
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
// RT_SATURDAY and RT_SUNDAY are the new rates
|
|
"RT_SATURDAY": {
|
|
ID: "RT_SATURDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 20,
|
|
},
|
|
},
|
|
FilterIDs: []string{"*lt:~*req.*usage:6"},
|
|
ActivationTimes: "* * * * 5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
Increment: utils.NewDecimal(int64(30*time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(30*time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(2*time.Minute), 0),
|
|
},
|
|
},
|
|
Blocker: true,
|
|
},
|
|
"RT_SUNDAY": {
|
|
ID: "RT_SUNDAY",
|
|
FilterIDs: []string{"*ai:~*req.SetupTime:2013-06-01T00:00:00Z"},
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 25,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 6",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(22, 2),
|
|
Increment: utils.NewDecimal(int64(5*time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(5*time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(time.Second), 1),
|
|
FixedFee: utils.NewDecimal(124, 3),
|
|
Increment: utils.NewDecimal(int64(2*time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(2*time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var result *string
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
argsRate, &result); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(result, utils.StringPointer("OK")) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON("OK"), utils.ToJSON(result))
|
|
}
|
|
|
|
// now that we set our rates, we have 4 rates: RT_THUESDAY,RT_FRIDAY,RT_SATURDAY,RT_SUNDAY
|
|
expectedRate := &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "MultipleRates",
|
|
FilterIDs: []string{"*exists:~*req.CGRID:", "*prefix:~*req.Destination:12354"},
|
|
Weights: []*utils.DynamicWeight{
|
|
{
|
|
Weight: 100,
|
|
},
|
|
},
|
|
MaxCostStrategy: "*free",
|
|
MinCost: utils.NewDecimal(2, 1),
|
|
MaxCost: utils.NewDecimal(20244, 3),
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_THUESDAY": {
|
|
ID: "RT_THUESDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 40,
|
|
},
|
|
},
|
|
FilterIDs: []string{"*string:~*opts.*rates:true"},
|
|
ActivationTimes: "* * * * 1",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(20, 2),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(45*time.Second), 0),
|
|
FixedFee: utils.NewDecimal(0, 0),
|
|
Increment: utils.NewDecimal(int64(time.Minute), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_FRIDAY": {
|
|
ID: "RT_FRIDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 10,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 4-6",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(5, 1),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_SATURDAY": {
|
|
ID: "RT_SATURDAY",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 20,
|
|
},
|
|
},
|
|
FilterIDs: []string{"*lt:~*req.*usage:6"},
|
|
ActivationTimes: "* * * * 5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
Increment: utils.NewDecimal(int64(30*time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(30*time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(2*time.Minute), 0),
|
|
},
|
|
},
|
|
Blocker: true,
|
|
},
|
|
"RT_SUNDAY": {
|
|
ID: "RT_SUNDAY",
|
|
FilterIDs: []string{"*ai:~*req.SetupTime:2013-06-01T00:00:00Z"},
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 25,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 6",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(22, 2),
|
|
Increment: utils.NewDecimal(int64(5*time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(5*time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(time.Second), 1),
|
|
FixedFee: utils.NewDecimal(124, 3),
|
|
Increment: utils.NewDecimal(int64(2*time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(2*time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var result2 *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
&utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "MultipleRates",
|
|
},
|
|
}, &result2); err != nil {
|
|
t.Error(err)
|
|
} else if *utils.DBType != utils.MetaMySQL && *utils.DBType != utils.MetaPostgres {
|
|
if !reflect.DeepEqual(result2, expectedRate) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expectedRate), utils.ToJSON(result2))
|
|
}
|
|
} else if *utils.DBType == utils.MetaMySQL || *utils.DBType == utils.MetaPostgres {
|
|
expectedRate.Rates["RT_THUESDAY"].IntervalRates[0].FixedFee = utils.NewDecimal(2, 1)
|
|
expectedRate.Rates["RT_SUNDAY"].IntervalRates[1].IntervalStart = utils.NewDecimal(100000000, 0)
|
|
if !reflect.DeepEqual(result2, expectedRate) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expectedRate), utils.ToJSON(result2))
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func testRateProfileUpdateProfileRatesOverwrite(t *testing.T) {
|
|
ratePrf := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "FirstNoUpdate",
|
|
FilterIDs: []string{"*string:~*req.Account:dan"},
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
FilterIDs: []string{"*prefix:~*req.Destination:+33223"},
|
|
Weight: 20,
|
|
},
|
|
{
|
|
Weight: 10,
|
|
},
|
|
},
|
|
MinCost: utils.NewDecimal(22, 2),
|
|
MaxCost: utils.NewDecimal(500000, 6),
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_WEEK": {
|
|
ID: "RT_WEEK",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var reply string
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error(err)
|
|
}
|
|
|
|
var result2 *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
&utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "FirstNoUpdate",
|
|
},
|
|
}, &result2); err != nil {
|
|
t.Error(err)
|
|
} else if *utils.DBType != utils.MetaMySQL && *utils.DBType != utils.MetaPostgres {
|
|
if !reflect.DeepEqual(result2, ratePrf.RateProfile) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(ratePrf.RateProfile), utils.ToJSON(result2))
|
|
}
|
|
} else if *utils.DBType == utils.MetaMySQL || *utils.DBType == utils.MetaPostgres {
|
|
ratePrf.RateProfile.MaxCost = utils.NewDecimal(5, 1)
|
|
if !reflect.DeepEqual(result2, ratePrf.RateProfile) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(ratePrf.RateProfile), utils.ToJSON(result2))
|
|
}
|
|
}
|
|
|
|
if !reflect.DeepEqual(result2, ratePrf.RateProfile) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(ratePrf.RateProfile), utils.ToJSON(result2))
|
|
}
|
|
|
|
// now we will update just some fields of the profile (some of them will remain the same)
|
|
ratePrf = &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "FirstNoUpdate",
|
|
FilterIDs: []string{"*string:~*req.CGRID:123sdf75623t5y"},
|
|
MaxCost: utils.NewDecimal(100, 0),
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_2": {
|
|
ID: "RT_2",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* * * * 1-5",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.MetaRateSOverwrite: true,
|
|
},
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error(err)
|
|
}
|
|
|
|
var result3 *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
&utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "FirstNoUpdate",
|
|
},
|
|
}, &result3); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(result3, ratePrf.RateProfile) {
|
|
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(ratePrf.RateProfile), utils.ToJSON(result3))
|
|
}
|
|
|
|
}
|
|
|
|
func testRateProfilesForEventMatchingEvents(t *testing.T) {
|
|
ratePrf := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "RT_101",
|
|
FilterIDs: []string{"*string:~*req.MonthToRate:july|august", "*prefix:~*req.Destination:2004"},
|
|
MinCost: utils.NewDecimal(22, 2),
|
|
MaxCost: utils.NewDecimal(500000, 6),
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_July": {
|
|
ID: "RT_July",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* 12 * * *",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
ratePrf2 := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "RT_102",
|
|
FilterIDs: []string{"*string:~*req.MonthToRate:july|august"},
|
|
MinCost: utils.NewDecimal(22, 2),
|
|
MaxCost: utils.NewDecimal(500000, 6),
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_August": {
|
|
ID: "RT_August",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* 2 * * *",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
ratePrf3 := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "RT_103",
|
|
FilterIDs: []string{"*prefix:~*req.Destination:2004"},
|
|
MinCost: utils.NewDecimal(22, 2),
|
|
MaxCost: utils.NewDecimal(500000, 6),
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_Everytime": {
|
|
ID: "RT_Everytime",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* 14 * * *",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
ratePrf4 := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "RT_104",
|
|
FilterIDs: []string{"*exists:~*req.Destination:"},
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_Everytime": {
|
|
ID: "RT_Everytime",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* 14 * * *",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
ratePrf5 := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "RT_105",
|
|
FilterIDs: []string{"*string:~*req.Account:1445"},
|
|
MinCost: utils.NewDecimal(22, 2),
|
|
MaxCost: utils.NewDecimal(500000, 6),
|
|
MaxCostStrategy: "*free",
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_not_available": {
|
|
ID: "RT_not_available",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 0,
|
|
},
|
|
},
|
|
ActivationTimes: "* 9 * * *",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var reply string
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error(err)
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf2, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error(err)
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf3, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error(err)
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf4, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error(err)
|
|
}
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf5, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error(err)
|
|
}
|
|
|
|
var rtPrfIDs []string
|
|
expected := []string{"RT_103", "RT_104"}
|
|
if err := rateSRPC.Call(context.Background(), utils.RateSv1RateProfilesForEvent,
|
|
&utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
Event: map[string]any{
|
|
"Destination": "2004",
|
|
},
|
|
}, &rtPrfIDs); err != nil {
|
|
t.Error(err)
|
|
} else {
|
|
sort.Slice(expected, func(i, j int) bool {
|
|
return expected[i] < expected[j]
|
|
})
|
|
sort.Slice(rtPrfIDs, func(i, j int) bool {
|
|
return rtPrfIDs[i] < rtPrfIDs[j]
|
|
})
|
|
if !reflect.DeepEqual(expected, rtPrfIDs) {
|
|
t.Errorf("Expected %+v, received %+v", expected, rtPrfIDs)
|
|
}
|
|
}
|
|
|
|
expected = []string{"RT_103", "RT_104", "RT_105"}
|
|
if err := rateSRPC.Call(context.Background(), utils.RateSv1RateProfilesForEvent,
|
|
&utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
Event: map[string]any{
|
|
"Account": "1445",
|
|
"Destination": "2004",
|
|
},
|
|
}, &rtPrfIDs); err != nil {
|
|
t.Error(err)
|
|
} else {
|
|
sort.Slice(expected, func(i, j int) bool {
|
|
return expected[i] < expected[j]
|
|
})
|
|
sort.Slice(rtPrfIDs, func(i, j int) bool {
|
|
return rtPrfIDs[i] < rtPrfIDs[j]
|
|
})
|
|
if !reflect.DeepEqual(expected, rtPrfIDs) {
|
|
t.Errorf("Expected %+v, received %+v", expected, rtPrfIDs)
|
|
}
|
|
}
|
|
|
|
expected = []string{"RT_101", "RT_102", "RT_103", "RT_104", "RT_105"}
|
|
if err := rateSRPC.Call(context.Background(), utils.RateSv1RateProfilesForEvent,
|
|
&utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
Event: map[string]any{
|
|
"Account": "1445",
|
|
"MonthToRate": "july",
|
|
"Destination": "2004",
|
|
},
|
|
}, &rtPrfIDs); err != nil {
|
|
t.Error(err)
|
|
} else {
|
|
sort.Slice(expected, func(i, j int) bool {
|
|
return expected[i] < expected[j]
|
|
})
|
|
sort.Slice(rtPrfIDs, func(i, j int) bool {
|
|
return rtPrfIDs[i] < rtPrfIDs[j]
|
|
})
|
|
if !reflect.DeepEqual(expected, rtPrfIDs) {
|
|
t.Errorf("Expected %+v, received %+v", expected, rtPrfIDs)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testRateProfileRatesForEventMatchingEvents(t *testing.T) {
|
|
// now for 2 of our profiles, we will set some rates and see what rates are matching our event
|
|
ratePrf1 := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
Tenant: utils.CGRateSorg,
|
|
ID: "RT_CGR202",
|
|
//FilterIDs: []string{"*lte:~*opts.*usage:2m"},
|
|
Rates: map[string]*utils.Rate{
|
|
"RT_ALWAYS": {
|
|
ID: "RT_ALWAYS",
|
|
FilterIDs: []string{"*prefix:~*req.Destination:2023", "*string:~*opts.*usage:1m"},
|
|
ActivationTimes: "* * * * *",
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
FixedFee: utils.NewDecimal(22, 2),
|
|
Increment: utils.NewDecimal(int64(5*time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(5*time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_WEEKEND": {
|
|
ID: "RT_WEEKEND",
|
|
ActivationTimes: "* * * * 5-6",
|
|
FilterIDs: []string{"*prefix:~*req.Destination:2023"},
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(0, 0),
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_SPECIAL": {
|
|
ID: "RT_SPECIAL",
|
|
ActivationTimes: "* 12 * * *",
|
|
FilterIDs: []string{"*string:~*req.Account:2021",
|
|
"*string:~*req.Destination:2023"},
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(50*time.Second), 0),
|
|
Increment: utils.NewDecimal(int64(2*time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(2*time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
"RT_DIFFERENT": {
|
|
ID: "RT_DIFFERENT",
|
|
ActivationTimes: "10 12 * * *",
|
|
FilterIDs: []string{"*lte:~*opts.*usage:2m", "*string:~*req.ToR:*voice"},
|
|
IntervalRates: []*utils.IntervalRate{
|
|
{
|
|
IntervalStart: utils.NewDecimal(int64(50*time.Second), 0),
|
|
Increment: utils.NewDecimal(int64(2*time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(int64(2*time.Second), 0),
|
|
Unit: utils.NewDecimal(int64(time.Minute), 0),
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
var reply string
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf1, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error(err)
|
|
}
|
|
|
|
expected := []string{"RT_DIFFERENT"}
|
|
var rateIDs []string
|
|
if err := rateSRPC.Call(context.Background(), utils.RateSv1RateProfileRatesForEvent,
|
|
&utils.CGREventWithRateProfile{
|
|
RateProfileID: "RT_CGR202",
|
|
CGREvent: &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
Event: map[string]any{
|
|
"ToR": "*voice",
|
|
"Account": "2021",
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.MetaUsage: "1m",
|
|
},
|
|
},
|
|
}, &rateIDs); err != nil {
|
|
t.Error(err)
|
|
} else {
|
|
sort.Slice(expected, func(i, j int) bool {
|
|
return expected[i] < expected[j]
|
|
})
|
|
sort.Slice(rateIDs, func(i, j int) bool {
|
|
return rateIDs[i] < rateIDs[j]
|
|
})
|
|
if !reflect.DeepEqual(expected, rateIDs) {
|
|
t.Errorf("Expected %+v, received %+v", expected, rateIDs)
|
|
}
|
|
}
|
|
|
|
expected = []string{"RT_SPECIAL", "RT_WEEKEND"}
|
|
if err := rateSRPC.Call(context.Background(), utils.RateSv1RateProfileRatesForEvent,
|
|
&utils.CGREventWithRateProfile{
|
|
RateProfileID: "RT_CGR202",
|
|
CGREvent: &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
Event: map[string]any{
|
|
"ToR": "*voice",
|
|
"Account": "2021",
|
|
"Destination": "2023",
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.MetaUsage: "3m",
|
|
},
|
|
},
|
|
}, &rateIDs); err != nil {
|
|
t.Error(err)
|
|
} else {
|
|
sort.Slice(expected, func(i, j int) bool {
|
|
return expected[i] < expected[j]
|
|
})
|
|
sort.Slice(rateIDs, func(i, j int) bool {
|
|
return rateIDs[i] < rateIDs[j]
|
|
})
|
|
if !reflect.DeepEqual(expected, rateIDs) {
|
|
t.Errorf("Expected %+v, received %+v", expected, rateIDs)
|
|
}
|
|
}
|
|
|
|
expected = []string{"RT_SPECIAL", "RT_WEEKEND", "RT_DIFFERENT", "RT_ALWAYS"}
|
|
if err := rateSRPC.Call(context.Background(), utils.RateSv1RateProfileRatesForEvent,
|
|
&utils.CGREventWithRateProfile{
|
|
RateProfileID: "RT_CGR202",
|
|
CGREvent: &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
Event: map[string]any{
|
|
"ToR": "*voice",
|
|
"Account": "2021",
|
|
"Destination": "2023",
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.MetaUsage: "1m",
|
|
},
|
|
},
|
|
}, &rateIDs); err != nil {
|
|
t.Error(err)
|
|
} else {
|
|
sort.Slice(expected, func(i, j int) bool {
|
|
return expected[i] < expected[j]
|
|
})
|
|
sort.Slice(rateIDs, func(i, j int) bool {
|
|
return rateIDs[i] < rateIDs[j]
|
|
})
|
|
if !reflect.DeepEqual(expected, rateIDs) {
|
|
t.Errorf("Expected %+v, received %+v", expected, rateIDs)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testRateSPaginateSetRateProfile(t *testing.T) {
|
|
ratePrf := &utils.APIRateProfile{
|
|
RateProfile: &utils.RateProfile{
|
|
ID: "RATE_PROFILE",
|
|
Tenant: "cgrates.org",
|
|
FilterIDs: []string{"*string:~*req.Account:1001"},
|
|
Rates: map[string]*utils.Rate{
|
|
"RateA1": {
|
|
ID: "RateA1",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 35,
|
|
},
|
|
},
|
|
},
|
|
"RateA2": {
|
|
ID: "RateA2",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 5,
|
|
},
|
|
},
|
|
},
|
|
"RateA3": {
|
|
ID: "RateA3",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 40,
|
|
},
|
|
},
|
|
},
|
|
"RateB5": {
|
|
ID: "RateB5",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 10,
|
|
},
|
|
},
|
|
},
|
|
"RateB1": {
|
|
ID: "RateB1",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 25,
|
|
},
|
|
},
|
|
},
|
|
"RateB3": {
|
|
ID: "RateB3",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 15,
|
|
},
|
|
},
|
|
},
|
|
"RateB2": {
|
|
ID: "RateB2",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 5,
|
|
},
|
|
},
|
|
},
|
|
"RateB6": {
|
|
ID: "RateB6",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 30,
|
|
},
|
|
},
|
|
},
|
|
"RateB4": {
|
|
ID: "RateB4",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 20,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
var reply string
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1SetRateProfile,
|
|
ratePrf, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error("Unexpected reply returned: ", reply)
|
|
}
|
|
}
|
|
|
|
func testRateSPaginateGetRateProfile1(t *testing.T) {
|
|
args := &utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
ID: "RATE_PROFILE",
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.PageLimitOpt: 4,
|
|
utils.PageOffsetOpt: 1,
|
|
utils.ItemsPrefixOpt: "RateB",
|
|
},
|
|
}
|
|
|
|
expected := utils.RateProfile{
|
|
ID: "RATE_PROFILE",
|
|
Tenant: "cgrates.org",
|
|
FilterIDs: []string{"*string:~*req.Account:1001"},
|
|
Rates: map[string]*utils.Rate{
|
|
"RateB2": {
|
|
ID: "RateB2",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 5,
|
|
},
|
|
},
|
|
},
|
|
"RateB3": {
|
|
ID: "RateB3",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 15,
|
|
},
|
|
},
|
|
},
|
|
"RateB4": {
|
|
ID: "RateB4",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 20,
|
|
},
|
|
},
|
|
},
|
|
"RateB5": {
|
|
ID: "RateB5",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 10,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
var reply *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else {
|
|
for rateID := range expected.Rates {
|
|
if _, ok := reply.Rates[rateID]; !ok {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>",
|
|
utils.ToJSON(expected), utils.ToJSON(reply))
|
|
t.Fatalf("rate <%+v> could not be found in reply", rateID)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func testRateSPaginateGetRateProfile2(t *testing.T) {
|
|
args := &utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
ID: "RATE_PROFILE",
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.PageLimitOpt: 4,
|
|
utils.PageOffsetOpt: 1,
|
|
utils.ItemsPrefixOpt: "RateA",
|
|
},
|
|
}
|
|
|
|
expected := utils.RateProfile{
|
|
ID: "RATE_PROFILE",
|
|
Tenant: "cgrates.org",
|
|
FilterIDs: []string{"*string:~*req.Account:1001"},
|
|
Rates: map[string]*utils.Rate{
|
|
"RateA2": {
|
|
ID: "RateA2",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 5,
|
|
},
|
|
},
|
|
},
|
|
"RateA3": {
|
|
ID: "RateA3",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 40,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
var reply *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if len(reply.Rates) != len(expected.Rates) {
|
|
t.Errorf("expected: %+v Rates, \nreceived: %+v Rates",
|
|
len(expected.Rates), len(reply.Rates))
|
|
} else {
|
|
for rateID := range expected.Rates {
|
|
if _, ok := reply.Rates[rateID]; !ok {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>",
|
|
utils.ToJSON(expected), utils.ToJSON(reply))
|
|
t.Fatalf("rate <%+v> could not be found in reply", rateID)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func testRateSPaginateGetRateProfile3(t *testing.T) {
|
|
args := &utils.TenantIDWithAPIOpts{
|
|
TenantID: &utils.TenantID{
|
|
ID: "RATE_PROFILE",
|
|
},
|
|
APIOpts: map[string]any{
|
|
utils.PageOffsetOpt: 1,
|
|
},
|
|
}
|
|
|
|
expected := utils.RateProfile{
|
|
ID: "RATE_PROFILE",
|
|
Tenant: "cgrates.org",
|
|
FilterIDs: []string{"*string:~*req.Account:1001"},
|
|
Rates: map[string]*utils.Rate{
|
|
"RateA2": {
|
|
ID: "RateA2",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 5,
|
|
},
|
|
},
|
|
},
|
|
"RateA3": {
|
|
ID: "RateA3",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 40,
|
|
},
|
|
},
|
|
},
|
|
"RateB5": {
|
|
ID: "RateB5",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 10,
|
|
},
|
|
},
|
|
},
|
|
"RateB1": {
|
|
ID: "RateB1",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 25,
|
|
},
|
|
},
|
|
},
|
|
"RateB3": {
|
|
ID: "RateB3",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 15,
|
|
},
|
|
},
|
|
},
|
|
"RateB2": {
|
|
ID: "RateB2",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 5,
|
|
},
|
|
},
|
|
},
|
|
"RateB6": {
|
|
ID: "RateB6",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 30,
|
|
},
|
|
},
|
|
},
|
|
"RateB4": {
|
|
ID: "RateB4",
|
|
Weights: utils.DynamicWeights{
|
|
{
|
|
Weight: 20,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
var reply *utils.RateProfile
|
|
if err := rateSRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
|
|
args, &reply); err != nil {
|
|
t.Error(err)
|
|
} else {
|
|
for rateID := range expected.Rates {
|
|
if _, ok := reply.Rates[rateID]; !ok {
|
|
t.Errorf("expected: <%+v>, \nreceived: <%+v>",
|
|
utils.ToJSON(expected), utils.ToJSON(reply))
|
|
t.Fatalf("rate <%+v> could not be found in reply", rateID)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Kill the engine when it is about to be finished
|
|
func testRateSKillEngine(t *testing.T) {
|
|
if err := engine.KillEngine(100); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|