VirtualBox

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

Last change on this file since 69606 was 69606, checked in by vboxsync, 7 years ago

tUnitTest1.py: Exclude tstOVF as it may create a mess if it/VBoxSVC fails.

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