VirtualBox

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

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

tdUnitTest1.py: Disable tstGIP-2 till it's fixed. (Do it in the right place this time.)

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