blob: 19b563761f1aedaffe1260f16da9e945a045790f [file] [log] [blame]
Benny Prijonof9bd1f22008-06-16 13:04:44 +00001# $Id$
Benny Prijonocc1ada52008-06-15 19:43:43 +00002import sys
3import imp
4import re
Benny Prijonof9bd1f22008-06-16 13:04:44 +00005import os
Benny Prijonocc1ada52008-06-15 19:43:43 +00006import subprocess
Benny Prijonof9bd1f22008-06-16 13:04:44 +00007import random
Benny Prijonocc1ada52008-06-15 19:43:43 +00008import time
Nanang Izzuddina680bd62008-06-27 21:12:12 +00009import getopt
Benny Prijonocc1ada52008-06-15 19:43:43 +000010
11import inc_const as const
Nanang Izzuddina680bd62008-06-27 21:12:12 +000012import inc_cfg as inc
13
14# Vars
15G_EXE = "" # pjsua executable path
16G_INUNIX = False # flags that test is running in Unix
17
18
19# Usage string
20usage = \
21"""
22run.py - Automated test driver
23
24Usage:
25 run.py [options] MODULE CONFIG
26Options:
27 --exe, -e pjsua executable path
28 --null-audio, -n use null audio
29Sample:
30 run.py -n mod_run.py scripts-run/100_simple.py
31"""
32
33# Parse arguments
34try:
35 opts, args = getopt.getopt(sys.argv[1:], "hne:", ["help", "null-audio", "exe="])
36except getopt.GetoptError, err:
37 print str(err)
38 print usage
39 sys.exit(2)
40for o, a in opts:
41 if o in ("-h", "--help"):
42 print usage
43 sys.exit()
44 elif o in ("-n", "--null-audio"):
45 inc.HAS_SND_DEV = 0
46 elif o in ("-e", "--exe"):
47 G_EXE = a
48 else:
49 print "Unknown options"
50 sys.exit(2)
51
52if len(args) != 2:
53 print "Invalid arguments"
54 print usage
55 sys.exit(2)
56
57# Set global ARGS to be used by modules
58inc.ARGS = args
Benny Prijonocc1ada52008-06-15 19:43:43 +000059
Benny Prijonof9bd1f22008-06-16 13:04:44 +000060# Get the pjsua executable name
Nanang Izzuddina680bd62008-06-27 21:12:12 +000061if G_EXE == "":
62 if sys.platform.find("win32")!=-1:
Nanang Izzuddin57ab9722010-08-05 07:24:40 +000063 EXE_DIR = "../../pjsip-apps/bin/"
64 EXECUTABLES = [ "pjsua_vc6d.exe",
65 "pjsua_vc6.exe",
66 "pjsua-i386-Win32-vc8-Debug.exe",
67 "pjsua-i386-Win32-vc8-Debug-Dynamic.exe",
68 "pjsua-i386-Win32-vc8-Debug-Static.exe",
69 "pjsua-i386-Win32-vc8-Release.exe",
70 "pjsua-i386-Win32-vc8-Release-Dynamic.exe",
71 "pjsua-i386-Win32-vc8-Release-Static.exe"
72 ]
73 e_ts = 0
74 for e in EXECUTABLES:
75 e = EXE_DIR + e
76 if os.access(e, os.F_OK):
77 st = os.stat(e)
78 if e_ts==0 or e_ts<st.st_mtime:
79 G_EXE = e
80 e_ts = st.st_mtime
81
Nanang Izzuddina680bd62008-06-27 21:12:12 +000082 if G_EXE=="":
83 print "Unable to find valid pjsua. Please build pjsip first"
84 sys.exit(1)
Nanang Izzuddin57ab9722010-08-05 07:24:40 +000085
Nanang Izzuddina680bd62008-06-27 21:12:12 +000086 G_INUNIX = False
87 else:
Benny Prijono43b6ece2008-12-29 14:52:29 +000088 f = open("../../build.mak", "r")
Nanang Izzuddina680bd62008-06-27 21:12:12 +000089 while True:
90 line = f.readline()
91 if not line:
92 break
93 if line.find("TARGET_NAME")!=-1:
94 print line
Benny Prijono945aeb22008-12-22 18:54:58 +000095 G_EXE="../../pjsip-apps/bin/pjsua-" + line.split(":= ")[1]
Nanang Izzuddina680bd62008-06-27 21:12:12 +000096 break
97 if G_EXE=="":
98 print "Unable to find ../../../build.mak. Please build pjsip first"
99 sys.exit(1)
100 G_INUNIX = True
Benny Prijono4fa16022010-04-20 09:52:54 +0000101else:
102 if sys.platform.lower().find("win32")!=-1 or sys.platform.lower().find("microsoft")!=-1:
103 G_INUNIX = False
104 else:
105 G_INUNIX = True
Benny Prijonof9bd1f22008-06-16 13:04:44 +0000106
107
108G_EXE = G_EXE.rstrip("\n\r \t")
Benny Prijonocc1ada52008-06-15 19:43:43 +0000109
110###################################
Benny Prijonocc1ada52008-06-15 19:43:43 +0000111# Poor man's 'expect'-like class
112class Expect:
113 proc = None
114 echo = False
115 trace_enabled = False
116 name = ""
117 inst_param = None
118 rh = re.compile(const.DESTROYED)
119 ra = re.compile(const.ASSERT, re.I)
120 rr = re.compile(const.STDOUT_REFRESH)
Benny Prijonoddd02de2008-06-26 22:20:11 +0000121 t0 = time.time()
Benny Prijonocc1ada52008-06-15 19:43:43 +0000122 def __init__(self, inst_param):
123 self.inst_param = inst_param
124 self.name = inst_param.name
125 self.echo = inst_param.echo_enabled
126 self.trace_enabled = inst_param.trace_enabled
Benny Prijono1e65e9a2008-06-27 23:53:00 +0000127 fullcmd = G_EXE + " " + inst_param.arg + " --stdout-refresh=5 --stdout-refresh-text=" + const.STDOUT_REFRESH
128 if not inst_param.enable_buffer:
129 fullcmd = fullcmd + " --stdout-no-buf"
Benny Prijonocc1ada52008-06-15 19:43:43 +0000130 self.trace("Popen " + fullcmd)
Benny Prijono5242a422008-06-26 16:27:17 +0000131 self.proc = subprocess.Popen(fullcmd, shell=G_INUNIX, bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=False)
Benny Prijonocc1ada52008-06-15 19:43:43 +0000132 def send(self, cmd):
133 self.trace("send " + cmd)
134 self.proc.stdin.writelines(cmd + "\n")
Benny Prijono5242a422008-06-26 16:27:17 +0000135 self.proc.stdin.flush()
136 def expect(self, pattern, raise_on_error=True, title=""):
Benny Prijonocc1ada52008-06-15 19:43:43 +0000137 self.trace("expect " + pattern)
138 r = re.compile(pattern, re.I)
139 refresh_cnt = 0
140 while True:
141 line = self.proc.stdout.readline()
142 if line == "":
Nanang Izzuddina680bd62008-06-27 21:12:12 +0000143 raise inc.TestError(self.name + ": Premature EOF")
Benny Prijonocc1ada52008-06-15 19:43:43 +0000144 # Print the line if echo is ON
145 if self.echo:
146 print self.name + ": " + line,
147 # Trap assertion error
148 if self.ra.search(line) != None:
149 if raise_on_error:
Nanang Izzuddina680bd62008-06-27 21:12:12 +0000150 raise inc.TestError(self.name + ": " + line)
Benny Prijonocc1ada52008-06-15 19:43:43 +0000151 else:
152 return None
153 # Count stdout refresh text.
154 if self.rr.search(line) != None:
155 refresh_cnt = refresh_cnt+1
156 if refresh_cnt >= 6:
157 self.trace("Timed-out!")
158 if raise_on_error:
Nanang Izzuddina680bd62008-06-27 21:12:12 +0000159 raise inc.TestError(self.name + " " + title + ": Timeout expecting pattern: \"" + pattern + "\"")
Benny Prijonocc1ada52008-06-15 19:43:43 +0000160 else:
161 return None # timeout
162 # Search for expected text
163 if r.search(line) != None:
164 return line
165
166 def sync_stdout(self):
167 self.trace("sync_stdout")
Benny Prijonoddd02de2008-06-26 22:20:11 +0000168 cmd = "echo 1" + str(random.randint(1000,9999))
169 self.send(cmd)
170 self.expect(cmd)
Benny Prijonocc1ada52008-06-15 19:43:43 +0000171
172 def wait(self):
173 self.trace("wait")
Benny Prijono8a0e97b2009-01-04 20:15:37 +0000174 self.proc.communicate()
Benny Prijonod5962672009-01-02 18:15:07 +0000175
Benny Prijonocc1ada52008-06-15 19:43:43 +0000176 def trace(self, s):
177 if self.trace_enabled:
Benny Prijonoddd02de2008-06-26 22:20:11 +0000178 now = time.time()
179 fmt = self.name + ": " + "================== " + s + " ==================" + " [at t=%(time)03d]"
180 print fmt % {'time':int(now - self.t0)}
Benny Prijonocc1ada52008-06-15 19:43:43 +0000181
182#########################
183# Error handling
Nanang Izzuddine6f85fb2008-06-20 17:43:55 +0000184def handle_error(errmsg, t, close_processes = True):
Benny Prijonocc1ada52008-06-15 19:43:43 +0000185 print "====== Caught error: " + errmsg + " ======"
Nanang Izzuddine6f85fb2008-06-20 17:43:55 +0000186 if (close_processes):
187 time.sleep(1)
188 for p in t.process:
189 p.send("q")
190 p.send("q")
Benny Prijonod5962672009-01-02 18:15:07 +0000191 is_err = False
192 try:
193 ret = p.expect(const.DESTROYED, False)
194 if not ret:
195 is_err = True
196 except:
197 is_err = True
198 if is_err:
199 if sys.hexversion >= 0x02060000:
200 p.proc.terminate()
201 else:
202 p.wait()
203 else:
204 p.wait()
Benny Prijonocc1ada52008-06-15 19:43:43 +0000205 print "Test completed with error: " + errmsg
206 sys.exit(1)
207
208
209#########################
210# MAIN
211
Benny Prijonocc1ada52008-06-15 19:43:43 +0000212# Import the test script
Nanang Izzuddina680bd62008-06-27 21:12:12 +0000213script = imp.load_source("script", inc.ARGS[0])
Benny Prijonocc1ada52008-06-15 19:43:43 +0000214
Benny Prijonof9bd1f22008-06-16 13:04:44 +0000215# Init random seed
216random.seed()
217
Benny Prijonocc1ada52008-06-15 19:43:43 +0000218# Validate
219if script.test == None:
220 print "Error: no test defined"
221 sys.exit(1)
222
Nanang Izzuddin6ee166d2008-06-26 12:26:52 +0000223if script.test.skip:
224 print "Test " + script.test.title + " is skipped"
225 sys.exit(0)
226
Benny Prijonocc1ada52008-06-15 19:43:43 +0000227if len(script.test.inst_params) == 0:
228 print "Error: test doesn't contain pjsua run descriptions"
229 sys.exit(1)
230
231# Instantiate pjsuas
232print "====== Running " + script.test.title + " ======"
Benny Prijonof9bd1f22008-06-16 13:04:44 +0000233print "Using " + G_EXE + " as pjsua executable"
234
Benny Prijonocc1ada52008-06-15 19:43:43 +0000235for inst_param in script.test.inst_params:
236 try:
237 # Create pjsua's Expect instance from the param
238 p = Expect(inst_param)
239 # Wait until registration completes
240 if inst_param.have_reg:
241 p.expect(inst_param.uri+".*registration success")
242 # Synchronize stdout
243 p.send("")
244 p.expect(const.PROMPT)
245 p.send("echo 1")
246 p.send("echo 1")
247 p.expect("echo 1")
248 # add running instance
249 script.test.process.append(p)
250
Nanang Izzuddina680bd62008-06-27 21:12:12 +0000251 except inc.TestError, e:
Benny Prijonocc1ada52008-06-15 19:43:43 +0000252 handle_error(e.desc, script.test)
253
254# Run the test function
255if script.test.test_func != None:
256 try:
Nanang Izzuddina680bd62008-06-27 21:12:12 +0000257 script.test.test_func(script.test)
258 except inc.TestError, e:
Benny Prijonocc1ada52008-06-15 19:43:43 +0000259 handle_error(e.desc, script.test)
260
261# Shutdown all instances
262time.sleep(2)
263for p in script.test.process:
264 # Unregister if we have_reg to make sure that next tests
265 # won't wail
266 if p.inst_param.have_reg:
267 p.send("ru")
268 p.expect(p.inst_param.uri+".*unregistration success")
269 p.send("q")
270 p.send("q")
271 time.sleep(0.5)
272 p.expect(const.DESTROYED, False)
273 p.wait()
274
Nanang Izzuddinf810f952008-06-18 21:04:14 +0000275# Run the post test function
276if script.test.post_func != None:
277 try:
Nanang Izzuddina680bd62008-06-27 21:12:12 +0000278 script.test.post_func(script.test)
279 except inc.TestError, e:
Nanang Izzuddine6f85fb2008-06-20 17:43:55 +0000280 handle_error(e.desc, script.test, False)
Nanang Izzuddinf810f952008-06-18 21:04:14 +0000281
Benny Prijonocc1ada52008-06-15 19:43:43 +0000282# Done
283print "Test " + script.test.title + " completed successfully"
284sys.exit(0)
285