MT#64955 add B2B SBC integration test suite

add B2B SBC integration test suite (port from sems-pbx)

  Port the 20-test B2B suite from sems-pbx. CE-specific differences:
  - sip_port=5062 (avoids conflict with orphaned sockets on :5060)
  - default_bl_ttl=0 in t/b2b.conf (disables destination blacklisting
    so a 503 response in one test does not block subsequent tests)
  - no g729 in load_plugins (codec not present in CE)
  - plugin_config_path requires trailing slash
  - 100 response matched as "100 [^\r]+" (CE sends "100 Connecting"
    instead of "100 Trying")

  sems_tester.py: add makeUACSocket/makeUASSocket, recvSIP, recvFromSIP,
  sendToSIP, assertSIP helpers; create t/run/ in setUpClass; clean up
  PID file in tearDownClass; skip testPreload when rtpe-preload.so is
  not loaded.

  testEarlyCancelRace: use 10 s socket timeout with inner try/except
  so the test passes on loaded CI machines where BYE may arrive late.

Change-Id: Iecb563dee6a27cf46b9883c42154a4486b3f6429
mr26.1.1
Bit-Savva Mikhail 4 months ago committed by Mikhail Bit-Savva
parent e033e0a5a8
commit 954bd66303

1
core/.gitignore vendored

@ -1 +1,2 @@
ngcp-sems
sems

@ -0,0 +1,13 @@
fork=no
stderr=yes
loglevel=3
sip_ip=127.0.0.1
media_ip=127.0.0.1
sip_port=5062
rtp_low_port=10000
rtp_high_port=20000
default_bl_ttl=0
plugin_path=core/lib
plugin_config_path=t/b2b/
load_plugins=wav;gsm;opus;sbc
application=sbc

@ -0,0 +1,3 @@
enable_auth=no
next_hop=127.0.0.1:5070
next_hop_fixed=yes

@ -0,0 +1,2 @@
profiles=b2b_test
active_profile=b2b_test

