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