mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-12 18:46:24 +05:00
1278 lines
40 KiB
Go
1278 lines
40 KiB
Go
/*
|
|
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 accounts
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/cgrates/birpc/context"
|
|
"github.com/cgrates/cgrates/utils"
|
|
"github.com/ericlagergren/decimal"
|
|
)
|
|
|
|
func TestABDebitUsageFromConcretes1(t *testing.T) {
|
|
aB := &abstractBalance{
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB1",
|
|
Type: utils.MetaConcrete,
|
|
Opts: map[string]interface{}{
|
|
utils.MetaBalanceLimit: -200.0,
|
|
},
|
|
UnitFactors: []*utils.UnitFactor{
|
|
{
|
|
Factor: utils.NewDecimal(100, 0), // EuroCents
|
|
},
|
|
},
|
|
Units: utils.NewDecimal(500, 0), // 500 EuroCents
|
|
},
|
|
},
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB2",
|
|
Type: utils.MetaConcrete,
|
|
Opts: map[string]interface{}{
|
|
utils.MetaBalanceLimit: -1.0,
|
|
},
|
|
Units: utils.NewDecimal(125, 2),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
// consume only from first balance
|
|
expectedEvCharg := &utils.EventCharges{
|
|
Concretes: utils.NewDecimal(5, 0),
|
|
Charges: []*utils.ChargeEntry{
|
|
{
|
|
ChargingID: "GENUUID", //will be changed
|
|
CompressFactor: 1,
|
|
},
|
|
},
|
|
Accounting: map[string]*utils.AccountCharge{
|
|
"GENUUID": {
|
|
BalanceID: "CB1",
|
|
Units: utils.NewDecimal(5, 0),
|
|
BalanceLimit: utils.NewDecimal(-200, 0),
|
|
UnitFactorID: "GENUUID",
|
|
},
|
|
},
|
|
UnitFactors: map[string]*utils.UnitFactor{
|
|
"GENUUID": {
|
|
Factor: utils.NewDecimal(100, 0),
|
|
},
|
|
},
|
|
Rating: make(map[string]*utils.RateSInterval),
|
|
Rates: make(map[string]*utils.IntervalRate),
|
|
Accounts: make(map[string]*utils.Account),
|
|
}
|
|
if evCh, err := debitConcreteUnits(context.Background(), decimal.New(5, 0),
|
|
utils.EmptyString, aB.cncrtBlncs, new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(0, 0)) != 0 {
|
|
t.Errorf("Unexpected units in first balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
} else if aB.cncrtBlncs[1].blnCfg.Units.Compare(utils.NewDecimal(125, 2)) != 0 {
|
|
t.Errorf("Unexpected units in second balance: %s", aB.cncrtBlncs[1].blnCfg.Units)
|
|
} else {
|
|
//as the names of accounting, charges, UF are GENUUIDs generator, we will change their names for comparing
|
|
expectedEvCharg.Charges[0].ChargingID = evCh.Charges[0].ChargingID
|
|
expectedEvCharg.Accounting = evCh.Accounting
|
|
expectedEvCharg.UnitFactors = evCh.UnitFactors
|
|
if !reflect.DeepEqual(evCh, expectedEvCharg) {
|
|
t.Errorf("Expected %+v, received %+v", utils.ToJSON(expectedEvCharg), utils.ToJSON(evCh))
|
|
}
|
|
}
|
|
|
|
//back with the main units
|
|
aB.cncrtBlncs[0].blnCfg.Units = utils.NewDecimal(500, 0)
|
|
expectedEvCharg = &utils.EventCharges{
|
|
Concretes: utils.NewDecimal(9, 0),
|
|
Charges: []*utils.ChargeEntry{
|
|
{
|
|
ChargingID: "GENUUID", //will be changed
|
|
CompressFactor: 1,
|
|
},
|
|
{
|
|
ChargingID: "GENUUID2", //will be changed
|
|
CompressFactor: 1,
|
|
},
|
|
},
|
|
Accounting: map[string]*utils.AccountCharge{
|
|
"GENUUID2": {
|
|
BalanceID: "CB2",
|
|
Units: utils.NewDecimal(2, 0),
|
|
BalanceLimit: utils.NewDecimal(-1, 0),
|
|
},
|
|
"GENUUID": {
|
|
BalanceID: "CB1",
|
|
Units: utils.NewDecimal(7, 0),
|
|
BalanceLimit: utils.NewDecimal(-200, 0),
|
|
UnitFactorID: "GENNUUID_FACTOR",
|
|
},
|
|
},
|
|
UnitFactors: map[string]*utils.UnitFactor{
|
|
"GENNUUID_FACTOR": {
|
|
Factor: utils.NewDecimal(100, 0),
|
|
},
|
|
},
|
|
Rating: make(map[string]*utils.RateSInterval),
|
|
Rates: make(map[string]*utils.IntervalRate),
|
|
Accounts: make(map[string]*utils.Account),
|
|
}
|
|
|
|
if evCh, err := debitConcreteUnits(context.Background(), decimal.New(9, 0),
|
|
utils.EmptyString, aB.cncrtBlncs, new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(-200, 0)) != 0 {
|
|
t.Errorf("Unexpected units in first balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
} else if aB.cncrtBlncs[1].blnCfg.Units.Compare(utils.NewDecimal(-75, 2)) != 0 {
|
|
t.Errorf("Unexpected units in second balance: %s", aB.cncrtBlncs[1].blnCfg.Units)
|
|
} else {
|
|
//as the names of accounting, charges, UF are GENUUIDs generator, we will change their names for comparing
|
|
expectedEvCharg.Charges = evCh.Charges
|
|
expectedEvCharg.Accounting = evCh.Accounting
|
|
expectedEvCharg.UnitFactors = evCh.UnitFactors
|
|
if !reflect.DeepEqual(evCh, expectedEvCharg) {
|
|
t.Errorf("Expected %+v, received %+v", utils.ToJSON(expectedEvCharg), utils.ToJSON(evCh))
|
|
}
|
|
}
|
|
|
|
//back with the main units
|
|
aB.cncrtBlncs[0].blnCfg.Units = utils.NewDecimal(500, 0)
|
|
aB.cncrtBlncs[1].blnCfg.Units = utils.NewDecimal(125, 2)
|
|
|
|
if _, err := debitConcreteUnits(context.Background(), decimal.New(int64(10*time.Minute), 0),
|
|
utils.EmptyString, aB.cncrtBlncs, new(utils.CGREvent)); err == nil || err != utils.ErrInsufficientCredit {
|
|
t.Error(err)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(500, 0)) != 0 {
|
|
t.Errorf("Unexpected units in first balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
} else if aB.cncrtBlncs[1].blnCfg.Units.Compare(utils.NewDecimal(125, 2)) != 0 {
|
|
t.Errorf("Unexpected units in second balance: %s", aB.cncrtBlncs[1].blnCfg.Units)
|
|
}
|
|
|
|
expectedEvCharg = &utils.EventCharges{
|
|
Concretes: utils.NewDecimal(925, 2),
|
|
Charges: []*utils.ChargeEntry{
|
|
{
|
|
ChargingID: "GENUUID", //will be changed
|
|
CompressFactor: 1,
|
|
},
|
|
{
|
|
ChargingID: "GENUUID2", //will be changed
|
|
CompressFactor: 1,
|
|
},
|
|
},
|
|
Accounting: map[string]*utils.AccountCharge{
|
|
"GENUUID": {
|
|
BalanceID: "CB1",
|
|
Units: utils.NewDecimal(7, 0),
|
|
BalanceLimit: utils.NewDecimal(-200, 0),
|
|
UnitFactorID: "GENNUUID_FACTOR",
|
|
},
|
|
"GENUUID2": {
|
|
BalanceID: "CB2",
|
|
Units: utils.NewDecimal(225, 2),
|
|
BalanceLimit: utils.NewDecimal(-1, 0),
|
|
},
|
|
},
|
|
UnitFactors: map[string]*utils.UnitFactor{
|
|
"GENNUUID_FACTOR": {
|
|
Factor: utils.NewDecimal(100, 0),
|
|
},
|
|
},
|
|
Rating: make(map[string]*utils.RateSInterval),
|
|
Rates: make(map[string]*utils.IntervalRate),
|
|
Accounts: make(map[string]*utils.Account),
|
|
}
|
|
if evCh, err := debitConcreteUnits(context.Background(), decimal.New(925, 2),
|
|
utils.EmptyString, aB.cncrtBlncs, new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(-200, 0)) != 0 {
|
|
t.Errorf("Unexpected units in first balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
} else if aB.cncrtBlncs[1].blnCfg.Units.Compare(utils.NewDecimal(-1, 0)) != 0 {
|
|
t.Errorf("Unexpected units in second balance: %s", aB.cncrtBlncs[1].blnCfg.Units)
|
|
} else {
|
|
//as the names of accounting, charges, UF are GENUUIDs generator, we will change their names for comparing
|
|
expectedEvCharg.Charges = evCh.Charges
|
|
expectedEvCharg.Accounting = evCh.Accounting
|
|
expectedEvCharg.UnitFactors = evCh.UnitFactors
|
|
if !reflect.DeepEqual(evCh, expectedEvCharg) {
|
|
t.Errorf("Expected %+v, received %+v", utils.ToJSON(expectedEvCharg), utils.ToJSON(evCh))
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
func TestABDebitAbstracts(t *testing.T) {
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB1",
|
|
Type: utils.MetaAbstract,
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(1, 0)},
|
|
},
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB1",
|
|
Type: utils.MetaConcrete,
|
|
UnitFactors: []*utils.UnitFactor{
|
|
{
|
|
Factor: utils.NewDecimal(1, 0), // EuroCents
|
|
},
|
|
},
|
|
Units: utils.NewDecimal(50, 0), // 50 EURcents
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(30*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(20, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
|
|
// limited by concrete
|
|
aB.blnCfg.Units = utils.NewDecimal(int64(60*time.Second), 0)
|
|
aB.cncrtBlncs[0].blnCfg.Units = utils.NewDecimal(29, 0) // not enough concrete
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(30*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(29*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(31*time.Second), 0)) != 0 { // used 29 units
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(0, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
|
|
// limited by concrete
|
|
aB.cncrtBlncs[0].blnCfg.Units = utils.NewDecimal(0, 0) // not enough concrete
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(30*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(0, 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(31*time.Second), 0)) != 0 { // same as above
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(0, 0)) != 0 { // same as above
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
|
|
// limited by abstract
|
|
aB.blnCfg.Units = utils.NewDecimal(int64(29*time.Second), 0) // not enough abstract
|
|
aB.cncrtBlncs[0].blnCfg.Units = utils.NewDecimal(60, 0)
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(30*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(29*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(0, 0)) != 0 { // should be all used
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(31, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCost0WithConcrete(t *testing.T) {
|
|
// consume units only from abstract balance
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(10, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(30*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(10, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCost0WithoutConcrete(t *testing.T) {
|
|
// consume units only from abstract balance
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(30*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCost0Exceed1(t *testing.T) {
|
|
// consume more units that has an abstract balance
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(10, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(70*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(60*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(0, 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(10, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCost0ExceedWithoutConcrete(t *testing.T) {
|
|
// consume more units that has an abstract balance
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(70*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(60*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(0, 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCost0WithUnlimitedWithConcrete(t *testing.T) {
|
|
// consume more units that has an abstract balance
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
Opts: map[string]interface{}{
|
|
utils.MetaBalanceUnlimited: true,
|
|
},
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(10, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(80*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(80*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(-int64(20*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(10, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCost0WithLimit(t *testing.T) {
|
|
// consume more units that has an abstract balance
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
Opts: map[string]interface{}{
|
|
utils.MetaBalanceLimit: 30000000000.0,
|
|
},
|
|
UnitFactors: []*utils.UnitFactor{
|
|
{
|
|
Factor: utils.NewDecimal(int64(2*time.Second), 0),
|
|
},
|
|
},
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(30*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Expected %+v, received %+v", decimal.New(int64(30*time.Second), 0), ec.Abstracts)
|
|
}
|
|
}
|
|
|
|
func TestABCost0WithLimitWithConcrete(t *testing.T) {
|
|
// consume more units that has an abstract balance
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
Opts: map[string]interface{}{
|
|
utils.MetaBalanceLimit: 30000000000.0,
|
|
},
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(10, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(30*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(10, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCost0WithLimitExceed(t *testing.T) {
|
|
// consume more units that has an abstract balance
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
Opts: map[string]interface{}{
|
|
utils.MetaBalanceLimit: 30000000000.0,
|
|
},
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(50*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCost0WithLimitExceedWithConcrete(t *testing.T) {
|
|
// consume more units that has an abstract balance
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
Opts: map[string]interface{}{
|
|
utils.MetaBalanceLimit: 30000000000.0,
|
|
},
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(0, 0),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(10, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(50*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(10, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestDebitUsageFiltersError(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
filters := engine.NewFilterS(cfg, nil, nil)
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "ID_TEST",
|
|
Type: utils.MetaAbstract,
|
|
FilterIDs: []string{"*string:*~req.Usage:10s"},
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(1*time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(2, 0),
|
|
},
|
|
},
|
|
Units: utils.NewDecimal(int64(50*time.Second), 0),
|
|
},
|
|
fltrS: filters,
|
|
}
|
|
|
|
cgrEv := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
Event: map[string]interface{}{
|
|
utils.Usage: "10s",
|
|
},
|
|
}
|
|
_, err := aB.debitAbstracts(decimal.New(int64(40*time.Second), 0),
|
|
cgrEv)
|
|
if err == nil || err != utils.ErrFilterNotPassingNoCaps {
|
|
t.Errorf("Expected %+v, received %+v", utils.ErrFilterNotPassingNoCaps, err)
|
|
}
|
|
|
|
aB.blnCfg.FilterIDs = []string{"invalid_filter_format"}
|
|
_, err = aB.debitAbstracts(decimal.New(int64(40*time.Second), 0),
|
|
cgrEv)
|
|
if err == nil || err != utils.ErrNoDatabaseConn {
|
|
t.Errorf("Expected %+v, received %+v", utils.ErrNoDatabaseConn, err)
|
|
}
|
|
}
|
|
|
|
func TestDebitUsageBalanceLimitErrors(t *testing.T) {
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "ID_TEST",
|
|
Type: utils.MetaAbstract,
|
|
Opts: map[string]interface{}{
|
|
utils.MetaBalanceLimit: "not_FLOAT64",
|
|
},
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(1*time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(2, 0),
|
|
},
|
|
},
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0),
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
cgrEv := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
Event: map[string]interface{}{
|
|
utils.Usage: "10s",
|
|
},
|
|
}
|
|
|
|
expectedErr := "unsupported *balanceLimit format"
|
|
_, err := aB.debitAbstracts(decimal.New(int64(40*time.Second), 0),
|
|
cgrEv)
|
|
if err == nil || err.Error() != expectedErr {
|
|
t.Errorf("Expected %+v, received %+v", expectedErr, err)
|
|
}
|
|
|
|
aB.blnCfg.Opts[utils.MetaBalanceLimit] = float64(16 * time.Second)
|
|
if _, err = aB.debitAbstracts(decimal.New(int64(40*time.Second), 0),
|
|
cgrEv); err != nil {
|
|
t.Error(err)
|
|
}
|
|
if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(60*time.Second), 0)) != 0 {
|
|
t.Errorf("Expected %+v, received %+v", aB.blnCfg.Units.Big, utils.NewDecimal(int64(50*time.Second), 0))
|
|
}
|
|
}
|
|
|
|
func TestDebitUsageUnitFactorsErrors(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
filters := engine.NewFilterS(cfg, nil, nil)
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "ID_TEST",
|
|
Type: utils.MetaAbstract,
|
|
UnitFactors: []*utils.UnitFactor{
|
|
{
|
|
FilterIDs: []string{"invalid_filter_fromat"},
|
|
Factor: utils.NewDecimal(2, 0),
|
|
},
|
|
},
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(1*time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(2, 0),
|
|
},
|
|
},
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0),
|
|
},
|
|
fltrS: filters,
|
|
}
|
|
|
|
cgrEv := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
Event: map[string]interface{}{
|
|
utils.Usage: "10s",
|
|
},
|
|
}
|
|
|
|
if _, err := aB.debitAbstracts(decimal.New(int64(20*time.Second), 0), cgrEv); err == nil ||
|
|
err != utils.ErrNoDatabaseConn {
|
|
t.Errorf("Expected %+v, received %+v", utils.ErrNoDatabaseConn, err)
|
|
}
|
|
|
|
aB.blnCfg.UnitFactors[0].FilterIDs = []string{"*string:*~req.Usage:10s"}
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(20*time.Second), 0), cgrEv); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(0, 0)) != 0 {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestDebitUsageCostIncrementError(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
filters := engine.NewFilterS(cfg, nil, nil)
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "ID_TEST",
|
|
Type: utils.MetaAbstract,
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
FilterIDs: []string{"INVALID_FILTER_FORMAT"},
|
|
Increment: utils.NewDecimal(int64(1*time.Second), 0),
|
|
},
|
|
},
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0),
|
|
},
|
|
fltrS: filters,
|
|
}
|
|
cgrEv := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
Event: map[string]interface{}{
|
|
utils.Usage: "10s",
|
|
},
|
|
}
|
|
|
|
if _, err := aB.debitAbstracts(decimal.New(int64(20*time.Second), 0), cgrEv); err == nil ||
|
|
err != utils.ErrNoDatabaseConn {
|
|
t.Errorf("Expected %+v, received %+v", utils.ErrNoDatabaseConn, err)
|
|
}
|
|
|
|
//Will check the error by making the event charge
|
|
//the cost is unknown, will use attributes to query from rates
|
|
aB.blnCfg.CostIncrements[0].FilterIDs = []string{}
|
|
aB.blnCfg.AttributeIDs = []string{"attr11"}
|
|
expected := "NOT_CONNECTED: AttributeS"
|
|
if _, err := aB.debitAbstracts(decimal.New(int64(20*time.Second), 0), cgrEv); err == nil ||
|
|
err.Error() != expected {
|
|
t.Errorf("Expected %+v, received %+v", expected, err)
|
|
}
|
|
}
|
|
|
|
func TestABCost(t *testing.T) {
|
|
// debit 10 seconds with cost of 0.1 per second
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(1, 1),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(10, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(10*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(10*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(50*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(9, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCostWithFiltersNotMatch(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
data := engine.NewInternalDB(nil, nil, true)
|
|
dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil)
|
|
filterS := engine.NewFilterS(cfg, nil, dm)
|
|
// we expect to receive an error because it will try calculate the cost from rates
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
FilterIDs: []string{"*string:~*req.CustomField:CustomValue"},
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(1, 1),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(10, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: filterS,
|
|
}
|
|
cgrEv := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "EV",
|
|
Event: map[string]interface{}{
|
|
"CustomField2": "CustomValue2",
|
|
},
|
|
APIOpts: map[string]interface{}{},
|
|
}
|
|
if _, err := aB.debitAbstracts(decimal.New(int64(10*time.Second), 0),
|
|
cgrEv); err == nil || err.Error() != "RATES_ERROR:NOT_CONNECTED: RateS" {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestABCostWithFilters(t *testing.T) {
|
|
// debit 10 seconds with cost of 0.1 per second
|
|
cfg := config.NewDefaultCGRConfig()
|
|
data := engine.NewInternalDB(nil, nil, true)
|
|
dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil)
|
|
filterS := engine.NewFilterS(cfg, nil, dm)
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
FilterIDs: []string{"*string:~*req.CustomField:CustomValue"},
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(1, 1),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(10, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: filterS,
|
|
}
|
|
cgrEv := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "EV",
|
|
Event: map[string]interface{}{
|
|
"CustomField": "CustomValue",
|
|
},
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(10*time.Second), 0),
|
|
cgrEv); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(10*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(50*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(9, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCostExceed(t *testing.T) {
|
|
// debit 70 seconds with cost of 0.1 per second
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(1, 1),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(10, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(70*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(60*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(0, 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(4, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCostUnlimitedExceed(t *testing.T) {
|
|
// debit 70 seconds with cost of 0.1 per second
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
Opts: map[string]interface{}{
|
|
utils.MetaBalanceUnlimited: true,
|
|
},
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(1, 1),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(10, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(70*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(70*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(-int64(10*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(3, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCostLimit(t *testing.T) {
|
|
// debit 70 seconds with cost of 0.1 per second
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
Opts: map[string]interface{}{
|
|
utils.MetaBalanceLimit: 30000000000.0,
|
|
},
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(1, 1),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(10, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(30*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(7, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCostLimitExceed(t *testing.T) {
|
|
// debit 70 seconds with cost of 0.1 per second
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
Opts: map[string]interface{}{
|
|
utils.MetaBalanceLimit: 30000000000.0,
|
|
},
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(1, 1),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(10, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(70*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(30*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(7, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCostNotEnoughConcrete(t *testing.T) {
|
|
// debit 55 seconds with cost of 0.1 per second
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(1, 1),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(5, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(55*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(50*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(10*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(0, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCostMultipleConcrete(t *testing.T) {
|
|
// debit 55 seconds with cost of 0.1 per second
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(1, 1),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB1",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(5, 0),
|
|
},
|
|
},
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB2",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(5, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(55*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(55*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(5*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(0, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
} else if aB.cncrtBlncs[1].blnCfg.Units.Compare(utils.NewDecimal(45, 1)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[1].blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestABCostMultipleConcreteUnlimited(t *testing.T) {
|
|
// debit 55 seconds with cost of 0.1 per second
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "AB_COST_0",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0), // 1 Minute
|
|
Opts: map[string]interface{}{
|
|
utils.MetaBalanceUnlimited: true,
|
|
},
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(1, 1),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB1",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(5, 0),
|
|
},
|
|
},
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB2",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(5, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: new(engine.FilterS),
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(70*time.Second), 0),
|
|
new(utils.CGREvent)); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(70*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(-int64(10*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(0, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
} else if aB.cncrtBlncs[1].blnCfg.Units.Compare(utils.NewDecimal(3, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[1].blnCfg.Units)
|
|
}
|
|
}
|
|
|
|
func TestAMCostWithUnitFactor(t *testing.T) {
|
|
cfg := config.NewDefaultCGRConfig()
|
|
data := engine.NewInternalDB(nil, nil, true)
|
|
dm := engine.NewDataManager(data, config.CgrConfig().CacheCfg(), nil)
|
|
filterS := engine.NewFilterS(cfg, nil, dm)
|
|
|
|
aB := &abstractBalance{
|
|
blnCfg: &utils.Balance{
|
|
ID: "ID_TEST",
|
|
Type: utils.MetaAbstract,
|
|
Units: utils.NewDecimal(int64(60*time.Second), 0),
|
|
UnitFactors: []*utils.UnitFactor{
|
|
{
|
|
Factor: utils.NewDecimal(2, 0),
|
|
},
|
|
},
|
|
CostIncrements: []*utils.CostIncrement{
|
|
{
|
|
Increment: utils.NewDecimal(int64(1*time.Second), 0),
|
|
RecurrentFee: utils.NewDecimal(1, 0),
|
|
},
|
|
},
|
|
},
|
|
cncrtBlncs: []*concreteBalance{
|
|
{
|
|
blnCfg: &utils.Balance{
|
|
ID: "CB1",
|
|
Type: utils.MetaConcrete,
|
|
Units: utils.NewDecimal(50, 0),
|
|
},
|
|
},
|
|
},
|
|
fltrS: filterS,
|
|
}
|
|
|
|
cgrEv := &utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
ID: "EV",
|
|
Event: map[string]interface{}{
|
|
"CustomField": "CustomValue",
|
|
},
|
|
}
|
|
|
|
if ec, err := aB.debitAbstracts(decimal.New(int64(10*time.Second), 0),
|
|
cgrEv); err != nil {
|
|
t.Error(err)
|
|
} else if ec.Abstracts.Cmp(decimal.New(int64(20*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected debited units: %s", ec.Abstracts)
|
|
} else if aB.blnCfg.Units.Compare(utils.NewDecimal(int64(40*time.Second), 0)) != 0 {
|
|
t.Errorf("Unexpected units in abstract balance: %s", aB.blnCfg.Units)
|
|
} else if aB.cncrtBlncs[0].blnCfg.Units.Compare(utils.NewDecimal(30, 0)) != 0 {
|
|
t.Errorf("Unexpected units in concrete balance: %s", aB.cncrtBlncs[0].blnCfg.Units)
|
|
}
|
|
}
|
|
*/
|