mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Merge branch 'master' into aliases
This commit is contained in:
@@ -168,8 +168,7 @@ func (self *ApierV1) SetAccount(attr utils.AttrSetAccount, reply *string) error
|
||||
ub = bal
|
||||
} else { // Not found in db, create it here
|
||||
ub = &engine.Account{
|
||||
Id: balanceId,
|
||||
AllowNegative: attr.AllowNegative,
|
||||
Id: balanceId,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,6 +182,12 @@ func (self *ApierV1) SetAccount(attr utils.AttrSetAccount, reply *string) error
|
||||
at.AccountIds = append(at.AccountIds, balanceId)
|
||||
}
|
||||
}
|
||||
if attr.AllowNegative != nil {
|
||||
ub.AllowNegative = *attr.AllowNegative
|
||||
}
|
||||
if attr.Disabled != nil {
|
||||
ub.Disabled = *attr.Disabled
|
||||
}
|
||||
// All prepared, save account
|
||||
if err := self.AccountDb.SetAccount(ub); err != nil {
|
||||
return 0, err
|
||||
|
||||
@@ -68,9 +68,11 @@ func (self *ApierV1) GetLcrSuppliers(lcrReq engine.LcrRequest, suppliers *string
|
||||
if err := self.Responder.GetLCR(&engine.AttrGetLcr{CallDescriptor: cd, Paginator: lcrReq.Paginator}, &lcrQried); err != nil {
|
||||
return utils.NewErrServerError(err)
|
||||
}
|
||||
if lcrQried.HasErrors() && !lcrReq.IgnoreErrors {
|
||||
if lcrQried.HasErrors() {
|
||||
lcrQried.LogErrors()
|
||||
return fmt.Errorf("%s:%s", utils.ErrServerError.Error(), "LCR_ERRORS")
|
||||
if !lcrReq.IgnoreErrors {
|
||||
return fmt.Errorf("%s:%s", utils.ErrServerError.Error(), "LCR_COMPUTE_ERRORS")
|
||||
}
|
||||
}
|
||||
if suppliersStr, err := lcrQried.SuppliersString(); err != nil {
|
||||
return utils.NewErrServerError(err)
|
||||
|
||||
Binary file not shown.
@@ -60,7 +60,7 @@ loadmodule "jsonrpc-s.so"
|
||||
# ----------------- setting module-specific parameters ---------------
|
||||
|
||||
# ----- mi_fifo params -----
|
||||
modparam("mi_fifo", "fifo_name", "/tmp/cgr_kamevapi/kamailio/run/kamailio_fifo")
|
||||
modparam("mi_fifo", "fifo_name", "/tmp/kamailio_fifo")
|
||||
|
||||
# ----- tm params -----
|
||||
modparam("tm", "failure_reply_mode", 3)
|
||||
|
||||
@@ -45,18 +45,20 @@ Database setup
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
For it's operation CGRateS uses more database types, depending on it's nature, install and configuration being further necessary.
|
||||
|
||||
At present we support the following databases:
|
||||
|
||||
As DataDB types (rating and accounting subsystems):
|
||||
|
||||
|
||||
- Redis_
|
||||
|
||||
As StorDB (persistent storage for CDRs and tariff plan versions).
|
||||
|
||||
Used as DataDb, optimized for real-time information access.
|
||||
Once installed there should be no special requirements in terms of setup since no schema is necessary.
|
||||
|
||||
|
||||
- MySQL_
|
||||
|
||||
Used as StorDb, optimized for CDR archiving and offline Tariff Plan versioning.
|
||||
Once database is installed, CGRateS database needs to be set-up out of provided scripts (example for the paths set-up by debian package)
|
||||
|
||||
::
|
||||
@@ -66,12 +68,13 @@ Once database is installed, CGRateS database needs to be set-up out of provided
|
||||
|
||||
- PostgreSQL_
|
||||
|
||||
Used as StorDb, optimized for CDR archiving and offline Tariff Plan versioning.
|
||||
Once database is installed, CGRateS database needs to be set-up out of provided scripts (example for the paths set-up by debian package)
|
||||
|
||||
::
|
||||
|
||||
cd /usr/share/cgrates/storage/postgres/
|
||||
./setup_cgr_db.sh root CGRateS.org localhost
|
||||
./setup_cgr_db.sh
|
||||
|
||||
.. _Redis: http://redis.io/
|
||||
.. _MySQL: http://www.mysql.org/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
sFreeSWITCH Integration Tutorials
|
||||
FreeSWITCH Integration Tutorials
|
||||
================================
|
||||
|
||||
In these tutorials we exemplify few cases of integration between FreeSWITCH_ and **CGRateS**. We start with common steps, installation and postinstall processes then we dive into particular configurations, depending on the case we run.
|
||||
In these tutorials we exemplify few cases of integration between FreeSWITCH_ and **CGRateS**. We start with common steps, installation and postinstall processes then we dive into particular configurations.
|
||||
|
||||
|
||||
.. toctree::
|
||||
@@ -10,7 +10,6 @@ In these tutorials we exemplify few cases of integration between FreeSWITCH_ and
|
||||
tut_freeswitch_installs
|
||||
tut_cgrates_installs
|
||||
tut_jitsi_installs
|
||||
tut_freeswitch_csv
|
||||
tut_freeswitch_json
|
||||
tut_cgrates_usage
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ FreeSWITCH_ generating *http-json* CDRs
|
||||
Scenario
|
||||
--------
|
||||
|
||||
- FreeSWITCH with *vanilla* configuration, replacing *mod_cdr_csv* with *mod_json_cdr*.
|
||||
- FreeSWITCH with *vanilla* configuration adding *mod_json_cdr* for CDR generation.
|
||||
|
||||
- Modified following users (with configs in *etc/freeswitch/directory/default*): 1001-prepaid, 1002-postpaid, 1003-pseudoprepaid, 1004-rated, 1006-prepaid, 1007-rated.
|
||||
- Have added inside default dialplan CGR own extensions just before routing towards users (*etc/freeswitch/dialplan/default.xml*).
|
||||
@@ -13,8 +13,8 @@ Scenario
|
||||
- **CGRateS** with following components:
|
||||
|
||||
- CGR-SM started as prepaid controller, with debits taking place at 5s intervals.
|
||||
- CGR-Mediator component attaching costs to the raw CDRs from FreeSWITCH_ inside CGR StorDB.
|
||||
- CGR-CDRE exporting mediated CDRs from CGR StorDB (export path: */tmp*).
|
||||
- CGR-CDRS component receiving raw CDRs from FreeSWITCH, storing them and attaching costs inside CGR StorDB.
|
||||
- CGR-CDRE exporting processed CDRs from CGR StorDB (export path: */tmp*).
|
||||
- CGR-History component keeping the archive of the rates modifications (path browsable with git client at */tmp/cgr_history*).
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ Starting FreeSWITCH_ with custom configuration
|
||||
|
||||
::
|
||||
|
||||
/usr/share/cgrates/tutorials/fs_json/freeswitch/etc/init.d/freeswitch start
|
||||
/usr/share/cgrates/tutorials/fs_evsock/freeswitch/etc/init.d/freeswitch start
|
||||
|
||||
To verify that FreeSWITCH_ is running we run the console command:
|
||||
|
||||
@@ -37,7 +37,7 @@ Starting **CGRateS** with custom configuration
|
||||
|
||||
::
|
||||
|
||||
/usr/share/cgrates/tutorials/fs_json/cgrates/etc/init.d/cgrates start
|
||||
/usr/share/cgrates/tutorials/fs_evsock/cgrates/etc/init.d/cgrates start
|
||||
|
||||
Check that cgrates is running
|
||||
|
||||
@@ -49,7 +49,7 @@ Check that cgrates is running
|
||||
CDR processing
|
||||
--------------
|
||||
|
||||
At the end of each call FreeSWITCH_ will issue a http post with the CDR. This will reach inside **CGRateS** through the *CDRS* component (close to real-time). Once in-there it will be instantly mediated and it is ready to be exported:
|
||||
At the end of each call FreeSWITCH_ will issue a http post with the CDR. This will reach inside **CGRateS** through the *CDRS* component (close to real-time). Once in-there it will be instantly rated and it is ready to be exported:
|
||||
|
||||
::
|
||||
|
||||
|
||||
18
docs/tut_kamailio.rst
Normal file
18
docs/tut_kamailio.rst
Normal file
@@ -0,0 +1,18 @@
|
||||
Kamailio_ Integration Tutorials
|
||||
===============================
|
||||
|
||||
In these tutorials we exemplify few cases of integration between Kamailio_ and CGRateS_. We start with common steps, installation and postinstall processes then we dive into particular configurations, depending on the case we run.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
tut_kamailio_installs
|
||||
tut_cgrates_installs
|
||||
tut_jitsi_installs
|
||||
tut_kamailio_evapi
|
||||
tut_cgrates_usage
|
||||
|
||||
.. _Kamailio: http://www.kamailio.org/
|
||||
.. _CGRateS: http://www.cgrates.org/
|
||||
|
||||
59
docs/tut_kamailio_evapi.rst
Normal file
59
docs/tut_kamailio_evapi.rst
Normal file
@@ -0,0 +1,59 @@
|
||||
Kamailio_ interaction via *evapi* module
|
||||
=========================================
|
||||
|
||||
Scenario
|
||||
--------
|
||||
|
||||
- Kamailio default configuration modified for **CGRateS** interaction. For script maintainability and simplicity we have separated CGRateS specific routes in *kamailio-cgrates.cfg* file which is included in main *kamailio.cfg* via include directive.
|
||||
|
||||
- Considering the following users (with configs hardcoded in the *kamailio.cfg* configuration script and loaded in htable): 1001-prepaid, 1002-postpaid, 1003-pseudoprepaid, 1004-rated, 1005-rated, 1006-prepaid, 1007-prepaid.
|
||||
|
||||
- **CGRateS** with following components:
|
||||
|
||||
- CGR-SM started as translator between Kamailio_ and CGR-Rater for both authorization events as well as accounting ones.
|
||||
- CGR-CDRS component processing raw CDRs from CGR-SM component and storing them inside CGR StorDB.
|
||||
- CGR-CDRE exporting rated CDRs from CGR StorDB (export path: */tmp*).
|
||||
- CGR-History component keeping the archive of the rates modifications (path browsable with git client at */tmp/cgr_history*).
|
||||
|
||||
|
||||
Starting Kamailio_ with custom configuration
|
||||
----------------------------------------------
|
||||
|
||||
::
|
||||
|
||||
/usr/share/cgrates/tutorials/kamevapi/kamailio/etc/init.d/kamailio start
|
||||
|
||||
To verify that Kamailio_ is running we run the console command:
|
||||
|
||||
::
|
||||
|
||||
kamctl moni
|
||||
|
||||
|
||||
Starting **CGRateS** with custom configuration
|
||||
----------------------------------------------
|
||||
|
||||
::
|
||||
|
||||
/usr/share/cgrates/tutorials/kamevapi/cgrates/etc/init.d/cgrates start
|
||||
|
||||
Make sure that cgrates is running
|
||||
|
||||
::
|
||||
|
||||
cgr-console status
|
||||
|
||||
|
||||
CDR processing
|
||||
--------------
|
||||
|
||||
At the end of each call Kamailio_ will generate an CDR event via *evapi* and this will be directed towards the port configured inside *cgrates.json*. This event will reach inside **CGRateS** through the *SM* component (close to real-time). Once in-there it will be instantly rated and be ready for export.
|
||||
|
||||
|
||||
**CGRateS** Usage
|
||||
-----------------
|
||||
|
||||
Since it is common to most of the tutorials, the example for **CGRateS** usage is provided in a separate page `here <http://cgrates.readthedocs.org/en/latest/tut_cgrates_usage.html>`_
|
||||
|
||||
|
||||
.. _Kamailio: http://www.kamailio.org/
|
||||
20
docs/tut_kamailio_installs.rst
Normal file
20
docs/tut_kamailio_installs.rst
Normal file
@@ -0,0 +1,20 @@
|
||||
Software installation
|
||||
=====================
|
||||
|
||||
As operating system we have choosen Debian Wheezy, since all the software components we use provide packaging for it.
|
||||
|
||||
Kamailio_
|
||||
---------
|
||||
|
||||
We got Kamailio_ installed via following commands:
|
||||
::
|
||||
|
||||
apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xfb40d3e6508ea4c8
|
||||
cd /etc/apt/sources.list.d/
|
||||
wget http://apt.itsyscom.com/conf/kamailio.apt.list .
|
||||
apt-get update
|
||||
apt-get install kamailio kamailio-extra-modules kamailio-json-modules
|
||||
|
||||
Once installed we proceed with loading the configuration out of specific tutorial cases bellow.
|
||||
|
||||
.. _Kamailio: http://www.kamailio.org/
|
||||
@@ -12,8 +12,8 @@ Scenario
|
||||
- **CGRateS** with following components:
|
||||
|
||||
- CGR-SM started as translator between OpenSIPS_ and **cgr-rater** for both authorization events (pseudoprepaid) as well as CDR ones.
|
||||
- CGR-Mediator component attaching costs to the raw CDRs from OpenSIPS_ inside CGR StorDB.
|
||||
- CGR-CDRE exporting mediated CDRs from CGR StorDB (export path: */tmp*).
|
||||
- CGR-CDRS component processing raw CDRs from CGR-SM component and storing them inside CGR StorDB.
|
||||
- CGR-CDRE exporting rated CDRs from CGR StorDB (export path: */tmp*).
|
||||
- CGR-History component keeping the archive of the rates modifications (path browsable with git client at */tmp/cgr_history*).
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ Starting OpenSIPS_ with custom configuration
|
||||
|
||||
::
|
||||
|
||||
/usr/share/cgrates/tutorials/osips_event/opensips/etc/init.d/opensips start
|
||||
/usr/share/cgrates/tutorials/osips_async/opensips/etc/init.d/opensips start
|
||||
|
||||
To verify that OpenSIPS_ is running we run the console command:
|
||||
|
||||
@@ -36,9 +36,9 @@ Starting **CGRateS** with custom configuration
|
||||
|
||||
::
|
||||
|
||||
/usr/share/cgrates/tutorials/osips_event/cgrates/etc/init.d/cgrates start
|
||||
/usr/share/cgrates/tutorials/osips_async/cgrates/etc/init.d/cgrates start
|
||||
|
||||
Check that cgrates is running
|
||||
Make sure that cgrates is running
|
||||
|
||||
::
|
||||
|
||||
@@ -48,7 +48,7 @@ Check that cgrates is running
|
||||
CDR processing
|
||||
--------------
|
||||
|
||||
At the end of each call OpenSIPS_ will generate an CDR event and due to automatic handler registration built in **CGRateS-SM** component, this will be directed towards the port configured inside *cgrates.cfg*. This event will reach inside **CGRateS** through the *SM* component (close to real-time). Once in-there it will be instantly mediated and it is ready to be exported.
|
||||
At the end of each call OpenSIPS_ will generate an CDR event and due to automatic handler registration built in **CGRateS-SM** component, this will be directed towards the port configured inside *cgrates.json*. This event will reach inside **CGRateS** through the *SM* component (close to real-time). Once in-there it will be instantly rated and be ready for export.
|
||||
|
||||
|
||||
**CGRateS** Usage
|
||||
|
||||
@@ -12,9 +12,9 @@ We got OpenSIPS_ installed via following commands:
|
||||
wget http://apt.opensips.org/key.asc
|
||||
apt-key add key.asc
|
||||
cd /etc/apt/sources.list.d/
|
||||
wget http://apt.itsyscom.com/conf/opensips.apt.list
|
||||
wget http://apt.itsyscom.com/conf/opensips.wheezy.apt.list
|
||||
apt-get update
|
||||
apt-get install
|
||||
apt-get install opensips opensips-json-module opensips-restclient-module
|
||||
|
||||
Once installed we proceed with loading the configuration out of specific tutorial cases bellow.
|
||||
|
||||
|
||||
@@ -5,4 +5,5 @@
|
||||
:maxdepth: 2
|
||||
|
||||
tut_freeswitch
|
||||
tut_kamailio
|
||||
tut_opensips
|
||||
|
||||
@@ -54,7 +54,7 @@ type LcrRequest struct {
|
||||
Account string
|
||||
Subject string
|
||||
Destination string
|
||||
StartTime string
|
||||
SetupTime string
|
||||
Duration string
|
||||
IgnoreErrors bool
|
||||
*utils.Paginator
|
||||
@@ -79,9 +79,9 @@ func (self *LcrRequest) AsCallDescriptor() (*CallDescriptor, error) {
|
||||
}
|
||||
var timeStart time.Time
|
||||
var err error
|
||||
if len(self.StartTime) == 0 {
|
||||
if len(self.SetupTime) == 0 {
|
||||
timeStart = time.Now()
|
||||
} else if timeStart, err = utils.ParseTimeDetectLayout(self.StartTime); err != nil {
|
||||
} else if timeStart, err = utils.ParseTimeDetectLayout(self.SetupTime); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var callDur time.Duration
|
||||
|
||||
@@ -215,11 +215,11 @@ func TestLcrGet(t *testing.T) {
|
||||
func TestLcrRequestAsCallDescriptor(t *testing.T) {
|
||||
sTime := time.Date(2015, 04, 06, 17, 40, 0, 0, time.UTC)
|
||||
callDur := time.Duration(1) * time.Minute
|
||||
lcrReq := &LcrRequest{Account: "2001", StartTime: sTime.String()}
|
||||
lcrReq := &LcrRequest{Account: "2001", SetupTime: sTime.String()}
|
||||
if _, err := lcrReq.AsCallDescriptor(); err == nil || err != utils.ErrMandatoryIeMissing {
|
||||
t.Error("Unexpected error received: %v", err)
|
||||
}
|
||||
lcrReq = &LcrRequest{Account: "2001", Destination: "2002", StartTime: sTime.String()}
|
||||
lcrReq = &LcrRequest{Account: "2001", Destination: "2002", SetupTime: sTime.String()}
|
||||
eCd := &CallDescriptor{
|
||||
Direction: utils.OUT,
|
||||
Tenant: config.CgrConfig().DefaultTenant,
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"net/rpc/jsonrpc"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -94,13 +95,11 @@ func TestTutFsCallsStartEngine(t *testing.T) {
|
||||
}
|
||||
|
||||
// Restart FS so we make sure reconnects are working
|
||||
|
||||
func TestTutFsCallsRestartFS(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
engine.KillProcName("freeswitch", 5000)
|
||||
if err := engine.CallScript(path.Join(*dataDir, "tutorials", "fs_evsock", "freeswitch", "etc", "init.d", "freeswitch"), "start", 3000); err != nil {
|
||||
if err := engine.CallScript(path.Join(*dataDir, "tutorials", "fs_evsock", "freeswitch", "etc", "init.d", "freeswitch"), "restart", 5000); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -174,6 +173,51 @@ func TestTutFsCallsAccountsBefore(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure all stats queues are in place
|
||||
func TestTutFsCallsCdrStatsBefore(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
//eQueueIds := []string{"*default", "CDRST1", "CDRST_1001", "CDRST_1002", "CDRST_1003", "STATS_SUPPL1", "STATS_SUPPL2"}
|
||||
var statMetrics map[string]float64
|
||||
eMetrics := map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1}
|
||||
if err := tutFsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST1"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.ACC: -1, engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1}
|
||||
if err := tutFsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1001"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1}
|
||||
if err := tutFsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1002"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1}
|
||||
if err := tutFsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1003"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1}
|
||||
if err := tutFsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL1"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1}
|
||||
if err := tutFsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL2"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
}
|
||||
|
||||
// Start Pjsua as listener and register it to receive calls
|
||||
func TestTutFsCallsStartPjsuaListener(t *testing.T) {
|
||||
if !*testCalls {
|
||||
@@ -181,12 +225,12 @@ func TestTutFsCallsStartPjsuaListener(t *testing.T) {
|
||||
}
|
||||
var err error
|
||||
acnts := []*engine.PjsuaAccount{
|
||||
&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:25060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:25060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:25060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:25060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:25060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:25060"}}
|
||||
&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}}
|
||||
if tutFsCallsPjSuaListener, err = engine.StartPjsuaListener(acnts, 5070, *waitRater); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -198,7 +242,7 @@ func TestTutFsCallsCall1001To1002(t *testing.T) {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*"}, "sip:1002@127.0.0.1",
|
||||
"sip:127.0.0.1:25060", time.Duration(67)*time.Second, 5071); err != nil {
|
||||
"sip:127.0.0.1:5060", time.Duration(67)*time.Second, 5071); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -209,7 +253,7 @@ func TestTutFsCallsCall1001To1003(t *testing.T) {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*"}, "sip:1003@127.0.0.1",
|
||||
"sip:127.0.0.1:25060", time.Duration(65)*time.Second, 5072); err != nil {
|
||||
"sip:127.0.0.1:5060", time.Duration(65)*time.Second, 5072); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -219,7 +263,7 @@ func TestTutFsCallsCall1002To1001(t *testing.T) {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "1234", Realm: "*"}, "sip:1001@127.0.0.1",
|
||||
"sip:127.0.0.1:25060", time.Duration(61)*time.Second, 5073); err != nil {
|
||||
"sip:127.0.0.1:5060", time.Duration(61)*time.Second, 5073); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -229,7 +273,7 @@ func TestTutFsCallsCall1003To1001(t *testing.T) {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "1234", Realm: "*"}, "sip:1001@127.0.0.1",
|
||||
"sip:127.0.0.1:25060", time.Duration(63)*time.Second, 5074); err != nil {
|
||||
"sip:127.0.0.1:5060", time.Duration(63)*time.Second, 5074); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -239,7 +283,7 @@ func TestTutFsCallsCall1004To1001(t *testing.T) {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "1234", Realm: "*"}, "sip:1001@127.0.0.1",
|
||||
"sip:127.0.0.1:25060", time.Duration(62)*time.Second, 5075); err != nil {
|
||||
"sip:127.0.0.1:5060", time.Duration(62)*time.Second, 5075); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -249,7 +293,7 @@ func TestTutFsCallsCall1006To1002(t *testing.T) {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "1234", Realm: "*"}, "sip:1002@127.0.0.1",
|
||||
"sip:127.0.0.1:25060", time.Duration(64)*time.Second, 5076); err != nil {
|
||||
"sip:127.0.0.1:5060", time.Duration(64)*time.Second, 5076); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -259,7 +303,7 @@ func TestTutFsCallsCall1007To1002(t *testing.T) {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "1234", Realm: "*"}, "sip:1002@127.0.0.1",
|
||||
"sip:127.0.0.1:25060", time.Duration(66)*time.Second, 5077); err != nil {
|
||||
"sip:127.0.0.1:5060", time.Duration(66)*time.Second, 5077); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -282,7 +326,7 @@ func TestTutFsCallsAccount1001(t *testing.T) {
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutFsCallsCdrs(t *testing.T) {
|
||||
func TestTutFsCalls1001Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
@@ -308,6 +352,9 @@ func TestTutFsCallsCdrs(t *testing.T) {
|
||||
if reply[0].Cost == -1.0 { // Cost was not calculated
|
||||
t.Errorf("Unexpected Cost for CDR: %+v", reply[0])
|
||||
}
|
||||
//if reply[0].Supplier != "suppl2" { // Usage as seconds
|
||||
// t.Errorf("Unexpected Supplier for CDR: %+v", reply[0])
|
||||
//}
|
||||
}
|
||||
// Make sure call cost contains the matched information
|
||||
if err := tutFsCallsRpc.Call("ApierV2.GetCallCostLog", utils.AttrGetCallCost{CgrId: cgrId}, &cCost); err != nil {
|
||||
@@ -352,7 +399,16 @@ func TestTutFsCallsCdrs(t *testing.T) {
|
||||
t.Errorf("Unexpected Subject for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1002"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutFsCalls1002Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1002"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
@@ -371,7 +427,15 @@ func TestTutFsCallsCdrs(t *testing.T) {
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1003"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutFsCalls1003Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1003"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
@@ -390,7 +454,16 @@ func TestTutFsCallsCdrs(t *testing.T) {
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1004"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutFsCalls1004Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1004"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
@@ -409,7 +482,16 @@ func TestTutFsCallsCdrs(t *testing.T) {
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1006"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutFsCalls1006Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1006"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
@@ -431,7 +513,15 @@ func TestTutFsCallsCdrs(t *testing.T) {
|
||||
t.Errorf("Unexpected Cost for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1007"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutFsCalls1007Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1007"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutFsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
|
||||
@@ -72,13 +72,13 @@ func TestTutKamCallsResetStorDb(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// start Kam server
|
||||
func TestTutKamCallsStartKam(t *testing.T) {
|
||||
// start FS server
|
||||
func TestTutKamCallsStartKamailio(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
engine.KillProcName("kamailio", *waitRater)
|
||||
if err := engine.CallScript(path.Join(*dataDir, "tutorials", "kamevapi", "kamailio", "etc", "init.d", "kamailio"), "start", 3000); err != nil {
|
||||
engine.KillProcName("kamailio", 3000)
|
||||
if err := engine.CallScript(path.Join(*dataDir, "tutorials", "kamevapi", "kamailio", "etc", "init.d", "kamailio"), "start", 2000); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -94,12 +94,12 @@ func TestTutKamCallsStartEngine(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Restart Kam so we make sure reconnects are working
|
||||
func TestTutKamCallsRestartKam(t *testing.T) {
|
||||
// Restart FS so we make sure reconnects are working
|
||||
func TestTutKamCallsRestartKamailio(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.CallScript(path.Join(*dataDir, "tutorials", "kamevapi", "kamailio", "etc", "init.d", "kamailio"), "restart", 4000); err != nil {
|
||||
if err := engine.CallScript(path.Join(*dataDir, "tutorials", "kamevapi", "kamailio", "etc", "init.d", "kamailio"), "restart", 3000); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -131,7 +131,7 @@ func TestTutKamCallsLoadTariffPlanFromFolder(t *testing.T) {
|
||||
time.Sleep(time.Duration(*waitRater) * time.Millisecond) // Give time for scheduler to execute topups
|
||||
}
|
||||
|
||||
// Make sure account was topped-up properly
|
||||
// Make sure account was debited properly
|
||||
func TestTutKamCallsAccountsBefore(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
@@ -180,13 +180,7 @@ func TestTutKamCallsCdrStatsBefore(t *testing.T) {
|
||||
}
|
||||
//eQueueIds := []string{"*default", "CDRST1", "CDRST_1001", "CDRST_1002", "CDRST_1003", "STATS_SUPPL1", "STATS_SUPPL2"}
|
||||
var statMetrics map[string]float64
|
||||
eMetrics := map[string]float64{engine.ACC: -1, engine.ACD: -1, engine.ASR: -1}
|
||||
if err := tutKamCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: utils.META_DEFAULT}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1}
|
||||
eMetrics := map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1}
|
||||
if err := tutKamCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST1"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
@@ -253,12 +247,23 @@ func TestTutKamCallsCall1001To1002(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Call from 1001 (prepaid) to 1003
|
||||
func TestTutKamCallsCall1001To1003(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "CGRateS.org", Realm: "*"}, "sip:1003@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(65)*time.Second, 5072); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTutKamCallsCall1002To1001(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "CGRateS.org", Realm: "*"}, "sip:1001@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(61)*time.Second, 5072); err != nil {
|
||||
"sip:127.0.0.1:5060", time.Duration(61)*time.Second, 5073); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -268,7 +273,7 @@ func TestTutKamCallsCall1003To1001(t *testing.T) {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "CGRateS.org", Realm: "*"}, "sip:1001@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(63)*time.Second, 5073); err != nil {
|
||||
"sip:127.0.0.1:5060", time.Duration(63)*time.Second, 5074); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -278,7 +283,7 @@ func TestTutKamCallsCall1004To1001(t *testing.T) {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "CGRateS.org", Realm: "*"}, "sip:1001@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(62)*time.Second, 5074); err != nil {
|
||||
"sip:127.0.0.1:5060", time.Duration(62)*time.Second, 5075); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -288,7 +293,7 @@ func TestTutKamCallsCall1006To1002(t *testing.T) {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "CGRateS.org", Realm: "*"}, "sip:1002@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(64)*time.Second, 5075); err != nil {
|
||||
"sip:127.0.0.1:5060", time.Duration(64)*time.Second, 5076); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -298,42 +303,7 @@ func TestTutKamCallsCall1007To1002(t *testing.T) {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "CGRateS.org", Realm: "*"}, "sip:1002@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(66)*time.Second, 5076); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Should hangup at 62 seconds, disconnect from SM
|
||||
func TestTutKamCallsCall1007To1007(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "CGRateS.org", Realm: "*"}, "sip:1007@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(75)*time.Second, 5077); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Should hangup at 62 seconds, disconnect from Kamailio
|
||||
func TestTutKamCallsCall1003To1007(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "CGRateS.org", Realm: "*"}, "sip:1007@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(73)*time.Second, 5078); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Call from 1001 (prepaid) to 1007, should not cost more than 62 which is MaxCallCost
|
||||
func TestTutKamCallsCall1001To1007(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "CGRateS.org", Realm: "*"}, "sip:1007@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(70)*time.Second, 5079); err != nil {
|
||||
"sip:127.0.0.1:5060", time.Duration(66)*time.Second, 5077); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -343,7 +313,7 @@ func TestTutKamCallsAccount1001(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Duration(80) * time.Second) // Allow calls to finish before start querying the results
|
||||
time.Sleep(time.Duration(70) * time.Second) // Allow calls to finish before start querying the results
|
||||
var reply *engine.Account
|
||||
attrs := &utils.AttrGetAccount{Tenant: "cgrates.org", Account: "1001", Direction: "*out"}
|
||||
if err := tutKamCallsRpc.Call("ApierV1.GetAccount", attrs, &reply); err != nil {
|
||||
@@ -356,17 +326,20 @@ func TestTutKamCallsAccount1001(t *testing.T) {
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutKamCallsCdrs(t *testing.T) {
|
||||
func TestTutKamCalls1001Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1001"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
var cgrId string // Share with getCostDetails
|
||||
var cCost engine.CallCost
|
||||
req := utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestPrefixes: []string{"1002"}}
|
||||
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 2 {
|
||||
} else if len(reply) != 1 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
} else {
|
||||
cgrId = reply[0].CgrId
|
||||
if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" {
|
||||
t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
|
||||
}
|
||||
@@ -374,11 +347,44 @@ func TestTutKamCallsCdrs(t *testing.T) {
|
||||
t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "67" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for 428CDR: %+v", reply[0])
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Supplier != "suppl2" { // Usage as seconds
|
||||
t.Errorf("Unexpected Supplier for CDR: %+v", reply[0])
|
||||
if reply[0].Cost == -1.0 { // Cost was not calculated
|
||||
t.Errorf("Unexpected Cost for CDR: %+v", reply[0])
|
||||
}
|
||||
//if reply[0].Supplier != "suppl2" { // Usage as seconds
|
||||
// t.Errorf("Unexpected Supplier for CDR: %+v", reply[0])
|
||||
//}
|
||||
}
|
||||
// Make sure call cost contains the matched information
|
||||
if err := tutKamCallsRpc.Call("ApierV2.GetCallCostLog", utils.AttrGetCallCost{CgrId: cgrId}, &cCost); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if utils.IsSliceMember([]string{cCost.Timespans[0].MatchedSubject, cCost.Timespans[0].MatchedPrefix, cCost.Timespans[0].MatchedDestId}, "") {
|
||||
t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0])
|
||||
}
|
||||
|
||||
req = utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestPrefixes: []string{"1003"}}
|
||||
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
} else {
|
||||
cgrId = reply[0].CgrId
|
||||
if reply[0].ReqType != utils.META_PREPAID {
|
||||
t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "65" && reply[0].Usage != "66" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Cost != 0 { // Cost was not calculated
|
||||
t.Errorf("Unexpected Cost for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
// Make sure call cost contains the matched information
|
||||
if err := tutKamCallsRpc.Call("ApierV2.GetCallCostLog", utils.AttrGetCallCost{CgrId: cgrId}, &cCost); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if utils.IsSliceMember([]string{cCost.Timespans[0].MatchedSubject, cCost.Timespans[0].MatchedPrefix, cCost.Timespans[0].MatchedDestId}, "") {
|
||||
t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0])
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1001"}, RunIds: []string{"derived_run1"}, FilterOnRated: true}
|
||||
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
@@ -392,11 +398,17 @@ func TestTutKamCallsCdrs(t *testing.T) {
|
||||
if reply[0].Subject != "1002" {
|
||||
t.Errorf("Unexpected Subject for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Supplier != "suppl2" {
|
||||
t.Errorf("Unexpected Supplier for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1002"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutKamCalls1002Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1002"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
@@ -414,11 +426,16 @@ func TestTutKamCallsCdrs(t *testing.T) {
|
||||
if reply[0].Usage != "61" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Supplier != "suppl1" {
|
||||
t.Errorf("Unexpected Supplier for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1003"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutKamCalls1003Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1003"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
@@ -433,14 +450,20 @@ func TestTutKamCallsCdrs(t *testing.T) {
|
||||
if reply[0].Destination != "1001" {
|
||||
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "63" { // Usage as seconds
|
||||
if reply[0].Usage != "63" && reply[0].Usage != "64" { // Usage as seconds, sometimes takes a second longer to disconnect
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Supplier != "suppl1" {
|
||||
t.Errorf("Unexpected Supplier for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1004"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutKamCalls1004Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1004"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
@@ -455,14 +478,20 @@ func TestTutKamCallsCdrs(t *testing.T) {
|
||||
if reply[0].Destination != "1001" {
|
||||
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "62" { // Usage as seconds
|
||||
if reply[0].Usage != "62" && reply[0].Usage != "63" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Supplier != "suppl1" {
|
||||
t.Errorf("Unexpected Supplier for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1006"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutKamCalls1006Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1006"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
@@ -477,84 +506,42 @@ func TestTutKamCallsCdrs(t *testing.T) {
|
||||
if reply[0].Destination != "1002" {
|
||||
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "64" { // Usage as seconds
|
||||
if reply[0].Usage != "64" && reply[0].Usage != "65" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Supplier != "suppl3" {
|
||||
t.Errorf("Unexpected Supplier for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1007"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
} else {
|
||||
if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" {
|
||||
t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].ReqType != utils.META_PREPAID {
|
||||
t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Destination != "1002" {
|
||||
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "66" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Supplier != "suppl3" {
|
||||
t.Errorf("Unexpected Supplier for CDR: %+v", reply[0])
|
||||
if reply[0].Cost == -1.0 { // Cost was not calculated
|
||||
t.Errorf("Unexpected Cost for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure all stats queues were updated
|
||||
func TestTutKamCallsCdrStatsAfter(t *testing.T) {
|
||||
// Make sure account was debited properly
|
||||
func TestTutKamCalls1007Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var statMetrics map[string]float64
|
||||
eMetrics := map[string]float64{engine.ACC: 0.9015222222, engine.ACD: 65.5555555556, engine.ASR: 100}
|
||||
if err := tutKamCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: utils.META_DEFAULT}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.ACC: 0.8829, engine.ACD: 64.7142857143, engine.ASR: 100, engine.TCC: 6.1803, engine.TCD: 453}
|
||||
if err := tutKamCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST1"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.TCC: 6.1803, engine.TCD: 453, engine.ACC: 0.32, engine.ACD: 68.5, engine.ASR: 100}
|
||||
if err := tutKamCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1001"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.ACD: 61, engine.ASR: 100, engine.TCC: 6.1803, engine.TCD: 453, engine.ACC: 1.2334}
|
||||
if err := tutKamCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1002"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.TCC: 6.1803, engine.TCD: 453, engine.ACC: 1.2334, engine.ACD: -1, engine.ASR: -1}
|
||||
if err := tutKamCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1003"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.ACC: 1.00404, engine.ACD: 65.2, engine.ASR: 100, engine.TCC: 5.0202, engine.TCD: 326}
|
||||
if err := tutKamCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL1"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.ACD: 67, engine.ASR: 100, engine.TCC: 1.2534, engine.TCD: 134, engine.ACC: 0.6267}
|
||||
if err := tutKamCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL2"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1007"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutKamCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
} else {
|
||||
if reply[0].CdrSource != "KAMAILIO_CGR_CALL_END" {
|
||||
t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].ReqType != utils.META_PREPAID {
|
||||
t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Destination != "1002" {
|
||||
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "66" && reply[0].Usage != "67" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Cost == -1.0 { // Cost was not calculated
|
||||
t.Errorf("Unexpected Cost for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"net/rpc/jsonrpc"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -71,13 +72,13 @@ func TestTutOsipsCallsResetStorDb(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// start Kam server
|
||||
// start FS server
|
||||
func TestTutOsipsCallsStartOsips(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
engine.KillProcName("opensips", *waitRater)
|
||||
if err := engine.CallScript(path.Join(*dataDir, "tutorials", "osips_async", "opensips", "etc", "init.d", "opensips"), "start", 100); err != nil {
|
||||
engine.KillProcName("opensips", 3000)
|
||||
if err := engine.CallScript(path.Join(*dataDir, "tutorials", "osips_async", "opensips", "etc", "init.d", "opensips"), "start", 3000); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -93,12 +94,12 @@ func TestTutOsipsCallsStartEngine(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Restart Kam so we make sure reconnects are working
|
||||
func TestTutOsipsCallsRestartKam(t *testing.T) {
|
||||
// Restart FS so we make sure reconnects are working
|
||||
func TestTutOsipsCallsRestartOsips(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.CallScript(path.Join(*dataDir, "tutorials", "osips_async", "opensips", "etc", "init.d", "opensips"), "restart", 200); err != nil {
|
||||
if err := engine.CallScript(path.Join(*dataDir, "tutorials", "osips_async", "opensips", "etc", "init.d", "opensips"), "restart", 3000); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -172,6 +173,51 @@ func TestTutOsipsCallsAccountsBefore(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure all stats queues are in place
|
||||
func TestTutOsipsCallsCdrStatsBefore(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
//eQueueIds := []string{"*default", "CDRST1", "CDRST_1001", "CDRST_1002", "CDRST_1003", "STATS_SUPPL1", "STATS_SUPPL2"}
|
||||
var statMetrics map[string]float64
|
||||
eMetrics := map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1}
|
||||
if err := tutOsipsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST1"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.ACC: -1, engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1}
|
||||
if err := tutOsipsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1001"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1}
|
||||
if err := tutOsipsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1002"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1}
|
||||
if err := tutOsipsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "CDRST_1003"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1}
|
||||
if err := tutOsipsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL1"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
eMetrics = map[string]float64{engine.ACD: -1, engine.ASR: -1, engine.TCC: -1, engine.TCD: -1, engine.ACC: -1}
|
||||
if err := tutOsipsCallsRpc.Call("CDRStatsV1.GetMetrics", v1.AttrGetMetrics{StatsQueueId: "STATS_SUPPL2"}, &statMetrics); err != nil {
|
||||
t.Error("Calling CDRStatsV1.GetMetrics, got error: ", err.Error())
|
||||
} else if !reflect.DeepEqual(eMetrics, statMetrics) {
|
||||
t.Errorf("Expecting: %v, received: %v", eMetrics, statMetrics)
|
||||
}
|
||||
}
|
||||
|
||||
// Start Pjsua as listener and register it to receive calls
|
||||
func TestTutOsipsCallsStartPjsuaListener(t *testing.T) {
|
||||
if !*testCalls {
|
||||
@@ -179,12 +225,12 @@ func TestTutOsipsCallsStartPjsuaListener(t *testing.T) {
|
||||
}
|
||||
var err error
|
||||
acnts := []*engine.PjsuaAccount{
|
||||
&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "CGRateS.org", Realm: "*", Registrar: "sip:127.0.0.1:5060"}}
|
||||
&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"},
|
||||
&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "1234", Realm: "*", Registrar: "sip:127.0.0.1:5060"}}
|
||||
if tutOsipsCallsPjSuaListener, err = engine.StartPjsuaListener(acnts, 5070, *waitRater); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -195,18 +241,29 @@ func TestTutOsipsCallsCall1001To1002(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "CGRateS.org", Realm: "*"}, "sip:1002@127.0.0.1",
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*"}, "sip:1002@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(67)*time.Second, 5071); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Call from 1001 (prepaid) to 1003
|
||||
func TestTutOsipsCallsCall1001To1003(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1001@127.0.0.1", Username: "1001", Password: "1234", Realm: "*"}, "sip:1003@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(65)*time.Second, 5072); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTutOsipsCallsCall1002To1001(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "CGRateS.org", Realm: "*"}, "sip:1001@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(61)*time.Second, 5072); err != nil {
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1002@127.0.0.1", Username: "1002", Password: "1234", Realm: "*"}, "sip:1001@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(61)*time.Second, 5073); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -215,8 +272,8 @@ func TestTutOsipsCallsCall1003To1001(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "CGRateS.org", Realm: "*"}, "sip:1001@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(63)*time.Second, 5073); err != nil {
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1003@127.0.0.1", Username: "1003", Password: "1234", Realm: "*"}, "sip:1001@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(63)*time.Second, 5074); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -225,8 +282,8 @@ func TestTutOsipsCallsCall1004To1001(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "CGRateS.org", Realm: "*"}, "sip:1001@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(62)*time.Second, 5074); err != nil {
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1004@127.0.0.1", Username: "1004", Password: "1234", Realm: "*"}, "sip:1001@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(62)*time.Second, 5075); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -235,8 +292,8 @@ func TestTutOsipsCallsCall1006To1002(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "CGRateS.org", Realm: "*"}, "sip:1002@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(64)*time.Second, 5075); err != nil {
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1006@127.0.0.1", Username: "1006", Password: "1234", Realm: "*"}, "sip:1002@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(64)*time.Second, 5076); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -245,8 +302,8 @@ func TestTutOsipsCallsCall1007To1002(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "CGRateS.org", Realm: "*"}, "sip:1002@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(66)*time.Second, 5076); err != nil {
|
||||
if err := engine.PjsuaCallUri(&engine.PjsuaAccount{Id: "sip:1007@127.0.0.1", Username: "1007", Password: "1234", Realm: "*"}, "sip:1002@127.0.0.1",
|
||||
"sip:127.0.0.1:5060", time.Duration(66)*time.Second, 5077); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
@@ -269,17 +326,20 @@ func TestTutOsipsCallsAccount1001(t *testing.T) {
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutOsipsCallsCdrs(t *testing.T) {
|
||||
func TestTutOsipsCalls1001Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1001"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
var cgrId string // Share with getCostDetails
|
||||
var cCost engine.CallCost
|
||||
req := utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestPrefixes: []string{"1002"}}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
} else {
|
||||
cgrId = reply[0].CgrId
|
||||
if reply[0].CdrSource != "OSIPS_E_ACC_EVENT" {
|
||||
t.Errorf("Unexpected CdrSource for CDR: %+v", reply[0])
|
||||
}
|
||||
@@ -289,11 +349,47 @@ func TestTutOsipsCallsCdrs(t *testing.T) {
|
||||
if reply[0].Usage != "67" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Cost == -1.0 { // Cost was not calculated
|
||||
t.Errorf("Unexpected Cost for CDR: %+v", reply[0])
|
||||
}
|
||||
//if reply[0].Supplier != "suppl2" { // Usage as seconds
|
||||
// t.Errorf("Unexpected Supplier for CDR: %+v", reply[0])
|
||||
//}
|
||||
}
|
||||
// Make sure call cost contains the matched information
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCallCostLog", utils.AttrGetCallCost{CgrId: cgrId}, &cCost); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if utils.IsSliceMember([]string{cCost.Timespans[0].MatchedSubject, cCost.Timespans[0].MatchedPrefix, cCost.Timespans[0].MatchedDestId}, "") {
|
||||
t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0])
|
||||
}
|
||||
|
||||
req = utils.RpcCdrsFilter{RunIds: []string{utils.META_DEFAULT}, Accounts: []string{"1001"}, DestPrefixes: []string{"1003"}}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
} else {
|
||||
cgrId = reply[0].CgrId
|
||||
if reply[0].ReqType != utils.META_PREPAID {
|
||||
t.Errorf("Unexpected ReqType for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "65" && reply[0].Usage != "66" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Cost != 0 { // Cost was not calculated
|
||||
t.Errorf("Unexpected Cost for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
// Make sure call cost contains the matched information
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCallCostLog", utils.AttrGetCallCost{CgrId: cgrId}, &cCost); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if utils.IsSliceMember([]string{cCost.Timespans[0].MatchedSubject, cCost.Timespans[0].MatchedPrefix, cCost.Timespans[0].MatchedDestId}, "") {
|
||||
t.Errorf("Unexpected Matched* for CallCost: %+v", cCost.Timespans[0])
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1001"}, RunIds: []string{"derived_run1"}, FilterOnRated: true}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
} else if len(reply) != 2 {
|
||||
t.Error("Unexpected number of CDRs returned: ", len(reply))
|
||||
} else {
|
||||
if reply[0].ReqType != utils.META_RATED {
|
||||
@@ -303,7 +399,16 @@ func TestTutOsipsCallsCdrs(t *testing.T) {
|
||||
t.Errorf("Unexpected Subject for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1002"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutOsipsCalls1002Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1002"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
@@ -322,7 +427,15 @@ func TestTutOsipsCallsCdrs(t *testing.T) {
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1003"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutOsipsCalls1003Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1003"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
@@ -337,11 +450,20 @@ func TestTutOsipsCallsCdrs(t *testing.T) {
|
||||
if reply[0].Destination != "1001" {
|
||||
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "63" { // Usage as seconds
|
||||
if reply[0].Usage != "63" && reply[0].Usage != "64" { // Usage as seconds, sometimes takes a second longer to disconnect
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1004"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutOsipsCalls1004Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1004"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
@@ -360,7 +482,16 @@ func TestTutOsipsCallsCdrs(t *testing.T) {
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1006"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutOsipsCalls1006Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1006"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
@@ -375,11 +506,22 @@ func TestTutOsipsCallsCdrs(t *testing.T) {
|
||||
if reply[0].Destination != "1002" {
|
||||
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "64" { // Usage as seconds
|
||||
if reply[0].Usage != "64" && reply[0].Usage != "65" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Cost == -1.0 { // Cost was not calculated
|
||||
t.Errorf("Unexpected Cost for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
req = utils.RpcCdrsFilter{Accounts: []string{"1007"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
}
|
||||
|
||||
// Make sure account was debited properly
|
||||
func TestTutOsipsCalls1007Cdrs(t *testing.T) {
|
||||
if !*testCalls {
|
||||
return
|
||||
}
|
||||
var reply []*engine.ExternalCdr
|
||||
req := utils.RpcCdrsFilter{Accounts: []string{"1007"}, RunIds: []string{utils.META_DEFAULT}}
|
||||
if err := tutOsipsCallsRpc.Call("ApierV2.GetCdrs", req, &reply); err != nil {
|
||||
t.Error("Unexpected error: ", err.Error())
|
||||
} else if len(reply) != 1 {
|
||||
@@ -394,9 +536,12 @@ func TestTutOsipsCallsCdrs(t *testing.T) {
|
||||
if reply[0].Destination != "1002" {
|
||||
t.Errorf("Unexpected Destination for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Usage != "66" { // Usage as seconds
|
||||
if reply[0].Usage != "66" && reply[0].Usage != "67" { // Usage as seconds
|
||||
t.Errorf("Unexpected Usage for CDR: %+v", reply[0])
|
||||
}
|
||||
if reply[0].Cost == -1.0 { // Cost was not calculated
|
||||
t.Errorf("Unexpected Cost for CDR: %+v", reply[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -386,7 +386,7 @@ func (fsev FSEvent) AsCallDescriptor() (*engine.CallDescriptor, error) {
|
||||
Account: fsev.GetAccount(utils.META_DEFAULT),
|
||||
Subject: fsev.GetSubject(utils.META_DEFAULT),
|
||||
Destination: fsev.GetDestination(utils.META_DEFAULT),
|
||||
StartTime: utils.FirstNonEmpty(fsev[SETUP_TIME], fsev[ANSWER_TIME]),
|
||||
SetupTime: utils.FirstNonEmpty(fsev[SETUP_TIME], fsev[ANSWER_TIME]),
|
||||
Duration: fsev[DURATION],
|
||||
}
|
||||
return lcrReq.AsCallDescriptor()
|
||||
|
||||
@@ -381,7 +381,7 @@ func (kev KamEvent) AsCallDescriptor() (*engine.CallDescriptor, error) {
|
||||
Account: kev.GetAccount(utils.META_DEFAULT),
|
||||
Subject: kev.GetSubject(utils.META_DEFAULT),
|
||||
Destination: kev.GetDestination(utils.META_DEFAULT),
|
||||
StartTime: utils.FirstNonEmpty(kev[CGR_SETUPTIME], kev[CGR_ANSWERTIME]),
|
||||
SetupTime: utils.FirstNonEmpty(kev[CGR_SETUPTIME], kev[CGR_ANSWERTIME]),
|
||||
Duration: kev[CGR_DURATION],
|
||||
}
|
||||
return lcrReq.AsCallDescriptor()
|
||||
|
||||
@@ -1078,7 +1078,8 @@ type AttrSetAccount struct {
|
||||
Direction string
|
||||
Account string
|
||||
ActionPlanId string
|
||||
AllowNegative bool
|
||||
AllowNegative *bool
|
||||
Disabled *bool
|
||||
}
|
||||
|
||||
type AttrRemoveAccount struct {
|
||||
|
||||
Reference in New Issue
Block a user