mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-22 23:58:44 +05:00
The (*CDRServer).processEvent function is now called processEvents and can be passed an array of CGREvents instead of only one. This was done because when calling the RateCDRs API we want to first refund all CDRs before starting to debit again. The rerate parameter is now no longer hardcoded to true for the RateCDRs API.If required, the "*rerate" flag must be provided by the caller. Now, the refundEventCost function returns an additional boolean, that signals whether the refund occured or didn't. If the reRate parameter is set to true, also set refund to true. In case CostDetails is not populated, retrieve it from StorDB if possible and add it to the CGREvent before converting to CDRs. Set CostDetails back to nil once the refund goes through. Remove the refund logic from within the store block. Now that the refund happens before the debit, revise the expected values for the "testV1CDRsProcessEventWithRefund" subtest within the apier/v1/cdrs_it_test.go file. Add an integration test for the following scenario: -create one account with one balance of 1 free minute and rating for the rest. -send one CDR of two minutes with ProcessEvent. This should consume 60s out of the free balance and charge 60s. The SetupTime in the CDR should be 1 hour after the second CDR. -send the second CDR with an usage of 2m. This should be charged entirely. -send a RateCDR API call with OrderBy: "SetupTime". This should rerate the two CDRs from above and change their order of rating.
845 lines
28 KiB
Go
845 lines
28 KiB
Go
//go:build integration
|
|
// +build integration
|
|
|
|
/*
|
|
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
|
Copyright (C) ITsysCOM GmbH
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU 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 v2
|
|
|
|
import (
|
|
"net/rpc"
|
|
"path"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
v1 "github.com/cgrates/cgrates/apier/v1"
|
|
"github.com/cgrates/cgrates/config"
|
|
"github.com/cgrates/cgrates/engine"
|
|
"github.com/cgrates/cgrates/utils"
|
|
)
|
|
|
|
var (
|
|
cdrsCfgPath string
|
|
cdrsCfg *config.CGRConfig
|
|
cdrsRpc *rpc.Client
|
|
cdrsConfDIR string // run the tests for specific configuration
|
|
|
|
// subtests to be executed for each confDIR
|
|
sTestsCDRsIT = []func(t *testing.T){
|
|
testV2CDRsInitConfig,
|
|
testV2CDRsInitDataDb,
|
|
testV2CDRsInitCdrDb,
|
|
testV2CDRsStartEngine,
|
|
testV2CDRsRpcConn,
|
|
testV2CDRsLoadTariffPlanFromFolder,
|
|
testV2CDRsProcessCDR,
|
|
testV2CDRsGetCdrs,
|
|
testV2CDRsRateCDRs,
|
|
testV2CDRsGetCdrs2,
|
|
testV2CDRsUsageNegative,
|
|
testV2CDRsDifferentTenants,
|
|
|
|
testV2CDRsRemoveRatingProfiles,
|
|
testV2CDRsProcessCDRNoRattingPlan,
|
|
testV2CDRsGetCdrsNoRattingPlan,
|
|
|
|
testV2CDRsRateCDRsWithRatingPlan,
|
|
testV2CDRsGetCdrsWithRattingPlan,
|
|
|
|
testV2CDRsSetThreshold,
|
|
testV2CDRsProcessCDRWithThreshold,
|
|
testV2CDRsGetThreshold,
|
|
|
|
testv2CDRsGetCDRsDest,
|
|
|
|
testV2CDRsKillEngine,
|
|
}
|
|
)
|
|
|
|
// Tests starting here
|
|
func TestCDRsIT(t *testing.T) {
|
|
switch *dbType {
|
|
case utils.MetaInternal:
|
|
cdrsConfDIR = "cdrsv2internal"
|
|
case utils.MetaMySQL:
|
|
cdrsConfDIR = "cdrsv2mysql"
|
|
case utils.MetaMongo:
|
|
cdrsConfDIR = "cdrsv2mongo"
|
|
case utils.MetaPostgres:
|
|
cdrsConfDIR = "cdrsv2psql"
|
|
default:
|
|
t.Fatal("Unknown Database type")
|
|
}
|
|
|
|
for _, stest := range sTestsCDRsIT {
|
|
t.Run(cdrsConfDIR, stest)
|
|
}
|
|
}
|
|
|
|
func testV2CDRsInitConfig(t *testing.T) {
|
|
var err error
|
|
cdrsCfgPath = path.Join(*dataDir, "conf", "samples", cdrsConfDIR)
|
|
if cdrsCfg, err = config.NewCGRConfigFromPath(cdrsCfgPath); err != nil {
|
|
t.Fatal("Got config error: ", err.Error())
|
|
}
|
|
}
|
|
|
|
func testV2CDRsInitDataDb(t *testing.T) {
|
|
if err := engine.InitDataDb(cdrsCfg); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// InitDb so we can rely on count
|
|
func testV2CDRsInitCdrDb(t *testing.T) {
|
|
if err := engine.InitStorDb(cdrsCfg); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func testV2CDRsStartEngine(t *testing.T) {
|
|
if _, err := engine.StopStartEngine(cdrsCfgPath, *waitRater); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// Connect rpc client to rater
|
|
func testV2CDRsRpcConn(t *testing.T) {
|
|
cdrsRpc, err = newRPCClient(cdrsCfg.ListenCfg()) // We connect over JSON so we can also troubleshoot if needed
|
|
if err != nil {
|
|
t.Fatal("Could not connect to rater: ", err.Error())
|
|
}
|
|
}
|
|
|
|
func testV2CDRsLoadTariffPlanFromFolder(t *testing.T) {
|
|
var loadInst utils.LoadInstance
|
|
if err := cdrsRpc.Call(utils.APIerSv2LoadTariffPlanFromFolder,
|
|
&utils.AttrLoadTpFromFolder{FolderPath: path.Join(
|
|
*dataDir, "tariffplans", "testit")}, &loadInst); err != nil {
|
|
t.Error(err)
|
|
}
|
|
time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups
|
|
}
|
|
|
|
func testV2CDRsProcessCDR(t *testing.T) {
|
|
args := &engine.ArgV1ProcessEvent{
|
|
Flags: []string{utils.MetaRALs},
|
|
CGREvent: utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
Event: map[string]interface{}{
|
|
utils.OriginID: "testV2CDRsProcessCDR1",
|
|
utils.OriginHost: "192.168.1.1",
|
|
utils.Source: "testV2CDRsProcessCDR",
|
|
utils.RequestType: utils.META_RATED,
|
|
// utils.Category: "call", //it will be populated as default in MapEvent.AsCDR
|
|
utils.Account: "testV2CDRsProcessCDR",
|
|
utils.Subject: "ANY2CNT",
|
|
utils.Destination: "+4986517174963",
|
|
utils.AnswerTime: time.Date(2018, 8, 24, 16, 00, 26, 0, time.UTC),
|
|
utils.Usage: time.Minute,
|
|
"field_extr1": "val_extr1",
|
|
"fieldextr2": "valextr2",
|
|
},
|
|
},
|
|
}
|
|
|
|
var reply string
|
|
if err := cdrsRpc.Call(utils.CDRsV1ProcessEvent, args, &reply); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if reply != utils.OK {
|
|
t.Error("Unexpected reply received: ", reply)
|
|
}
|
|
}
|
|
|
|
func testV2CDRsGetCdrs(t *testing.T) {
|
|
var cdrCnt int64
|
|
req := utils.AttrGetCdrs{}
|
|
if err := cdrsRpc.Call(utils.APIerSv2CountCDRs, req, &cdrCnt); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if cdrCnt != 3 {
|
|
t.Error("Unexpected number of CDRs returned: ", cdrCnt)
|
|
}
|
|
var cdrs []*engine.ExternalCDR
|
|
args := utils.RPCCDRsFilter{RunIDs: []string{utils.MetaRaw}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
} else {
|
|
if cdrs[0].Cost != -1.0 {
|
|
t.Errorf("Unexpected cost for CDR: %f", cdrs[0].Cost)
|
|
}
|
|
if cdrs[0].ExtraFields["PayPalAccount"] != "paypal@cgrates.org" {
|
|
t.Errorf("PayPalAccount should be added by AttributeS, have: %s",
|
|
cdrs[0].ExtraFields["PayPalAccount"])
|
|
}
|
|
}
|
|
args = utils.RPCCDRsFilter{RunIDs: []string{"CustomerCharges"}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
} else {
|
|
if cdrs[0].Cost != 0.0198 {
|
|
t.Errorf("Unexpected cost for CDR: %f", cdrs[0].Cost)
|
|
}
|
|
if cdrs[0].ExtraFields["PayPalAccount"] != "paypal@cgrates.org" {
|
|
t.Errorf("PayPalAccount should be added by AttributeS, have: %s",
|
|
cdrs[0].ExtraFields["PayPalAccount"])
|
|
}
|
|
}
|
|
args = utils.RPCCDRsFilter{RunIDs: []string{"SupplierCharges"}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
} else {
|
|
if cdrs[0].Cost != 0.0102 {
|
|
t.Errorf("Unexpected cost for CDR: %f", cdrs[0].Cost)
|
|
}
|
|
if cdrs[0].ExtraFields["PayPalAccount"] != "paypal@cgrates.org" {
|
|
t.Errorf("PayPalAccount should be added by AttributeS, have: %s",
|
|
cdrs[0].ExtraFields["PayPalAccount"])
|
|
}
|
|
}
|
|
}
|
|
|
|
// Should re-rate the supplier1 cost with RP_ANY2CNT
|
|
func testV2CDRsRateCDRs(t *testing.T) {
|
|
var rpl engine.RatingProfile
|
|
attrGetRatingPlan := &utils.AttrGetRatingProfile{
|
|
Tenant: "cgrates.org", Category: "call", Subject: "SUPPLIER1"}
|
|
actTime, err := utils.ParseTimeDetectLayout("2018-01-01T00:00:00Z", "")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
expected := engine.RatingProfile{
|
|
Id: "*out:cgrates.org:call:SUPPLIER1",
|
|
RatingPlanActivations: engine.RatingPlanActivations{
|
|
{
|
|
ActivationTime: actTime,
|
|
RatingPlanId: "RP_ANY1CNT",
|
|
},
|
|
},
|
|
}
|
|
if err := cdrsRpc.Call(utils.APIerSv1GetRatingProfile, attrGetRatingPlan, &rpl); err != nil {
|
|
t.Errorf("Got error on APIerSv1.GetRatingProfile: %+v", err)
|
|
} else if !reflect.DeepEqual(expected, rpl) {
|
|
t.Errorf("Calling APIerSv1.GetRatingProfile expected: %+v, received: %+v", utils.ToJSON(expected), utils.ToJSON(rpl))
|
|
}
|
|
|
|
rpf := &utils.AttrSetRatingProfile{
|
|
Tenant: "cgrates.org",
|
|
Category: "call",
|
|
Subject: "SUPPLIER1",
|
|
RatingPlanActivations: []*utils.TPRatingActivation{
|
|
{
|
|
ActivationTime: "2018-01-01T00:00:00Z",
|
|
RatingPlanId: "RP_ANY2CNT"}},
|
|
Overwrite: true,
|
|
}
|
|
var reply string
|
|
if err := cdrsRpc.Call(utils.APIerSv1SetRatingProfile, rpf, &reply); err != nil {
|
|
t.Error("Got error on APIerSv1.SetRatingProfile: ", err.Error())
|
|
} else if reply != utils.OK {
|
|
t.Error("Calling APIerSv1.SetRatingProfile got reply: ", reply)
|
|
}
|
|
|
|
expected = engine.RatingProfile{
|
|
Id: "*out:cgrates.org:call:SUPPLIER1",
|
|
RatingPlanActivations: engine.RatingPlanActivations{
|
|
{
|
|
ActivationTime: actTime,
|
|
RatingPlanId: "RP_ANY2CNT",
|
|
},
|
|
},
|
|
}
|
|
if err := cdrsRpc.Call(utils.APIerSv1GetRatingProfile, attrGetRatingPlan, &rpl); err != nil {
|
|
t.Errorf("Got error on APIerSv1.GetRatingProfile: %+v", err)
|
|
} else if !reflect.DeepEqual(expected, rpl) {
|
|
t.Errorf("Calling APIerSv1.GetRatingProfile expected: %+v, received: %+v", utils.ToJSON(expected), utils.ToJSON(rpl))
|
|
}
|
|
|
|
if err := cdrsRpc.Call(utils.CDRsV1RateCDRs, &engine.ArgRateCDRs{
|
|
RPCCDRsFilter: utils.RPCCDRsFilter{NotRunIDs: []string{utils.MetaRaw}},
|
|
Flags: []string{"*chargers:false", utils.MetaRerate},
|
|
}, &reply); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if reply != utils.OK {
|
|
t.Error("Unexpected reply received: ", reply)
|
|
}
|
|
}
|
|
|
|
func testV2CDRsGetCdrs2(t *testing.T) {
|
|
var cdrCnt int64
|
|
req := utils.AttrGetCdrs{}
|
|
if err := cdrsRpc.Call(utils.APIerSv2CountCDRs, req, &cdrCnt); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if cdrCnt != 3 {
|
|
t.Error("Unexpected number of CDRs returned: ", cdrCnt)
|
|
}
|
|
var cdrs []*engine.ExternalCDR
|
|
args := utils.RPCCDRsFilter{RunIDs: []string{utils.MetaRaw}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
} else {
|
|
if cdrs[0].Cost != -1.0 {
|
|
t.Errorf("Unexpected cost for CDR: %f", cdrs[0].Cost)
|
|
}
|
|
}
|
|
args = utils.RPCCDRsFilter{RunIDs: []string{"CustomerCharges"}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
} else {
|
|
if cdrs[0].Cost != 0.0198 {
|
|
t.Errorf("Unexpected cost for CDR: %f", cdrs[0].Cost)
|
|
}
|
|
}
|
|
args = utils.RPCCDRsFilter{RunIDs: []string{"SupplierCharges"}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
} else {
|
|
if cdrs[0].Cost != 0.0102 {
|
|
t.Errorf("Unexpected cost for CDR: %f", cdrs[0].Cost)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testV2CDRsUsageNegative(t *testing.T) {
|
|
argsCdr := &engine.ArgV1ProcessEvent{
|
|
Flags: []string{utils.MetaRALs},
|
|
CGREvent: utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
Event: map[string]interface{}{
|
|
utils.OriginID: "testV2CDRsUsageNegative",
|
|
utils.OriginHost: "192.168.1.1",
|
|
utils.Source: "testV2CDRsUsageNegative",
|
|
utils.RequestType: utils.META_RATED,
|
|
utils.Category: "call",
|
|
utils.Account: "testV2CDRsUsageNegative",
|
|
utils.Subject: "ANY2CNT",
|
|
utils.Destination: "+4986517174963",
|
|
utils.AnswerTime: time.Date(2018, 8, 24, 16, 00, 26, 0, time.UTC),
|
|
utils.Usage: -time.Minute,
|
|
"field_extr1": "val_extr1",
|
|
"fieldextr2": "valextr2",
|
|
},
|
|
},
|
|
}
|
|
var reply string
|
|
if err := cdrsRpc.Call(utils.CDRsV1ProcessEvent, argsCdr, &reply); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if reply != utils.OK {
|
|
t.Error("Unexpected reply received: ", reply)
|
|
}
|
|
|
|
var cdrs []*engine.ExternalCDR
|
|
args := utils.RPCCDRsFilter{RunIDs: []string{utils.MetaRaw}, OriginIDs: []string{"testV2CDRsUsageNegative"}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
} else {
|
|
if cdrs[0].Cost != -1.0 {
|
|
t.Errorf("Unexpected cost for CDR: %f", cdrs[0].Cost)
|
|
}
|
|
if cdrs[0].Usage != "-1m0s" {
|
|
t.Errorf("Unexpected usage for CDR: %s", cdrs[0].Usage)
|
|
}
|
|
}
|
|
cdrs = nil // gob doesn't modify zero-value fields
|
|
args = utils.RPCCDRsFilter{RunIDs: []string{"CustomerCharges"}, OriginIDs: []string{"testV2CDRsUsageNegative"}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
} else {
|
|
if cdrs[0].Cost != 0 {
|
|
t.Errorf("Unexpected cost for CDR: %f", cdrs[0].Cost)
|
|
}
|
|
if cdrs[0].Usage != "0s" {
|
|
t.Errorf("Unexpected usage for CDR: %s", cdrs[0].Usage)
|
|
}
|
|
}
|
|
cdrs = nil // gob doesn't modify zero-value fields
|
|
args = utils.RPCCDRsFilter{RunIDs: []string{"SupplierCharges"}, OriginIDs: []string{"testV2CDRsUsageNegative"}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
} else {
|
|
if cdrs[0].Cost != 0 {
|
|
t.Errorf("Unexpected cost for CDR: %f", cdrs[0].Cost)
|
|
}
|
|
if cdrs[0].Usage != "0s" {
|
|
t.Errorf("Unexpected usage for CDR: %s", cdrs[0].Usage)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testV2CDRsDifferentTenants(t *testing.T) {
|
|
//add an attribute
|
|
alsPrf := &v1.AttributeWithCache{
|
|
AttributeProfile: &engine.AttributeProfile{
|
|
Tenant: "cgrates.com",
|
|
ID: "ATTR_Tenant",
|
|
Contexts: []string{utils.META_ANY},
|
|
FilterIDs: []string{"*string:~*req.Tenant:cgrates.com"},
|
|
ActivationInterval: &utils.ActivationInterval{
|
|
ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC),
|
|
},
|
|
Attributes: []*engine.Attribute{
|
|
{
|
|
Path: utils.MetaTenant,
|
|
Type: utils.META_CONSTANT,
|
|
Value: config.RSRParsers{
|
|
&config.RSRParser{
|
|
Rules: "CustomTenant",
|
|
AllFiltersMatch: true,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Path: utils.MetaReq + utils.NestingSep + utils.Tenant,
|
|
Type: utils.META_CONSTANT,
|
|
Value: config.RSRParsers{
|
|
&config.RSRParser{
|
|
Rules: "CustomTenant",
|
|
AllFiltersMatch: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Blocker: false,
|
|
Weight: 10,
|
|
},
|
|
Cache: utils.StringPointer(utils.MetaReload),
|
|
}
|
|
alsPrf.Compile()
|
|
var result string
|
|
if err := cdrsRpc.Call(utils.APIerSv1SetAttributeProfile, alsPrf, &result); err != nil {
|
|
t.Error(err)
|
|
} else if result != utils.OK {
|
|
t.Error("Unexpected reply returned", result)
|
|
}
|
|
var reply *engine.AttributeProfile
|
|
if err := cdrsRpc.Call(utils.APIerSv1GetAttributeProfile,
|
|
&utils.TenantIDWithArgDispatcher{TenantID: &utils.TenantID{Tenant: "cgrates.com", ID: "ATTR_Tenant"}}, &reply); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
reply.Compile()
|
|
if !reflect.DeepEqual(alsPrf.AttributeProfile, reply) {
|
|
t.Errorf("Expecting : %+v, received: %+v", alsPrf.AttributeProfile, reply)
|
|
}
|
|
//add a charger
|
|
chargerProfile := &v1.ChargerWithCache{
|
|
ChargerProfile: &engine.ChargerProfile{
|
|
Tenant: "CustomTenant",
|
|
ID: "CustomCharger",
|
|
ActivationInterval: &utils.ActivationInterval{
|
|
ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC),
|
|
ExpiryTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC),
|
|
},
|
|
RunID: "CustomRunID",
|
|
AttributeIDs: []string{"*none"},
|
|
Weight: 20,
|
|
},
|
|
Cache: utils.StringPointer(utils.MetaReload),
|
|
}
|
|
if err := cdrsRpc.Call(utils.APIerSv1SetChargerProfile, chargerProfile, &result); err != nil {
|
|
t.Error(err)
|
|
} else if result != utils.OK {
|
|
t.Error("Unexpected reply returned", result)
|
|
}
|
|
var reply2 *engine.ChargerProfile
|
|
if err := cdrsRpc.Call(utils.APIerSv1GetChargerProfile,
|
|
&utils.TenantID{Tenant: "CustomTenant", ID: "CustomCharger"}, &reply2); err != nil {
|
|
t.Error(err)
|
|
} else if !reflect.DeepEqual(chargerProfile.ChargerProfile, reply2) {
|
|
t.Errorf("Expecting : %+v, received: %+v", chargerProfile.ChargerProfile, reply2)
|
|
}
|
|
|
|
argsCdr := &engine.ArgV1ProcessEvent{
|
|
Flags: []string{utils.MetaAttributes, utils.MetaChargers, "*stats:false", "*thresholds:false", utils.MetaStore},
|
|
CGREvent: utils.CGREvent{
|
|
Tenant: "cgrates.com",
|
|
Event: map[string]interface{}{
|
|
utils.OriginID: "testV2CDRsDifferentTenants",
|
|
utils.OriginHost: "192.168.1.1",
|
|
utils.Source: "testV2CDRsDifferentTenants",
|
|
utils.RequestType: utils.META_RATED,
|
|
utils.Category: "call",
|
|
utils.Account: "testV2CDRsDifferentTenants",
|
|
utils.Destination: "+4986517174963",
|
|
utils.Tenant: "cgrates.com",
|
|
utils.AnswerTime: time.Date(2018, 8, 24, 16, 00, 26, 0, time.UTC),
|
|
utils.Usage: time.Second,
|
|
"field_extr1": "val_extr1",
|
|
"fieldextr2": "valextr2",
|
|
},
|
|
},
|
|
}
|
|
var reply3 string
|
|
if err := cdrsRpc.Call(utils.CDRsV1ProcessEvent, argsCdr, &reply3); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if reply3 != utils.OK {
|
|
t.Error("Unexpected reply received: ", reply3)
|
|
}
|
|
|
|
var cdrs []*engine.ExternalCDR
|
|
args := utils.RPCCDRsFilter{Tenants: []string{"CustomTenant"}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 { // no raw Charger defined
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
}
|
|
}
|
|
|
|
func testV2CDRsRemoveRatingProfiles(t *testing.T) {
|
|
var reply string
|
|
if err := cdrsRpc.Call(utils.APIerSv1RemoveRatingProfile, &v1.AttrRemoveRatingProfile{
|
|
Tenant: "cgrates.org",
|
|
Category: utils.CALL,
|
|
Subject: utils.ANY,
|
|
}, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Errorf("Expected: %s, received: %s ", utils.OK, reply)
|
|
}
|
|
if err := cdrsRpc.Call(utils.APIerSv1RemoveRatingProfile, &v1.AttrRemoveRatingProfile{
|
|
Tenant: "cgrates.org",
|
|
Category: utils.CALL,
|
|
Subject: "SUPPLIER1",
|
|
}, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Errorf("Expected: %s, received: %s ", utils.OK, reply)
|
|
}
|
|
}
|
|
|
|
func testV2CDRsProcessCDRNoRattingPlan(t *testing.T) {
|
|
args := &engine.ArgV1ProcessEvent{
|
|
Flags: []string{utils.MetaRALs},
|
|
CGREvent: utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
Event: map[string]interface{}{
|
|
utils.OriginID: "testV2CDRsProcessCDR4",
|
|
utils.OriginHost: "192.168.1.1",
|
|
utils.Source: "testV2CDRsProcessCDR4",
|
|
utils.RequestType: utils.META_RATED,
|
|
utils.Account: "testV2CDRsProcessCDR4",
|
|
utils.Subject: "NoSubject",
|
|
utils.Destination: "+1234567",
|
|
utils.AnswerTime: time.Date(2018, 8, 24, 16, 00, 26, 0, time.UTC),
|
|
utils.Usage: time.Minute,
|
|
"field_extr1": "val_extr1",
|
|
"fieldextr2": "valextr2",
|
|
},
|
|
},
|
|
}
|
|
|
|
var reply string
|
|
if err := cdrsRpc.Call(utils.CDRsV1ProcessEvent, args, &reply); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if reply != utils.OK {
|
|
t.Error("Unexpected reply received: ", reply)
|
|
}
|
|
}
|
|
|
|
func testV2CDRsGetCdrsNoRattingPlan(t *testing.T) {
|
|
var cdrCnt int64
|
|
req := utils.AttrGetCdrs{}
|
|
if err := cdrsRpc.Call(utils.APIerSv2CountCDRs, req, &cdrCnt); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if cdrCnt != 10 {
|
|
t.Error("Unexpected number of CDRs returned: ", cdrCnt)
|
|
}
|
|
var cdrs []*engine.ExternalCDR
|
|
args := utils.RPCCDRsFilter{RunIDs: []string{utils.MetaRaw}, Accounts: []string{"testV2CDRsProcessCDR4"}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
} else {
|
|
if cdrs[0].Cost != -1.0 {
|
|
t.Errorf("Unexpected cost for CDR: %f", cdrs[0].Cost)
|
|
}
|
|
}
|
|
args = utils.RPCCDRsFilter{RunIDs: []string{"CustomerCharges"}, Accounts: []string{"testV2CDRsProcessCDR4"}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
} else {
|
|
if cdrs[0].Cost != -1 {
|
|
t.Errorf("Unexpected cost for CDR: %f", cdrs[0].Cost)
|
|
}
|
|
if cdrs[0].ExtraInfo != utils.ErrRatingPlanNotFound.Error() {
|
|
t.Errorf("Expected ExtraInfo : %s received :%s", utils.ErrRatingPlanNotFound.Error(), cdrs[0].ExtraInfo)
|
|
}
|
|
}
|
|
args = utils.RPCCDRsFilter{RunIDs: []string{"SupplierCharges"}, Accounts: []string{"testV2CDRsProcessCDR4"}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
} else {
|
|
if cdrs[0].Cost != -1 {
|
|
t.Errorf("Unexpected cost for CDR: %f", cdrs[0].Cost)
|
|
}
|
|
if cdrs[0].ExtraInfo != utils.ErrRatingPlanNotFound.Error() {
|
|
t.Errorf("Expected ExtraInfo : %s received :%s", utils.ErrRatingPlanNotFound.Error(), cdrs[0].ExtraInfo)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Should re-rate the supplier1 cost with RP_ANY2CNT
|
|
func testV2CDRsRateCDRsWithRatingPlan(t *testing.T) {
|
|
rpf := &utils.AttrSetRatingProfile{
|
|
Tenant: "cgrates.org",
|
|
Category: "call",
|
|
Subject: "SUPPLIER1",
|
|
RatingPlanActivations: []*utils.TPRatingActivation{
|
|
{
|
|
ActivationTime: "2018-01-01T00:00:00Z",
|
|
RatingPlanId: "RP_ANY1CNT"}},
|
|
Overwrite: true,
|
|
}
|
|
var reply string
|
|
if err := cdrsRpc.Call(utils.APIerSv1SetRatingProfile, rpf, &reply); err != nil {
|
|
t.Error("Got error on APIerSv1.SetRatingProfile: ", err.Error())
|
|
} else if reply != utils.OK {
|
|
t.Error("Calling APIerSv1.SetRatingProfile got reply: ", reply)
|
|
}
|
|
|
|
rpf = &utils.AttrSetRatingProfile{
|
|
Tenant: "cgrates.org",
|
|
Category: "call",
|
|
Subject: utils.ANY,
|
|
RatingPlanActivations: []*utils.TPRatingActivation{
|
|
{
|
|
ActivationTime: "2018-01-01T00:00:00Z",
|
|
RatingPlanId: "RP_TESTIT1"}},
|
|
Overwrite: true,
|
|
}
|
|
if err := cdrsRpc.Call(utils.APIerSv1SetRatingProfile, rpf, &reply); err != nil {
|
|
t.Error("Got error on APIerSv1.SetRatingProfile: ", err.Error())
|
|
} else if reply != utils.OK {
|
|
t.Error("Calling APIerSv1.SetRatingProfile got reply: ", reply)
|
|
}
|
|
|
|
if err := cdrsRpc.Call(utils.CDRsV1RateCDRs, &engine.ArgRateCDRs{
|
|
RPCCDRsFilter: utils.RPCCDRsFilter{NotRunIDs: []string{utils.MetaRaw}, Accounts: []string{"testV2CDRsProcessCDR4"}},
|
|
Flags: []string{"*chargers:true", utils.MetaRerate},
|
|
}, &reply); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if reply != utils.OK {
|
|
t.Error("Unexpected reply received: ", reply)
|
|
}
|
|
}
|
|
|
|
func testV2CDRsGetCdrsWithRattingPlan(t *testing.T) {
|
|
var cdrCnt int64
|
|
req := utils.AttrGetCdrs{}
|
|
if err := cdrsRpc.Call(utils.APIerSv2CountCDRs, req, &cdrCnt); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if cdrCnt != 10 {
|
|
t.Error("Unexpected number of CDRs returned: ", cdrCnt)
|
|
}
|
|
var cdrs []*engine.ExternalCDR
|
|
args := utils.RPCCDRsFilter{RunIDs: []string{utils.MetaRaw}, Accounts: []string{"testV2CDRsProcessCDR4"}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
} else {
|
|
if cdrs[0].Cost != -1.0 {
|
|
t.Errorf("Unexpected cost for CDR: %f", cdrs[0].Cost)
|
|
}
|
|
}
|
|
cdrs = []*engine.ExternalCDR{} // gob will not update zero value fields
|
|
args = utils.RPCCDRsFilter{RunIDs: []string{"CustomerCharges"}, Accounts: []string{"testV2CDRsProcessCDR4"}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
} else {
|
|
if cdrs[0].Cost != 0.0102 {
|
|
t.Errorf("Unexpected cost for CDR: %f", cdrs[0].Cost)
|
|
}
|
|
if cdrs[0].ExtraInfo != "" {
|
|
t.Errorf("Expected ExtraInfo : %s received :%s", "", cdrs[0].ExtraInfo)
|
|
}
|
|
}
|
|
cdrs = []*engine.ExternalCDR{} // gob will not update zero value fields
|
|
args = utils.RPCCDRsFilter{RunIDs: []string{"SupplierCharges"}, Accounts: []string{"testV2CDRsProcessCDR4"}}
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, args, &cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 1 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(cdrs))
|
|
} else {
|
|
if cdrs[0].Cost != 0.0102 {
|
|
t.Errorf("Unexpected cost for CDR: %f", cdrs[0].Cost)
|
|
}
|
|
if cdrs[0].ExtraInfo != "" {
|
|
t.Errorf("Expected ExtraInfo : %s received :%s", "", cdrs[0].ExtraInfo)
|
|
}
|
|
}
|
|
}
|
|
func testV2CDRsSetThreshold(t *testing.T) {
|
|
var reply string
|
|
if err := cdrsRpc.Call(utils.APIerSv2SetActions, &utils.AttrSetActions{
|
|
ActionsId: "ACT_LOG",
|
|
Actions: []*utils.TPAction{{Identifier: utils.LOG}},
|
|
}, &reply); err != nil && err.Error() != utils.ErrExists.Error() {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Errorf("Calling APIerSv2.SetActions received: %s", reply)
|
|
}
|
|
tPrfl := engine.ThresholdWithCache{
|
|
ThresholdProfile: &engine.ThresholdProfile{
|
|
Tenant: "cgrates.org",
|
|
ID: "THD_Test",
|
|
FilterIDs: []string{
|
|
"*lt:~*req.CostDetails.AccountSummary.BalanceSummaries[0].Value:10",
|
|
"*string:~*req.Account:1005", // only for indexes
|
|
},
|
|
MaxHits: -1,
|
|
Weight: 30,
|
|
ActionIDs: []string{"ACT_LOG"},
|
|
},
|
|
}
|
|
if err := cdrsRpc.Call(utils.APIerSv1SetThresholdProfile, tPrfl, &reply); err != nil {
|
|
t.Error(err)
|
|
} else if reply != utils.OK {
|
|
t.Error("Unexpected reply returned", reply)
|
|
}
|
|
attrSetAcnt := AttrSetAccount{
|
|
Tenant: "cgrates.org",
|
|
Account: "1005",
|
|
ExtraOptions: map[string]bool{
|
|
utils.AllowNegative: true,
|
|
},
|
|
}
|
|
if err := cdrsRpc.Call(utils.APIerSv2SetAccount, attrSetAcnt, &reply); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
attrs := &utils.AttrSetBalance{
|
|
Tenant: "cgrates.org",
|
|
Account: "1005",
|
|
BalanceType: utils.MONETARY,
|
|
Value: 1,
|
|
Balance: map[string]interface{}{
|
|
utils.ID: utils.MetaDefault,
|
|
utils.Weight: 10.0,
|
|
},
|
|
}
|
|
if err := cdrsRpc.Call(utils.APIerSv2SetBalance, attrs, &reply); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func testV2CDRsProcessCDRWithThreshold(t *testing.T) {
|
|
args := &engine.ArgV1ProcessEvent{
|
|
Flags: []string{utils.MetaThresholds, utils.MetaRALs, utils.ConcatenatedKey(utils.MetaChargers, "false")},
|
|
CGREvent: utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
Event: map[string]interface{}{
|
|
utils.OriginID: "testV2CDRsProcessCDRWithThreshold",
|
|
utils.OriginHost: "192.168.1.1",
|
|
utils.Source: "testV2CDRsProcessCDRWithThreshold",
|
|
utils.RequestType: utils.META_POSTPAID,
|
|
utils.Category: "call",
|
|
utils.Account: "1005",
|
|
utils.Subject: "ANY2CNT",
|
|
utils.Destination: "+4986517174963",
|
|
utils.AnswerTime: time.Date(2018, 8, 24, 16, 00, 26, 0, time.UTC),
|
|
utils.Usage: 100 * time.Minute,
|
|
"field_extr1": "val_extr1",
|
|
"fieldextr2": "valextr2",
|
|
},
|
|
},
|
|
}
|
|
var reply string
|
|
if err := cdrsRpc.Call(utils.CDRsV1ProcessEvent, args, &reply); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if reply != utils.OK {
|
|
t.Error("Unexpected reply received: ", reply)
|
|
}
|
|
}
|
|
|
|
func testV2CDRsGetThreshold(t *testing.T) {
|
|
var td engine.Threshold
|
|
if err := cdrsRpc.Call(utils.ThresholdSv1GetThreshold,
|
|
&utils.TenantIDWithArgDispatcher{TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "THD_Test"}}, &td); err != nil {
|
|
t.Error(err)
|
|
} else if td.Hits != 1 {
|
|
t.Errorf("Expecting threshold to be hit once received: %v", td.Hits)
|
|
}
|
|
}
|
|
|
|
func testv2CDRsGetCDRsDest(t *testing.T) {
|
|
args := &engine.ArgV1ProcessEvent{
|
|
Flags: []string{utils.MetaStore},
|
|
CGREvent: utils.CGREvent{
|
|
Tenant: "cgrates.org",
|
|
Event: map[string]interface{}{
|
|
utils.CGRID: "9b3cd5e698af94f8916220866c831a982ed16318",
|
|
utils.ToR: utils.VOICE,
|
|
utils.RunID: utils.MetaRaw,
|
|
utils.OriginID: "25160047719:0",
|
|
utils.OriginHost: "192.168.1.1",
|
|
utils.Source: "*sessions",
|
|
utils.RequestType: utils.META_NONE,
|
|
utils.Category: "call",
|
|
utils.Account: "1001",
|
|
utils.Subject: "1001",
|
|
utils.Destination: "+4915117174963",
|
|
utils.AnswerTime: time.Date(2018, 8, 24, 16, 00, 26, 0, time.UTC),
|
|
utils.Usage: 100 * time.Minute,
|
|
},
|
|
},
|
|
}
|
|
var reply string
|
|
if err := cdrsRpc.Call(utils.CDRsV1ProcessEvent, args, &reply); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if reply != utils.OK {
|
|
t.Error("Unexpected reply received: ", reply)
|
|
}
|
|
|
|
var cdrs []*engine.ExternalCDR
|
|
if err := cdrsRpc.Call(utils.APIerSv2GetCDRs, utils.RPCCDRsFilter{DestinationPrefixes: []string{"+4915117174963"}},
|
|
&cdrs); err != nil {
|
|
t.Error("Unexpected error: ", err.Error())
|
|
} else if len(cdrs) != 3 {
|
|
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
|
}
|
|
}
|
|
|
|
func testV2CDRsKillEngine(t *testing.T) {
|
|
if err := engine.KillEngine(*waitRater); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|