VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/tests/unittests/tdUnitTest1.py@ 55382

Last change on this file since 55382 was 54699, checked in by vboxsync, 10 years ago

whitespace

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 30.4 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdUnitTest1.py 54699 2015-03-09 13:53:07Z vboxsync $
4
5"""
6VirtualBox Validation Kit - Unit Tests.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2010-2014 Oracle Corporation
12
13This file is part of VirtualBox Open Source Edition (OSE), as
14available from http://www.virtualbox.org. This file is free software;
15you can redistribute it and/or modify it under the terms of the GNU
16General Public License (GPL) as published by the Free Software
17Foundation, in version 2 as it comes in the "COPYING" file of the
18VirtualBox OSE distribution. VirtualBox OSE is distributed in the
19hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20
21The contents of this file may alternatively be used under the terms
22of the Common Development and Distribution License Version 1.0
23(CDDL) only, as it comes in the "COPYING.CDDL" file of the
24VirtualBox OSE distribution, in which case the provisions of the
25CDDL are applicable instead of those of the GPL.
26
27You may elect to license modified versions of this file under the
28terms and conditions of either the GPL or the CDDL or both.
29"""
30__version__ = "$Revision: 54699 $"
31
32
33# Standard Python imports.
34import os
35import sys
36import re
37import subprocess
38import shutil
39
40
41# Only the main script needs to modify the path.
42try: __file__
43except: __file__ = sys.argv[0];
44g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
45sys.path.append(g_ksValidationKitDir)
46
47# Validation Kit imports.
48from common import utils;
49from testdriver import vbox
50from testdriver import reporter
51
52
53class tdUnitTest1(vbox.TestDriver):
54 """
55 Unit Tests.
56 """
57
58 ## The temporary exclude list.
59 ## @note This shall be empty before we release 4.3!
60 kdTestCasesBuggyPerOs = {
61 'darwin': {
62 'testcase/tstRTR0DbgKrnlInfoDriver': '', # Busted testcase, probably. (VERR_SYMBOL_NOT_FOUND)
63 },
64 'solaris': {
65 'testcase/tstIntNet-1': '', # Fails opening rge0, probably a generic issue figuring which nic to use.
66 'testcase/tstIprtList': '', # Crashes in the multithreaded test, I think.
67 'testcase/tstRTCritSect': '', # Fairness/whatever issue here.
68 'testcase/tstRTR0DbgKrnlInfoDriver': '', # Doesn't even load R0.
69 'testcase/tstRTR0MemUserKernelDriver': '', # Failes when kernel to kernel buffers.
70 'testcase/tstRTSemRW': '', # line 338: RTSemRWReleaseRead(hSemRW): got VERR_ACCESS_DENIED
71 'testcase/tstRTStrAlloc': '', # VERR_NO_STR_MEMORY!
72 'testcase/tstRTFileGetSize-1': '', # VERR_DEV_IO_ERROR on /dev/null!
73 },
74 'win': {
75 'testcase/tstFile': '', # ??
76 'testcase/tstIntNet-1': '', # possibly same issue as solaris.
77 'testcase/tstMouseImpl': '', # STATUS_ACCESS_VIOLATION
78 'testcase/tstRTR0ThreadPreemptionDriver': '', # ??
79 'testcase/tstRTPath': '<4.3.51r89894',
80 'testcase/tstRTPipe': '', # ??
81 'testcase/tstRTR0MemUserKernelDriver': '', # ??
82 'testcase/tstRTR0SemMutexDriver': '', # ??
83 'testcase/tstRTStrAlloc': '', # ??
84 'testcase/tstRTStrFormat': '', # ??
85 'testcase/tstRTSystemQueryOsInfo': '', # ??
86 'testcase/tstRTTemp': '', # ??
87 'testcase/tstRTTime': '', # ??
88 'testcase/tstTime-2': '', # Total time differs too much! ... delta=-10859859
89 'testcase/tstUtf8': '', # ??
90 'testcase/tstVMMR0CallHost-2': '', # STATUS_STACK_OVERFLOW
91 'testcase/tstX86-1': '', # Fails on win.x86.
92 'tscpasswd': '', # ??
93 'tstVMREQ': '', # ?? Same as darwin.x86?
94 }
95 };
96
97 kdTestCasesBuggy = {
98 'testcase/tstGuestPropSvc': '', # GET_NOTIFICATION fails on testboxlin5.de.oracle.com and others.
99 'testcase/tstRTProcCreateEx': '', # Seen failing on wei01-b6ka-9.de.oracle.com.
100 'testcase/tstTimer': '', # Sometimes fails on linux, not important atm.
101 };
102
103 ## The permanent exclude list.
104 # @note Stripped extensions!
105 kdTestCasesBlackList = {
106 'testcase/tstClipboardX11Smoke': '',
107 'testcase/tstFileLock': '',
108 'testcase/tstDisasm-2': '', # without parameters it will disassembler 1GB starting from 0
109 'testcase/tstFileAppendWin-1': '',
110 'testcase/tstDir': '', # useless without parameters
111 'testcase/tstDir-2': '', # useless without parameters
112 'testcase/tstGlobalConfig': '',
113 'testcase/tstHostHardwareLinux': '', # must be killed with CTRL-C
114 'testcase/tstHttp': '', # Talks to outside servers.
115 'testcase/tstRTHttp': '', # parameters required
116 'testcase/tstLdr-2': '', # parameters required
117 'testcase/tstLdr-3': '', # parameters required
118 'testcase/tstLdr': '', # parameters required
119 'testcase/tstLdrLoad': '', # parameters required
120 'testcase/tstMove': '', # parameters required
121 'testcase/tstRTR0Timer': '', # loads 'tstRTR0Timer.r0'
122 'testcase/tstRTR0ThreadDriver': '', # loads 'tstRTR0Thread.r0'
123 'testcase/tstRunTestcases': '', # that's a script like this one
124 'testcase/tstRTReqPool': '', # fails sometimes, testcase buggy
125 'testcase/tstRTS3': '', # parameters required
126 'testcase/tstSDL': '', # graphics test
127 'testcase/tstSupLoadModule': '', # Needs parameters and vboxdrv access. Covered elsewhere.
128 'testcase/tstSeamlessX11': '', # graphics test
129 'testcase/tstTime-3': '', # parameters required
130 'testcase/tstVBoxControl': '', # works only inside a guest
131 'testcase/tstVDCopy': '', # parameters required
132 'tstAnimate': '', # parameters required
133 'tstAPI': '', # user interaction required
134 'tstCollector': '', # takes forever
135 'testcase/tstHeadless': '', # parameters required
136 'tstHeadless': '', # parameters required
137 'tstMicroRC': '', # required by tstMicro
138 'tstVBoxDbg': '', # interactive test
139 'testcase/tstTestServMgr': '', # some strange xpcom18a4 test, does not work
140 'tstTestServMgr': '', # some strange xpcom18a4 test, does not work
141 'tstPDMAsyncCompletion': '', # parameters required
142 'testcase/tstXptDump': '', # parameters required
143 'tstXptDump': '', # parameters required
144 'testcase/tstnsIFileEnumerator': '', # some strange xpcom18a4 test, does not work
145 'tstnsIFileEnumerator': '', # some strange xpcom18a4 test, does not work
146 'testcase/tstSimpleTypeLib': '', # parameters required
147 'tstSimpleTypeLib': '', # parameters required
148 'testcase/tstTestAtoms': '', # additional test file (words.txt) required
149 'tstTestAtoms': '', # additional test file (words.txt) required
150 'testcase/tstXptLink': '', # parameters required
151 'tstXptLink': '', # parameters required
152 'tstXPCOMCGlue': '', # user interaction required
153 'testcase/tstXPCOMCGlue': '', # user interaction required
154 'testcase/tstCAPIGlue': '', # user interaction required
155 'testcase/tstTestCallTemplates': '', # some strange xpcom18a4 test, segfaults
156 'tstTestCallTemplates': '', # some strange xpcom18a4 test, segfaults
157 'testcase/tstRTFilesystem': '', # parameters required
158 'testcase/tstRTDvm': '', # parameters required
159 # later
160 'testcase/tstIntNetR0': '', # RTSPINLOCK_FLAGS_INTERRUPT_SAFE == RTSPINLOCK_FLAGS_INTERRUPT_UNSAFE
161 # slow stuff
162 'testcase/tstAvl': '', # SLOW!
163 'testcase/tstRTAvl': '', # SLOW! (new name)
164 'testcase/tstVD': '', # 8GB fixed-sized vmdk
165 # failed or hang
166 'testcase/tstCryptoPkcs7Verify': '', # hang
167 'tstOVF': '', # hang (only ancient version, now in new place)
168 'testcase/tstRTLockValidator': '', # Lock validation is not enabled for critical sections
169 'testcase/tstGuestControlSvc': '', # failed: line 288: testHost(&svcTable): expected VINF_SUCCESS, got VERR_NOT_FOUND
170 'testcase/tstRTMemEf': '', # failed w/o error message
171 'testcase/tstSupSem': '', # failed: SRE Timeout Accuracy (ms) : FAILED (1 errors)
172 'testcase/tstCryptoPkcs7Sign': '',# failed: 29330:error:02001002:lib(2):func(1):reason(2):NA:0:fopen('server.pem': '','r')
173 'testcase/tstCompressionBenchmark': '', # failed: error: RTZipBlockCompress failed
174 # for 'RTZipBlock/LZJB' (#4): VERR_NOT_SUPPORTED
175 'testcase/tstLdr-4': '', # failed: Failed to get bits for '/home/vbox/test/tmp/bin/testcase/tstLdrObjR0.r0'/0,
176 # rc=VERR_SYMBOL_VALUE_TOO_BIG. aborting test
177 'tstPDMAsyncCompletionStress': '', # VERR_INVALID_PARAMETER (cbSize = 0)
178 'tstMicro': '', # doesn't work on solaris, fix later if we care.
179 'tstVMM-HwAccm': '', # failed: Only checked AMD-V on linux
180 'tstVMM-HM': '', # failed: Only checked AMD-V on linux
181 'tstVMMFork': '', # failed: xtracker 6171
182 'tstTestFactory': '', # some strange xpcom18a4 test, does not work
183 'testcase/tstRTSemXRoads': '', # sporadically failed: Traffic - 8 threads per direction, 10 sec : FAILED (8 errors)
184 'tstVBoxAPILinux': '', # creates VirtualBox directories for root user because of sudo (should be in vbox)
185 'testcase/tstVMStructDTrace': '', # This is a D-script generator.
186 'tstVMStructRC': '', # This is a C-code generator.
187 'tstDeviceStructSizeRC': '', # This is a C-code generator.
188 'testcase/tstTSC': '', # Doesn't test anything and might fail with HT or/and too many cores.
189 'testcase/tstOpenUSBDev': '', # Not a useful testcase.
190 };
191
192 # Suffix exclude list.
193 kasSuffixBlackList = [
194 '.r0',
195 '.gc',
196 '.debug',
197 '.rel',
198 '.sys',
199 '.ko',
200 '.o',
201 '.obj',
202 '.lib',
203 '.a',
204 '.so',
205 '.dll',
206 '.dylib',
207 '.tmp',
208 '.log',
209 '.py',
210 '.pyc',
211 '.pyo',
212 '.pdb',
213 '.dSYM',
214 '.sym',
215 ];
216
217 ## The exclude list.
218 # @note Stripped extensions!
219 kasHardened = [
220 "testcase/tstIntNet-1",
221 "testcase/tstR0ThreadPreemptionDriver", # VBox 4.3
222 "testcase/tstRTR0ThreadPreemptionDriver",
223 "testcase/tstRTR0MemUserKernelDriver",
224 "testcase/tstRTR0SemMutexDriver",
225 "testcase/tstRTR0TimerDriver",
226 "testcase/tstRTR0ThreadDriver",
227 'testcase/tstRTR0DbgKrnlInfoDriver',
228 "tstInt",
229 "tstVMM",
230 "tstVMMFork",
231 "tstVMREQ",
232 'testcase/tstCFGM',
233 'testcase/tstContiguous',
234 'testcase/tstGetPagingMode',
235 'testcase/tstGIP-2',
236 'testcase/tstInit',
237 'testcase/tstLow',
238 'testcase/tstMMHyperHeap',
239 'testcase/tstPage',
240 'testcase/tstPin',
241 'testcase/tstRTTime', 'testcase/tstTime', # GIP test case.
242 'testcase/tstSSM',
243 'testcase/tstSupSem-Zombie',
244 ]
245
246 ## Argument lists
247 kdArguments = {
248 'testcase/tstbntest': [ '-out', os.devnull, ], # Very noisy.
249 };
250
251
252 ## Status code translations.
253 ## @{
254 kdExitCodeNames = {
255 0: 'RTEXITCODE_SUCCESS',
256 1: 'RTEXITCODE_FAILURE',
257 2: 'RTEXITCODE_SYNTAX',
258 3: 'RTEXITCODE_INIT',
259 4: 'RTEXITCODE_SKIPPED',
260 };
261 kdExitCodeNamesWin = {
262 -1073741515: 'STATUS_DLL_NOT_FOUND',
263 -1073741512: 'STATUS_ORDINAL_NOT_FOUND',
264 -1073741511: 'STATUS_ENTRYPOINT_NOT_FOUND',
265 -1073741502: 'STATUS_DLL_INIT_FAILED',
266 -1073741500: 'STATUS_UNHANDLED_EXCEPTION',
267 -1073741499: 'STATUS_APP_INIT_FAILURE',
268 -1073741819: 'STATUS_ACCESS_VIOLATION',
269 -1073741571: 'STATUS_STACK_OVERFLOW',
270 };
271 ## @}
272
273 def __init__(self):
274 """
275 Reinitialize child class instance.
276 """
277 vbox.TestDriver.__init__(self)
278 self.oTestVmSet = None;
279
280 self.sVBoxInstallRoot = None
281
282 self.cSkipped = 0
283 self.cPassed = 0
284 self.cFailed = 0
285
286 self.sUnitTestsPathBase = None
287 self.sExeSuff = '.exe' if utils.getHostOs() in [ 'win', 'dos', 'os2' ] else '';
288
289 self.aiVBoxVer = (4, 3, 0, 0);
290
291 # For testing testcase logic.
292 self.fDryRun = False;
293
294
295 def _detectPaths(self):
296 """
297 Internal worker for actionVerify and actionExecute that detects paths.
298
299 This sets sVBoxInstallRoot and sUnitTestsPathBase and returns True/False.
300 """
301
302 #
303 # We need a VBox install (/ build) to test.
304 #
305 if False:
306 if not self.importVBoxApi():
307 reporter.error('Unabled to import the VBox Python API.')
308 return False
309 else:
310 self._detectBuild();
311 if self.oBuild is None:
312 reporter.error('Unabled to detect the VBox build.');
313 return False;
314
315 #
316 # Where are the files installed?
317 # Solaris requires special handling because of it's multi arch subdirs.
318 #
319 self.sVBoxInstallRoot = self.oBuild.sInstallPath
320 if not self.oBuild.isDevBuild() and utils.getHostOs() == 'solaris':
321 sArchDir = utils.getHostArch();
322 if sArchDir == 'x86': sArchDir = 'i386';
323 self.sVBoxInstallRoot = os.path.join(self.sVBoxInstallRoot, sArchDir);
324
325 # Add the installation root to the PATH on windows so we can get DLLs from it.
326 if utils.getHostOs() == 'win':
327 sPathName = 'PATH';
328 if not sPathName in os.environ:
329 sPathName = 'Path';
330 sPath = os.environ.get(sPathName, '.');
331 if len(sPath) > 0 and sPath[-1] != ';':
332 sPath += ';';
333 os.environ[sPathName] = sPath + self.sVBoxInstallRoot + ';';
334
335 #
336 # The unittests are generally not installed, so look for them.
337 #
338 sBinOrDist = 'dist' if utils.getHostOs() in [ 'darwin', ] else 'bin';
339 asCandidates = [
340 self.oBuild.sInstallPath,
341 os.path.join(self.sScratchPath, sBinOrDist + '.' + utils.getHostArch()),
342 os.path.join(self.sScratchPath, sBinOrDist, utils.getHostArch()),
343 os.path.join(self.sScratchPath, sBinOrDist),
344 ];
345 if utils.getHostOs() == 'darwin':
346 for i in range(1, len(asCandidates)):
347 asCandidates[i] = os.path.join(asCandidates[i], 'VirtualBox.app', 'Contents', 'MacOS');
348
349 for sCandidat in asCandidates:
350 if os.path.exists(os.path.join(sCandidat, 'testcase', 'tstVMStructSize' + self.sExeSuff)):
351 self.sUnitTestsPathBase = sCandidat;
352 return True;
353
354 reporter.error('Unable to find unit test dir. Candidates: %s' % (asCandidates,))
355 return False;
356
357 #
358 # Overridden methods.
359 #
360
361 def actionVerify(self):
362 return self._detectPaths();
363
364 def actionExecute(self):
365
366 if self.sUnitTestsPathBase is None and self._detectPaths():
367 return False;
368
369 self._figureVersion();
370
371 self.testRunUnitTestsSet(r'^tst*', 'testcase')
372 self.testRunUnitTestsSet(r'^tst*', '.')
373
374 reporter.log('')
375 reporter.log('********************')
376 reporter.log('*** PASSED: %d' % self.cPassed)
377 reporter.log('*** FAILED: %d' % self.cFailed)
378 reporter.log('*** SKIPPED: %d' % self.cSkipped)
379 reporter.log('*** TOTAL: %d' % (self.cPassed + self.cFailed + self.cSkipped))
380
381 return self.cFailed == 0
382
383 #
384 # Test execution helpers.
385 #
386
387 def _figureVersion(self):
388 """ Tries to figure which VBox version this is, setting self.aiVBoxVer. """
389 try:
390 sVer = utils.processOutputChecked(['VBoxManage', '--version'])
391
392 sVer = sVer.strip();
393 sVer = re.sub(r'_BETA.*r', '.', sVer);
394 sVer = re.sub(r'_ALPHA.*r', '.', sVer);
395 sVer = re.sub(r'_RC.*r', '.', sVer);
396 sVer = sVer.replace('r', '.');
397
398 self.aiVBoxVer = [int(sComp) for sComp in sVer.split('.')];
399
400 reporter.log('VBox version: %s' % (self.aiVBoxVer,));
401 except:
402 reporter.logXcpt();
403 return False;
404 return True;
405
406 def _compareVersion(self, aiVer):
407 """
408 Compares the give version string with the vbox version string,
409 returning a result similar to C strcmp(). aiVer is on the right side.
410 """
411 cComponents = min(len(self.aiVBoxVer), len(aiVer));
412 for i in range(cComponents):
413 if self.aiVBoxVer[i] < aiVer[i]:
414 return -1;
415 if self.aiVBoxVer[i] > aiVer[i]:
416 return 1;
417 return len(self.aiVBoxVer) - len(aiVer);
418
419 def _isExcluded(self, sTest, dExclList):
420 """ Checks if the testcase is excluded or not. """
421 if sTest in dExclList:
422 sFullExpr = dExclList[sTest].replace(' ', '').strip();
423 if sFullExpr == '':
424 return True;
425
426 # Consider each exclusion expression. These are generally ranges,
427 # either open ended or closed: "<4.3.51r12345", ">=4.3.0 && <=4.3.4".
428 asExprs = sFullExpr.split(';');
429 for sExpr in asExprs:
430
431 # Split it on the and operator and process each sub expression.
432 fResult = True;
433 for sSubExpr in sExpr.split('&&'):
434 # Split out the comparison operator and the version value.
435 if sSubExpr.startswith('<=') or sSubExpr.startswith('>='):
436 sOp = sSubExpr[:2];
437 sValue = sSubExpr[2:];
438 elif sSubExpr.startswith('<') or sSubExpr.startswith('>') or sSubExpr.startswith('='):
439 sOp = sSubExpr[:1];
440 sValue = sSubExpr[1:];
441 else:
442 sOp = sValue = '';
443
444 # Convert the version value, making sure we've got a valid one.
445 try: aiValue = [int(sComp) for sComp in sValue.replace('r', '.').split('.')];
446 except: aiValue = ();
447 if len(aiValue) == 0 or len(aiValue) > 4:
448 reporter.error('Invalid exclusion expression for %s: "%s" [%s]' % (sTest, sSubExpr, dExclList[sTest]));
449 return True;
450
451 # Do the compare.
452 iCmp = self._compareVersion(aiValue);
453 if sOp == '>=' and iCmp < 0:
454 fResult = False;
455 elif sOp == '>' and iCmp <= 0:
456 fResult = False;
457 elif sOp == '<' and iCmp >= 0:
458 fResult = False;
459 elif sOp == '>=' and iCmp < 0:
460 fResult = False;
461 reporter.log2('iCmp=%s; %s %s %s -> %s' % (iCmp, self.aiVBoxVer, sOp, aiValue, fResult));
462
463 # Did the expression match?
464 if fResult:
465 return True;
466
467 return False;
468
469 def _sudoExecuteSync(self, asArgs):
470 """
471 Executes a sudo child process synchronously.
472 Returns True if the process executed successfully and returned 0,
473 otherwise False is returned.
474 """
475 reporter.log('Executing [sudo]: %s' % (asArgs, ));
476 try:
477 iRc = utils.sudoProcessCall(asArgs, shell = False, close_fds = False);
478 except:
479 reporter.errorXcpt();
480 return False;
481 reporter.log('Exit code [sudo]: %s (%s)' % (iRc, asArgs));
482 return iRc is 0;
483
484 def _hardenedMkDir(self, sPath):
485 """
486 Creates the directory specified sPath (including parents).
487 """
488 reporter.log('_hardenedMkDir: %s' % (sPath,));
489 if utils.getHostOs() in [ 'win', 'os2' ]:
490 os.makedirs(sPath, 0755);
491 else:
492 fRc = self._sudoExecuteSync(['/bin/mkdir', '-p', '-m', '0755', sPath]);
493 if fRc is not True:
494 raise Exception('Failed to create dir "%s".' % (sPath,));
495 return True;
496
497 def _hardenedCopyFile(self, sSrc, sDst, iMode):
498 """
499 Copies a file.
500 """
501 reporter.log('_hardenedCopyFile: %s -> %s (mode: %o)' % (sSrc, sDst, iMode,));
502 if utils.getHostOs() in [ 'win', 'os2' ]:
503 shutil.copyfile(sSrc, sDst);
504 os.chmod(sDst, iMode);
505 else:
506 fRc = self._sudoExecuteSync(['/bin/cp', sSrc, sDst]);
507 if fRc is not True:
508 raise Exception('Failed to copy "%s" to "%s".' % (sSrc, sDst,));
509 fRc = self._sudoExecuteSync(['/bin/chmod', '%o' % (iMode,), sDst]);
510 if fRc is not True:
511 raise Exception('Failed to chmod "%s".' % (sDst,));
512 return True;
513
514 def _hardenedDeleteFile(self, sPath):
515 """
516 Deletes a file.
517 """
518 reporter.log('_hardenedDeleteFile: %s' % (sPath,));
519 if os.path.exists(sPath):
520 if utils.getHostOs() in [ 'win', 'os2' ]:
521 os.remove(sPath);
522 else:
523 fRc = self._sudoExecuteSync(['/bin/rm', sPath]);
524 if fRc is not True:
525 raise Exception('Failed to remove "%s".' % (sPath,));
526 return True;
527
528 def _hardenedRemoveDir(self, sPath):
529 """
530 Removes a directory.
531 """
532 reporter.log('_hardenedRemoveDir: %s' % (sPath,));
533 if os.path.exists(sPath):
534 if utils.getHostOs() in [ 'win', 'os2' ]:
535 os.rmdir(sPath);
536 else:
537 fRc = self._sudoExecuteSync(['/bin/rmdir', sPath]);
538 if fRc is not True:
539 raise Exception('Failed to remove "%s".' % (sPath,));
540 return True;
541
542 def _executeTestCase(self, sName, sFullPath, sTestCaseSubDir, oDevNull): # pylint: disable=R0914
543 """
544 Executes a test case.
545 """
546
547 fSkipped = False;
548
549 #
550 # If hardening is enabled, some test cases and their dependencies
551 # needs to be copied to and execute from the sVBoxInstallRoot
552 # directory in order to work. They also have to be executed as
553 # root, i.e. via sudo.
554 #
555 fHardened = False;
556 asFilesToRemove = []; # Stuff to clean up.
557 asDirsToRemove = []; # Ditto.
558 if sName in self.kasHardened \
559 and self.sUnitTestsPathBase != self.sVBoxInstallRoot:
560
561 sDstDir = os.path.join(self.sVBoxInstallRoot, sTestCaseSubDir);
562 if not os.path.exists(sDstDir):
563 self._hardenedMkDir(sDstDir);
564 asDirsToRemove.append(sDstDir);
565
566 sDst = os.path.join(sDstDir, os.path.basename(sFullPath));
567 self._hardenedCopyFile(sFullPath, sDst, 0755);
568 asFilesToRemove.append(sDst);
569
570 # Copy any associated .dll/.so/.dylib.
571 for sSuff in [ '.dll', '.so', '.dylib' ]:
572 sSrc = os.path.splitext(sFullPath)[0] + sSuff;
573 if os.path.exists(sSrc):
574 sDst = os.path.join(sDstDir, os.path.basename(sSrc));
575 self._hardenedCopyFile(sSrc, sDst, 0644);
576 asFilesToRemove.append(sDst);
577
578 # Copy any associated .r0, .rc and .gc modules.
579 offDriver = sFullPath.rfind('Driver')
580 if offDriver > 0:
581 for sSuff in [ '.r0', 'RC.rc', 'RC.gc' ]:
582 sSrc = sFullPath[:offDriver] + sSuff;
583 if os.path.exists(sSrc):
584 sDst = os.path.join(sDstDir, os.path.basename(sSrc));
585 self._hardenedCopyFile(sSrc, sDst, 0644);
586 asFilesToRemove.append(sDst);
587
588 sFullPath = os.path.join(sDstDir, os.path.basename(sFullPath));
589 fHardened = True;
590
591 #
592 # Set up arguments and environment.
593 #
594 asArgs = [sFullPath,]
595 if sName in self.kdArguments:
596 asArgs.extend(self.kdArguments[sName]);
597
598 os.environ['IPRT_TEST_OMIT_TOP_TEST'] = '1';
599 os.environ['IPRT_TEST_FILE'] = sXmlFile = os.path.join(self.sScratchPath, 'result.xml');
600 if os.path.exists(sXmlFile):
601 try: os.unlink(sXmlFile);
602 except: self._hardenedDeleteFile(sXmlFile);
603
604 #
605 # Execute the test case.
606 #
607 # Windows is confusing output. Trying a few things to get rid of this.
608 # First, flush both stderr and stdout before running the child. Second,
609 # assign the child stderr to stdout. If this doesn't help, we'll have
610 # to capture the child output.
611 #
612 reporter.log('*** Executing %s%s...' % (asArgs, ' [hardened]' if fHardened else ''));
613 try: sys.stdout.flush();
614 except: pass;
615 try: sys.stderr.flush();
616 except: pass;
617 if not self.fDryRun:
618 try:
619 if fHardened:
620 oChild = utils.sudoProcessPopen(asArgs, stdin = oDevNull, stdout = sys.stdout, stderr = sys.stdout);
621 else:
622 oChild = subprocess.Popen( asArgs, stdin = oDevNull, stdout = sys.stdout, stderr = sys.stdout);
623 except:
624 if sName in [ 'tstAsmStructsRC', # 32-bit, may fail to start on 64-bit linux. Just ignore.
625 ]:
626 reporter.logXcpt();
627 fSkipped = True;
628 else:
629 reporter.errorXcpt();
630 iRc = 1023;
631 oChild = None;
632
633 if oChild is not None:
634 self.pidFileAdd(oChild.pid, fSudo = fHardened);
635 iRc = oChild.wait();
636 self.pidFileRemove(oChild.pid);
637 else:
638 iRc = 0;
639
640 #
641 # Clean up
642 #
643 for sPath in asFilesToRemove:
644 self._hardenedDeleteFile(sPath);
645 for sPath in asDirsToRemove:
646 self._hardenedRemoveDir(sPath);
647
648 #
649 # Report.
650 #
651 if os.path.exists(sXmlFile):
652 reporter.addSubXmlFile(sXmlFile);
653 if fHardened:
654 self._hardenedDeleteFile(sXmlFile);
655 else:
656 os.unlink(sXmlFile);
657
658 if iRc == 0:
659 reporter.log('*** %s: exit code %d' % (sFullPath, iRc));
660 self.cPassed += 1
661
662 elif iRc == 4: # RTEXITCODE_SKIPPED
663 reporter.log('*** %s: exit code %d (RTEXITCODE_SKIPPED)' % (sFullPath, iRc));
664 fSkipped = True;
665 self.cSkipped += 1;
666
667 elif fSkipped:
668 reporter.log('*** %s: exit code %d (Skipped)' % (sFullPath, iRc));
669 self.cSkipped += 1;
670
671 else:
672 sName = self.kdExitCodeNames.get(iRc, '');
673 if iRc in self.kdExitCodeNamesWin and utils.getHostOs() == 'win':
674 sName = self.kdExitCodeNamesWin[iRc];
675 if sName != '':
676 sName = ' (%s)' % (sName);
677
678 if iRc != 1:
679 reporter.testFailure('Exit status: %d%s' % (iRc, sName));
680 reporter.log( '!*! %s: exit code %d%s' % (sFullPath, iRc, sName));
681 else:
682 reporter.error('!*! %s: exit code %d%s' % (sFullPath, iRc, sName));
683 self.cFailed += 1
684
685 return fSkipped;
686
687 def testRunUnitTestsSet(self, sTestCasePattern, sTestCaseSubDir):
688 """
689 Run subset of the unit tests set.
690 """
691
692 # Open /dev/null for use as stdin further down.
693 try:
694 oDevNull = open(os.path.devnull, 'w+');
695 except:
696 oDevNull = None;
697
698 # Determin the host OS specific exclusion lists.
699 dTestCasesBuggyForHostOs = self.kdTestCasesBuggyPerOs.get(utils.getHostOs(), []);
700
701 #
702 # Process the file list and run everything looking like a testcase.
703 #
704 for sFilename in sorted(os.listdir(os.path.join(self.sUnitTestsPathBase, sTestCaseSubDir))):
705 # Separate base and suffix and morph the base into something we
706 # can use for reporting and array lookups.
707 sName, sSuffix = os.path.splitext(sFilename);
708 if sTestCaseSubDir != '.':
709 sName = sTestCaseSubDir + '/' + sName;
710
711 # Basic exclusion.
712 if not re.match(sTestCasePattern, sFilename) \
713 or sSuffix in self.kasSuffixBlackList:
714 reporter.log('"%s" is not a test case.' % (sFilename,))
715 continue
716
717 # Check if the testcase is black listed or buggy before executing it.
718 if self._isExcluded(sName, self.kdTestCasesBlackList):
719 # (No testStart/Done or accounting here!)
720 reporter.log('%s: SKIPPED (blacklisted)' % (sName,));
721
722 elif self._isExcluded(sName, self.kdTestCasesBuggy):
723 reporter.testStart(sName);
724 reporter.log('%s: Skipping, buggy in general.' % (sName,));
725 reporter.testDone(fSkipped = True);
726 self.cSkipped += 1;
727
728 elif self._isExcluded(sName, dTestCasesBuggyForHostOs):
729 reporter.testStart(sName);
730 reporter.log('%s: Skipping, buggy on %s.' % (sName, utils.getHostOs(),));
731 reporter.testDone(fSkipped = True);
732 self.cSkipped += 1;
733
734 else:
735 sFullPath = os.path.normpath(os.path.join(self.sUnitTestsPathBase, os.path.join(sTestCaseSubDir, sFilename)));
736 reporter.testStart(sName);
737 try:
738 fSkipped = self._executeTestCase(sName, sFullPath, sTestCaseSubDir, oDevNull);
739 except:
740 reporter.errorXcpt('!*!');
741 self.cFailed += 1;
742 fSkipped = False;
743 reporter.testDone(fSkipped);
744
745
746
747if __name__ == '__main__':
748 sys.exit(tdUnitTest1().main(sys.argv))
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette