VirtualBox

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

Last change on this file since 84245 was 83211, checked in by vboxsync, 5 years ago

bugref:9684. string which cuts '_SPB' part from VBox version

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