Started sessions volume discount test

This commit is contained in:
porosnicuadrian
2021-09-24 17:00:38 +03:00
committed by Dan Christian Bogos
parent be55e28eb2
commit aa1a3042da
4 changed files with 453 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
{
// CGRateS Configuration file
//
// Used for sessions/sessions_volume_discount_it_test.go
"general": {
"log_level": 7,
},
"data_db": {
"db_type": "*internal",
},
"stor_db": {
"db_type": "*internal",
},
"sessions": {
"enabled": true,
"routes_conns": ["*internal"],
},
"loaders": [
{
"id": "*default",
"enabled": true,
"tenant": "cgrates.org",
"tp_in_dir": "/usr/share/cgrates/tariffplans/sessions_discount_volume",
"tp_out_dir": "",
"lockfile_path": "",
},
],
"routes": {
"enabled": true,
},
"admins": {
"enabled": true,
},
}

View File

@@ -0,0 +1,16 @@
#Tenant,ID,FilterIDs,Weights,MinCost,MaxCost,MaxCostStrategy,RateID,RateFilterIDs,RateActivationStart,RateWeights,RateBlocker,RateIntervalStart,RateFixedFee,RateRecurrentFee,RateUnit,RateIncrement
cgrates.org,RP1,,,,,,RT_10,*prefix:~*req.Destination:10,,;10,,,,0.03,1m,1s
cgrates.org,RP1,,,,,,RT_20,*prefix:~*req.Destination:20,,;10,,,,0.01,1m,1s
cgrates.org,RP1,,,,,,RT_DFLT,,,,,,,0.92,1m,1s
cgrates.org,RP2,,,,,,RT_100,*prefix:~*req.Destination:100,,;10,,,,0.92,1m,1s
cgrates.org,RP2,,,,,,RT_DFLT,,,,,,,0.95,1m,1s
cgrates.org,RP3,,,,,,RT_1,*prefix:~*req.Destination:1,,;10,,,,0.01,1m,1s
cgrates.org,RP3,,,,,,RT_DFLT,,,,,,,0.97,1m,1s
cgrates.org,RP4,,,,,,RT_200,*prefix:~*req.Destination:200,,,,,,0.02,1m,1s
cgrates.org,RP4,,,,,,RT_1002,*prefix:~*req.Destination:1002,,;10,,,,0.09,1m,1s
cgrates.org,RP4,,,,,,RT_6,*prefix:~*req.Destination:6,,;10,,,,0.09,1m,1s
cgrates.org,RP4,,,,,,RT_DFLT,,,,,,,0.91,1m,1s
1 #Tenant ID FilterIDs Weights MinCost MaxCost MaxCostStrategy RateID RateFilterIDs RateActivationStart RateWeights RateBlocker RateIntervalStart RateFixedFee RateRecurrentFee RateUnit RateIncrement
2 cgrates.org RP1 RT_10 *prefix:~*req.Destination:10 ;10 0.03 1m 1s
3 cgrates.org RP1 RT_20 *prefix:~*req.Destination:20 ;10 0.01 1m 1s
4 cgrates.org RP1 RT_DFLT 0.92 1m 1s
5 cgrates.org RP2 RT_100 *prefix:~*req.Destination:100 ;10 0.92 1m 1s
6 cgrates.org RP2 RT_DFLT 0.95 1m 1s
7 cgrates.org RP3 RT_1 *prefix:~*req.Destination:1 ;10 0.01 1m 1s
8 cgrates.org RP3 RT_DFLT 0.97 1m 1s
9 cgrates.org RP4 RT_200 *prefix:~*req.Destination:200 0.02 1m 1s
10 cgrates.org RP4 RT_1002 *prefix:~*req.Destination:1002 ;10 0.09 1m 1s
11 cgrates.org RP4 RT_6 *prefix:~*req.Destination:6 ;10 0.09 1m 1s
12 cgrates.org RP4 RT_DFLT 0.91 1m 1s

View File

