blob: 0b374def24c7af2670bb11786e18399b7091fe69 [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
9
10import inc_const as const
11
Benny Prijonof9bd1f22008-06-16 13:04:44 +000012# Get the pjsua executable name
13if sys.platform.find("win32")!=-1:
14 e = "../../bin/pjsua_vc6d.exe"
15 st1 = os.stat(e)
16 if st1 != None:
17 G_EXE = e
18 e = "../../bin/pjsua_vc6d.exe"
19 st2 = os.stat(e)
20 if st2 != None and st2.st_mtime > st1.st_mtime:
21 G_EXE = e
22 st1 = st2
23 if G_EXE=="":
24 print "Unable to find valid pjsua. Please build pjsip first"
25 sys.exit(1)
26 G_INUNIX = False
27else:
28 f = open("../../../build.mak", "r")
29 while True:
30 line = f.readline()
31 if not line:
32 break
33 if line.find("TARGET_NAME")!=-1:
34 print line
35 G_EXE="../../bin/pjsua-" + line.split(":= ")[1]
36 break
37 if G_EXE=="":
38 print "Unable to find ../../../build.mak. Please build pjsip first"
39 sys.exit(1)
40 G_INUNIX = True
41
42
43G_EXE = G_EXE.rstrip("\n\r \t")
Benny Prijonocc1ada52008-06-15 19:43:43 +000044
45###################################
46# TestError exception
47class TestError:
48 desc = ""
49 def __init__(self, desc):
50 self.desc = desc
51
52###################################
53# Poor man's 'expect'-like class
54class Expect:
55 proc = None
56 echo = False
57 trace_enabled = False
58 name = ""
59 inst_param = None
60 rh = re.compile(const.DESTROYED)
61 ra = re.compile(const.ASSERT, re.I)
62 rr = re.compile(const.STDOUT_REFRESH)
63 def __init__(self, inst_param):
64 self.inst_param = inst_param
65 self.name = inst_param.name
66 self.echo = inst_param.echo_enabled
67 self.trace_enabled = inst_param.trace_enabled
68 fullcmd = G_EXE + " " + inst_param.arg + " --stdout-refresh=5 --stdout-refresh-text=" + const.STDOUT_REFRESH
69 self.trace("Popen " + fullcmd)
Benny Prijonof9bd1f22008-06-16 13:04:44 +000070 self.proc = subprocess.Popen(fullcmd, shell=G_INUNIX, bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True)
Benny Prijonocc1ada52008-06-15 19:43:43 +000071 def send(self, cmd):
72 self.trace("send " + cmd)
73 self.proc.stdin.writelines(cmd + "\n")
74 def expect(self, pattern, raise_on_error=True):
75 self.trace("expect " + pattern)
76 r = re.compile(pattern, re.I)
77 refresh_cnt = 0
78 while True:
79 line = self.proc.stdout.readline()
80 if line == "":
81 raise TestError(self.name + ": Premature EOF")
82 # Print the line if echo is ON
83 if self.echo:
84 print self.name + ": " + line,
85 # Trap assertion error
86 if self.ra.search(line) != None:
87 if raise_on_error:
88 raise TestError(self.name + ": " + line)
89 else:
90 return None
91 # Count stdout refresh text.
92 if self.rr.search(line) != None:
93 refresh_cnt = refresh_cnt+1
94 if refresh_cnt >= 6:
95 self.trace("Timed-out!")
96 if raise_on_error:
97 raise TestError(self.name + ": Timeout expecting pattern: " + pattern)
98 else:
99 return None # timeout
100 # Search for expected text
101 if r.search(line) != None:
102 return line
103
104 def sync_stdout(self):
105 self.trace("sync_stdout")
106 self.send("echo 1")
107 self.expect("echo 1")
108
109 def wait(self):
110 self.trace("wait")
111 self.proc.wait()
112 def trace(self, s):
113 if self.trace_enabled:
114 print self.name + ": " + "====== " + s + " ======"
115
116#########################
117# Error handling
118def handle_error(errmsg, t):
119 print "====== Caught error: " + errmsg + " ======"
120 time.sleep(1)
121 for p in t.process:
122 p.send("q")
123 p.send("q")
124 p.expect(const.DESTROYED, False)
125 p.wait()
126 print "Test completed with error: " + errmsg
127 sys.exit(1)
128
129
130#########################
131# MAIN
132
133if len(sys.argv)!=3:
134 print "Usage: run.py MODULE CONFIG"
135 print "Sample:"
136 print " run.py mod_run.py scripts-run/100_simple.py"
137 sys.exit(1)
138
139
140# Import the test script
141script = imp.load_source("script", sys.argv[1])
142
Benny Prijonof9bd1f22008-06-16 13:04:44 +0000143# Init random seed
144random.seed()
145
Benny Prijonocc1ada52008-06-15 19:43:43 +0000146# Validate
147if script.test == None:
148 print "Error: no test defined"
149 sys.exit(1)
150
151if len(script.test.inst_params) == 0:
152 print "Error: test doesn't contain pjsua run descriptions"
153 sys.exit(1)
154
155# Instantiate pjsuas
156print "====== Running " + script.test.title + " ======"
Benny Prijonof9bd1f22008-06-16 13:04:44 +0000157print "Using " + G_EXE + " as pjsua executable"
158
Benny Prijonocc1ada52008-06-15 19:43:43 +0000159for inst_param in script.test.inst_params:
160 try:
161 # Create pjsua's Expect instance from the param
162 p = Expect(inst_param)
163 # Wait until registration completes
164 if inst_param.have_reg:
165 p.expect(inst_param.uri+".*registration success")
166 # Synchronize stdout
167 p.send("")
168 p.expect(const.PROMPT)
169 p.send("echo 1")
170 p.send("echo 1")
171 p.expect("echo 1")
172 # add running instance
173 script.test.process.append(p)
174
175 except TestError, e:
176 handle_error(e.desc, script.test)
177
178# Run the test function
179if script.test.test_func != None:
180 try:
181 script.test.test_func(script.test)
182 except TestError, e:
183 handle_error(e.desc, script.test)
184
185# Shutdown all instances
186time.sleep(2)
187for p in script.test.process:
188 # Unregister if we have_reg to make sure that next tests
189 # won't wail
190 if p.inst_param.have_reg:
191 p.send("ru")
192 p.expect(p.inst_param.uri+".*unregistration success")
193 p.send("q")
194 p.send("q")
195 time.sleep(0.5)
196 p.expect(const.DESTROYED, False)
197 p.wait()
198
199# Done
200print "Test " + script.test.title + " completed successfully"
201sys.exit(0)
202