VirtualBox

Changeset 79185 in vbox


Ignore:
Timestamp:
Jun 17, 2019 2:19:41 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
131357
Message:

vboxtestfileset.py: Generatlized and split up, leaving vboxtestfilesset.py containing the VBox VM specialization. bugref:9151 bugref:9320

Location:
trunk/src/VBox/ValidationKit
Files:
3 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/Makefile.kmk

    r79158 r79185  
    6969        $(PATH_SUB_CURRENT)/testdriver/btresolver.py \
    7070        $(PATH_SUB_CURRENT)/testdriver/reporter.py \
     71        $(PATH_SUB_CURRENT)/testdriver/testfileset.py \
    7172        $(PATH_SUB_CURRENT)/testdriver/tst-txsclient.py \
    7273        $(PATH_SUB_CURRENT)/testdriver/txsclient.py \
  • trunk/src/VBox/ValidationKit/testdriver/testfileset.py

    r79180 r79185  
    44
    55"""
    6 VirtualBox Test File Set
     6Test File Set
    77"""
    88
     
    3737import sys;
    3838import tarfile;
     39import unittest;
    3940
    4041# Validation Kit imports.
    4142from common     import utils;
     43from common     import pathutils;
    4244from testdriver import reporter;
    4345
     
    4850
    4951
    50 class GstFsObj(object):
    51     """ A file system object we created in the guest for test purposes. """
     52class TestFsObj(object):
     53    """ A file system object we created in for test purposes. """
    5254    def __init__(self, oParent, sPath):
    53         self.oParent   = oParent    # type: GstDir
     55        self.oParent   = oParent    # type: TestDir
    5456        self.sPath     = sPath      # type: str
    5557        self.sName     = sPath      # type: str
     
    6163            oParent.dChildrenUpper[self.sName.upper()] = self;
    6264
    63 class GstFile(GstFsObj):
     65class TestFile(TestFsObj):
    6466    """ A file object in the guest. """
    6567    def __init__(self, oParent, sPath, abContent):
    66         GstFsObj.__init__(self, oParent, sPath);
     68        TestFsObj.__init__(self, oParent, sPath);
    6769        self.abContent = abContent          # type: bytearray
    6870        self.cbContent = len(abContent);
     
    7072
    7173    def read(self, cbToRead):
     74        """ read() emulation. """
    7275        assert self.off <= self.cbContent;
    7376        cbLeft = self.cbContent - self.off;
     
    8184        return abRet;
    8285
    83 class GstDir(GstFsObj):
     86class TestDir(TestFsObj):
    8487    """ A file object in the guest. """
    8588    def __init__(self, oParent, sPath):
    86         GstFsObj.__init__(self, oParent, sPath);
    87         self.aoChildren     = []  # type: list(GsFsObj)
    88         self.dChildrenUpper = {}  # type: dict(str,GsFsObj)
     89        TestFsObj.__init__(self, oParent, sPath);
     90        self.aoChildren     = []  # type: list(TestFsObj)
     91        self.dChildrenUpper = {}  # type: dict(str, TestFsObj)
    8992
    9093    def contains(self, sName):
     
    9598class TestFileSet(object):
    9699    """
    97     Generates a set of files and directories for use in a test.
    98 
    99     Uploaded as a tarball and expanded via TXS (if new enough) or uploaded vts_tar
    100     utility from the validation kit.
     100    A generated set of files and directories for use in a test.
     101
     102    Can be wrapped up into a tarball or written directly to the file system.
    101103    """
    102104
     
    106108    ksReservedTrailingUnix   = '';
    107109
    108     def __init__(self, oTestVm, sBasePath, sSubDir, # pylint: disable=too-many-arguments
     110    ## @name Path style.
     111    ## @{
     112
     113    ## @}
     114
     115    def __init__(self, fDosStyle, sBasePath, sSubDir, # pylint: disable=too-many-arguments
     116                 asCompatibleWith = None,             # List of getHostOs values to the names must be compatible with.
    109117                 oRngFileSizes = xrange(0, 16384),
    110118                 oRngManyFiles = xrange(128, 512),
     
    113121                 oRngTreeDirs  = xrange(2, 16),
    114122                 cchMaxPath    = 230,
    115                  cchMaxName    = 230):
     123                 cchMaxName    = 230,
     124                 uSeed         = None):
    116125        ## @name Parameters
    117126        ## @{
    118         self.oTestVm       = oTestVm;
    119         self.sBasePath     = sBasePath;
    120         self.sSubDir       = sSubDir;
    121         self.oRngFileSizes = oRngFileSizes;
    122         self.oRngManyFiles = oRngManyFiles;
    123         self.oRngTreeFiles = oRngTreeFiles;
    124         self.oRngTreeDepth = oRngTreeDepth;
    125         self.oRngTreeDirs  = oRngTreeDirs;
    126         self.cchMaxPath    = cchMaxPath;
    127         self.cchMaxName    = cchMaxName
     127        self.fDosStyle          = fDosStyle;
     128        self.sMinStyle          = 'win' if fDosStyle else 'linux';
     129        if asCompatibleWith is not None:
     130            for sOs in asCompatibleWith:
     131                assert sOs in ('win', 'os2', 'darwin', 'linux', 'solaris',), sOs;
     132            if 'os2' in asCompatibleWith:
     133                self.sMinStyle      = 'os2';
     134            elif 'win' in asCompatibleWith:
     135                self.sMinStyle      = 'win';
     136        self.sBasePath          = sBasePath;
     137        self.sSubDir            = sSubDir;
     138        self.oRngFileSizes      = oRngFileSizes;
     139        self.oRngManyFiles      = oRngManyFiles;
     140        self.oRngTreeFiles      = oRngTreeFiles;
     141        self.oRngTreeDepth      = oRngTreeDepth;
     142        self.oRngTreeDirs       = oRngTreeDirs;
     143        self.cchMaxPath         = cchMaxPath;
     144        self.cchMaxName         = cchMaxName
    128145        ## @}
    129146
    130147        ## @name Charset stuff
    131148        ## @todo allow more chars for unix hosts + guests.
     149        ## @todo include unicode stuff, except on OS/2 and DOS.
    132150        ## @{
    133151        ## The filename charset.
    134152        self.sFileCharset             = string.printable;
    135         ## The filename charset common to host and guest.
    136         self.sFileCharsetCommon       = string.printable;
    137153        ## Set of characters that should not trail a guest filename.
    138154        self.sReservedTrailing        = self.ksReservedTrailingWinOS2;
    139         ## Set of characters that should not trail a host or guest filename.
    140         self.sReservedTrailingCommon  = self.ksReservedTrailingWinOS2;
    141         if oTestVm.isWindows() or oTestVm.isOS2():
     155        if self.sMinStyle in ('win', 'os2'):
    142156            for ch in self.ksReservedWinOS2:
    143157                self.sFileCharset     = self.sFileCharset.replace(ch, '');
     
    146160            for ch in self.ksReservedUnix:
    147161                self.sFileCharset     = self.sFileCharset.replace(ch, '');
     162        # More spaces and dot:
    148163        self.sFileCharset            += '   ...';
    149 
    150         for ch in self.ksReservedWinOS2:
    151             self.sFileCharsetCommon   = self.sFileCharset.replace(ch, '');
    152         self.sFileCharsetCommon      += '   ...';
    153164        ## @}
    154165
    155166        ## The root directory.
    156         self.oRoot      = None      # type: GstDir;
     167        self.oRoot      = None      # type: TestDir;
    157168        ## An empty directory (under root).
    158         self.oEmptyDir  = None      # type: GstDir;
     169        self.oEmptyDir  = None      # type: TestDir;
    159170
    160171        ## A directory with a lot of files in it.
    161         self.oManyDir   = None      # type: GstDir;
     172        self.oManyDir   = None      # type: TestDir;
    162173
    163174        ## A directory with a mixed tree structure under it.
    164         self.oTreeDir   = None      # type: GstDir;
     175        self.oTreeDir   = None      # type: TestDir;
    165176        ## Number of files in oTreeDir.
    166177        self.cTreeFiles = 0;
     
    171182
    172183        ## All directories in creation order.
    173         self.aoDirs     = []        # type: list(GstDir);
     184        self.aoDirs     = []        # type: list(TestDir);
    174185        ## All files in creation order.
    175         self.aoFiles    = []        # type: list(GstFile);
     186        self.aoFiles    = []        # type: list(TestFile);
    176187        ## Path to object lookup.
    177         self.dPaths     = {}        # type: dict(str, GstFsObj);
     188        self.dPaths     = {}        # type: dict(str, TestFsObj);
    178189
    179190        #
    180191        # Do the creating.
    181192        #
    182         self.uSeed   = utils.timestampMilli();
     193        self.uSeed   = uSeed if uSeed is not None else utils.timestampMilli();
    183194        self.oRandom = random.Random();
    184195        self.oRandom.seed(self.uSeed);
     
    214225        return ''; # never reached, but makes pylint happy.
    215226
    216     def generateFilenameEx(self, cchMax = -1, cchMin = -1, fCommonCharset = True):
     227    def generateFilenameEx(self, cchMax = -1, cchMin = -1):
    217228        """
    218229        Generates a filename according to the given specs.
     
    228239            cchMax = self.cchMaxName;
    229240
    230         if fCommonCharset:
    231             sCharset            = self.sFileCharsetCommon;
    232             sReservedTrailing   = self.sReservedTrailingCommon;
    233         else:
    234             sCharset            = self.sFileCharset;
    235             sReservedTrailing   = self.sReservedTrailing;
    236 
    237241        while True:
    238242            cchName = self.oRandom.randrange(cchMin, cchMax + 1);
    239             sName = ''.join(self.oRandom.choice(sCharset) for _ in xrange(cchName));
    240             if sName[-1] not in sReservedTrailing:
     243            sName = ''.join(self.oRandom.choice(self.sFileCharset) for _ in xrange(cchName));
     244            if sName[-1] not in self.sReservedTrailing:
    241245                if sName not in ('.', '..',):
    242246                    return sName;
     
    247251        Creates a test directory.
    248252        """
    249         oDir = GstDir(oParent, sDir);
     253        oDir = TestDir(oParent, sDir);
    250254        self.aoDirs.append(oDir);
    251255        self.dPaths[sDir] = oDir;
     
    259263        abContent = bytearray(self.oRandom.getrandbits(8) for _ in xrange(cbFile));
    260264
    261         oFile = GstFile(oParent, sFile, abContent);
     265        oFile = TestFile(oParent, sFile, abContent);
    262266        self.aoFiles.append(oFile);
    263267        self.dPaths[sFile] = oFile;
     
    273277        # Create the root test dir.
    274278        #
    275         sRoot = self.oTestVm.pathJoin(self.sBasePath, self.sSubDir);
     279        sRoot = pathutils.joinEx(self.fDosStyle, self.sBasePath, self.sSubDir);
    276280        self.oRoot     = self.__createTestDir(None, sRoot);
    277         self.oEmptyDir = self.__createTestDir(self.oRoot, self.oTestVm.pathJoin(sRoot, 'empty'));
    278 
    279         #
    280         # Create a directory with about files in it using the guest specific charset:
    281         #
    282         oDir = self.__createTestDir(self.oRoot, self.oTestVm.pathJoin(sRoot, 'many'));
     281        self.oEmptyDir = self.__createTestDir(self.oRoot, pathutils.joinEx(self.fDosStyle, sRoot, 'empty'));
     282
     283        #
     284        # Create a directory with lots of files in it:
     285        #
     286        oDir = self.__createTestDir(self.oRoot, pathutils.joinEx(self.fDosStyle, sRoot, 'many'));
    283287        self.oManyDir = oDir;
    284288        cManyFiles = self.oRandom.choice(self.oRngManyFiles);
    285289        for _ in xrange(cManyFiles):
    286290            sName = self.__createFilename(oDir, self.sFileCharset, self.sReservedTrailing);
    287             self.__createTestFile(oDir, self.oTestVm.pathJoin(oDir.sPath, sName));
    288 
    289         #
    290         # Generate a tree of files and dirs. Portable character set.
    291         #
    292         oDir = self.__createTestDir(self.oRoot, self.oTestVm.pathJoin(sRoot, 'tree'));
     291            self.__createTestFile(oDir, pathutils.joinEx(self.fDosStyle, oDir.sPath, sName));
     292
     293        #
     294        # Generate a tree of files and dirs.
     295        #
     296        oDir = self.__createTestDir(self.oRoot, pathutils.joinEx(self.fDosStyle, sRoot, 'tree'));
    293297        uMaxDepth       = self.oRandom.choice(self.oRngTreeDepth);
    294298        cMaxFiles       = self.oRandom.choice(self.oRngTreeFiles);
     
    302306            # 0: Add a file:
    303307            if iAction == 0 and self.cTreeFiles < cMaxFiles and len(oDir.sPath) < 230 - 2:
    304                 sName = self.__createFilename(oDir, self.sFileCharsetCommon, self.sReservedTrailingCommon);
    305                 self.__createTestFile(oDir, self.oTestVm.pathJoin(oDir.sPath, sName));
     308                sName = self.__createFilename(oDir, self.sFileCharset, self.sReservedTrailing);
     309                self.__createTestFile(oDir, pathutils.joinEx(self.fDosStyle, oDir.sPath, sName));
    306310                self.cTreeFiles += 1;
    307311            # 1: Add a subdirector and descend into it:
    308312            elif iAction == 1 and self.cTreeDirs < cMaxDirs and uDepth < uMaxDepth and len(oDir.sPath) < 220:
    309                 sName = self.__createFilename(oDir, self.sFileCharsetCommon, self.sReservedTrailingCommon);
    310                 oDir  = self.__createTestDir(oDir, self.oTestVm.pathJoin(oDir.sPath, sName));
     313                sName = self.__createFilename(oDir, self.sFileCharset, self.sReservedTrailing);
     314                oDir  = self.__createTestDir(oDir, pathutils.joinEx(self.fDosStyle, oDir.sPath, sName));
    311315                self.cTreeDirs  += 1;
    312316                uDepth += 1;
     
    325329        reporter.log('Creating tarball "%s" with test files for the guest...' % (sTarFileHst,));
    326330
    327         chOtherSlash = '\\' if self.oTestVm.isWindows() or self.oTestVm.isOS2() else '/';
    328         cchSkip      = len(self.sBasePath) + 1;
     331        cchSkip = len(self.sBasePath) + 1;
    329332
    330333        # Open the tarball:
     
    336339        # Directories:
    337340        for oDir in self.aoDirs:
    338             oTarInfo = tarfile.TarInfo(oDir.sPath[cchSkip:].replace(chOtherSlash, '/') + '/');
     341            sPath = oDir.sPath[cchSkip:];
     342            if self.fDosStyle:
     343                sPath = sPath.replace('\\', '/');
     344            oTarInfo = tarfile.TarInfo(sPath + '/');
    339345            oTarInfo.mode = 0o777;
    340346            oTarInfo.type = tarfile.DIRTYPE;
     
    346352        # Files:
    347353        for oFile in self.aoFiles:
    348             oTarInfo = tarfile.TarInfo(oFile.sPath[cchSkip:].replace(chOtherSlash, '/'));
     354            sPath = oFile.sPath[cchSkip:];
     355            if self.fDosStyle:
     356                sPath = sPath.replace('\\', '/');
     357            oTarInfo = tarfile.TarInfo(sPath);
    349358            oTarInfo.size = len(oFile.abContent);
    350359            oFile.off = 0;
     
    361370        return True;
    362371
    363     def __uploadFallback(self, oTxsSession, sTarFileGst, oTstDrv):
    364         """
    365         Fallback upload method.
    366         """
    367 
    368         ## Directories:
    369         #for oDir in self.aoDirs:
    370         #    if oTxsSession.syncMkDirPath(oDir.sPath, 0o777) is not True:
    371         #        return reporter.error('Failed to create directory "%s"!' % (oDir.sPath,));
    372         #
    373         ## Files:
    374         #for oFile in self.aoFiles:
    375         #    if oTxsSession.syncUploadString(oFile.abContent, oFile.sPath) is not True:
    376         #        return reporter.error('Failed to create file "%s" with %s content bytes!' % (oFile.sPath, oFile.cbContent));
    377 
    378         sVtsTarExe = 'vts_tar' + self.oTestVm.getGuestExeSuff();
    379         sVtsTarHst = os.path.join(oTstDrv.sVBoxValidationKit, self.oTestVm.getGuestOs(),
    380                                   self.oTestVm.getGuestArch(), sVtsTarExe);
    381         sVtsTarGst = self.oTestVm.pathJoin(self.sBasePath, sVtsTarExe);
    382 
    383         if oTxsSession.syncUploadFile(sVtsTarHst, sVtsTarGst) is not True:
    384             return reporter.error('Failed to upload "%s" to the guest as "%s"!' % (sVtsTarHst, sVtsTarGst,));
    385 
    386         fRc = oTxsSession.syncExec(sVtsTarGst, [sVtsTarGst, '-xzf', sTarFileGst, '-C', self.sBasePath,], fWithTestPipe = False);
    387         if fRc is not True:
    388             return reporter.error('vts_tar failed!');
     372    def writeToDisk(self, sAltBase = None):
     373        """
     374        Writes out the files to disk.
     375        Returns True on success, False + error logging on failure.
     376        """
     377
     378        # The directories:
     379        for oDir in self.aoDirs:
     380            sPath = oDir.sPath;
     381            if sAltBase:
     382                sPath = sAltBase + sPath[len(self.sBasePath):];
     383
     384            try:
     385                os.mkdir(sPath, 0o770);
     386            except:
     387                return reporter.errorXcpt('mkdir(%s) failed' % (sPath,));
     388
     389        # The files:
     390        for oFile in self.aoFiles:
     391            sPath = oFile.sPath;
     392            if sAltBase:
     393                sPath = sAltBase + sPath[len(self.sBasePath):];
     394
     395            try:
     396                oFile = open(sPath, 'wb');
     397            except:
     398                return reporter.errorXcpt('open(%s, "wb") failed' % (sPath,));
     399            try:
     400                if sys.version_info[0] < 3:
     401                    oFile.write(bytes(oFile.abContent));
     402                else:
     403                    oFile.write(oFile.abContent);
     404            except:
     405                try:    oFile.close();
     406                except: pass;
     407                return reporter.errorXcpt('%s: write(%s bytes) failed' % (sPath, oFile.cbContent,));
     408            try:
     409                oFile.close();
     410            except:
     411                return reporter.errorXcpt('%s: close() failed' % (sPath,));
     412
    389413        return True;
    390414
    391     def upload(self, oTxsSession, oTstDrv):
    392         """
    393         Uploads the files into the guest via the given TXS session.
    394 
    395         Returns True / False.
    396         """
    397 
    398         #
    399         # Create a tarball.
    400         #
    401         sTarFileHst = os.path.join(oTstDrv.sScratchPath, 'tdAddGuestCtrl-1-Stuff.tar.gz');
    402         sTarFileGst = self.oTestVm.pathJoin(self.sBasePath, 'tdAddGuestCtrl-1-Stuff.tar.gz');
    403         if self.createTarball(sTarFileHst) is not True:
    404             return False;
    405 
    406         #
    407         # Upload it.
    408         #
    409         reporter.log('Uploading tarball "%s" to the guest as "%s"...' % (sTarFileHst, sTarFileGst));
    410         if oTxsSession.syncUploadFile(sTarFileHst, sTarFileGst) is not True:
    411             return reporter.error('Failed upload tarball "%s" as "%s"!' % (sTarFileHst, sTarFileGst,));
    412 
    413         #
    414         # Try unpack it.
    415         #
    416         reporter.log('Unpacking "%s" into "%s"...' % (sTarFileGst, self.sBasePath));
    417         if oTxsSession.syncUnpackFile(sTarFileGst, self.sBasePath, fIgnoreErrors = True) is not True:
    418             reporter.log('Failed to expand tarball "%s" into "%s", falling back on individual directory and file creation...'
    419                          % (sTarFileGst, self.sBasePath,));
    420             if self.__uploadFallback(oTxsSession, sTarFileGst, oTstDrv) is not True:
    421                 return False;
    422         reporter.log('Successfully placed test files and directories in the VM.');
    423         return True;
    424 
    425     def chooseRandomFileFromTree(self):
    426         """
    427         Returns a random file from the tree (self.oTreeDir).
    428         """
    429         while True:
    430             oFile = self.aoFiles[self.oRandom.choice(xrange(len(self.aoFiles)))];
    431             oParent = oFile.oParent;
    432             while oParent is not None:
    433                 if oParent is self.oTreeDir:
    434                     return oFile;
    435                 oParent = oParent.oParent;
     415
     416    def chooseRandomFile(self):
     417        """
     418        Returns a random file.
     419        """
     420        return self.aoFiles[self.oRandom.choice(xrange(len(self.aoFiles)))];
    436421
    437422    def chooseRandomDirFromTree(self, fLeaf = False, fNonEmpty = False):
    438423        """
    439         Returns a random directoryr from the tree (self.oTreeDir).
     424        Returns a random directory from the tree (self.oTreeDir).
    440425        """
    441426        while True:
     
    446431                if not fLeaf:
    447432                    for oChild in oDir.aoChildren:
    448                         if isinstance(oChild, GstDir):
     433                        if isinstance(oChild, TestDir):
    449434                            continue; # skip it.
    450435
     
    456441                    oParent = oParent.oParent;
    457442
    458 
     443#
     444# Unit testing.
     445#
     446
     447# pylint: disable=missing-docstring
     448# pylint: disable=undefined-variable
     449class TestFileSetUnitTests(unittest.TestCase):
     450    def testGeneral(self):
     451        oSet = TestFileSet(False, '/tmp', 'unittest');
     452        self.assertTrue(isinstance(oSet.chooseRandomDirFromTree(), TestDir));
     453        self.assertTrue(isinstance(oSet.chooseRandomFile(), TestFile));
     454
     455
     456if __name__ == '__main__':
     457    unittest.main();
     458    # not reached.
     459
  • trunk/src/VBox/ValidationKit/testdriver/vboxtestfileset.py

    r79182 r79185  
    44
    55"""
    6 VirtualBox Test File Set
     6Test File Set
    77"""
    88
     
    3333# Standard Python imports.
    3434import os;
    35 import random;
    36 import string;
    3735import sys;
    38 import tarfile;
    3936
    4037# Validation Kit imports.
    4138from common     import utils;
    4239from testdriver import reporter;
     40from testdriver import testfileset;
    4341
    4442# Python 3 hacks:
     
    4745
    4846
     47class TestFileSet(testfileset.TestFileSet):
     48    """
     49    A generated set of files and directories for uploading to a VM.
    4950
    50 class GstFsObj(object):
    51     """ A file system object we created in the guest for test purposes. """
    52     def __init__(self, oParent, sPath):
    53         self.oParent   = oParent    # type: GstDir
    54         self.sPath     = sPath      # type: str
    55         self.sName     = sPath      # type: str
    56         if oParent:
    57             assert sPath.startswith(oParent.sPath);
    58             self.sName = sPath[len(oParent.sPath) + 1:];
    59             # Add to parent.
    60             oParent.aoChildren.append(self);
    61             oParent.dChildrenUpper[self.sName.upper()] = self;
    62 
    63 class GstFile(GstFsObj):
    64     """ A file object in the guest. """
    65     def __init__(self, oParent, sPath, abContent):
    66         GstFsObj.__init__(self, oParent, sPath);
    67         self.abContent = abContent          # type: bytearray
    68         self.cbContent = len(abContent);
    69         self.off       = 0;
    70 
    71     def read(self, cbToRead):
    72         assert self.off <= self.cbContent;
    73         cbLeft = self.cbContent - self.off;
    74         if cbLeft < cbToRead:
    75             cbToRead = cbLeft;
    76         abRet = self.abContent[self.off:(self.off + cbToRead)];
    77         assert len(abRet) == cbToRead;
    78         self.off += cbToRead;
    79         if sys.version_info[0] < 3:
    80             return bytes(abRet);
    81         return abRet;
    82 
    83 class GstDir(GstFsObj):
    84     """ A file object in the guest. """
    85     def __init__(self, oParent, sPath):
    86         GstFsObj.__init__(self, oParent, sPath);
    87         self.aoChildren     = []  # type: list(GsFsObj)
    88         self.dChildrenUpper = {}  # type: dict(str,GsFsObj)
    89 
    90     def contains(self, sName):
    91         """ Checks if the directory contains the given name. """
    92         return sName.upper() in self.dChildrenUpper
    93 
    94 
    95 class TestFileSet(object):
    96     """
    97     Generates a set of files and directories for use in a test.
     51    The file and directory names are compatible with the host, so it is
     52    possible to copy them to the host without changing any names.
    9853
    9954    Uploaded as a tarball and expanded via TXS (if new enough) or uploaded vts_tar
    10055    utility from the validation kit.
    10156    """
    102 
    103     ksReservedWinOS2         = '/\\"*:<>?|\t\v\n\r\f\a\b';
    104     ksReservedUnix           = '/';
    105     ksReservedTrailingWinOS2 = ' .';
    106     ksReservedTrailingUnix   = '';
    10757
    10858    def __init__(self, oTestVm, sBasePath, sSubDir, # pylint: disable=too-many-arguments
     
    11363                 oRngTreeDirs  = xrange(2, 16),
    11464                 cchMaxPath    = 230,
    115                  cchMaxName    = 230):
    116         ## @name Parameters
    117         ## @{
    118         self.oTestVm       = oTestVm;
    119         self.sBasePath     = sBasePath;
    120         self.sSubDir       = sSubDir;
    121         self.oRngFileSizes = oRngFileSizes;
    122         self.oRngManyFiles = oRngManyFiles;
    123         self.oRngTreeFiles = oRngTreeFiles;
    124         self.oRngTreeDepth = oRngTreeDepth;
    125         self.oRngTreeDirs  = oRngTreeDirs;
    126         self.cchMaxPath    = cchMaxPath;
    127         self.cchMaxName    = cchMaxName
    128         ## @}
     65                 cchMaxName    = 230,
     66                 uSeed         = None):
    12967
    130         ## @name Charset stuff
    131         ## @todo allow more chars for unix hosts + guests.
    132         ## @{
    133         ## The filename charset.
    134         self.sFileCharset             = string.printable;
    135         ## The filename charset common to host and guest.
    136         self.sFileCharsetCommon       = string.printable;
    137         ## Set of characters that should not trail a guest filename.
    138         self.sReservedTrailing        = self.ksReservedTrailingWinOS2;
    139         ## Set of characters that should not trail a host or guest filename.
    140         self.sReservedTrailingCommon  = self.ksReservedTrailingWinOS2;
    141         if oTestVm.isWindows() or oTestVm.isOS2():
    142             for ch in self.ksReservedWinOS2:
    143                 self.sFileCharset     = self.sFileCharset.replace(ch, '');
    144         else:
    145             self.sReservedTrailing    = self.ksReservedTrailingUnix;
    146             for ch in self.ksReservedUnix:
    147                 self.sFileCharset     = self.sFileCharset.replace(ch, '');
    148         self.sFileCharset            += '   ...';
     68        asCompOses = [oTestVm.getGuestOs(), ];
     69        sHostOs = utils.getHostOs();
     70        if sHostOs not in asCompOses:
     71            asCompOses.append(sHostOs);
    14972
    150         for ch in self.ksReservedWinOS2:
    151             self.sFileCharsetCommon   = self.sFileCharset.replace(ch, '');
    152         self.sFileCharsetCommon      += '   ...';
    153         ## @}
    154 
    155         ## The root directory.
    156         self.oRoot      = None      # type: GstDir;
    157         ## An empty directory (under root).
    158         self.oEmptyDir  = None      # type: GstDir;
    159 
    160         ## A directory with a lot of files in it.
    161         self.oManyDir   = None      # type: GstDir;
    162 
    163         ## A directory with a mixed tree structure under it.
    164         self.oTreeDir   = None      # type: GstDir;
    165         ## Number of files in oTreeDir.
    166         self.cTreeFiles = 0;
    167         ## Number of directories under oTreeDir.
    168         self.cTreeDirs  = 0;
    169         ## Number of other file types under oTreeDir.
    170         self.cTreeOthers = 0;
    171 
    172         ## All directories in creation order.
    173         self.aoDirs     = []        # type: list(GstDir);
    174         ## All files in creation order.
    175         self.aoFiles    = []        # type: list(GstFile);
    176         ## Path to object lookup.
    177         self.dPaths     = {}        # type: dict(str, GstFsObj);
    178 
    179         #
    180         # Do the creating.
    181         #
    182         self.uSeed   = utils.timestampMilli();
    183         self.oRandom = random.Random();
    184         self.oRandom.seed(self.uSeed);
    185         reporter.log('prepareGuestForTesting: random seed %s' % (self.uSeed,));
    186 
    187         self.__createTestStuff();
    188 
    189     def __createFilename(self, oParent, sCharset, sReservedTrailing):
    190         """
    191         Creates a filename contains random characters from sCharset and together
    192         with oParent.sPath doesn't exceed the given max chars in length.
    193         """
    194         ## @todo Consider extending this to take UTF-8 and UTF-16 encoding so we
    195         ##       can safely use the full unicode range.  Need to check how
    196         ##       RTZipTarCmd handles file name encoding in general...
    197 
    198         if oParent:
    199             cchMaxName = self.cchMaxPath - len(oParent.sPath) - 1;
    200         else:
    201             cchMaxName = self.cchMaxPath - 4;
    202         if cchMaxName > self.cchMaxName:
    203             cchMaxName = self.cchMaxName;
    204         if cchMaxName <= 1:
    205             cchMaxName = 2;
    206 
    207         while True:
    208             cchName = self.oRandom.randrange(1, cchMaxName);
    209             sName = ''.join(self.oRandom.choice(sCharset) for _ in xrange(cchName));
    210             if oParent is None or not oParent.contains(sName):
    211                 if sName[-1] not in sReservedTrailing:
    212                     if sName not in ('.', '..',):
    213                         return sName;
    214         return ''; # never reached, but makes pylint happy.
    215 
    216     def generateFilenameEx(self, cchMax = -1, cchMin = -1, fCommonCharset = True):
    217         """
    218         Generates a filename according to the given specs.
    219 
    220         This is for external use, whereas __createFilename is for internal.
    221 
    222         Returns generated filename.
    223         """
    224         assert cchMax == -1 or (cchMax >= 1 and cchMax > cchMin);
    225         if cchMin <= 0:
    226             cchMin = 1;
    227         if cchMax < cchMin:
    228             cchMax = self.cchMaxName;
    229 
    230         if fCommonCharset:
    231             sCharset            = self.sFileCharsetCommon;
    232             sReservedTrailing   = self.sReservedTrailingCommon;
    233         else:
    234             sCharset            = self.sFileCharset;
    235             sReservedTrailing   = self.sReservedTrailing;
    236 
    237         while True:
    238             cchName = self.oRandom.randrange(cchMin, cchMax + 1);
    239             sName = ''.join(self.oRandom.choice(sCharset) for _ in xrange(cchName));
    240             if sName[-1] not in sReservedTrailing:
    241                 if sName not in ('.', '..',):
    242                     return sName;
    243         return ''; # never reached, but makes pylint happy.
    244 
    245     def __createTestDir(self, oParent, sDir):
    246         """
    247         Creates a test directory.
    248         """
    249         oDir = GstDir(oParent, sDir);
    250         self.aoDirs.append(oDir);
    251         self.dPaths[sDir] = oDir;
    252         return oDir;
    253 
    254     def __createTestFile(self, oParent, sFile):
    255         """
    256         Creates a test file with random size up to cbMaxContent and random content.
    257         """
    258         cbFile = self.oRandom.choice(self.oRngFileSizes);
    259         abContent = bytearray(self.oRandom.getrandbits(8) for _ in xrange(cbFile));
    260 
    261         oFile = GstFile(oParent, sFile, abContent);
    262         self.aoFiles.append(oFile);
    263         self.dPaths[sFile] = oFile;
    264         return oFile;
    265 
    266     def __createTestStuff(self):
    267         """
    268         Create a random file set that we can work on in the tests.
    269         Returns True/False.
    270         """
    271 
    272         #
    273         # Create the root test dir.
    274         #
    275         sRoot = self.oTestVm.pathJoin(self.sBasePath, self.sSubDir);
    276         self.oRoot     = self.__createTestDir(None, sRoot);
    277         self.oEmptyDir = self.__createTestDir(self.oRoot, self.oTestVm.pathJoin(sRoot, 'empty'));
    278 
    279         #
    280         # Create a directory with about files in it using the guest specific charset:
    281         #
    282         oDir = self.__createTestDir(self.oRoot, self.oTestVm.pathJoin(sRoot, 'many'));
    283         self.oManyDir = oDir;
    284         cManyFiles = self.oRandom.choice(self.oRngManyFiles);
    285         for _ in xrange(cManyFiles):
    286             sName = self.__createFilename(oDir, self.sFileCharset, self.sReservedTrailing);
    287             self.__createTestFile(oDir, self.oTestVm.pathJoin(oDir.sPath, sName));
    288 
    289         #
    290         # Generate a tree of files and dirs. Portable character set.
    291         #
    292         oDir = self.__createTestDir(self.oRoot, self.oTestVm.pathJoin(sRoot, 'tree'));
    293         uMaxDepth       = self.oRandom.choice(self.oRngTreeDepth);
    294         cMaxFiles       = self.oRandom.choice(self.oRngTreeFiles);
    295         cMaxDirs        = self.oRandom.choice(self.oRngTreeDirs);
    296         self.oTreeDir   = oDir;
    297         self.cTreeFiles = 0;
    298         self.cTreeDirs  = 0;
    299         uDepth          = 0;
    300         while self.cTreeFiles < cMaxFiles and self.cTreeDirs < cMaxDirs:
    301             iAction = self.oRandom.randrange(0, 2+1);
    302             # 0: Add a file:
    303             if iAction == 0 and self.cTreeFiles < cMaxFiles and len(oDir.sPath) < 230 - 2:
    304                 sName = self.__createFilename(oDir, self.sFileCharsetCommon, self.sReservedTrailingCommon);
    305                 self.__createTestFile(oDir, self.oTestVm.pathJoin(oDir.sPath, sName));
    306                 self.cTreeFiles += 1;
    307             # 1: Add a subdirector and descend into it:
    308             elif iAction == 1 and self.cTreeDirs < cMaxDirs and uDepth < uMaxDepth and len(oDir.sPath) < 220:
    309                 sName = self.__createFilename(oDir, self.sFileCharsetCommon, self.sReservedTrailingCommon);
    310                 oDir  = self.__createTestDir(oDir, self.oTestVm.pathJoin(oDir.sPath, sName));
    311                 self.cTreeDirs  += 1;
    312                 uDepth += 1;
    313             # 2: Ascend to parent dir:
    314             elif iAction == 2 and uDepth > 0:
    315                 oDir = oDir.oParent;
    316                 uDepth -= 1;
    317 
    318         return True;
    319 
    320     def createTarball(self, sTarFileHst):
    321         """
    322         Creates a tarball on the host.
    323         Returns success indicator.
    324         """
    325         reporter.log('Creating tarball "%s" with test files for the guest...' % (sTarFileHst,));
    326 
    327         chOtherSlash = '\\' if self.oTestVm.isWindows() or self.oTestVm.isOS2() else '/';
    328         cchSkip      = len(self.sBasePath) + 1;
    329 
    330         # Open the tarball:
    331         try:
    332             oTarFile = tarfile.open(sTarFileHst, 'w:gz');
    333         except:
    334             return reporter.errorXcpt('Failed to open new tar file: %s' % (sTarFileHst,));
    335 
    336         # Directories:
    337         for oDir in self.aoDirs:
    338             oTarInfo = tarfile.TarInfo(oDir.sPath[cchSkip:].replace(chOtherSlash, '/') + '/');
    339             oTarInfo.mode = 0o777;
    340             oTarInfo.type = tarfile.DIRTYPE;
    341             try:
    342                 oTarFile.addfile(oTarInfo);
    343             except:
    344                 return reporter.errorXcpt('Failed adding directory tarfile: %s' % (oDir.sPath,));
    345 
    346         # Files:
    347         for oFile in self.aoFiles:
    348             oTarInfo = tarfile.TarInfo(oFile.sPath[cchSkip:].replace(chOtherSlash, '/'));
    349             oTarInfo.size = len(oFile.abContent);
    350             oFile.off = 0;
    351             try:
    352                 oTarFile.addfile(oTarInfo, oFile);
    353             except:
    354                 return reporter.errorXcpt('Failed adding directory tarfile: %s' % (oFile.sPath,));
    355 
    356         # Complete the tarball.
    357         try:
    358             oTarFile.close();
    359         except:
    360             return reporter.errorXcpt('Error closing new tar file: %s' % (sTarFileHst,));
    361         return True;
     73        testfileset.TestFileSet.__init__(self,
     74                                         fDosStyle        = oTestVm.isWindows() or oTestVm.isOS2(),
     75                                         asCompatibleWith = asCompOses,
     76                                         sBasePath        = sBasePath,
     77                                         sSubDir          = sSubDir,
     78                                         oRngFileSizes    = oRngFileSizes,
     79                                         oRngManyFiles    = oRngManyFiles,
     80                                         oRngTreeFiles    = oRngTreeFiles,
     81                                         oRngTreeDepth    = oRngTreeDepth,
     82                                         oRngTreeDirs     = oRngTreeDirs,
     83                                         cchMaxPath       = cchMaxPath,
     84                                         cchMaxName       = cchMaxName,
     85                                         uSeed            = uSeed);
     86        self.oTestVm = oTestVm;
    36287
    36388    def __uploadFallback(self, oTxsSession, sTarFileGst, oTstDrv):
     
    36590        Fallback upload method.
    36691        """
    367 
    368         ## Directories:
    369         #for oDir in self.aoDirs:
    370         #    if oTxsSession.syncMkDirPath(oDir.sPath, 0o777) is not True:
    371         #        return reporter.error('Failed to create directory "%s"!' % (oDir.sPath,));
    372         #
    373         ## Files:
    374         #for oFile in self.aoFiles:
    375         #    if oTxsSession.syncUploadString(oFile.abContent, oFile.sPath) is not True:
    376         #        return reporter.error('Failed to create file "%s" with %s content bytes!' % (oFile.sPath, oFile.cbContent));
    377 
    37892        sVtsTarExe = 'vts_tar' + self.oTestVm.getGuestExeSuff();
    37993        sVtsTarHst = os.path.join(oTstDrv.sVBoxValidationKit, self.oTestVm.getGuestOs(),
     
    423137        return True;
    424138
    425     def chooseRandomFileFromTree(self):
    426         """
    427         Returns a random file from the tree (self.oTreeDir).
    428         """
    429         while True:
    430             oFile = self.aoFiles[self.oRandom.choice(xrange(len(self.aoFiles)))];
    431             oParent = oFile.oParent;
    432             while oParent is not None:
    433                 if oParent is self.oTreeDir:
    434                     return oFile;
    435                 oParent = oParent.oParent;
    436 
    437     def chooseRandomDirFromTree(self, fLeaf = False, fNonEmpty = False):
    438         """
    439         Returns a random directoryr from the tree (self.oTreeDir).
    440         """
    441         while True:
    442             oDir = self.aoDirs[self.oRandom.choice(xrange(len(self.aoDirs)))];
    443             # Check fNonEmpty requirement:
    444             if not fNonEmpty or oDir.aoChildren:
    445                 # Check leaf requirement:
    446                 if not fLeaf:
    447                     for oChild in oDir.aoChildren:
    448                         if isinstance(oChild, GstDir):
    449                             continue; # skip it.
    450 
    451                 # Return if in the tree:
    452                 oParent = oDir.oParent;
    453                 while oParent is not None:
    454                     if oParent is self.oTreeDir:
    455                         return oDir;
    456                     oParent = oParent.oParent;
    457 
  • trunk/src/VBox/ValidationKit/tests/additions/tdAddGuestCtrl.py

    r79180 r79185  
    4949from testdriver import reporter;
    5050from testdriver import base;
     51from testdriver import testfileset;
    5152from testdriver import vbox;
    5253from testdriver import vboxcon;
     
    233234        self.sDst = sDst;
    234235        self.fFlags = fFlags;
    235         self.oSrc = oSrc  # type: vboxtestfileset.GstFsObj
     236        self.oSrc = oSrc  # type: testfileset.TestFsObj
    236237        if oSrc and not sSrc:
    237238            self.sSrc = oSrc.sPath;
     
    13491350        return (fRc, cDirs, cFiles, cOthers);
    13501351
    1351     def gctrlReadDirTree2(self, oGuestSession, oDir): # type: (vboxtestfileset.GstDir) -> bool
     1352    def gctrlReadDirTree2(self, oGuestSession, oDir): # type: (testfileset.TestDir) -> bool
    13521353        """
    13531354        Helper function to recursively read a guest directory tree specified in the current test.
     
    14041405
    14051406                    # Check type
    1406                     if isinstance(oFsObj, vboxtestfileset.GstDir):
     1407                    if isinstance(oFsObj, testfileset.TestDir):
    14071408                        if eType != vboxcon.FsObjType_Directory:
    14081409                            fRc = reporter.error('%s: expected directory (%d), got eType=%d!'
    14091410                                                 % (oFsObj.sPath, vboxcon.FsObjType_Directory, eType,));
    1410                     elif isinstance(oFsObj, vboxtestfileset.GstFile):
     1411                    elif isinstance(oFsObj, testfileset.TestFile):
    14111412                        if eType != vboxcon.FsObjType_File:
    14121413                            fRc = reporter.error('%s: expected file (%d), got eType=%d!'
     
    14201421
    14211422                    # Check the size if a file.
    1422                     if isinstance(oFsObj, vboxtestfileset.GstFile) and cbFile != oFsObj.cbContent:
     1423                    if isinstance(oFsObj, testfileset.TestFile) and cbFile != oFsObj.cbContent:
    14231424                        fRc = reporter.error('%s: expected size %s, got %s instead!' % (oFsObj.sPath, oFsObj.cbContent, cbFile,));
    14241425
     
    14461447        #
    14471448        for oFsObj in oDir.aoChildren:
    1448             if isinstance(oFsObj, vboxtestfileset.GstDir):
     1449            if isinstance(oFsObj, testfileset.TestDir):
    14491450                fRc = self.gctrlReadDirTree2(oGuestSession, oFsObj) and fRc;
    14501451
     
    35753576        #
    35763577        sScratchHst             = os.path.join(self.oTstDrv.sScratchPath, "testGctrlCopyFrom");
    3577         oExistingFileGst        = self.oTestFiles.chooseRandomFileFromTree();
     3578        oExistingFileGst        = self.oTestFiles.chooseRandomFile();
    35783579        oNonEmptyDirGst         = self.oTestFiles.chooseRandomDirFromTree(fNonEmpty = True);
    35793580        oEmptyDirGst            = self.oTestFiles.oEmptyDir;
Note: See TracChangeset for help on using the changeset viewer.

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