summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/pjsua/mod_sipp.py8
-rw-r--r--tests/pjsua/run.py123
-rw-r--r--tests/pjsua/scripts-sipp/uas-reinv-with-less-media.py4
3 files changed, 98 insertions, 37 deletions
diff --git a/tests/pjsua/mod_sipp.py b/tests/pjsua/mod_sipp.py
index c705c966..25081086 100644
--- a/tests/pjsua/mod_sipp.py
+++ b/tests/pjsua/mod_sipp.py
@@ -40,7 +40,7 @@ else:
FDEVNULL = None
# SIPp executable path and param
-#SIPP_PATH = '"C:\\Program Files (x86)\\Sipp_3.2\\sipp.exe"'
+#SIPP_PATH = '"C:\\devs\\bin\\Sipp_3.2\\sipp.exe"'
SIPP_PATH = 'sipp'
SIPP_PORT = 6000
SIPP_PARAM = "-m 1 -i 127.0.0.1 -p " + str(SIPP_PORT)
@@ -224,8 +224,10 @@ def exec_pjsua_expects(t, sipp):
# PJSUA process may stuck.
# Ideally the poll should be done contiunously until SIPp process is
# terminated.
- for ua_idx in range(len(ua)):
- ua[ua_idx].expect(inc_const.STDOUT_REFRESH, raise_on_error = False)
+ # Update: now pjsua stdout is polled continuously by a dedicated thread,
+ # so the poll is no longer needed
+ #for ua_idx in range(len(ua)):
+ # ua[ua_idx].expect(inc_const.STDOUT_REFRESH, raise_on_error = False)
return ua_err_st
diff --git a/tests/pjsua/run.py b/tests/pjsua/run.py
index 7eee316a..78e1b214 100644
--- a/tests/pjsua/run.py
+++ b/tests/pjsua/run.py
@@ -6,6 +6,8 @@ import os
import subprocess
import random
import time
+import threading
+import traceback
import getopt
import inc_const as const
@@ -109,59 +111,94 @@ G_EXE = G_EXE.rstrip("\n\r \t")
###################################
# Poor man's 'expect'-like class
-class Expect:
+class Expect(threading.Thread):
proc = None
echo = False
trace_enabled = False
- name = ""
inst_param = None
rh = re.compile(const.DESTROYED)
ra = re.compile(const.ASSERT, re.I)
rr = re.compile(const.STDOUT_REFRESH)
t0 = time.time()
+ output = ""
+ lock = threading.Lock()
+ running = False
def __init__(self, inst_param):
+ threading.Thread.__init__(self)
self.inst_param = inst_param
self.name = inst_param.name
self.echo = inst_param.echo_enabled
self.trace_enabled = inst_param.trace_enabled
+
+ def run(self):
fullcmd = G_EXE + " " + inst_param.arg + " --stdout-refresh=5 --stdout-refresh-text=" + const.STDOUT_REFRESH
if not inst_param.enable_buffer:
fullcmd = fullcmd + " --stdout-no-buf"
self.trace("Popen " + fullcmd)
self.proc = subprocess.Popen(fullcmd, shell=G_INUNIX, bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=False)
+ self.running = True
+ while self.proc.poll() == None:
+ line = self.proc.stdout.readline()
+ if line == "":
+ break;
+
+ #Print the line if echo is ON
+ if self.echo:
+ print self.name + ": " + line.rstrip()
+
+ self.lock.acquire()
+ self.output += line
+ self.lock.release()
+ self.running = False
+
def send(self, cmd):
self.trace("send " + cmd)
self.proc.stdin.writelines(cmd + "\n")
self.proc.stdin.flush()
+
def expect(self, pattern, raise_on_error=True, title=""):
self.trace("expect " + pattern)
r = re.compile(pattern, re.I)
- refresh_cnt = 0
- while True:
- line = self.proc.stdout.readline()
- if line == "":
- raise inc.TestError(self.name + ": Premature EOF")
- # Print the line if echo is ON
- if self.echo:
- print self.name + ": " + line.rstrip()
- # Trap assertion error
- if self.ra.search(line) != None:
+ found_at = -1
+ t0 = time.time()
+ while found_at < 0:
+ self.lock.acquire()
+ lines = self.output.splitlines()
+
+ for i, line in enumerate(lines):
+ # Search for expected text
+ if r.search(line) != None:
+ found_at = i
+ break
+
+ # Trap assertion error
if raise_on_error:
- raise inc.TestError(self.name + ": " + line)
- else:
- return None
- # Count stdout refresh text.
- if self.rr.search(line) != None:
- refresh_cnt = refresh_cnt+1
- if refresh_cnt >= 6:
+ if self.ra.search(line) != None:
+ self.lock.release()
+ raise inc.TestError(self.name + ": " + line)
+
+ self.output = '\n'.join(lines[found_at+1:]) if found_at >= 0 else ""
+ self.lock.release()
+
+ if found_at >= 0:
+ return line
+
+ if not self.running:
+ if raise_on_error:
+ raise inc.TestError(self.name + ": Premature EOF")
+ break
+ else:
+ t1 = time.time()
+ dur = int(t1 - t0)
+ if dur > 15:
self.trace("Timed-out!")
if raise_on_error:
raise inc.TestError(self.name + " " + title + ": Timeout expecting pattern: \"" + pattern + "\"")
- else:
- return None # timeout
- # Search for expected text
- if r.search(line) != None:
- return line
+ break
+ else:
+ time.sleep(0.01)
+ return None
+
def sync_stdout(self):
self.trace("sync_stdout")
@@ -171,6 +208,7 @@ class Expect:
def wait(self):
self.trace("wait")
+ self.join()
self.proc.communicate()
def trace(self, s):
@@ -206,6 +244,7 @@ def handle_error(errmsg, t, close_processes = True):
p.wait()
else:
p.wait()
+
print "Test completed with error: " + errmsg
sys.exit(1)
@@ -240,17 +279,32 @@ for inst_param in script.test.inst_params:
try:
# Create pjsua's Expect instance from the param
p = Expect(inst_param)
+ p.start()
+ except inc.TestError, e:
+ handle_error(e.desc, script.test)
+
+ # wait process ready
+ while True:
+ try:
+ p.send("echo 1")
+ except:
+ time.sleep(0.1)
+ continue
+ break
+
+ # add running instance
+ script.test.process.append(p)
+
+for p in script.test.process:
+ try:
# Wait until registration completes
- if inst_param.have_reg:
- p.expect(inst_param.uri+".*registration success")
+ if p.inst_param.have_reg:
+ p.expect(p.inst_param.uri+".*registration success")
# Synchronize stdout
p.send("")
p.expect(const.PROMPT)
p.send("echo 1")
- p.send("echo 1")
p.expect("echo 1")
- # add running instance
- script.test.process.append(p)
except inc.TestError, e:
handle_error(e.desc, script.test)
@@ -261,9 +315,10 @@ if script.test.test_func != None:
script.test.test_func(script.test)
except inc.TestError, e:
handle_error(e.desc, script.test)
+ except:
+ handle_error("Unknown error: " + str(traceback.format_exc()), script.test)
# Shutdown all instances
-time.sleep(2)
for p in script.test.process:
# Unregister if we have_reg to make sure that next tests
# won't wail
@@ -271,9 +326,11 @@ for p in script.test.process:
p.send("ru")
p.expect(p.inst_param.uri+".*unregistration success")
p.send("q")
- p.send("q")
- time.sleep(0.5)
- p.expect(const.DESTROYED, False)
+
+time.sleep(0.5)
+for p in script.test.process:
+ if p.running:
+ p.expect(const.DESTROYED, False)
p.wait()
# Run the post test function
diff --git a/tests/pjsua/scripts-sipp/uas-reinv-with-less-media.py b/tests/pjsua/scripts-sipp/uas-reinv-with-less-media.py
index 42b2b881..83ba3997 100644
--- a/tests/pjsua/scripts-sipp/uas-reinv-with-less-media.py
+++ b/tests/pjsua/scripts-sipp/uas-reinv-with-less-media.py
@@ -5,4 +5,6 @@ import inc_const as const
PJSUA = ["--null-audio --extra-audio --max-calls=1 $SIPP_URI"]
# Send hold after remote holds (double hold)
-PJSUA_EXPECTS = [[0, const.MEDIA_HOLD, "H"]]
+PJSUA_EXPECTS = [[0, const.MEDIA_HOLD, ""],
+ [0, "ACK sip:", "H"]
+ ]