VirtualBox

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

Last change on this file since 57700 was 57700, checked in by vboxsync, 9 years ago

tdUnitTest1.py: Disabled tstRTFileAio for on linux, awaiting resolution of #8035.

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