@@ -0,0 +1,14 @@
#Tenant,ID,FilterIDs,Weight,Sorting,SortingParameters,RouteID,RouteFilterIDs,RouteAccountIDs,RouteRateProfileIDs,RouteResourceIDs,RouteStatIDs,RouteWeight,RouteBlocker,RouteParameters
cgrates.org,LC1,,,*lc,,,,,,,,,,
cgrates.org,LC1,,,,,supplier1,,,RP1,,,,,
cgrates.org,LC1,,,,,supplier2,,,RP2,,,,,
cgrates.org,LC1,,,,,supplier3,,,RP3,,,,,
cgrates.org,LC1,,,,,supplier4,,,RP4,,,,,
#cgrates.org,DEFAULT_ROUTES,,,*weight,,,,,,,,,,
#cgrates.org,DEFAULT_ROUTES,,,,,supplier1,,,,,,10,,
#cgrates.org,DEFAULT_ROUTES,,,,,supplier2,,,,,,20,,
#cgrates.org,DEFAULT_ROUTES,,,,,supplier3,,,,,,40,,
#cgrates.org,DEFAULT_ROUTES,,,,,supplier4,,,,,,35,,
1 #Tenant ID FilterIDs Weight Sorting SortingParameters RouteID RouteFilterIDs RouteAccountIDs RouteRateProfileIDs RouteResourceIDs RouteStatIDs RouteWeight RouteBlocker RouteParameters
2 cgrates.org LC1 *lc
3 cgrates.org LC1 supplier1 RP1
4 cgrates.org LC1 supplier2 RP2
5 cgrates.org LC1 supplier3 RP3
6 cgrates.org LC1 supplier4 RP4
7 #cgrates.org DEFAULT_ROUTES *weight
8 #cgrates.org DEFAULT_ROUTES supplier1 10
9 #cgrates.org DEFAULT_ROUTES supplier2 20
10 #cgrates.org DEFAULT_ROUTES supplier3 40
11 #cgrates.org DEFAULT_ROUTES supplier4 35

View File

