~noskcaj/ubuntu/saucy/sflphone/merge-1.2.3-2

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject/tests/pjsua/run.py

  • Committer: Jackson Doak
  • Date: 2013-07-10 21:04:46 UTC
  • mfrom: (20.1.3 sid)
  • Revision ID: noskcaj@ubuntu.com-20130710210446-y8f587vza807icr9
Properly merged from upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# $Id: run.py 3475 2011-03-23 03:48:13Z bennylp $
2
 
import sys
3
 
import imp
4
 
import re
5
 
import os
6
 
import subprocess
7
 
import random
8
 
import time
9
 
import getopt
10
 
 
11
 
import inc_const as const
12
 
import inc_cfg as inc
13
 
 
14
 
# Vars
15
 
G_EXE = ""              # pjsua executable path
16
 
G_INUNIX = False        # flags that test is running in Unix
17
 
 
18
 
 
19
 
# Usage string
20
 
usage = \
21
 
"""
22
 
run.py - Automated test driver
23
 
 
24
 
Usage:
25
 
        run.py [options] MODULE CONFIG
26
 
Options:
27
 
        --exe, -e               pjsua executable path
28
 
        --null-audio, -n        use null audio
29
 
Sample:
30
 
        run.py -n mod_run.py scripts-run/100_simple.py
31
 
"""
32
 
 
33
 
# Parse arguments
34
 
try:
35
 
    opts, args = getopt.getopt(sys.argv[1:], "hne:", ["help", "null-audio", "exe="])
36
 
except getopt.GetoptError, err:
37
 
    print str(err)
38
 
    print usage
39
 
    sys.exit(2)
40
 
for 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
 
 
52
 
if len(args) != 2:
53
 
        print "Invalid arguments"
54
 
        print usage
55
 
        sys.exit(2)
56
 
 
57
 
# Set global ARGS to be used by modules
58
 
inc.ARGS = args
59
 
 
60
 
# Get the pjsua executable name
61
 
if G_EXE == "":
62
 
        if sys.platform.find("win32")!=-1:
63
 
            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
 
 
82
 
            if G_EXE=="":
83
 
                print "Unable to find valid pjsua. Please build pjsip first"
84
 
                sys.exit(1)
85
 
                
86
 
            G_INUNIX = False
87
 
        else:
88
 
            f = open("../../build.mak", "r")
89
 
            while True:
90
 
                line = f.readline()
91
 
                if not line:
92
 
                    break
93
 
                if line.find("TARGET_NAME")!=-1:
94
 
                    print line
95
 
                    G_EXE="../../pjsip-apps/bin/pjsua-" + line.split(":= ")[1]
96
 
                    break
97
 
            if G_EXE=="":
98
 
                print "Unable to find ../../../build.mak. Please build pjsip first"
99
 
                sys.exit(1)
100
 
            G_INUNIX = True
101
 
else:
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
106
 
 
107
 
 
108
 
G_EXE = G_EXE.rstrip("\n\r \t")
109
 
 
110
 
###################################
111
 
# Poor man's 'expect'-like class
112
 
class 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)
121
 
        t0 = time.time()
122
 
        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
127
 
                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"
130
 
                self.trace("Popen " + fullcmd)
131
 
                self.proc = subprocess.Popen(fullcmd, shell=G_INUNIX, bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=False)
132
 
        def send(self, cmd):
133
 
                self.trace("send " + cmd)
134
 
                self.proc.stdin.writelines(cmd + "\n")
135
 
                self.proc.stdin.flush()
136
 
        def expect(self, pattern, raise_on_error=True, title=""):
137
 
                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 == "":
143
 
                                raise inc.TestError(self.name + ": Premature EOF")
144
 
                        # 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:
150
 
                                        raise inc.TestError(self.name + ": " + line)
151
 
                                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:
159
 
                                                raise inc.TestError(self.name + " " + title + ": Timeout expecting pattern: \"" + pattern + "\"")
160
 
                                        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")
168
 
                cmd = "echo 1" + str(random.randint(1000,9999))
169
 
                self.send(cmd)
170
 
                self.expect(cmd)
171
 
 
172
 
        def wait(self):
173
 
                self.trace("wait")
174
 
                self.proc.communicate()
175
 
 
176
 
        def trace(self, s):
177
 
                if self.trace_enabled:
178
 
                        now = time.time()
179
 
                        fmt = self.name + ": " + "================== " + s + " ==================" + " [at t=%(time)03d]"
180
 
                        print fmt % {'time':int(now - self.t0)}
181
 
 
182
 
#########################
183
 
# Error handling
184
 
def handle_error(errmsg, t, close_processes = True):
185
 
        print "====== Caught error: " + errmsg + " ======"
186
 
        if (close_processes):
187
 
                time.sleep(1)
188
 
                for p in t.process:
189
 
                        # Protect against 'Broken pipe' exception
190
 
                        try:
191
 
                                p.send("q")
192
 
                                p.send("q")
193
 
                        except:
194
 
                                pass
195
 
                        is_err = False
196
 
                        try:
197
 
                                ret = p.expect(const.DESTROYED, False)
198
 
                                if not ret:
199
 
                                        is_err = True
200
 
                        except:
201
 
                                is_err = True
202
 
                        if is_err:
203
 
                                if sys.hexversion >= 0x02060000:
204
 
                                        p.proc.terminate()
205
 
                                else:
206
 
                                        p.wait()
207
 
                        else:
208
 
                                p.wait()
209
 
        print "Test completed with error: " + errmsg
210
 
        sys.exit(1)
211
 
 
212
 
 
213
 
#########################
214
 
# MAIN  
215
 
 
216
 
# Import the test script
217
 
script = imp.load_source("script", inc.ARGS[0])  
218
 
 
219
 
# Init random seed
220
 
random.seed()
221
 
 
222
 
# Validate
223
 
if script.test == None:
224
 
        print "Error: no test defined"
225
 
        sys.exit(1)
226
 
 
227
 
if script.test.skip:
228
 
        print "Test " + script.test.title + " is skipped"
229
 
        sys.exit(0)
230
 
 
231
 
if len(script.test.inst_params) == 0:
232
 
        print "Error: test doesn't contain pjsua run descriptions"
233
 
        sys.exit(1)
234
 
 
235
 
# Instantiate pjsuas
236
 
print "====== Running " + script.test.title + " ======"
237
 
print "Using " + G_EXE + " as pjsua executable"
238
 
 
239
 
for inst_param in script.test.inst_params:
240
 
        try:
241
 
                # Create pjsua's Expect instance from the param
242
 
                p = Expect(inst_param)
243
 
                # Wait until registration completes
244
 
                if inst_param.have_reg:
245
 
                        p.expect(inst_param.uri+".*registration success")
246
 
                # Synchronize stdout
247
 
                p.send("")
248
 
                p.expect(const.PROMPT)
249
 
                p.send("echo 1")
250
 
                p.send("echo 1")
251
 
                p.expect("echo 1")
252
 
                # add running instance
253
 
                script.test.process.append(p)
254
 
 
255
 
        except inc.TestError, e:
256
 
                handle_error(e.desc, script.test)
257
 
 
258
 
# Run the test function
259
 
if script.test.test_func != None:
260
 
        try:
261
 
                script.test.test_func(script.test)
262
 
        except inc.TestError, e:
263
 
                handle_error(e.desc, script.test)
264
 
 
265
 
# Shutdown all instances
266
 
time.sleep(2)
267
 
for p in script.test.process:
268
 
        # Unregister if we have_reg to make sure that next tests
269
 
        # won't wail
270
 
        if p.inst_param.have_reg:
271
 
                p.send("ru")
272
 
                p.expect(p.inst_param.uri+".*unregistration success")
273
 
        p.send("q")
274
 
        p.send("q")
275
 
        time.sleep(0.5)
276
 
        p.expect(const.DESTROYED, False)
277
 
        p.wait()
278
 
 
279
 
# Run the post test function
280
 
if script.test.post_func != None:
281
 
        try:
282
 
                script.test.post_func(script.test)
283
 
        except inc.TestError, e:
284
 
                handle_error(e.desc, script.test, False)
285
 
 
286
 
# Done
287
 
print "Test " + script.test.title + " completed successfully"
288
 
sys.exit(0)
289