Changeset 93842 in vbox
- Timestamp:
- Feb 18, 2022 2:25:05 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/tests/unittests/tdUnitTest1.py
r93208 r93842 245 245 ]; 246 246 247 # White list, which contains tests considered to be safe to execute, 248 # even on remote targets (guests). 249 kdTestCasesWhiteList = { 250 'testcase/tstFile': '', 251 'testcase/tstFileLock': '', 252 'testcase/tstRTLocalIpc': '', 253 'testcase/tstRTPathQueryInfo': '', 254 'testcase/tstRTPipe': '', 255 'testcase/tstRTProcCreateEx': '', 256 'testcase/tstRTProcCreatePrf': '', 257 'testcase/tstRTProcIsRunningByName': '', 258 'testcase/tstRTProcQueryUsername': '', 259 'testcase/tstRTProcWait': '', 260 'testcase/tstTime-2': '', 261 'testcase/tstTime-3': '', 262 'testcase/tstTime-4': '', 263 'testcase/tstTimer': '', 264 'testcase/tstThread-1': '', 265 'testcase/tstUtf8': '', 266 } 267 268 # Test dependency list -- libraries. 269 # Needed in order to execute testcases on remote targets which don't have a VBox installation present. 270 kdTestCaseDepsLibs = [ 271 "VBoxRT" 272 ]; 273 247 274 ## The exclude list. 248 275 # @note Stripped extensions! … … 307 334 Reinitialize child class instance. 308 335 """ 309 vbox.TestDriver.__init__(self) 310 self.oTestVmSet = None; 311 312 self.sVBoxInstallRoot = None 313 314 self.cSkipped = 0 315 self.cPassed = 0 316 self.cFailed = 0 317 318 self.sUnitTestsPathBase = None 336 vbox.TestDriver.__init__(self); 337 338 # We need to set a default test VM set here -- otherwise the test 339 # driver base class won't let us use the "--test-vms" switch. 340 # 341 # See the "--local" switch in self.parseOption(). 342 self.oTestVmSet = self.oTestVmManager.getSmokeVmSet('nat'); 343 344 # Session handling stuff. 345 # Only needed for remote tests executed by TxS. 346 self.oSession = None; 347 self.oTxsSession = None; 348 349 self.sVBoxInstallRoot = None; 350 351 self.cSkipped = 0; 352 self.cPassed = 0; 353 self.cFailed = 0; 354 355 # The source directory where our unit tests live. 356 # This most likely is our out/ or some staging directory and 357 # also acts the source for copying over the testcases to a remote target. 358 self.sUnitTestsPathSrc = None; 359 360 # Array of environment variables with NAME=VAL entries 361 # to be applied for testcases. 362 # 363 # This is also needed for testcases which are being executed remotely. 364 self.asEnv = []; 365 366 # The destination directory our unit tests live when being 367 # copied over to a remote target (via TxS). 368 self.sUnitTestsPathDst = None; 369 319 370 self.sExeSuff = '.exe' if utils.getHostOs() in [ 'win', 'dos', 'os2' ] else ''; 320 371 … … 322 373 323 374 # For testing testcase logic. 324 self.fDryRun = False; 375 self.fDryRun = False; 376 self.fOnlyWhiteList = False; 325 377 326 378 … … 335 387 # We need a VBox install (/ build) to test. 336 388 # 337 if False is True: 389 if False is True: ## @todo r=andy WTF? 338 390 if not self.importVBoxApi(): 339 391 reporter.error('Unabled to import the VBox Python API.') … … 387 439 for sCandidat in asCandidates: 388 440 if os.path.exists(os.path.join(sCandidat, 'testcase', 'tstVMStructSize' + self.sExeSuff)): 389 self.sUnitTestsPath Base= sCandidat;441 self.sUnitTestsPathSrc = sCandidat; 390 442 return True; 391 443 … … 397 449 # 398 450 451 def showUsage(self): 452 """ 453 Shows the testdriver usage. 454 """ 455 fRc = vbox.TestDriver.showUsage(self); 456 reporter.log(''); 457 reporter.log('Unit Test #1 options:'); 458 reporter.log(' --dryrun'); 459 reporter.log(' Performs a dryrun (no tests being executed).'); 460 reporter.log(' --local'); 461 reporter.log(' Runs unit tests locally (this host).'); 462 reporter.log(' --only-whitelist'); 463 reporter.log(' Only processes the white list.'); 464 reporter.log(' --quick'); 465 reporter.log(' Very selective testing.'); 466 return fRc; 467 468 def parseOption(self, asArgs, iArg): 469 """ 470 Parses the testdriver arguments from the command line. 471 """ 472 if asArgs[iArg] == '--dryrun': 473 self.fDryRun = True; 474 elif asArgs[iArg] == '--local': 475 # Disable the test VM set and only run stuff locally. 476 self.oTestVmSet = None; 477 elif asArgs[iArg] == '--only-whitelist': 478 self.fOnlyWhiteList = True; 479 elif asArgs[iArg] == '--quick': 480 self.fOnlyWhiteList = True; 481 else: 482 return vbox.TestDriver.parseOption(self, asArgs, iArg); 483 return iArg + 1; 484 399 485 def actionVerify(self): 400 return self._detectPaths(); 486 if not self._detectPaths(): 487 return False; 488 489 if self.oTestVmSet: 490 return vbox.TestDriver.actionVerify(self); 491 492 return True; 493 494 def actionConfig(self): 495 # Make sure vboxapi has been imported so we can use the constants. 496 if not self.importVBoxApi(): 497 return False; 498 499 # Do the configuring. 500 if self.oTestVmSet: 501 if self.sNicAttachment == 'nat': eNic0AttachType = vboxcon.NetworkAttachmentType_NAT; 502 elif self.sNicAttachment == 'bridged': eNic0AttachType = vboxcon.NetworkAttachmentType_Bridged; 503 else: eNic0AttachType = None; 504 return self.oTestVmSet.actionConfig(self, eNic0AttachType = eNic0AttachType); 505 506 return True; 401 507 402 508 def actionExecute(self): 403 404 if self.sUnitTestsPathBase is None and self._detectPaths(): 509 if self.sUnitTestsPathSrc is None and not self._detectPaths(): 405 510 return False; 406 511 407 self._figureVersion(); 408 self._makeEnvironmentChanges(); 409 410 self.testRunUnitTestsSet(r'^tst*', 'testcase') 411 self.testRunUnitTestsSet(r'^tst*', '.') 412 413 reporter.log('') 414 reporter.log('********************') 415 reporter.log('*** PASSED: %d' % self.cPassed) 416 reporter.log('*** FAILED: %d' % self.cFailed) 417 reporter.log('*** SKIPPED: %d' % self.cSkipped) 418 reporter.log('*** TOTAL: %d' % (self.cPassed + self.cFailed + self.cSkipped)) 419 420 return self.cFailed == 0 512 if not self.sUnitTestsPathDst: 513 self.sUnitTestsPathDst = self.sScratchPath; 514 reporter.log('Unit test destination path is "%s"\n' % self.sUnitTestsPathDst); 515 516 if self.oTestVmSet: # Run on a test VM (guest). 517 fRc = self.oTestVmSet.actionExecute(self, self.testOneVmConfig); 518 else: # Run locally (host). 519 self._figureVersion(); 520 self._makeEnvironmentChanges(); 521 fRc = self._testRunUnitTests(None); 522 523 return fRc; 524 525 # 526 # Test execution helpers. 527 # 528 529 def _testRunUnitTests(self, oTestVm): 530 """ 531 Main function to execute all unit tests. 532 """ 533 self._testRunUnitTestsSet(r'^tst*', 'testcase'); 534 self._testRunUnitTestsSet(r'^tst*', '.'); 535 536 fRc = self.cFailed == 0; 537 538 reporter.log(''); 539 reporter.log('********************'); 540 reporter.log('Target: %s' % (oTestVm.sVmName if oTestVm else 'local')); 541 reporter.log('********************'); 542 reporter.log('*** PASSED: %d' % self.cPassed); 543 reporter.log('*** FAILED: %d' % self.cFailed); 544 reporter.log('*** SKIPPED: %d' % self.cSkipped); 545 reporter.log('*** TOTAL: %d' % (self.cPassed + self.cFailed + self.cSkipped)); 546 547 return fRc; 548 549 550 def testOneVmConfig(self, oVM, oTestVm): 551 """ 552 Runs the specified VM thru test #1. 553 """ 554 555 # Simple test. 556 self.logVmInfo(oVM); 557 # Try waiting for a bit longer (5 minutes) until the CD is available to avoid running into timeouts. 558 self.oSession, self.oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, fCdWait = False); 559 if self.oSession is not None: 560 self.addTask(self.oTxsSession); 561 562 # Determine the unit tests destination path. 563 self.sUnitTestsPathDst = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'testUnitTests'); 564 565 # Run the unit tests. 566 self._testRunUnitTests(oTestVm); 567 568 # Cleanup. 569 self.removeTask(self.oTxsSession); 570 self.terminateVmBySession(self.oSession); 571 return True; 572 573 return False; 421 574 422 575 # … … 514 667 """ 515 668 reporter.log('Executing [sudo]: %s' % (asArgs, )); 516 try: 517 iRc = utils.sudoProcessCall(asArgs, shell = False, close_fds = False); 518 except: 519 reporter.errorXcpt(); 520 return False; 521 reporter.log('Exit code [sudo]: %s (%s)' % (iRc, asArgs)); 669 if self.oTestVmSet: 670 iRc = -1; ## @todo Not used remotely yet. 671 else: 672 try: 673 iRc = utils.sudoProcessCall(asArgs, shell = False, close_fds = False); 674 except: 675 reporter.errorXcpt(); 676 return False; 677 reporter.log('Exit code [sudo]: %s (%s)' % (iRc, asArgs)); 522 678 return iRc == 0; 523 679 680 def _hardenedPathExists(self, sPath): 681 """ 682 Creates the directory specified sPath (including parents). 683 """ 684 reporter.log('_hardenedPathExists: %s' % (sPath,)); 685 fRc = False; 686 if self.oTestVmSet: 687 fRc = self.txsIsDir(self.oSession, self.oTxsSession, sPath, fIgnoreErrors = True); 688 if not fRc: 689 fRc = self.txsIsFile(self.oSession, self.oTxsSession, sPath, fIgnoreErrors = True); 690 else: 691 fRc = os.path.exists(sPath); 692 return fRc; 693 524 694 def _hardenedMkDir(self, sPath): 525 695 """ … … 527 697 """ 528 698 reporter.log('_hardenedMkDir: %s' % (sPath,)); 529 if utils.getHostOs() in [ 'win', 'os2' ]: 530 os.makedirs(sPath, 0o755); 699 fRc = True; 700 if self.oTestVmSet: 701 fRc = self.txsMkDirPath(self.oSession, self.oTxsSession, sPath, fMode = 0o755); 531 702 else: 532 fRc = self._sudoExecuteSync(['/bin/mkdir', '-p', '-m', '0755', sPath]); 533 if fRc is not True: 534 raise Exception('Failed to create dir "%s".' % (sPath,)); 703 if utils.getHostOs() in [ 'win', 'os2' ]: 704 os.makedirs(sPath, 0o755); 705 else: 706 fRc = self._sudoExecuteSync(['/bin/mkdir', '-p', '-m', '0755', sPath]); 707 if fRc is not True: 708 raise Exception('Failed to create dir "%s".' % (sPath,)); 535 709 return True; 536 710 … … 540 714 """ 541 715 reporter.log('_hardenedCopyFile: %s -> %s (mode: %o)' % (sSrc, sDst, iMode,)); 542 if utils.getHostOs() in [ 'win', 'os2' ]: 543 utils.copyFileSimple(sSrc, sDst); 544 os.chmod(sDst, iMode); 716 fRc = True; 717 if self.oTestVmSet: 718 fRc = self.txsUploadFile(self.oSession, self.oTxsSession, sSrc, sDst); 719 if fRc: 720 self.oTxsSession.syncChMod(sDst, 0o755); 545 721 else: 546 fRc = self._sudoExecuteSync(['/bin/cp', sSrc, sDst]); 547 if fRc is not True: 548 raise Exception('Failed to copy "%s" to "%s".' % (sSrc, sDst,)); 549 fRc = self._sudoExecuteSync(['/bin/chmod', '%o' % (iMode,), sDst]); 550 if fRc is not True: 551 raise Exception('Failed to chmod "%s".' % (sDst,)); 722 if utils.getHostOs() in [ 'win', 'os2' ]: 723 utils.copyFileSimple(sSrc, sDst); 724 os.chmod(sDst, iMode); 725 else: 726 fRc = self._sudoExecuteSync(['/bin/cp', sSrc, sDst]); 727 if fRc: 728 fRc = self._sudoExecuteSync(['/bin/chmod', '%o' % (iMode,), sDst]); 729 if fRc is not True: 730 raise Exception('Failed to chmod "%s".' % (sDst,)); 731 if fRc is not True: 732 raise Exception('Failed to copy "%s" to "%s".' % (sSrc, sDst,)); 552 733 return True; 553 734 … … 557 738 """ 558 739 reporter.log('_hardenedDeleteFile: %s' % (sPath,)); 559 if os.path.exists(sPath): 560 if utils.getHostOs() in [ 'win', 'os2' ]: 561 os.remove(sPath); 562 else: 563 fRc = self._sudoExecuteSync(['/bin/rm', sPath]); 564 if fRc is not True: 565 raise Exception('Failed to remove "%s".' % (sPath,)); 740 fRc = True; 741 if self.oTestVmSet: 742 if self.txsIsFile(self.oSession, self.oTxsSession, sPath): 743 fRc = self.txsRmFile(self.oSession, self.oTxsSession, sPath); 744 else: 745 if os.path.exists(sPath): 746 if utils.getHostOs() in [ 'win', 'os2' ]: 747 os.remove(sPath); 748 else: 749 fRc = self._sudoExecuteSync(['/bin/rm', sPath]); 750 if fRc is not True: 751 raise Exception('Failed to remove "%s".' % (sPath,)); 566 752 return True; 567 753 … … 571 757 """ 572 758 reporter.log('_hardenedRemoveDir: %s' % (sPath,)); 573 if os.path.exists(sPath): 574 if utils.getHostOs() in [ 'win', 'os2' ]: 575 os.rmdir(sPath); 576 else: 577 fRc = self._sudoExecuteSync(['/bin/rmdir', sPath]); 578 if fRc is not True: 579 raise Exception('Failed to remove "%s".' % (sPath,)); 759 fRc = True; 760 if self.oTestVmSet: 761 if self.txsIsDir(self.oSession, self.oTxsSession, sPath): 762 fRc = self.txsRmDir(self.oSession, self.oTxsSession, sPath); 763 else: 764 if os.path.exists(sPath): 765 if utils.getHostOs() in [ 'win', 'os2' ]: 766 os.rmdir(sPath); 767 else: 768 fRc = self._sudoExecuteSync(['/bin/rmdir', sPath]); 769 if fRc is not True: 770 raise Exception('Failed to remove "%s".' % (sPath,)); 771 return True; 772 773 def _envSet(self, sName, sValue): 774 if self.oTestVmSet: 775 # For remote execution we cache the environment block and pass it 776 # right when the process execution happens. 777 self.asEnv.append([ sName, sValue ]); 778 else: 779 os.environ[sName] = sValue; 580 780 return True; 581 781 … … 594 794 # 595 795 fHardened = False; 796 fToRemote = False; 797 fCopyDeps = False; 596 798 asFilesToRemove = []; # Stuff to clean up. 597 799 asDirsToRemove = []; # Ditto. 598 if sName in self.kasHardened \ 599 and self.sUnitTestsPathBase != self.sVBoxInstallRoot: 600 601 sDstDir = os.path.join(self.sVBoxInstallRoot, sTestCaseSubDir); 602 if not os.path.exists(sDstDir): 800 801 if sName in self.kasHardened \ 802 and self.sUnitTestsPathSrc != self.sVBoxInstallRoot: 803 fHardened = True; 804 805 if self.oTestVmSet: 806 fToRemote = True; 807 fCopyDeps = True; 808 809 if fHardened \ 810 or fToRemote: 811 if fToRemote: 812 sDstDir = os.path.join(self.sUnitTestsPathDst, sTestCaseSubDir); 813 else: 814 sDstDir = os.path.join(self.sVBoxInstallRoot, sTestCaseSubDir); 815 if not self._hardenedPathExists(sDstDir): 603 816 self._hardenedMkDir(sDstDir); 604 817 asDirsToRemove.append(sDstDir); … … 607 820 self._hardenedCopyFile(sFullPath, sDst, 0o755); 608 821 asFilesToRemove.append(sDst); 822 823 # Copy required dependencies to destination. 824 if fCopyDeps: 825 for sLib in self.kdTestCaseDepsLibs: 826 for sSuff in [ '.dll', '.so', '.dylib' ]: 827 sSrc = os.path.join(self.sVBoxInstallRoot, sLib + sSuff); 828 if os.path.exists(sSrc): 829 sDst = os.path.join(sDstDir, os.path.basename(sSrc)); 830 self._hardenedCopyFile(sSrc, sDst, 0o644); 831 asFilesToRemove.append(sDst); 609 832 610 833 # Copy any associated .dll/.so/.dylib. … … 627 850 628 851 sFullPath = os.path.join(sDstDir, os.path.basename(sFullPath)); 629 fHardened = True;630 852 631 853 # … … 636 858 asArgs.extend(self.kdArguments[sName]); 637 859 638 os.environ['IPRT_TEST_OMIT_TOP_TEST'] = '1'; 639 os.environ['IPRT_TEST_FILE'] = sXmlFile = os.path.join(self.sScratchPath, 'result.xml'); 640 if os.path.exists(sXmlFile): 860 sXmlFile = os.path.join(self.sUnitTestsPathDst, 'result.xml'); 861 862 self._envSet('IPRT_TEST_OMIT_TOP_TEST', '1'); 863 self._envSet('IPRT_TEST_FILE', sXmlFile); 864 865 if self._hardenedPathExists(sXmlFile): 641 866 try: os.unlink(sXmlFile); 642 867 except: self._hardenedDeleteFile(sXmlFile); … … 656 881 except: pass; 657 882 if not self.fDryRun: 658 try: 659 if fHardened: 660 oChild = utils.sudoProcessPopen(asArgs, stdin = oDevNull, stdout = sys.stdout, stderr = sys.stdout); 883 if fToRemote: 884 fRc = self.txsRunTest(self.oTxsSession, sName, 30 * 60 * 1000, asArgs[0], asArgs, self.asEnv, \ 885 fCheckSessionStatus = True); 886 if fRc: 887 iRc = 0; 661 888 else: 662 oChild = utils.processPopenSafe(asArgs, stdin = oDevNull, stdout = sys.stdout, stderr = sys.stdout); 663 except: 664 if sName in [ 'tstAsmStructsRC', # 32-bit, may fail to start on 64-bit linux. Just ignore. 665 ]: 666 reporter.logXcpt(); 667 fSkipped = True; 668 else: 669 reporter.errorXcpt(); 670 iRc = 1023; 671 oChild = None; 672 673 if oChild is not None: 674 self.pidFileAdd(oChild.pid, sName, fSudo = fHardened); 675 iRc = oChild.wait(); 676 self.pidFileRemove(oChild.pid); 889 (_, sOpcode, abPayload) = self.oTxsSession.getLastReply(); 890 if sOpcode.startswith('PROC NOK '): # Extract process rc. 891 iRc = abPayload[0]; # ASSUMES 8-bit rc for now. 892 if iRc == 0: # Might happen if the testcase misses some dependencies. Set it to -42 then. 893 iRc = -42; 894 else: 895 iRc = -1; ## @todo 896 else: 897 try: 898 if fHardened: 899 oChild = utils.sudoProcessPopen(asArgs, stdin = oDevNull, stdout = sys.stdout, stderr = sys.stdout); 900 else: 901 oChild = utils.processPopenSafe(asArgs, stdin = oDevNull, stdout = sys.stdout, stderr = sys.stdout); 902 except: 903 if sName in [ 'tstAsmStructsRC', # 32-bit, may fail to start on 64-bit linux. Just ignore. 904 ]: 905 reporter.logXcpt(); 906 fSkipped = True; 907 else: 908 reporter.errorXcpt(); 909 iRc = 1023; 910 oChild = None; 911 912 if oChild is not None: 913 self.pidFileAdd(oChild.pid, sName, fSudo = fHardened); 914 iRc = oChild.wait(); 915 self.pidFileRemove(oChild.pid); 677 916 else: 678 917 iRc = 0; … … 698 937 if iRc == 0: 699 938 reporter.log('*** %s: exit code %d' % (sFullPath, iRc)); 700 self.cPassed += 1 939 self.cPassed += 1; 701 940 702 941 elif iRc == 4: # RTEXITCODE_SKIPPED … … 721 960 else: 722 961 reporter.error('!*! %s: exit code %d%s' % (sFullPath, iRc, sName)); 723 self.cFailed += 1 962 self.cFailed += 1; 724 963 725 964 return fSkipped; 726 965 727 def testRunUnitTestsSet(self, sTestCasePattern, sTestCaseSubDir):966 def _testRunUnitTestsSet(self, sTestCasePattern, sTestCaseSubDir): 728 967 """ 729 968 Run subset of the unit tests set. … … 740 979 dTestCasesBuggyForHostOs.update(self.kdTestCasesBuggyPerOs.get(utils.getHostOsDotArch(), [])); 741 980 742 ## @todo Add filtering for more specif c OSes (like OL server, doesn't have X installed) by adding a separate981 ## @todo Add filtering for more specific OSes (like OL server, doesn't have X installed) by adding a separate 743 982 # black list + using utils.getHostOsVersion(). 744 983 … … 746 985 # Process the file list and run everything looking like a testcase. 747 986 # 748 for sFilename in sorted(os.listdir(os.path.join(self.sUnitTestsPath Base, sTestCaseSubDir))):987 for sFilename in sorted(os.listdir(os.path.join(self.sUnitTestsPathSrc, sTestCaseSubDir))): 749 988 # Separate base and suffix and morph the base into something we 750 989 # can use for reporting and array lookups. … … 753 992 sName = sTestCaseSubDir + '/' + sName; 754 993 994 # Process white list first, if set. 995 if self.fOnlyWhiteList \ 996 and sName not in self.kdTestCasesWhiteList: 997 reporter.log2('"%s" is not in white list, skipping.' % (sFilename,)); 998 continue; 999 755 1000 # Basic exclusion. 756 1001 if not re.match(sTestCasePattern, sFilename) \ 757 1002 or sSuffix in self.kasSuffixBlackList: 758 reporter.log ('"%s" is not a test case.' % (sFilename,))759 continue 1003 reporter.log2('"%s" is not a test case.' % (sFilename,)); 1004 continue; 760 1005 761 1006 # Check if the testcase is black listed or buggy before executing it. … … 777 1022 778 1023 else: 779 sFullPath = os.path.normpath(os.path.join(self.sUnitTestsPath Base, os.path.join(sTestCaseSubDir, sFilename)));1024 sFullPath = os.path.normpath(os.path.join(self.sUnitTestsPathSrc, os.path.join(sTestCaseSubDir, sFilename))); 780 1025 reporter.testStart(sName); 781 1026 try:
Note:
See TracChangeset
for help on using the changeset viewer.