Files
cgrates/accounts/abstractbalance_test.go
2021-05-17 17:58:44 +02:00

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)
}
}
*/