mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
224 lines
8.7 KiB
Go
224 lines
8.7 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 agents
|
|
|
|
import (
|
|
"net"
|
|
"path"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/cgrates/birpc"
|
|
"github.com/cgrates/birpc/context"
|
|
"github.com/cgrates/cgrates/config"
|
|
"github.com/cgrates/cgrates/engine"
|
|
"github.com/cgrates/cgrates/utils"
|
|
"github.com/cgrates/sipingo"
|
|
)
|
|
|
|
var (
|
|
saonfigDIR string
|
|
saCfgPath string
|
|
saCfg *config.CGRConfig
|
|
saRPC *birpc.Client
|
|
saConn net.Conn
|
|
|
|
sTestsSIP = []func(t *testing.T){
|
|
testSAitInitCfg,
|
|
testSAitResetDataDb,
|
|
testSAitResetStorDb,
|
|
testSAitStartEngine,
|
|
testSAitApierRpcConn,
|
|
testSAitTPFromFolder,
|
|
|
|
testSAitSIPRegister,
|
|
testSAitSIPInvite,
|
|
|
|
testSAitStopCgrEngine,
|
|
}
|
|
)
|
|
|
|
// Test start here
|
|
func TestSAit(t *testing.T) {
|
|
// engine.KillEngine(0)
|
|
switch *utils.DBType {
|
|
case utils.MetaInternal:
|
|
saonfigDIR = "sipagent_internal"
|
|
case utils.MetaMySQL:
|
|
saonfigDIR = "sipagent_mysql"
|
|
case utils.MetaMongo:
|
|
saonfigDIR = "sipagent_mongo"
|
|
case utils.MetaPostgres:
|
|
t.SkipNow()
|
|
default:
|
|
t.Fatal("Unknown Database type")
|
|
}
|
|
for _, stest := range sTestsSIP {
|
|
t.Run(saonfigDIR, stest)
|
|
}
|
|
}
|
|
|
|
func testSAitInitCfg(t *testing.T) {
|
|
saCfgPath = path.Join(*utils.DataDir, "conf", "samples", saonfigDIR)
|
|
// Init config first
|
|
var err error
|
|
saCfg, err = config.NewCGRConfigFromPath(saCfgPath)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
if isDispatcherActive {
|
|
saCfg.ListenCfg().RPCJSONListen = ":6012"
|
|
}
|
|
}
|
|
|
|
// Remove data in both rating and accounting db
|
|
func testSAitResetDataDb(t *testing.T) {
|
|
if err := engine.InitDataDB(saCfg); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// Wipe out the cdr database
|
|
func testSAitResetStorDb(t *testing.T) {
|
|
if err := engine.InitStorDb(saCfg); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// Start CGR Engine
|
|
func testSAitStartEngine(t *testing.T) {
|
|
if _, err := engine.StartEngine(saCfgPath, *utils.WaitRater); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// Connect rpc client to rater
|
|
func testSAitApierRpcConn(t *testing.T) {
|
|
var err error
|
|
saRPC, err = newRPCClient(saCfg.ListenCfg()) // We connect over JSON so we can also troubleshoot if needed
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if saConn, err = net.Dial(utils.TCP, "127.0.0.1:5060"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// Load the tariff plan, creating accounts and their balances
|
|
func testSAitTPFromFolder(t *testing.T) {
|
|
attrs := &utils.AttrLoadTpFromFolder{FolderPath: path.Join(*utils.DataDir, "tariffplans", "tut_sip_redirect")}
|
|
var loadInst utils.LoadInstance
|
|
if err := saRPC.Call(context.Background(), utils.APIerSv2LoadTariffPlanFromFolder, attrs, &loadInst); err != nil {
|
|
t.Error(err)
|
|
}
|
|
time.Sleep(time.Duration(*utils.WaitRater) * time.Millisecond) // Give time for scheduler to execute topups
|
|
}
|
|
|
|
func testSAitStopCgrEngine(t *testing.T) {
|
|
if err := engine.KillEngine(100); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func testSAitSIPRegister(t *testing.T) {
|
|
registerMessage := "REGISTER sip:192.168.58.203 SIP/2.0\r\nCall-ID: d72a4ed6feb4167b5adb208525879db5@0:0:0:0:0:0:0:0\r\nCSeq: 1 REGISTER\r\nFrom: \"1002\" <sip:1002@192.168.58.203>;tag=d28739b9\r\nTo: \"1002\" <sip:1002@192.168.58.203>\r\nVia: SIP/2.0/UDP 192.168.58.201:5060;branch=z9hG4bK-323131-311ce8716a7bf1f6094859ae516a44eb\r\nMax-Forwards: 70\r\nUser-Agent: Jitsi2.11.20200408Linux\r\nExpires: 600\r\nContact: \"1002\" <sip:1002@192.168.58.201:5060;transport=udp;registering_acc=192_168_58_203>;expires=600\r\nContent-Length: 0\r\n"
|
|
if saConn == nil {
|
|
t.Fatal("connection not initialized")
|
|
}
|
|
var err error
|
|
if _, err = saConn.Write([]byte(registerMessage)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
buffer := make([]byte, bufferSize)
|
|
if _, err = saConn.Read(buffer); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var received sipingo.Message
|
|
if received, err = sipingo.NewMessage(string(buffer)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if expected := "SIP/2.0 405 Method Not Allowed"; received["Request"] != expected {
|
|
t.Errorf("Expected %q, received: %q", expected, received["Request"])
|
|
}
|
|
}
|
|
|
|
func testSAitSIPInvite(t *testing.T) {
|
|
inviteMessage := "INVITE sip:1002@192.168.58.203 SIP/2.0\r\nCall-ID: 4d4d84b0cc83fc90aca41e295cd8ff43@0:0:0:0:0:0:0:0\r\nCSeq: 2 INVITE\r\nFrom: \"1001\" <sip:1001@192.168.58.203>;tag=99f35805\r\nTo: <sip:1002@192.168.58.203>\r\nMax-Forwards: 70\r\nContact: \"1001\" <sip:1001@192.168.58.201:5060;transport=udp;registering_acc=192_168_58_203>\r\nUser-Agent: Jitsi2.11.20200408Linux\r\nContent-Type: application/sdp\r\nVia: SIP/2.0/UDP 192.168.58.201:5060;branch=z9hG4bK-393139-939e89686023b86822cb942ede452b62\r\nProxy-Authorization: Digest username=\"1001\",realm=\"192.168.58.203\",nonce=\"XruO2167ja8uRODnSv8aXqv+/hqPJiXh\",uri=\"sip:1002@192.168.58.203\",response=\"5b814c709d1541d72ea778599c2e48a4\"\r\nContent-Length: 897\r\n\r\nv=0\r\no=1001-jitsi.org 0 0 IN IP4 192.168.58.201\r\ns=-\r\nc=IN IP4 192.168.58.201\r\nt=0 0\r\nm=audio 5000 RTP/AVP 96 97 98 9 100 102 0 8 103 3 104 101\r\na=rtpmap:96 opus/48000/2\r\na=fmtp:96 usedtx=1\r\na=ptime:20\r\na=rtpmap:97 SILK/24000\r\na=rtpmap:98 SILK/16000\r\na=rtpmap:9 G722/8000\r\na=rtpmap:100 speex/32000\r\na=rtpmap:102 speex/16000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:103 iLBC/8000\r\na=rtpmap:3 GSM/8000\r\na=rtpmap:104 speex/8000\r\na=rtpmap:101 telephone-event/8000\r\na=extmap:1 urn:ietf:params:rtp-hdrext:csrc-audio-level\r\na=extmap:2 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=rtcp-xr:voip-metrics\r\nm=video 5002 RTP/AVP 105 99\r\na=recvonly\r\na=rtpmap:105 h264/90000\r\na=fmtp:105 profile-level-id=42E01f;packetization-mode=1\r\na=imageattr:105 send * recv [x=[1:1920],y=[1:1080]]\r\na=rtpmap:\r\n"
|
|
ack := "ACK sip:1001@192.168.56.203:6060 SIP/2.0\r\nVia: SIP/2.0/UDP 192.168.56.203;rport;branch=z9hG4bKQeB89BamX86UD\r\nMax-Forwards: 69\r\nFrom: \"1001\" <sip:1001@192.168.58.203>;tag=99f35805\r\nTo: <sip:1001@192.168.56.203:6060>\r\nCall-ID: 4d4d84b0cc83fc90aca41e295cd8ff43@0:0:0:0:0:0:0:0\r\nCSeq: 21984733 ACK\r\nContent-Length: 0\r\n"
|
|
if saConn == nil {
|
|
t.Fatal("connection not initialized")
|
|
}
|
|
var err error
|
|
if _, err = saConn.Write([]byte(inviteMessage)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
buffer := make([]byte, bufferSize)
|
|
if _, err = saConn.Read(buffer); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var received sipingo.Message
|
|
if received, err = sipingo.NewMessage(string(buffer)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if expected := "SIP/2.0 302 Moved Temporarily"; received["Request"] != expected {
|
|
t.Errorf("Expected %q, received: %q", expected, received["Request"])
|
|
}
|
|
if expected := "\"1002\" <sip:1002@cgrates.org>;q=0.7; expires=3600;cgr_cost=0.3;cgr_maxusage=30000000000,\"1002\" <sip:1002@cgrates.net>;q=0.2;cgr_cost=0.6;cgr_maxusage=30000000000,\"1002\" <sip:1002@cgrates.com>;q=0.1;cgr_cost=0.01;cgr_maxusage=30000000000"; received["Contact"] != expected {
|
|
t.Errorf("Expected %q, received: %q", expected, received["Contact"])
|
|
}
|
|
|
|
time.Sleep(time.Second)
|
|
buffer = make([]byte, bufferSize)
|
|
if _, err = saConn.Read(buffer); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if received, err = sipingo.NewMessage(string(buffer)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if expected := "SIP/2.0 302 Moved Temporarily"; received["Request"] != expected {
|
|
t.Errorf("Expected %q, received: %q", expected, received["Request"])
|
|
}
|
|
if expected := "\"1002\" <sip:1002@cgrates.org>;q=0.7; expires=3600;cgr_cost=0.3;cgr_maxusage=30000000000,\"1002\" <sip:1002@cgrates.net>;q=0.2;cgr_cost=0.6;cgr_maxusage=30000000000,\"1002\" <sip:1002@cgrates.com>;q=0.1;cgr_cost=0.01;cgr_maxusage=30000000000"; received["Contact"] != expected {
|
|
t.Errorf("Expected %q, received: %q", expected, received["Contact"])
|
|
}
|
|
|
|
if expected := "<sip:1002@route1.com>"; received["P-Charge-Info"] != expected {
|
|
t.Errorf("Expected %q, received: %q", expected, received["P-Charge-Info"])
|
|
}
|
|
|
|
if _, err = saConn.Write([]byte(ack)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
buffer = make([]byte, bufferSize)
|
|
saConn.SetDeadline(time.Now().Add(time.Second))
|
|
if _, err = saConn.Read(buffer); err == nil {
|
|
t.Error("Expected error received nil")
|
|
} else if nerr, ok := err.(net.Error); !ok {
|
|
t.Errorf("Expected net.Error received:%v", err)
|
|
} else if !nerr.Timeout() {
|
|
t.Errorf("Expected a timeout error received:%v", err)
|
|
}
|
|
}
|