VirtualBox

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

Last change on this file since 53517 was 52776, checked in by vboxsync, 10 years ago

fix OSE

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