591
|
1 |
#
|
|
2 |
# Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
|
|
3 |
# All rights reserved.
|
|
4 |
# This component and the accompanying materials are made available
|
|
5 |
# under the terms of the License "Eclipse Public License v1.0"
|
|
6 |
# which accompanies this distribution, and is available
|
|
7 |
# at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
8 |
#
|
|
9 |
# Initial Contributors:
|
|
10 |
# Nokia Corporation - initial contribution.
|
|
11 |
#
|
|
12 |
# Contributors:
|
|
13 |
#
|
|
14 |
# Description:
|
|
15 |
#
|
|
16 |
|
|
17 |
# run the smoke tests
|
|
18 |
|
|
19 |
import os
|
|
20 |
import re
|
|
21 |
import stat
|
|
22 |
import sys
|
|
23 |
import subprocess
|
|
24 |
import traceback
|
|
25 |
from shutil import rmtree
|
|
26 |
|
|
27 |
sys.path.append(os.environ["SBS_HOME"]+"/python")
|
|
28 |
from raptor_meta import BldInfFile
|
|
29 |
|
|
30 |
logDir = "$(EPOCROOT)/epoc32/build/smoketestlogs"
|
|
31 |
|
|
32 |
debug_mode_active = False
|
|
33 |
|
|
34 |
# Environment #################################################################
|
|
35 |
|
|
36 |
# On MYS there is USERNAME but not USER
|
|
37 |
if 'USER' not in os.environ:
|
|
38 |
os.environ['USER'] = os.environ['USERNAME']
|
|
39 |
|
|
40 |
def activate_debug():
|
|
41 |
"""
|
|
42 |
Activate debug-mode remotely
|
|
43 |
"""
|
|
44 |
global debug_mode_active
|
|
45 |
debug_mode_active = True
|
|
46 |
|
|
47 |
# Determine the OS version in the epocroot we're testing
|
|
48 |
# since some tests expect different outcomes for 9.4 and 9.5
|
|
49 |
def getsymbianversion():
|
|
50 |
epocroot = os.environ['EPOCROOT']
|
|
51 |
b = open (epocroot+"/epoc32/data/buildinfo.txt","r")
|
|
52 |
binfo = " ".join(b.readlines())
|
|
53 |
vmatch = (re.compile("v(9\.[0-9])")).search(binfo)
|
|
54 |
if vmatch:
|
|
55 |
osversion = vmatch.group(1)
|
|
56 |
else:
|
|
57 |
osversion = '9.4'
|
|
58 |
return osversion
|
|
59 |
|
|
60 |
envRegex = re.compile("\$\((.+?)\)")
|
|
61 |
fixEnvironment = ['EPOCROOT', 'SBS_HOME', 'SBS_CYGWIN', 'SBS_MINGW', 'SBS_PYTHON']
|
|
62 |
|
|
63 |
def ReplaceEnvs(item):
|
|
64 |
|
|
65 |
envs = envRegex.findall(item)
|
|
66 |
|
|
67 |
for e in set(envs):
|
|
68 |
try:
|
|
69 |
val = os.environ[e]
|
|
70 |
if e in fixEnvironment:
|
|
71 |
# Raptor "fixes up" EPOCROOT etc. so we must do the same:
|
|
72 |
# add the drive letter (make absolute)
|
|
73 |
val = os.path.abspath(val)
|
|
74 |
# use forward slashes
|
|
75 |
val = val.replace("\\", "/")
|
|
76 |
# remove trailing slashes
|
|
77 |
val = val.rstrip("/")
|
|
78 |
item = item.replace("$(" + e + ")", val)
|
|
79 |
except KeyError:
|
|
80 |
print e, "is not set in the environment"
|
|
81 |
raise ValueError
|
|
82 |
|
|
83 |
return item
|
|
84 |
|
|
85 |
# Utility functions ###########################################################
|
|
86 |
|
|
87 |
|
|
88 |
|
|
89 |
def where(input_file):
|
|
90 |
"""Search for 'input_file' in the system path"""
|
|
91 |
locations = []
|
|
92 |
if sys.platform.startswith("win"):
|
|
93 |
if not input_file.lower().endswith(".exe"):
|
|
94 |
input_file += ".exe"
|
|
95 |
for current_file in [loop_number + "\\" + input_file for loop_number in
|
|
96 |
os.environ["PATH"].split(";")]:
|
|
97 |
try:
|
|
98 |
stat = os.stat(current_file)
|
|
99 |
locations.append(current_file)
|
|
100 |
except OSError, error:
|
|
101 |
pass
|
|
102 |
else:
|
|
103 |
whichproc = subprocess.Popen(args=["which", input_file],
|
|
104 |
stdout=subprocess.PIPE,
|
|
105 |
stderr=subprocess.STDOUT,
|
|
106 |
shell=False,
|
|
107 |
universal_newlines=True)
|
|
108 |
output = whichproc.stdout.readlines()
|
|
109 |
whichproc.wait()
|
|
110 |
|
|
111 |
if len(output) > 0:
|
|
112 |
locations.append(output[0:(len(output) - 1)])
|
|
113 |
|
|
114 |
if len(locations) == 0:
|
|
115 |
print "Error: " + input_file + " not defined in PATH environment variable"
|
|
116 |
else:
|
|
117 |
return locations[0]
|
|
118 |
|
|
119 |
def clean_epocroot():
|
|
120 |
"""
|
|
121 |
This method walks through epocroot and cleans every file and folder that is
|
|
122 |
not present in the manifest file
|
|
123 |
"""
|
|
124 |
epocroot = os.path.abspath(os.environ['EPOCROOT']).replace('\\','/')
|
|
125 |
print "Cleaning Epocroot: %s" % epocroot
|
|
126 |
all_files = {} # dictionary to hold all files
|
|
127 |
folders = [] # holds all unique folders in manifest
|
|
128 |
host_platform = os.environ["HOSTPLATFORM_DIR"]
|
|
129 |
try:
|
|
130 |
mani = "$(EPOCROOT)/manifest"
|
|
131 |
manifest = open(ReplaceEnvs(mani), "r")
|
|
132 |
le = len(epocroot)
|
|
133 |
for line in manifest:
|
|
134 |
line = line.replace("$(HOSTPLATFORM_DIR)", host_platform)
|
|
135 |
line = line.replace("./", epocroot+"/").rstrip("\n")
|
|
136 |
all_files[line] = True
|
|
137 |
# This bit makes a record of unique folders into a list
|
|
138 |
pos = line.rfind("/", le)
|
|
139 |
while pos > le: # Look through the parent folders
|
|
140 |
f = line[:pos]
|
|
141 |
if f not in folders:
|
|
142 |
folders.append(f)
|
|
143 |
pos = line.rfind("/", le, pos)
|
|
144 |
|
|
145 |
|
|
146 |
# This algorithm walks through epocroot and handles files and folders
|
|
147 |
walkpath = "$(EPOCROOT)"
|
|
148 |
for (root, dirs, files) in os.walk(ReplaceEnvs(walkpath), topdown =
|
|
149 |
False):
|
|
150 |
if root.find(".hg") != -1:
|
|
151 |
continue
|
|
152 |
|
|
153 |
# This loop handles all files
|
|
154 |
for name in files:
|
|
155 |
name = os.path.join(root, name).replace("\\", "/")
|
|
156 |
|
|
157 |
if name not in all_files:
|
|
158 |
try:
|
|
159 |
os.remove(name)
|
|
160 |
except:
|
|
161 |
# chmod to rw and try again
|
|
162 |
try:
|
|
163 |
os.chmod(name, stat.S_IRWXU)
|
|
164 |
os.remove(name)
|
|
165 |
except:
|
|
166 |
print "\nEPOCROOT-CLEAN ERROR:"
|
|
167 |
print (sys.exc_type.__name__ + ":"), \
|
|
168 |
sys.exc_value
|
|
169 |
if sys.exc_type.__name__ != "WindowsError":
|
|
170 |
print traceback.print_tb(sys.exc_traceback)
|
|
171 |
|
|
172 |
# This loop handles folders
|
|
173 |
for name in dirs:
|
|
174 |
if name.find(".hg") != -1:
|
|
175 |
continue
|
|
176 |
|
|
177 |
name = os.path.join(root, name).replace("\\", "/")
|
|
178 |
if name not in all_files and name not in folders:
|
|
179 |
# Remove the folder fully with no errors if full
|
|
180 |
try:
|
|
181 |
rmtree(ReplaceEnvs(name))
|
|
182 |
except:
|
|
183 |
print "\nEPOCROOT-CLEAN ERROR:"
|
|
184 |
print (sys.exc_type.__name__ + ":"), \
|
|
185 |
sys.exc_value
|
|
186 |
if sys.exc_type.__name__ != "WindowsError":
|
|
187 |
print traceback.print_tb(sys.exc_traceback)
|
|
188 |
except IOError,e:
|
|
189 |
print e
|
|
190 |
|
|
191 |
print "Epocroot Cleaned"
|
|
192 |
|
|
193 |
def fix_id(input_id):
|
|
194 |
return input_id.zfill(4)
|
|
195 |
|
|
196 |
|
|
197 |
def grep(file, string):
|
|
198 |
return
|
|
199 |
|
|
200 |
|
|
201 |
# Test classes ################################################################
|
|
202 |
|
|
203 |
class SmokeTest(object):
|
|
204 |
"""Base class for Smoke Test objects.
|
|
205 |
|
|
206 |
Each test is defined (minimally) by,
|
|
207 |
1) an ID number as a string
|
|
208 |
2) a name
|
|
209 |
3) a raptor command-line
|
|
210 |
4) some parameters to check the command results against
|
|
211 |
|
|
212 |
The run() method will,
|
|
213 |
1) delete all the listed target files
|
|
214 |
2) execute the raptor command
|
|
215 |
3) check that the test results match the test parameters
|
|
216 |
4) count the warnings and errors reported
|
|
217 |
"""
|
|
218 |
|
|
219 |
PASS = "pass"
|
|
220 |
FAIL = "fail"
|
|
221 |
SKIP = "skip"
|
|
222 |
|
|
223 |
def __init__(self):
|
|
224 |
|
|
225 |
self.id = "0"
|
|
226 |
self.name = "smoketest"
|
|
227 |
self.description = ""
|
|
228 |
self.command = "sbs --do_what_i_want"
|
|
229 |
self.targets = []
|
|
230 |
self.missing = 0
|
|
231 |
self.warnings = 0
|
|
232 |
self.errors = 0
|
|
233 |
self.exceptions = 0
|
|
234 |
self.returncode = 0
|
|
235 |
|
|
236 |
self.onWindows = sys.platform.startswith("win")
|
|
237 |
|
|
238 |
# These variables are for tests that treat the text as a list of lines. In
|
|
239 |
# particular, "." will not match end-of-line. This means that, for example,
|
|
240 |
# "abc.*def" will only match if "abc" and "def" appear on the same line.
|
|
241 |
self.mustmatch = []
|
|
242 |
self.mustnotmatch = []
|
|
243 |
self.mustmatch_singleline = []
|
|
244 |
self.mustnotmatch_singleline = []
|
|
245 |
|
|
246 |
# These variables are for tests that treat the text as a single string of
|
|
247 |
# characters. The pattern "." will match anything, including end-of-line.
|
|
248 |
self.mustmatch_multiline = []
|
|
249 |
self.mustnotmatch_multiline = []
|
|
250 |
|
|
251 |
self.countmatch = []
|
|
252 |
|
|
253 |
self.outputok = True
|
|
254 |
self.usebash = False
|
|
255 |
self.failsbecause = None
|
|
256 |
self.result = SmokeTest.SKIP
|
|
257 |
self.environ = {} # Allow tests to set the environment in which commands run.
|
|
258 |
self.sbs_build_dir = "$(EPOCROOT)/epoc32/build"
|
|
259 |
|
|
260 |
def run(self, platform = "all"):
|
|
261 |
previousResult = self.result
|
|
262 |
self.id = fix_id(self.id)
|
|
263 |
try:
|
|
264 |
if self.runnable(platform):
|
|
265 |
|
|
266 |
if not self.pretest():
|
|
267 |
self.result = SmokeTest.FAIL
|
|
268 |
|
|
269 |
elif not self.test():
|
|
270 |
self.result = SmokeTest.FAIL
|
|
271 |
|
|
272 |
elif not self.posttest():
|
|
273 |
self.result = SmokeTest.FAIL
|
|
274 |
|
|
275 |
else:
|
|
276 |
self.result = SmokeTest.PASS
|
|
277 |
else:
|
|
278 |
self.skip(platform)
|
|
279 |
except Exception, e:
|
|
280 |
print e
|
|
281 |
self.result = SmokeTest.FAIL
|
|
282 |
|
|
283 |
# print the result of this run()
|
|
284 |
self.print_result(internal = True)
|
|
285 |
|
|
286 |
# if a previous run() failed then the overall result is a FAIL
|
|
287 |
if previousResult == SmokeTest.FAIL:
|
|
288 |
self.result = SmokeTest.FAIL
|
|
289 |
|
|
290 |
def print_result(self, value = "", internal = False):
|
|
291 |
# the test passed :-)
|
|
292 |
|
|
293 |
result = self.result
|
|
294 |
|
|
295 |
string = ""
|
|
296 |
if not internal:
|
|
297 |
string += "\n" + self.name + ": "
|
|
298 |
|
|
299 |
if value:
|
|
300 |
print string + value
|
|
301 |
else:
|
|
302 |
if result == SmokeTest.PASS:
|
|
303 |
string += "PASSED"
|
|
304 |
elif result == SmokeTest.FAIL:
|
|
305 |
string += "FAILED"
|
|
306 |
|
|
307 |
print string
|
|
308 |
|
|
309 |
def runnable(self, platform):
|
|
310 |
# can this test run on this platform?
|
|
311 |
if platform == "all":
|
|
312 |
return True
|
|
313 |
|
|
314 |
isWin = self.onWindows
|
|
315 |
wantWin = platform.startswith("win")
|
|
316 |
|
|
317 |
return (isWin == wantWin)
|
|
318 |
|
|
319 |
def skip(self, platform):
|
|
320 |
print "\nSKIPPING:", self.name, "for", platform
|
|
321 |
|
|
322 |
def logfileOption(self):
|
|
323 |
return "-f " + self.logfile();
|
|
324 |
|
|
325 |
def logfile(self):
|
|
326 |
return logDir + "/" + self.name + ".log"
|
|
327 |
|
|
328 |
def makefileOption(self):
|
|
329 |
return "-m " + self.makefile();
|
|
330 |
|
|
331 |
def makefile(self):
|
|
332 |
return logDir + "/" + self.name + ".mk"
|
|
333 |
|
|
334 |
def removeFiles(self, files):
|
|
335 |
for t in files:
|
|
336 |
tgt = os.path.normpath(ReplaceEnvs(t))
|
|
337 |
|
|
338 |
if os.path.exists(tgt):
|
|
339 |
try:
|
|
340 |
os.chmod(tgt, stat.S_IRWXU)
|
|
341 |
if os.path.isdir(tgt):
|
|
342 |
rmtree(tgt)
|
|
343 |
else:
|
|
344 |
os.remove(tgt)
|
|
345 |
except OSError:
|
|
346 |
print "Could not remove", tgt, "before the test"
|
|
347 |
return False
|
|
348 |
return True
|
|
349 |
|
|
350 |
|
|
351 |
def clean(self):
|
|
352 |
# remove all the target files
|
|
353 |
|
|
354 |
# flatten any lists first (only 1 level of flattenening expected)
|
|
355 |
# these indicate alternative files - one of them will exist after a build
|
|
356 |
removables = []
|
|
357 |
for i in self.targets:
|
|
358 |
if type(i) is not list:
|
|
359 |
removables.append(i)
|
|
360 |
else:
|
|
361 |
removables.extend(i)
|
|
362 |
|
|
363 |
return self.removeFiles(removables)
|
|
364 |
|
|
365 |
def pretest(self):
|
|
366 |
# what to do before the test runs
|
|
367 |
|
|
368 |
print "\nID:", self.id
|
|
369 |
print "TEST:", self.name
|
|
370 |
|
|
371 |
return self.clean()
|
|
372 |
|
|
373 |
def test(self):
|
|
374 |
# run the actual test
|
|
375 |
|
|
376 |
# put the makefile and log in $EPOCROOT/build/smoketestlogs
|
|
377 |
if self.usebash:
|
|
378 |
command = ReplaceEnvs(self.command)
|
|
379 |
else:
|
|
380 |
command = ReplaceEnvs(self.command +
|
|
381 |
" " + self.makefileOption() +
|
|
382 |
" " + self.logfileOption())
|
|
383 |
|
|
384 |
print "COMMAND:", command
|
|
385 |
|
|
386 |
|
|
387 |
# Any environment settings specific to this test
|
|
388 |
shellenv = os.environ.copy()
|
|
389 |
for ev in self.environ:
|
|
390 |
shellenv[ev] = self.environ[ev]
|
|
391 |
|
|
392 |
if self.usebash:
|
|
393 |
shellpath = shellenv['PATH']
|
|
394 |
|
|
395 |
if 'SBS_SHELL' in os.environ:
|
|
396 |
BASH = os.environ['SBS_SHELL']
|
|
397 |
else:
|
|
398 |
if self.onWindows:
|
|
399 |
if 'SBS_CYGWIN' in shellenv:
|
|
400 |
BASH = ReplaceEnvs("$(SBS_CYGWIN)/bin/bash.exe")
|
|
401 |
else:
|
|
402 |
BASH = ReplaceEnvs("$(SBS_HOME)/win32/cygwin/bin/bash.exe")
|
|
403 |
else:
|
|
404 |
BASH = ReplaceEnvs("$(SBS_HOME)/$(HOSTPLATFORM_DIR)/bin/bash")
|
|
405 |
|
|
406 |
if self.onWindows:
|
|
407 |
if 'SBS_CYGWIN' in shellenv:
|
|
408 |
shellpath = ReplaceEnvs("$(SBS_CYGWIN)/bin") + ";" + shellpath
|
|
409 |
else:
|
|
410 |
shellpath = ReplaceEnvs("$(SBS_HOME)/win32/cygwin/bin") + ";" + shellpath
|
|
411 |
|
|
412 |
shellenv['SBSMAKEFILE']=ReplaceEnvs(self.makefile())
|
|
413 |
shellenv['SBSLOGFILE']=ReplaceEnvs(self.logfile())
|
|
414 |
shellenv['PATH']=shellpath
|
|
415 |
shellenv['PYTHON_HOME'] = ""
|
|
416 |
shellenv['CYGWIN']="nontsec nosmbntsec"
|
|
417 |
|
|
418 |
p = subprocess.Popen(args=[BASH, '-c', command],
|
|
419 |
stdout=subprocess.PIPE,
|
|
420 |
stderr=subprocess.PIPE,
|
|
421 |
env=shellenv,
|
|
422 |
shell=False,
|
|
423 |
universal_newlines=True)
|
|
424 |
|
|
425 |
(std_out, std_err) = p.communicate()
|
|
426 |
|
|
427 |
self.output = std_out + std_err
|
|
428 |
else:
|
|
429 |
p = subprocess.Popen(command,
|
|
430 |
stdout=subprocess.PIPE,
|
|
431 |
stderr=subprocess.PIPE,
|
|
432 |
env=shellenv,
|
|
433 |
shell=True,
|
|
434 |
universal_newlines=True)
|
|
435 |
|
|
436 |
(std_out, std_err) = p.communicate()
|
|
437 |
|
|
438 |
self.output = std_out + std_err
|
|
439 |
|
|
440 |
if debug_mode_active:
|
|
441 |
print self.output
|
|
442 |
|
|
443 |
if p.returncode != self.returncode:
|
|
444 |
print "RETURN: got", p.returncode, "expected", self.returncode
|
|
445 |
return False
|
|
446 |
|
|
447 |
return True
|
|
448 |
|
|
449 |
def posttest(self):
|
|
450 |
# what to do after the test has run
|
|
451 |
|
|
452 |
# count the targets that got built
|
|
453 |
found = 0
|
|
454 |
missing = []
|
|
455 |
for t in self.targets:
|
|
456 |
if type(t) is not list:
|
|
457 |
target_alternatives=[t]
|
|
458 |
|
|
459 |
found_flag = False
|
|
460 |
for alt in target_alternatives:
|
|
461 |
tgt = os.path.normpath(ReplaceEnvs(alt))
|
|
462 |
if os.path.exists(tgt):
|
|
463 |
found_flag = True
|
|
464 |
break
|
|
465 |
if found_flag:
|
|
466 |
found += 1
|
|
467 |
else:
|
|
468 |
missing.append(tgt)
|
|
469 |
|
|
470 |
# count the errors and warnings
|
|
471 |
warn = 0
|
|
472 |
error = 0
|
|
473 |
exception = 0
|
|
474 |
lines = self.output.split("\n")
|
|
475 |
|
|
476 |
for line in lines:
|
|
477 |
if line.find("sbs: warning:") != -1 or line.find("<warning") != -1:
|
|
478 |
warn += 1
|
|
479 |
elif line.find("sbs: error:") != -1 or line.find("<error") != -1:
|
|
480 |
error += 1
|
|
481 |
elif line.startswith("Traceback"):
|
|
482 |
exception += 1
|
|
483 |
|
|
484 |
# Check the output for required, forbidden and counted regexp matches
|
|
485 |
self.outputok = True
|
|
486 |
|
|
487 |
for expr in self.mustmatch_singleline + self.mustmatch:
|
|
488 |
if not re.search(expr, self.output, re.MULTILINE):
|
|
489 |
self.outputok = False
|
|
490 |
print "OUTPUTMISMATCH: output did not match: %s" % expr
|
|
491 |
|
|
492 |
for expr in self.mustnotmatch_singleline + self.mustnotmatch:
|
|
493 |
if re.search(expr, self.output, re.MULTILINE):
|
|
494 |
self.outputok = False
|
|
495 |
print "OUTPUTMISMATCH: output should not have matched: %s" % expr
|
|
496 |
|
|
497 |
for expr in self.mustmatch_multiline:
|
|
498 |
if not re.search(expr, self.output, re.DOTALL):
|
|
499 |
self.outputok = False
|
|
500 |
print "OUTPUTMISMATCH: output did not match: %s" % expr
|
|
501 |
|
|
502 |
for expr in self.mustnotmatch_multiline:
|
|
503 |
if re.search(expr, self.output, re.DOTALL):
|
|
504 |
self.outputok = False
|
|
505 |
print "OUTPUTMISMATCH: output should not have matched: %s" % expr
|
|
506 |
|
|
507 |
for (expr,num) in self.countmatch:
|
|
508 |
expr_re = re.compile(expr)
|
|
509 |
matchnum = len(expr_re.findall(self.output))
|
|
510 |
if matchnum != num:
|
|
511 |
print "OUTPUTMISMATCH: %d matches occurred when %d were expected: %s" % (matchnum, num, expr)
|
|
512 |
self.outputok = False
|
|
513 |
|
|
514 |
# Ignore errors/warnings if they are set to (-1)
|
|
515 |
if self.errors == (-1):
|
|
516 |
self.errors = error
|
|
517 |
if self.warnings == (-1):
|
|
518 |
self.warnings= warn
|
|
519 |
|
|
520 |
# all as expected?
|
|
521 |
if self.missing == len(missing) \
|
|
522 |
and self.warnings == warn \
|
|
523 |
and self.errors == error \
|
|
524 |
and self.exceptions == exception \
|
|
525 |
and self.outputok:
|
|
526 |
return True
|
|
527 |
|
|
528 |
# something was wrong :-(
|
|
529 |
|
|
530 |
if len(missing) != self.missing:
|
|
531 |
print "MISSING: %d, expected %s" % (len(missing), self.missing)
|
|
532 |
for file in missing:
|
|
533 |
print "\t%s" % (file)
|
|
534 |
|
|
535 |
if warn != self.warnings:
|
|
536 |
print "WARNINGS: %d, expected %d" % (warn, self.warnings)
|
|
537 |
|
|
538 |
if error != self.errors:
|
|
539 |
print "ERRORS: %d, expected %d" % ( error, self.errors)
|
|
540 |
|
|
541 |
if exception != self.exceptions:
|
|
542 |
print "EXCEPTIONS: %d, expected %d" % (exception, self.exceptions)
|
|
543 |
|
|
544 |
return False
|
|
545 |
|
|
546 |
def addbuildtargets(self, bldinfsourcepath, targetsuffixes):
|
|
547 |
"""Add targets that are under epoc32/build whose path
|
|
548 |
can change based on an md5 hash of the path to the bld.inf.
|
|
549 |
"""
|
|
550 |
|
|
551 |
fragment = BldInfFile.outputPathFragment(bldinfsourcepath)
|
|
552 |
|
|
553 |
for t in targetsuffixes:
|
|
554 |
if type(t) is not list:
|
|
555 |
newt=self.sbs_build_dir+'/'+fragment+"/"+t
|
|
556 |
self.targets.append(newt)
|
|
557 |
else:
|
|
558 |
self.targets.append([self.sbs_build_dir+'/'+fragment+"/"+x for x in t])
|
|
559 |
return
|
|
560 |
|
|
561 |
# derived class for tests that invoke some process, which have no log file and no makefile
|
|
562 |
# e.g. unit tests
|
|
563 |
|
|
564 |
class GenericSmokeTest(SmokeTest):
|
|
565 |
|
|
566 |
def __init__(self):
|
|
567 |
SmokeTest.__init__(self)
|
|
568 |
|
|
569 |
def logfileOption(self):
|
|
570 |
return ""
|
|
571 |
|
|
572 |
def makefileOption(self):
|
|
573 |
return ""
|
|
574 |
|
|
575 |
def posttest(self):
|
|
576 |
# dump the standard output to a log file
|
|
577 |
dir = ReplaceEnvs(logDir)
|
|
578 |
logfile = os.path.join(dir, self.name + ".log")
|
|
579 |
try:
|
|
580 |
if not os.path.exists(dir):
|
|
581 |
os.makedirs(dir)
|
|
582 |
file = open(logfile, "w")
|
|
583 |
file.write(self.output)
|
|
584 |
file.close()
|
|
585 |
except:
|
|
586 |
print "Could not save stdout in", logfile
|
|
587 |
return False
|
|
588 |
|
|
589 |
# do the base class things too
|
|
590 |
return SmokeTest.posttest(self)
|
|
591 |
|
|
592 |
# derived class for --check, --what and .whatlog tests - these all write to stdout, but may
|
|
593 |
# not actually build anything
|
|
594 |
|
|
595 |
class CheckWhatSmokeTest(SmokeTest):
|
|
596 |
|
|
597 |
def __init__(self):
|
|
598 |
SmokeTest.__init__(self)
|
|
599 |
|
|
600 |
# regular expression match object to restrict comparisons to specific lines
|
|
601 |
self.regexlinefilter = None
|
|
602 |
|
|
603 |
# paths in --what output are tailored to the host OS, hence slashes are converted appropriately
|
|
604 |
# .whatlog output is used verbatim from the build/TEM/EM output
|
|
605 |
self.hostossensitive = True
|
|
606 |
|
|
607 |
# Indicate whether output is expected to appear only once. If so, set it to True
|
|
608 |
self.output_expected_only_once = False
|
|
609 |
|
|
610 |
def posttest(self):
|
|
611 |
outlines = self.output.splitlines()
|
|
612 |
if self.output_expected_only_once:
|
|
613 |
outlines_left = list(outlines)
|
|
614 |
|
|
615 |
ok = True
|
|
616 |
seen = []
|
|
617 |
|
|
618 |
# check for lines that we expected to see, optionally filtered
|
|
619 |
for line in self.stdout:
|
|
620 |
if self.regexlinefilter and not self.regexlinefilter.match(line):
|
|
621 |
continue
|
|
622 |
line = ReplaceEnvs(line)
|
|
623 |
if self.hostossensitive and self.onWindows:
|
|
624 |
line = line.replace("/", "\\")
|
|
625 |
|
|
626 |
if line in outlines:
|
|
627 |
seen.append(line)
|
|
628 |
if self.output_expected_only_once:
|
|
629 |
outlines_left.remove(line)
|
|
630 |
else:
|
|
631 |
print "OUTPUT NOT FOUND:", line
|
|
632 |
ok = False
|
|
633 |
|
|
634 |
# and check for extra lines that we didn't expect, optionally filtered
|
|
635 |
for line in outlines:
|
|
636 |
if self.regexlinefilter and not self.regexlinefilter.match(line):
|
|
637 |
continue
|
|
638 |
if not line in seen:
|
|
639 |
print "UNEXPECTED OUTPUT:", line
|
|
640 |
ok = False
|
|
641 |
|
|
642 |
# and check for lines that we expected to see only once
|
|
643 |
if self.output_expected_only_once:
|
|
644 |
for line in outlines_left:
|
|
645 |
print "OUTPUT MORE THAN ONCE:", line
|
|
646 |
ok = False
|
|
647 |
|
|
648 |
|
|
649 |
# do the base class things too
|
|
650 |
return (SmokeTest.posttest(self) and ok)
|
|
651 |
|
|
652 |
# derived class for tests that also need to make sure that certain files
|
|
653 |
# are NOT created - sort of anti-targets.
|
|
654 |
|
|
655 |
class AntiTargetSmokeTest(SmokeTest):
|
|
656 |
|
|
657 |
def __init__(self):
|
|
658 |
SmokeTest.__init__(self)
|
|
659 |
self.antitargets = []
|
|
660 |
|
|
661 |
def pretest(self):
|
|
662 |
""" Prepare for the test """
|
|
663 |
# parent pretest first
|
|
664 |
ok = SmokeTest.pretest(self)
|
|
665 |
|
|
666 |
# remove all the anti-target files
|
|
667 |
return (self.removeFiles(self.antitargets) and ok)
|
|
668 |
|
|
669 |
def posttest(self):
|
|
670 |
""" look for antitargets """
|
|
671 |
ok = True
|
|
672 |
for t in self.antitargets:
|
|
673 |
tgt = os.path.normpath(ReplaceEnvs(t))
|
|
674 |
if os.path.exists(tgt):
|
|
675 |
print "UNWANTED", tgt
|
|
676 |
ok = False
|
|
677 |
|
|
678 |
# do the base class things too
|
|
679 |
return (SmokeTest.posttest(self) and ok)
|
|
680 |
|
|
681 |
def addbuildantitargets(self, bldinfsourcepath, targetsuffixes):
|
|
682 |
"""Add targets that are under epoc32/build whose path
|
|
683 |
can change based on an md5 hash of the path to the bld.inf.
|
|
684 |
"""
|
|
685 |
|
|
686 |
fragment = BldInfFile.outputPathFragment(bldinfsourcepath)
|
|
687 |
|
|
688 |
for t in targetsuffixes:
|
|
689 |
if type(t) is not list:
|
|
690 |
newt="$(EPOCROOT)/epoc32/build/"+fragment+"/"+t
|
|
691 |
self.antitargets.append(newt)
|
|
692 |
else:
|
|
693 |
self.antitargets.append(["$(EPOCROOT)/epoc32/build/"+fragment+"/"+x for x in t])
|
|
694 |
return
|
|
695 |
|
|
696 |
|
|
697 |
# the end
|