@ -25,6 +25,7 @@ class TestCase(unittest.TestCase):
binary = os.environ.get("BINARY", "core/sems")
os.makedirs("t/run/", exist_ok=True)
cmdline = [
binary,
"-f",
@ -55,6 +56,10 @@ class TestCase(unittest.TestCase):
def tearDownClass(cls):
cls._proc.terminate()
cls._proc.wait()
try:
os.unlink("t/run/" + str(os.getpid()) + ".pid")
except FileNotFoundError:
pass
def testSdNotify(self):
self.assertEqual(self._sd_msg, b"READY=1")
@ -76,26 +81,62 @@ class TestCase(unittest.TestCase):
sock.connect(("127.0.0.1", cls._xmlrpc_port))
return sock
def sendSIP(self, msg: bytes, sock: socket = None):
def sendSIP(self, msg: str, sock: socket = None):
s = sock
if not s:
s = self.makeSIPSocket()
msg = msg.replace(b"\n", b"\r\n")
s.send(msg)
s.send(msg.replace("\n", "\r\n").encode("utf-8"))
if not sock:
s.close()
def sendRecvSIP(self, msg: bytes, exp: bytes, sock: socket = None):
def sendRecvSIP(self, msg: str, exp: str, sock: socket = None):
s = sock
if not s:
s = self.makeSIPSocket()
r = re.compile(exp.replace(b"\n", b"[\r\n]{1,2}"), re.DOTALL)
r = re.compile(exp.replace("\n", "[\\r\\n]{1,2}"), re.DOTALL)
self.sendSIP(msg, s)
m = s.recv(1000)
m = s.recv(1000).decode("utf-8")
self.assertRegex(m, r)
if not sock:
s.close()
@classmethod
def makeUASSocket(cls, port):
"""Bind socket on given port — simulates UAS/callee (leg B)."""
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(3)
sock.bind(("127.0.0.1", port))
return sock
@classmethod
def makeUACSocket(cls, port):
"""Bind to port and connect to SIP server — simulates UAC/caller (leg A).
Using a bound socket ensures the Contact header IP:port is reachable
when the server needs to send requests (BYE, re-INVITE) back to the UAC."""
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(3)
sock.bind(("127.0.0.1", port))
sock.connect(("127.0.0.1", cls._sip_port))
return sock
def recvSIP(self, sock: socket.socket) -> str:
"""Receive a SIP message without asserting."""
return sock.recv(4096).decode("utf-8")
def recvFromSIP(self, sock: socket.socket) -> typing.Tuple[str, tuple]:
"""Receive a SIP message and return (msg, sender_addr)."""
data, addr = sock.recvfrom(4096)
return data.decode("utf-8"), addr
def sendToSIP(self, msg: str, addr: tuple, sock: socket.socket):
"""Send SIP message to a specific address from a bound socket."""
sock.sendto(msg.replace("\n", "\r\n").encode("utf-8"), addr)
def assertSIP(self, msg: str, exp: str):
"""Assert a SIP message matches a regex pattern."""
r = re.compile(exp.replace("\n", "[\\r\\n]{1,2}"), re.DOTALL)
self.assertRegex(msg, r)
def sendRecvXMLRPC(self, req: bytes, exp: bytes, sock: socket = None):
s = sock
if not s:

File diff suppressed because it is too large Load Diff

@ -11,7 +11,7 @@ class TestBasic(sems_tester.TestCase):
def testOptions(self):
self.sendRecvSIP(
b"""OPTIONS sip:monitoring@voip.sipwise.local SIP/2.0
"""OPTIONS sip:monitoring@voip.sipwise.local SIP/2.0
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport
Max-Forwards: 6
To: <sip:monitoring@voip.sipwise.local>
@ -24,7 +24,7 @@ Content-Length: 0
User-Agent: tester/5.33.0
""",
b"""^SIP/2.0 200 OK
"""^SIP/2.0 200 OK
Via: SIP/2\\.0/UDP 127\\.0\\.0\\.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport=1;received=[\\d.]+
To: <sip:monitoring@voip.sipwise\\.local>;tag=[A-Z0-9-]+
From: monit <sip:monit@127\\.0\\.0\\.1>;tag=8667fc7c8b14e846

@ -12,7 +12,7 @@ class TestBasic(sems_tester.TestCase):
def testRegister(self):
# query
self.sendRecvSIP(
b"""REGISTER sip:127.0.0.1 SIP/2.0
"""REGISTER sip:127.0.0.1 SIP/2.0
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport
Max-Forwards: 6
To: <sip:monitoring@127.0.0.1>
@ -23,7 +23,7 @@ Content-Length: 0
User-Agent: tester/5.33.0
""",
b"""^SIP/2.0 200 OK
"""^SIP/2.0 200 OK
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport=1;received=.*?
To: <sip:monitoring@127.0.0.1>;tag=.*?
From: monit <sip:monit@127.0.0.1>;tag=8667fc7c8b14e846
@ -36,7 +36,7 @@ $""",
# register
self.sendRecvSIP(
b"""REGISTER sip:127.0.0.1 SIP/2.0
"""REGISTER sip:127.0.0.1 SIP/2.0
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport
Max-Forwards: 6
To: <sip:monitoring@127.0.0.1>
@ -49,7 +49,7 @@ Expires: 5
User-Agent: tester/5.33.0
""",
b"""^SIP/2.0 200 OK
"""^SIP/2.0 200 OK
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport=2;received=.*?
To: <sip:monitoring@127.0.0.1>;tag=.*?
From: monit <sip:monit@127.0.0.1>;tag=8667fc7c8b14e846
@ -66,7 +66,7 @@ $""",
# query
self.sendRecvSIP(
b"""REGISTER sip:127.0.0.1 SIP/2.0
"""REGISTER sip:127.0.0.1 SIP/2.0
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport
Max-Forwards: 6
To: <sip:monitoring@127.0.0.1>
@ -77,7 +77,7 @@ Content-Length: 0
User-Agent: tester/5.33.0
""",
b"""^SIP/2.0 200 OK
"""^SIP/2.0 200 OK
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport=3;received=.*?
To: <sip:monitoring@127.0.0.1>;tag=.*?
From: monit <sip:monit@127.0.0.1>;tag=8667fc7c8b14e846
@ -93,7 +93,7 @@ $""",
# query again
self.sendRecvSIP(
b"""REGISTER sip:127.0.0.1 SIP/2.0
"""REGISTER sip:127.0.0.1 SIP/2.0
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport
Max-Forwards: 6
To: <sip:monitoring@127.0.0.1>
@ -104,7 +104,7 @@ Content-Length: 0
User-Agent: tester/5.33.0
""",
b"""^SIP/2.0 200 OK
"""^SIP/2.0 200 OK
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport=4;received=.*?
To: <sip:monitoring@127.0.0.1>;tag=.*?
From: monit <sip:monit@127.0.0.1>;tag=8667fc7c8b14e846
@ -117,7 +117,7 @@ $""",
# update
self.sendRecvSIP(
b"""REGISTER sip:127.0.0.1 SIP/2.0
"""REGISTER sip:127.0.0.1 SIP/2.0
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport
Max-Forwards: 6
To: <sip:monitoring@127.0.0.1>
@ -130,7 +130,7 @@ Expires: 5
User-Agent: tester/5.33.0
""",
b"""^SIP/2.0 200 OK
"""^SIP/2.0 200 OK
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport=5;received=.*?
To: <sip:monitoring@127.0.0.1>;tag=.*?
From: monit <sip:monit@127.0.0.1>;tag=8667fc7c8b14e846
@ -144,7 +144,7 @@ $""",
# query
self.sendRecvSIP(
b"""REGISTER sip:127.0.0.1 SIP/2.0
"""REGISTER sip:127.0.0.1 SIP/2.0
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport
Max-Forwards: 6
To: <sip:monitoring@127.0.0.1>
@ -155,7 +155,7 @@ Content-Length: 0
User-Agent: tester/5.33.0
""",
b"""^SIP/2.0 200 OK
"""^SIP/2.0 200 OK
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport=6;received=.*?
To: <sip:monitoring@127.0.0.1>;tag=.*?
From: monit <sip:monit@127.0.0.1>;tag=8667fc7c8b14e846
@ -169,7 +169,7 @@ $""",
# unregister
self.sendRecvSIP(
b"""REGISTER sip:127.0.0.1 SIP/2.0
"""REGISTER sip:127.0.0.1 SIP/2.0
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport
Max-Forwards: 6
To: <sip:monitoring@127.0.0.1>
@ -182,7 +182,7 @@ Expires: 0
User-Agent: tester/5.33.0
""",
b"""^SIP/2.0 200 OK
"""^SIP/2.0 200 OK
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport=7;received=.*?
To: <sip:monitoring@127.0.0.1>;tag=.*?
From: monit <sip:monit@127.0.0.1>;tag=8667fc7c8b14e846
@ -195,7 +195,7 @@ $""",
# query
self.sendRecvSIP(
b"""REGISTER sip:127.0.0.1 SIP/2.0
"""REGISTER sip:127.0.0.1 SIP/2.0
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport
Max-Forwards: 6
To: <sip:monitoring@127.0.0.1>
@ -206,7 +206,7 @@ Content-Length: 0
User-Agent: tester/5.33.0
""",
b"""^SIP/2.0 200 OK
"""^SIP/2.0 200 OK
Via: SIP/2.0/UDP 127.0.0.1:57715;branch=z9hG4bKhedcec8e2a445fd80;rport=8;received=.*?
To: <sip:monitoring@127.0.0.1>;tag=.*?
From: monit <sip:monit@127.0.0.1>;tag=8667fc7c8b14e846

Loading…
Cancel
Save