@@ -0,0 +1,382 @@
//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 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package sessions
import (
"errors"
"path"
"reflect"
"sort"
"testing"
"time"
"github.com/cgrates/birpc"
"github.com/cgrates/birpc/context"
"github.com/cgrates/birpc/jsonrpc"
"github.com/cgrates/cgrates/apis"
"github.com/cgrates/cgrates/config"
"github.com/cgrates/cgrates/engine"
"github.com/cgrates/cgrates/loaders"
"github.com/cgrates/cgrates/utils"
)
var (
tSessVolDiscCfgPath string
tSessVolDiscCfgDIR string
tSessVolDiscCfg *config.CGRConfig
tSessVolDiscBiRPC *birpc.Client
tSessVolDiscITtests = []func(t *testing.T){
testSessVolDiscInitCfg,
testSessVolDiscResetDataDb,
testSessVolDiscResetStorDb,
testSessVolDiscStartEngine,
testSessVolDiscApierRpcConn,
testSessVolDiscLoadersLoad,
testSessVolDiscCheckRoutesAndRateProfiles,
testSessVolDiscSetAccounts,
testSessVolDiscStopCgrEngine,
}
)
func newBiRPCClient(cfg *config.ListenCfg) (c *birpc.Client, err error) {
switch *encoding {
case utils.MetaJSON:
return jsonrpc.Dial(utils.TCP, cfg.RPCJSONListen)
case utils.MetaGOB:
return birpc.Dial(utils.TCP, cfg.RPCGOBListen)
default:
return nil, errors.New("UNSUPPORTED_RPC")
}
}
func TestSessVolDiscount(t *testing.T) {
switch *dbType {
case utils.MetaInternal:
tSessVolDiscCfgDIR = "session_volume_discount_internal"
case utils.MetaMySQL:
tSessVolDiscCfgDIR = "session_volume_discount_mysql"
case utils.MetaMongo:
tSessVolDiscCfgDIR = "session_volume_discount_mongo"
case utils.MetaPostgres:
t.SkipNow()
default:
t.Fatal("Unknown Database type")
}
for _, stest := range tSessVolDiscITtests {
t.Run(tSessVolDiscCfgDIR, stest)
}
}
// Init config firs
func testSessVolDiscInitCfg(t *testing.T) {
tSessVolDiscCfgPath = path.Join(*dataDir, "conf", "samples", tSessVolDiscCfgDIR)
var err error
tSessVolDiscCfg, err = config.NewCGRConfigFromPath(context.Background(), tSessVolDiscCfgPath)
if err != nil {
t.Error(err)
}
}
// Remove data in both rating and accounting db
func testSessVolDiscResetDataDb(t *testing.T) {
if err := engine.InitDataDB(tSessVolDiscCfg); err != nil {
t.Fatal(err)
}
}
// Wipe out the cdr database
func testSessVolDiscResetStorDb(t *testing.T) {
if err := engine.InitStorDB(tSessVolDiscCfg); err != nil {
t.Fatal(err)
}
}
// Start CGR Engine
func testSessVolDiscStartEngine(t *testing.T) {
if _, err := engine.StopStartEngine(tSessVolDiscCfgPath, *waitRater); err != nil {
t.Fatal(err)
}
}
// Connect rpc client to rater
func testSessVolDiscApierRpcConn(t *testing.T) {
var err error
tSessVolDiscBiRPC, err = newBiRPCClient(tSessVolDiscCfg.ListenCfg()) // We connect over JSON so we can also troubleshoot if needed
if err != nil {
t.Fatal(err)
}
}
func testSessVolDiscLoadersLoad(t *testing.T) {
var reply string
if err := tSessVolDiscBiRPC.Call(context.Background(), utils.LoaderSv1Load,
&loaders.ArgsProcessFolder{
// StopOnError: true,
Caching: utils.StringPointer(utils.MetaReload),
}, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error("Unexpected reply returned:", reply)
}
}
func testSessVolDiscCheckRoutesAndRateProfiles(t *testing.T) {
expRp := &utils.RateProfile{
Tenant: "cgrates.org",
ID: "RP1",
FilterIDs: []string{},
MinCost: utils.NewDecimal(0, 0),
MaxCost: utils.NewDecimal(0, 0),
Rates: map[string]*utils.Rate{
"RT_10": {
ID: "RT_10",
FilterIDs: []string{"*prefix:~*req.Destination:10"},
IntervalRates: []*utils.IntervalRate{
{
IntervalStart: utils.NewDecimal(0, 0),
FixedFee: utils.NewDecimal(0, 0),
RecurrentFee: utils.NewDecimal(3, 2),
Unit: utils.NewDecimal(60000000000, 0),
Increment: utils.NewDecimal(1000000000, 0),
},
},
},
"RT_20": {
ID: "RT_20",
FilterIDs: []string{"*prefix:~*req.Destination:20"},
IntervalRates: []*utils.IntervalRate{
{
IntervalStart: utils.NewDecimal(0, 0),
FixedFee: utils.NewDecimal(0, 0),
RecurrentFee: utils.NewDecimal(1, 2),
Unit: utils.NewDecimal(60000000000, 0),
Increment: utils.NewDecimal(1000000000, 0),
},
},
},
"RT_DFLT": {
ID: "RT_DFLT",
IntervalRates: []*utils.IntervalRate{
{
IntervalStart: utils.NewDecimal(0, 0),
FixedFee: utils.NewDecimal(0, 0),
RecurrentFee: utils.NewDecimal(92, 2),
Unit: utils.NewDecimal(60000000000, 0),
Increment: utils.NewDecimal(1000000000, 0),
},
},
},
},
}
var reply *utils.RateProfile
if err := tSessVolDiscBiRPC.Call(context.Background(), utils.AdminSv1GetRateProfile,
&utils.TenantIDWithAPIOpts{
TenantID: &utils.TenantID{
Tenant: "cgrates.org",
ID: "RP1",
},
}, &reply); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(reply, expRp) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expRp), utils.ToJSON(reply))
}
expRoutePrf := &engine.APIRouteProfile{
Tenant: "cgrates.org",
ID: "LC1",
FilterIDs: []string{},
Sorting: "*lc",
SortingParameters: []string{},
Routes: []*engine.ExternalRoute{
{
ID: "supplier1",
RateProfileIDs: []string{"RP1"},
},
{
ID: "supplier2",
RateProfileIDs: []string{"RP2"},
},
{
ID: "supplier3",
RateProfileIDs: []string{"RP3"},
},
{
ID: "supplier4",
RateProfileIDs: []string{"RP4"},
},
},
}
var result *engine.APIRouteProfile
if err := tSessVolDiscBiRPC.Call(context.Background(), utils.AdminSv1GetRouteProfile,
&utils.TenantIDWithAPIOpts{
TenantID: &utils.TenantID{
Tenant: "cgrates.org",
ID: "LC1",
},
}, &result); err != nil {
t.Error(err)
} else {
sort.Slice(result.Routes, func(i, j int) bool {
return result.Routes[i].ID < result.Routes[j].ID
})
if !reflect.DeepEqual(result, expRoutePrf) {
t.Errorf("Expected %+v \n, received %+v", utils.ToJSON(expRoutePrf), utils.ToJSON(result))
}
}
}
func testSessVolDiscSetAccounts(t *testing.T) {
accPrf1 := &apis.APIAccountWithAPIOpts{
APIAccount: &utils.APIAccount{
Tenant: "cgrates.org",
ID: "ACC1",
FilterIDs: []string{"*string:~*req.Account:1"},
Balances: map[string]*utils.APIBalance{
"AbstractBalance1": {
ID: "AbstractBalance1",
Type: utils.MetaAbstract,
Units: float64(40 * time.Second),
CostIncrements: []*utils.APICostIncrement{
{
Increment: utils.Float64Pointer(float64(time.Second)),
FixedFee: utils.Float64Pointer(float64(0)),
RecurrentFee: utils.Float64Pointer(float64(1)),
},
},
},
},
Weights: ";10",
},
APIOpts: nil,
}
accPrf2 := &apis.APIAccountWithAPIOpts{
APIAccount: &utils.APIAccount{
Tenant: "cgrates.org",
ID: "ACC2",
FilterIDs: []string{"*string:~*req.Account:2"},
Balances: map[string]*utils.APIBalance{
"AbstractBalance2": {
ID: "AbstractBalance2",
Type: utils.MetaAbstract,
Units: float64(80 * time.Second),
CostIncrements: []*utils.APICostIncrement{
{
Increment: utils.Float64Pointer(float64(time.Minute)),
FixedFee: utils.Float64Pointer(float64(0)),
RecurrentFee: utils.Float64Pointer(float64(1)),
},
},
},
},
Weights: ";10",
},
APIOpts: nil,
}
accPrf3 := &apis.APIAccountWithAPIOpts{
APIAccount: &utils.APIAccount{
Tenant: "cgrates.org",
ID: "ACC3",
FilterIDs: []string{"*string:~*req.Account:3"},
Balances: map[string]*utils.APIBalance{
"AbstractBalance3": {
ID: "AbstractBalance3",
Type: utils.MetaAbstract,
Units: float64(120 * time.Second),
UnitFactors: []*utils.APIUnitFactor{
{
Factor: 100,
},
},
CostIncrements: []*utils.APICostIncrement{
{
Increment: utils.Float64Pointer(float64(time.Minute)),
FixedFee: utils.Float64Pointer(float64(0)),
RecurrentFee: utils.Float64Pointer(float64(1)),
},
},
},
},
Weights: ";10",
},
APIOpts: nil,
}
accPrf4 := &apis.APIAccountWithAPIOpts{
APIAccount: &utils.APIAccount{
Tenant: "cgrates.org",
ID: "ACC3",
FilterIDs: []string{"*string:~*req.Account:4"},
Balances: map[string]*utils.APIBalance{
"AbstractBalance4": {
ID: "AbstractBalance4",
Type: utils.MetaAbstract,
Units: float64(30 * time.Second),
UnitFactors: []*utils.APIUnitFactor{
{
Factor: 100,
},
},
CostIncrements: []*utils.APICostIncrement{
{
Increment: utils.Float64Pointer(float64(time.Second)),
FixedFee: utils.Float64Pointer(float64(0.01)),
RecurrentFee: utils.Float64Pointer(float64(2)),
},
},
},
},
Weights: ";10",
},
APIOpts: nil,
}
var reply string
if err := tSessVolDiscBiRPC.Call(context.Background(), utils.AdminSv1SetAccount,
accPrf1, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error(err)
}
if err := tSessVolDiscBiRPC.Call(context.Background(), utils.AdminSv1SetAccount,
accPrf2, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error(err)
}
if err := tSessVolDiscBiRPC.Call(context.Background(), utils.AdminSv1SetAccount,
accPrf3, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error(err)
}
if err := tSessVolDiscBiRPC.Call(context.Background(), utils.AdminSv1SetAccount,
accPrf4, &reply); err != nil {
t.Error(err)
} else if reply != utils.OK {
t.Error(err)
}
}
func testSessVolDiscStopCgrEngine(t *testing.T) {
if err := engine.KillEngine(*waitRater); err != nil {
t.Error(err)
}
}