VirtualBox

Ignore:
Timestamp:
Feb 24, 2022 8:07:29 AM (3 years ago)
Author:
vboxsync
Message:

Validation Kit: Extended unit test test driver so that it also allows running directly off a remote location (i.e. Validation Kit .ISO, if included). Useful for testing cross arch unit tests (i.e. host 64-bit, guest 32-bit) See command line help / comments for more. bugref:10195

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/tests/unittests/tdUnitTest1.py

    r93876 r93903  
    4545# Validation Kit imports.
    4646from common     import utils;
     47from testdriver import base;
    4748from testdriver import reporter;
    4849from testdriver import vbox;
     
    264265        'testcase/tstTimer': '',
    265266        'testcase/tstThread-1': '',
    266         'testcase/tstUtf8': '',
    267     }
     267        'testcase/tstUtf8': ''
     268    };
    268269
    269270    # Test dependency list -- libraries.
     
    354355        self.sVBoxInstallRoot = None;
    355356
     357        # Testing mode being used:
     358        #   "local":       Execute unit tests locally (same host, default).
     359        #   "remote-copy": Copies unit tests from host to the remote, then executing it.
     360        #   "remote-exec": Executes unit tests right on the remote from a given source.
     361        self.sMode = 'local';
     362
    356363        self.cSkipped   = 0;
    357364        self.cPassed    = 0;
     
    463470        reporter.log('  --dryrun');
    464471        reporter.log('      Performs a dryrun (no tests being executed).');
    465         reporter.log('  --local');
    466         reporter.log('      Runs unit tests locally (this host).');
     472        reporter.log('  --mode <local|remote>');
     473        reporter.log('      Specifies the execution mode.');
    467474        reporter.log('  --only-whitelist');
    468475        reporter.log('      Only processes the white list.');
    469476        reporter.log('  --quick');
    470477        reporter.log('      Very selective testing.');
     478        reporter.log('  --unittest-source <dir>');
     479        reporter.log('      Sets the unit test source to <dir>.');
     480        reporter.log('      Also used for remote execution.');
     481        reporter.log('  --vbox-install-root <dir>');
     482        reporter.log('      Sets the VBox install root to <dir>.');
     483        reporter.log('      Also used for remote execution.');
    471484        return fRc;
    472485
     
    477490        if asArgs[iArg] == '--dryrun':
    478491            self.fDryRun = True;
    479         elif asArgs[iArg] == '--local':
    480             # Disable the test VM set and only run stuff locally.
    481             self.oTestVmSet = None;
     492        elif asArgs[iArg] == '--mode':
     493            iArg += 1;
     494            if iArg >= len(asArgs):
     495                raise base.InvalidOption('Option "%s" needs a value' % (asArgs[iArg - 1]));
     496            if asArgs[iArg] == 'local':
     497                self.sMode = asArgs[iArg];
     498            elif asArgs[iArg] == 'remote':
     499                if self.sUnitTestsPathSrc:
     500                    self.sMode = 'remote-exec';
     501                else:
     502                    self.sMode = 'remote-copy';
     503            else:
     504                raise base.InvalidOption('Argument "%s" invalid' % (asArgs[iArg]));
     505        elif asArgs[iArg] == '--unittest-source':
     506            iArg += 1;
     507            if iArg >= len(asArgs):
     508                raise base.InvalidOption('Option "%s" needs a value' % (asArgs[iArg - 1]));
     509            self.sUnitTestsPathSrc = asArgs[iArg];
     510            self.sMode = 'remote-exec';
    482511        elif asArgs[iArg] == '--only-whitelist':
    483512            self.fOnlyWhiteList = True;
    484513        elif asArgs[iArg] == '--quick':
    485514            self.fOnlyWhiteList = True;
     515        elif asArgs[iArg] == '--vbox-install-root':
     516            iArg += 1;
     517            if iArg >= len(asArgs):
     518                raise base.InvalidOption('Option "%s" needs a value' % (asArgs[iArg - 1]));
     519            self.sVBoxInstallRoot = asArgs[iArg];
    486520        else:
    487521            return vbox.TestDriver.parseOption(self, asArgs, iArg);
     
    503537
    504538        # Do the configuring.
    505         if self.oTestVmSet:
     539        if self.sMode.startswith('remote'):
    506540            if   self.sNicAttachment == 'nat':     eNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
    507541            elif self.sNicAttachment == 'bridged': eNic0AttachType = vboxcon.NetworkAttachmentType_Bridged;
     
    524558        if self.sUnitTestsPathSrc is None and not self._detectPaths():
    525559            return False;
     560        reporter.log2('Unit test source path is "%s"\n' % self.sUnitTestsPathSrc);
    526561
    527562        if not self.sUnitTestsPathDst:
    528563            self.sUnitTestsPathDst = self.sScratchPath;
    529         reporter.log('Unit test destination path is "%s"\n' % self.sUnitTestsPathDst);
    530 
    531         if self.oTestVmSet: # Run on a test VM (guest).
     564        reporter.log2('Unit test destination path is "%s"\n' % self.sUnitTestsPathDst);
     565
     566        if self.sMode.startswith('remote'): # Run on a test VM (guest).
     567            assert self.oTestVmSet is not None;
    532568            fRc = self.oTestVmSet.actionExecute(self, self.testOneVmConfig);
    533569        else: # Run locally (host).
     
    552588
    553589        reporter.log('');
    554         reporter.log('********************');
    555         reporter.log('Target: %s' % (oTestVm.sVmName if oTestVm else 'local'));
    556         reporter.log('********************');
     590        if self.fDryRun:
     591            reporter.log('*********************************************************');
     592            reporter.log('DRY RUN - DRY RUN - DRY RUN - DRY RUN - DRY RUN - DRY RUN');
     593            reporter.log('*********************************************************');
     594        reporter.log('*********************************************************');
     595        reporter.log('           Target: %s' % (oTestVm.sVmName if oTestVm else 'local'));
     596        reporter.log('             Mode: %s' % (self.sMode));
     597        reporter.log('Unit tests source: %s %s' % (self.sUnitTestsPathSrc, \
     598                    '(on remote)' if self.sMode is 'remote-exec' else ''));
     599        reporter.log('VBox install root: %s %s' % (self.sVBoxInstallRoot, \
     600                     '(on remote)' if self.sMode is 'remote-exec' else ''));
     601        reporter.log('*********************************************************');
    557602        reporter.log('***  PASSED: %d' % self.cPassed);
    558603        reporter.log('***  FAILED: %d' % self.cFailed);
     
    570615        # Simple test.
    571616        self.logVmInfo(oVM);
    572         # Try waiting for a bit longer (5 minutes) until the CD is available to avoid running into timeouts.
    573         self.oSession, self.oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, \
    574                                                                             fCdWait = True, \
    575                                                                             cMsCdWait = 5 * 60 * 1000);
     617
     618        if not self.fDryRun:
     619            # Try waiting for a bit longer (5 minutes) until the CD is available to avoid running into timeouts.
     620            self.oSession, self.oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, \
     621                                                                                fCdWait = not self.fDryRun, \
     622                                                                                cMsCdWait = 5 * 60 * 1000);
     623            if self.oSession is None:
     624                return False;
     625
     626            self.addTask(self.oTxsSession);
     627
     628        # Determine the unit tests destination path.
     629        self.sUnitTestsPathDst = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'testUnitTests');
     630
     631        # Run the unit tests.
     632        self._testRunUnitTests(oTestVm);
     633
     634        # Cleanup.
    576635        if self.oSession is not None:
    577             self.addTask(self.oTxsSession);
    578 
    579             # Determine the unit tests destination path.
    580             self.sUnitTestsPathDst = oTestVm.pathJoin(self.getGuestTempDir(oTestVm), 'testUnitTests');
    581 
    582             # Run the unit tests.
    583             self._testRunUnitTests(oTestVm);
    584 
    585             # Cleanup.
    586636            self.removeTask(self.oTxsSession);
    587637            self.terminateVmBySession(self.oSession);
    588             return True;
    589 
    590         return False;
     638        return True;
    591639
    592640    #
     
    683731        otherwise False is returned.
    684732        """
    685         reporter.log('Executing [sudo]: %s' % (asArgs, ));
    686         if self.oTestVmSet:
     733        reporter.log2('Executing [sudo]: %s' % (asArgs, ));
     734        if self.sMode.startswith('remote'):
    687735            iRc = -1; ## @todo Not used remotely yet.
    688736        else:
     
    695743        return iRc == 0;
    696744
    697     def _hardenedPathExists(self, sPath):
     745    def _wrapPathExists(self, sPath):
    698746        """
    699747        Creates the directory specified sPath (including parents).
    700748        """
    701         reporter.log('_hardenedPathExists: %s' % (sPath,));
     749        reporter.log2('_wrapPathExists: %s' % (sPath,));
     750        if self.fDryRun:
     751            return True;
    702752        fRc = False;
    703         if self.oTestVmSet:
     753        if self.sMode.startswith('remote'):
    704754            fRc = self.txsIsDir(self.oSession, self.oTxsSession, sPath, fIgnoreErrors = True);
    705755            if not fRc:
     
    709759        return fRc;
    710760
    711     def _hardenedMkDir(self, sPath):
     761    def _wrapMkDir(self, sPath):
    712762        """
    713763        Creates the directory specified sPath (including parents).
    714764        """
    715         reporter.log('_hardenedMkDir: %s' % (sPath,));
     765        reporter.log2('_wrapMkDir: %s' % (sPath,));
     766        if self.fDryRun:
     767            return True;
    716768        fRc = True;
    717         if self.oTestVmSet:
     769        if self.sMode.startswith('remote'):
    718770            fRc = self.txsMkDirPath(self.oSession, self.oTxsSession, sPath, fMode = 0o755);
    719771        else:
     
    726778        return True;
    727779
    728     def _hardenedCopyFile(self, sSrc, sDst, iMode):
     780    def _wrapCopyFile(self, sSrc, sDst, iMode):
    729781        """
    730782        Copies a file.
    731783        """
    732         reporter.log('_hardenedCopyFile: %s -> %s (mode: %o)' % (sSrc, sDst, iMode,));
     784        reporter.log2('_wrapCopyFile: %s -> %s (mode: %o)' % (sSrc, sDst, iMode,));
     785        if self.fDryRun:
     786            return True;
    733787        fRc = True;
    734         if self.oTestVmSet:
    735             fRc = self.txsUploadFile(self.oSession, self.oTxsSession, sSrc, sDst);
    736             if fRc:
    737                 self.oTxsSession.syncChMod(sDst, 0o755);
     788        if self.sMode.startswith('remote'):
     789            if self.sMode == 'remote-exec':
     790                self.oTxsSession.txsCopyFile(self.oSession, self.oTxsSession, sSrc, sDst, iMode);
     791            else:
     792                fRc = self.txsUploadFile(self.oSession, self.oTxsSession, sSrc, sDst);
     793                if fRc:
     794                    self.oTxsSession.syncChMod(sDst, iMode);
    738795        else:
    739796            if utils.getHostOs() in [ 'win', 'os2' ]:
     
    750807        return True;
    751808
    752     def _hardenedDeleteFile(self, sPath):
     809    def _wrapDeleteFile(self, sPath):
    753810        """
    754811        Deletes a file.
    755812        """
    756         reporter.log('_hardenedDeleteFile: %s' % (sPath,));
     813        reporter.log2('_wrapDeleteFile: %s' % (sPath,));
     814        if self.fDryRun:
     815            return True;
    757816        fRc = True;
    758         if self.oTestVmSet:
     817        if self.sMode.startswith('remote'):
    759818            if self.txsIsFile(self.oSession, self.oTxsSession, sPath):
    760819                fRc = self.txsRmFile(self.oSession, self.oTxsSession, sPath);
     
    769828        return True;
    770829
    771     def _hardenedRemoveDir(self, sPath):
     830    def _wrapRemoveDir(self, sPath):
    772831        """
    773832        Removes a directory.
    774833        """
    775         reporter.log('_hardenedRemoveDir: %s' % (sPath,));
     834        reporter.log2('_wrapRemoveDir: %s' % (sPath,));
     835        if self.fDryRun:
     836            return True;
    776837        fRc = True;
    777         if self.oTestVmSet:
     838        if self.sMode.startswith('remote'):
    778839            if self.txsIsDir(self.oSession, self.oTxsSession, sPath):
    779840                fRc = self.txsRmDir(self.oSession, self.oTxsSession, sPath);
     
    789850
    790851    def _envSet(self, sName, sValue):
    791         if self.oTestVmSet:
     852        if self.sMode.startswith('remote'):
    792853            # For remote execution we cache the environment block and pass it
    793854            # right when the process execution happens.
     
    806867        #
    807868        # If hardening is enabled, some test cases and their dependencies
    808         # needs to be copied to and execute from the sVBoxInstallRoot
     869        # needs to be copied to and execute from the source
    809870        # directory in order to work. They also have to be executed as
    810871        # root, i.e. via sudo.
    811872        #
    812873        fHardened       = False;
    813         fToRemote       = False;
     874        fCopyToRemote   = False;
    814875        fCopyDeps       = False;
    815876        asFilesToRemove = []; # Stuff to clean up.
     
    820881            fHardened = True;
    821882
    822         if self.oTestVmSet:
    823             fToRemote = True;
    824             fCopyDeps = True;
     883        if self.sMode.startswith('remote'):
     884            fCopyToRemote = True;
     885            fCopyDeps     = True;
    825886
    826887        if fHardened \
    827         or fToRemote:
    828             if fToRemote:
     888        or fCopyToRemote:
     889            if fCopyToRemote:
    829890                sDstDir = os.path.join(self.sUnitTestsPathDst, sTestCaseSubDir);
    830891            else:
    831892                sDstDir = os.path.join(self.sVBoxInstallRoot, sTestCaseSubDir);
    832             if not self._hardenedPathExists(sDstDir):
    833                 self._hardenedMkDir(sDstDir);
     893            if not self._wrapPathExists(sDstDir):
     894                self._wrapMkDir(sDstDir);
    834895                asDirsToRemove.append(sDstDir);
    835896
    836897            sDst = os.path.join(sDstDir, os.path.basename(sFullPath));
    837             self._hardenedCopyFile(sFullPath, sDst, 0o755);
     898            self._wrapCopyFile(sFullPath, sDst, 0o755);
    838899            asFilesToRemove.append(sDst);
    839900
     
    842903                for sLib in self.kdTestCaseDepsLibs:
    843904                    for sSuff in [ '.dll', '.so', '.dylib' ]:
     905                        assert self.sVBoxInstallRoot is not None;
    844906                        sSrc = os.path.join(self.sVBoxInstallRoot, sLib + sSuff);
    845                         if os.path.exists(sSrc):
     907                        if self._wrapPathExists(sSrc):
    846908                            sDst = os.path.join(sDstDir, os.path.basename(sSrc));
    847                             self._hardenedCopyFile(sSrc, sDst, 0o644);
     909                            self._wrapCopyFile(sSrc, sDst, 0o644);
    848910                            asFilesToRemove.append(sDst);
    849911
     
    853915                if os.path.exists(sSrc):
    854916                    sDst = os.path.join(sDstDir, os.path.basename(sSrc));
    855                     self._hardenedCopyFile(sSrc, sDst, 0o644);
     917                    self._wrapCopyFile(sSrc, sDst, 0o644);
    856918                    asFilesToRemove.append(sDst);
    857919
     
    863925                    if os.path.exists(sSrc):
    864926                        sDst = os.path.join(sDstDir, os.path.basename(sSrc));
    865                         self._hardenedCopyFile(sSrc, sDst, 0o644);
     927                        self._wrapCopyFile(sSrc, sDst, 0o644);
    866928                        asFilesToRemove.append(sDst);
    867929
     
    880942        self._envSet('IPRT_TEST_FILE', sXmlFile);
    881943
    882         if self._hardenedPathExists(sXmlFile):
     944        if self._wrapPathExists(sXmlFile):
    883945            try:    os.unlink(sXmlFile);
    884             except: self._hardenedDeleteFile(sXmlFile);
     946            except: self._wrapDeleteFile(sXmlFile);
    885947
    886948        #
     
    897959        try:    sys.stderr.flush();
    898960        except: pass;
     961
     962        iRc = 0;
     963
    899964        if not self.fDryRun:
    900             if fToRemote:
     965            if fCopyToRemote:
    901966                fRc = self.txsRunTest(self.oTxsSession, sName, 30 * 60 * 1000, asArgs[0], asArgs, self.asEnv, \
    902                                       fCheckSessionStatus = True);
     967                                        fCheckSessionStatus = True);
    903968                if fRc:
    904969                    iRc = 0;
     
    912977                        iRc = -1; ## @todo
    913978            else:
     979                oChild = None;
    914980                try:
    915981                    if fHardened:
     
    931997                    iRc = oChild.wait();
    932998                    self.pidFileRemove(oChild.pid);
    933         else:
    934             iRc = 0;
    935 
    936999        #
    9371000        # Clean up
    9381001        #
    9391002        for sPath in asFilesToRemove:
    940             self._hardenedDeleteFile(sPath);
     1003            self._wrapDeleteFile(sPath);
    9411004        for sPath in asDirsToRemove:
    942             self._hardenedRemoveDir(sPath);
     1005            self._wrapRemoveDir(sPath);
    9431006
    9441007        #
     
    9481011            reporter.addSubXmlFile(sXmlFile);
    9491012            if fHardened:
    950                 self._hardenedDeleteFile(sXmlFile);
     1013                self._wrapDeleteFile(sXmlFile);
    9511014            else:
    9521015                os.unlink(sXmlFile);
     
    10021065        # Process the file list and run everything looking like a testcase.
    10031066        #
    1004         for sFilename in sorted(os.listdir(os.path.join(self.sUnitTestsPathSrc, sTestCaseSubDir))):
     1067        if not self.fOnlyWhiteList:
     1068            if self.sMode == 'local' \
     1069            or self.sMode == 'remote-copy':
     1070                asFiles = sorted(os.listdir(os.path.join(self.sUnitTestsPathSrc, sTestCaseSubDir)));
     1071            else: # 'remote-exec'
     1072                ## @todo Implement remote file enumeration / directory listing.
     1073                reporter.error('Sorry, no remote file enumeration implemented yet!\nUse --only-whitelist instead.');
     1074                return False;
     1075        else:
     1076            # Transform our dict into a list, where the keys are the list elements.
     1077            asFiles = list(self.kdTestCasesWhiteList.keys());
     1078            # Make sure to only keep the list item's base name so that the iteration down below works
     1079            # with our white list without any additional modification.
     1080            asFiles = [os.path.basename(s) for s in asFiles];
     1081
     1082        for sFilename in asFiles:
    10051083            # Separate base and suffix and morph the base into something we
    10061084            # can use for reporting and array lookups.
    1007             sName, sSuffix = os.path.splitext(sFilename);
     1085            sBaseName = os.path.basename(sFilename);
     1086            sName, sSuffix = os.path.splitext(sBaseName);
    10081087            if sTestCaseSubDir != '.':
    10091088                sName = sTestCaseSubDir + '/' + sName;
    10101089
     1090            reporter.log2('sTestCasePattern=%s, sBaseName=%s, sName=%s, sFileName=%s' \
     1091                          % (sTestCasePattern, sBaseName, sName, sFilename,));
     1092
    10111093            # Process white list first, if set.
    10121094            if  self.fOnlyWhiteList \
    1013             and sName not in self.kdTestCasesWhiteList:
    1014                 reporter.log2('"%s" is not in white list, skipping.' % (sFilename,));
     1095            and not self._isExcluded(sName, self.kdTestCasesWhiteList):
     1096                reporter.log('%s: SKIPPED (not in white list)' % (sName,));
    10151097                continue;
    10161098
    10171099            # Basic exclusion.
    1018             if   not re.match(sTestCasePattern, sFilename) \
     1100            if   not re.match(sTestCasePattern, sBaseName) \
    10191101              or sSuffix in self.kasSuffixBlackList:
    1020                 reporter.log2('"%s" is not a test case.' % (sFilename,));
     1102                reporter.log2('"%s" is not a test case.' % (sName,));
    10211103                continue;
    10221104
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette