2
# builder.py - PJSIP test scenarios builder
4
# Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31
The Operation class describes the individual ccdash operation to be
36
UPDATE = "update" # Update operation
37
CONFIGURE = "configure" # Configure operation
38
BUILD = "build" # Build operation
39
TEST = "test" # Unit test operation
41
def __init__(self, type, cmdline, name="", wdir=""):
43
self.cmdline = cmdline
46
if self.type==self.TEST and not self.name:
47
raise "name required for tests"
49
def encode(self, base_dir):
51
if self.type == self.TEST:
53
if self.type != self.UPDATE:
54
s.append(self.cmdline)
57
s.append(base_dir + "/" + self.wdir)
66
update_ops = [Operation(Operation.UPDATE, "")]
69
# The standard library tests (e.g. pjlib-test, pjsip-test, etc.)
72
Operation(Operation.TEST, "./pjlib-test$SUFFIX", name="pjlib test",
74
Operation(Operation.TEST, "./pjlib-util-test$SUFFIX",
75
name="pjlib-util test", wdir="pjlib-util/bin"),
76
Operation(Operation.TEST, "./pjnath-test$SUFFIX", name="pjnath test",
78
Operation(Operation.TEST, "./pjmedia-test$SUFFIX", name="pjmedia test",
80
Operation(Operation.TEST, "./pjsip-test$SUFFIX", name="pjsip test",
85
# These are pjsua Python based unit test operations
87
def build_pjsua_test_ops(pjsua_exe=""):
90
exe = " -e ../../pjsip-apps/bin/" + pjsua_exe
95
os.system("python runall.py --list > list")
99
(mod,param) = e.split(None,2)
100
name = mod[4:mod.find(".py")] + "_" + \
101
param[param.find("/")+1:param.find(".py")]
102
ops.append(Operation(Operation.TEST, "python run.py" + exe + " " + \
103
e, name=name, wdir="tests/pjsua"))
112
def gcc_version(gcc):
113
proc = subprocess.Popen(gcc + " -v", stdout=subprocess.PIPE,
114
stderr=subprocess.STDOUT, shell=True)
117
s = proc.stdout.readline()
120
if s.find("gcc version") >= 0:
121
ver = s.split(None, 3)[2]
127
# Get Visual Studio version
129
def vs_get_version():
130
proc = subprocess.Popen("cl", stdout=subprocess.PIPE,
131
stderr=subprocess.STDOUT)
133
s = proc.stdout.readline()
136
pos = s.find("Version")
140
ver = s.split(None, 1)[0]
160
def __init__(self, base_dir, url, site, group, options=None):
161
self.base_dir = base_dir
165
self.options = options
168
# Base class for test configurator
171
def __init__(self, config, build_config_name="",
172
user_mak="", config_site="", exclude=[], not_exclude=[]):
173
self.config = config # BaseConfig instance
174
self.build_config_name = build_config_name # Optional build suffix
175
self.user_mak = user_mak # To be put in user.mak
176
self.config_site = config_site # To be put in config_s..
177
self.saved_user_mak = "" # To restore user.mak
178
self.saved_config_site = "" # To restore config_s..
179
self.exclude = exclude # List of exclude pattern
180
self.not_exclude = not_exclude # List of include pattern
181
self.ccdash_args = [] # ccdash cmd line
184
return time.strftime("%Y%m%d-%H%M", time.localtime())
186
def pre_action(self):
188
name = self.config.base_dir + "/user.mak"
189
if os.access(name, os.F_OK):
191
self.saved_user_mak = f.read()
195
f.write(self.user_mak)
197
# Override config_site.h
198
name = self.config.base_dir + "/pjlib/include/pj/config_site.h"
199
if os.access(name, os.F_OK):
201
self.saved_config_site= f.read()
205
f.write(self.config_site)
209
def post_action(self):
211
name = self.config.base_dir + "/user.mak"
213
f.write(self.saved_user_mak)
215
# Restore config_site.h
216
name = self.config.base_dir + "/pjlib/include/pj/config_site.h"
218
f.write(self.saved_config_site)
221
def build_tests(self):
222
# This should be overridden by subclasses
226
if len(self.ccdash_args)==0:
229
mandatory_op = ["update", "configure", "build"]
231
for a in self.ccdash_args:
232
# Check if this test is in exclusion list
233
fullcmd = " ".join(a)
236
for pat in self.exclude:
237
if pat and re.search(pat, fullcmd) != None:
241
for pat in self.not_exclude:
242
if pat and re.search(pat, fullcmd) != None:
245
if excluded and not included:
247
fullcmd = fullcmd[0:60] + ".."
248
print "Skipping '%s'" % (fullcmd)
259
print "**** Error: ccdash got exception %s ****" % errmsg
262
print "**** Error: ccdash got unknown exception ****"
265
if rc!=0 and a[1] in mandatory_op:
266
print "Stopping because of error.."
268
counter = counter + 1
273
# GNU test configurator
275
class GNUTestBuilder(TestBuilder):
277
This class creates list of tests suitable for GNU targets.
280
def __init__(self, config, build_config_name="", user_mak="", \
281
config_site="", cross_compile="", exclude=[], not_exclude=[]):
284
config - BaseConfig instance
285
build_config_name - Optional name to be added as suffix to the build
286
name. Sample: "min-size", "O4", "TLS", etc.
287
user_mak - Contents to be put on user.mak
288
config_site - Contents to be put on config_site.h
289
cross_compile - Optional cross-compile prefix. Must include the
290
trailing dash, e.g. "arm-unknown-linux-"
291
exclude - List of regular expression patterns for tests
292
that will be excluded from the run
293
not_exclude - List of regular expression patterns for tests
294
that will be run regardless of whether they
295
match the excluded pattern.
298
TestBuilder.__init__(self, config, build_config_name=build_config_name,
299
user_mak=user_mak, config_site=config_site,
300
exclude=exclude, not_exclude=not_exclude)
301
self.cross_compile = cross_compile
302
if self.cross_compile and self.cross_compile[-1] != '-':
303
self.cross_compile.append("-")
305
def build_tests(self):
306
if self.cross_compile:
307
suffix = "-" + self.cross_compile[0:-1]
308
build_name = self.cross_compile + \
309
gcc_version(self.cross_compile + "gcc")
311
proc = subprocess.Popen("sh "+self.config.base_dir+"/config.guess",
312
shell=True, stdout=subprocess.PIPE)
313
plat = proc.stdout.readline().rstrip(" \r\n")
314
build_name = plat + "-"+gcc_version(self.cross_compile + "gcc")
317
if self.build_config_name:
318
build_name = build_name + "-" + self.build_config_name
320
cmds.extend(update_ops)
321
cmds.append(Operation(Operation.CONFIGURE, "sh ./configure"))
322
if sys.platform=="win32":
323
# Don't build python module on Mingw
324
cmds.append(Operation(Operation.BUILD,
325
"sh -c 'make distclean && make dep && make'"))
327
cmds.append(Operation(Operation.BUILD,
328
"sh -c 'make distclean && make dep && make" + \
329
" && cd pjsip-apps/src/python && " + \
330
"python setup.py clean build'"))
332
cmds.extend(std_test_ops)
333
cmds.extend(build_pjsua_test_ops())
334
self.ccdash_args = []
336
c.cmdline = c.cmdline.replace("$SUFFIX", suffix)
337
args = c.encode(self.config.base_dir)
338
args.extend(["-U", self.config.url,
339
"-S", self.config.site,
342
"-G", self.config.group])
343
args.extend(self.config.options)
344
self.ccdash_args.append(args)
347
# MSVC test configurator
349
class MSVCTestBuilder(TestBuilder):
351
This class creates list of tests suitable for Visual Studio builds.
352
You need to set the MSVC environment variables (typically by calling
353
vcvars32.bat) prior to running this class.
356
def __init__(self, config, target="Release|Win32", build_config_name="",
357
config_site="", exclude=[], not_exclude=[]):
360
config - BaseConfig instance
361
target - Visual Studio build configuration to build.
362
Sample: "Debug|Win32", "Release|Win32".
363
build_config_name - Optional name to be added as suffix to the build
364
name. Sample: "Debug", "Release", "IPv6", etc.
365
config_site - Contents to be put on config_site.h
366
exclude - List of regular expression patterns for tests
367
that will be excluded from the run
368
not_exclude - List of regular expression patterns for tests
369
that will be run regardless of whether they
370
match the excluded pattern.
373
TestBuilder.__init__(self, config, build_config_name=build_config_name,
374
config_site=config_site, exclude=exclude,
375
not_exclude=not_exclude)
376
self.target = target.lower()
378
def build_tests(self):
380
(vsbuild,sys) = self.target.split("|",2)
382
build_name = sys + "-" + vs_get_version() + "-" + vsbuild
384
if self.build_config_name:
385
build_name = build_name + "-" + self.build_config_name
387
vccmd = "vcbuild.exe /nologo /nohtmllog /nocolor /rebuild " + \
388
"pjproject-vs8.sln " + " \"" + self.target + "\""
390
suffix = "-i386-win32-vc8-" + vsbuild
396
cmds.extend(update_ops)
397
cmds.append(Operation(Operation.CONFIGURE, "CMD /C echo Nothing to do"))
398
cmds.append(Operation(Operation.BUILD, vccmd))
399
cmds.extend(std_test_ops)
400
cmds.extend(build_pjsua_test_ops(pjsua))
402
self.ccdash_args = []
404
c.cmdline = c.cmdline.replace("$SUFFIX", suffix)
405
args = c.encode(self.config.base_dir)
406
args.extend(["-U", self.config.url,
407
"-S", self.config.site,
410
"-G", self.config.group])
411
args.extend(self.config.options)
412
self.ccdash_args.append(args)
416
# Symbian test configurator
418
class SymbianTestBuilder(TestBuilder):
420
This class creates list of tests suitable for Symbian builds. You need to
421
set the command line build settings prior to running this class (typically
422
that involves setting the EPOCROOT variable and current device).
425
def __init__(self, config, target="gcce urel", build_config_name="",
426
config_site="", exclude=[], not_exclude=[]):
429
config - BaseConfig instance
430
target - Symbian target to build. Default is "gcce urel".
431
build_config_name - Optional name to be added as suffix to the build
432
name. Sample: "APS", "VAS", etc.
433
config_site - Contents to be put on config_site.h
434
exclude - List of regular expression patterns for tests
435
that will be excluded from the run
436
not_exclude - List of regular expression patterns for tests
437
that will be run regardless of whether they
438
match the excluded pattern.
441
TestBuilder.__init__(self, config, build_config_name=build_config_name,
442
config_site=config_site, exclude=exclude,
443
not_exclude=not_exclude)
444
self.target = target.lower()
446
def build_tests(self):
448
# Check that EPOCROOT is set
449
if not "EPOCROOT" in os.environ:
450
print "Error: EPOCROOT environment variable is not set"
452
epocroot = os.environ["EPOCROOT"]
453
# EPOCROOT must have trailing backslash
454
if epocroot[-1] != "\\":
455
epocroot = epocroot + "\\"
456
os.environ["EPOCROOT"] = epocroot
457
sdk1 = epocroot.split("\\")[-2]
459
# Check that correct device is set
460
proc = subprocess.Popen("devices", stdout=subprocess.PIPE,
461
stderr=subprocess.STDOUT, shell=True)
464
line = proc.stdout.readline()
465
if line.find("- default") > 0:
466
sdk2 = line.split(":",1)[0]
471
print "Error: default SDK in device doesn't match EPOCROOT"
472
print "Default device SDK =", sdk2
473
print "EPOCROOT SDK =", sdk1
476
build_name = sdk2.replace("_", "-") + "-" + \
477
self.target.replace(" ", "-")
479
if self.build_config_name:
480
build_name = build_name + "-" + self.build_config_name
482
cmdline = "cmd /C \"cd build.symbian && bldmake bldfiles && abld build %s\"" % (self.target)
485
cmds.extend(update_ops)
486
cmds.append(Operation(Operation.CONFIGURE, "CMD /C echo Nothing to do"))
487
cmds.extend([Operation(Operation.BUILD, cmdline)])
489
self.ccdash_args = []
492
c.cmdline = c.cmdline.replace("$SUFFIX", suffix)
493
args = c.encode(self.config.base_dir)
494
args.extend(["-U", self.config.url,
495
"-S", self.config.site,
498
"-G", self.config.group])
499
args.extend(self.config.options)
500
self.ccdash_args.append(args)