VirtualBox

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

Last change on this file since 84601 was 84374, checked in by vboxsync, 5 years ago

tdUnitTest1.py: Skip tstSSLCertDownloads as it is obsoleted by the removal of the root cert zip.

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