Changeset 79185 in vbox
- Timestamp:
- Jun 17, 2019 2:19:41 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 131357
- Location:
- trunk/src/VBox/ValidationKit
- Files:
-
- 3 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/Makefile.kmk
r79158 r79185 69 69 $(PATH_SUB_CURRENT)/testdriver/btresolver.py \ 70 70 $(PATH_SUB_CURRENT)/testdriver/reporter.py \ 71 $(PATH_SUB_CURRENT)/testdriver/testfileset.py \ 71 72 $(PATH_SUB_CURRENT)/testdriver/tst-txsclient.py \ 72 73 $(PATH_SUB_CURRENT)/testdriver/txsclient.py \ -
trunk/src/VBox/ValidationKit/testdriver/testfileset.py
r79180 r79185 4 4 5 5 """ 6 VirtualBoxTest File Set6 Test File Set 7 7 """ 8 8 … … 37 37 import sys; 38 38 import tarfile; 39 import unittest; 39 40 40 41 # Validation Kit imports. 41 42 from common import utils; 43 from common import pathutils; 42 44 from testdriver import reporter; 43 45 … … 48 50 49 51 50 class GstFsObj(object):51 """ A file system object we created in the guestfor test purposes. """52 class TestFsObj(object): 53 """ A file system object we created in for test purposes. """ 52 54 def __init__(self, oParent, sPath): 53 self.oParent = oParent # type: GstDir55 self.oParent = oParent # type: TestDir 54 56 self.sPath = sPath # type: str 55 57 self.sName = sPath # type: str … … 61 63 oParent.dChildrenUpper[self.sName.upper()] = self; 62 64 63 class GstFile(GstFsObj):65 class TestFile(TestFsObj): 64 66 """ A file object in the guest. """ 65 67 def __init__(self, oParent, sPath, abContent): 66 GstFsObj.__init__(self, oParent, sPath);68 TestFsObj.__init__(self, oParent, sPath); 67 69 self.abContent = abContent # type: bytearray 68 70 self.cbContent = len(abContent); … … 70 72 71 73 def read(self, cbToRead): 74 """ read() emulation. """ 72 75 assert self.off <= self.cbContent; 73 76 cbLeft = self.cbContent - self.off; … … 81 84 return abRet; 82 85 83 class GstDir(GstFsObj):86 class TestDir(TestFsObj): 84 87 """ A file object in the guest. """ 85 88 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) 89 92 90 93 def contains(self, sName): … … 95 98 class TestFileSet(object): 96 99 """ 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. 101 103 """ 102 104 … … 106 108 ksReservedTrailingUnix = ''; 107 109 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. 109 117 oRngFileSizes = xrange(0, 16384), 110 118 oRngManyFiles = xrange(128, 512), … … 113 121 oRngTreeDirs = xrange(2, 16), 114 122 cchMaxPath = 230, 115 cchMaxName = 230): 123 cchMaxName = 230, 124 uSeed = None): 116 125 ## @name Parameters 117 126 ## @{ 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 128 145 ## @} 129 146 130 147 ## @name Charset stuff 131 148 ## @todo allow more chars for unix hosts + guests. 149 ## @todo include unicode stuff, except on OS/2 and DOS. 132 150 ## @{ 133 151 ## The filename charset. 134 152 self.sFileCharset = string.printable; 135 ## The filename charset common to host and guest.136 self.sFileCharsetCommon = string.printable;137 153 ## Set of characters that should not trail a guest filename. 138 154 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'): 142 156 for ch in self.ksReservedWinOS2: 143 157 self.sFileCharset = self.sFileCharset.replace(ch, ''); … … 146 160 for ch in self.ksReservedUnix: 147 161 self.sFileCharset = self.sFileCharset.replace(ch, ''); 162 # More spaces and dot: 148 163 self.sFileCharset += ' ...'; 149 150 for ch in self.ksReservedWinOS2:151 self.sFileCharsetCommon = self.sFileCharset.replace(ch, '');152 self.sFileCharsetCommon += ' ...';153 164 ## @} 154 165 155 166 ## The root directory. 156 self.oRoot = None # type: GstDir;167 self.oRoot = None # type: TestDir; 157 168 ## An empty directory (under root). 158 self.oEmptyDir = None # type: GstDir;169 self.oEmptyDir = None # type: TestDir; 159 170 160 171 ## A directory with a lot of files in it. 161 self.oManyDir = None # type: GstDir;172 self.oManyDir = None # type: TestDir; 162 173 163 174 ## A directory with a mixed tree structure under it. 164 self.oTreeDir = None # type: GstDir;175 self.oTreeDir = None # type: TestDir; 165 176 ## Number of files in oTreeDir. 166 177 self.cTreeFiles = 0; … … 171 182 172 183 ## All directories in creation order. 173 self.aoDirs = [] # type: list( GstDir);184 self.aoDirs = [] # type: list(TestDir); 174 185 ## All files in creation order. 175 self.aoFiles = [] # type: list( GstFile);186 self.aoFiles = [] # type: list(TestFile); 176 187 ## Path to object lookup. 177 self.dPaths = {} # type: dict(str, GstFsObj);188 self.dPaths = {} # type: dict(str, TestFsObj); 178 189 179 190 # 180 191 # Do the creating. 181 192 # 182 self.uSeed = u tils.timestampMilli();193 self.uSeed = uSeed if uSeed is not None else utils.timestampMilli(); 183 194 self.oRandom = random.Random(); 184 195 self.oRandom.seed(self.uSeed); … … 214 225 return ''; # never reached, but makes pylint happy. 215 226 216 def generateFilenameEx(self, cchMax = -1, cchMin = -1 , fCommonCharset = True):227 def generateFilenameEx(self, cchMax = -1, cchMin = -1): 217 228 """ 218 229 Generates a filename according to the given specs. … … 228 239 cchMax = self.cchMaxName; 229 240 230 if fCommonCharset:231 sCharset = self.sFileCharsetCommon;232 sReservedTrailing = self.sReservedTrailingCommon;233 else:234 sCharset = self.sFileCharset;235 sReservedTrailing = self.sReservedTrailing;236 237 241 while True: 238 242 cchName = self.oRandom.randrange(cchMin, cchMax + 1); 239 sName = ''.join(self.oRandom.choice(s Charset) for _ in xrange(cchName));240 if sName[-1] not in s ReservedTrailing:243 sName = ''.join(self.oRandom.choice(self.sFileCharset) for _ in xrange(cchName)); 244 if sName[-1] not in self.sReservedTrailing: 241 245 if sName not in ('.', '..',): 242 246 return sName; … … 247 251 Creates a test directory. 248 252 """ 249 oDir = GstDir(oParent, sDir);253 oDir = TestDir(oParent, sDir); 250 254 self.aoDirs.append(oDir); 251 255 self.dPaths[sDir] = oDir; … … 259 263 abContent = bytearray(self.oRandom.getrandbits(8) for _ in xrange(cbFile)); 260 264 261 oFile = GstFile(oParent, sFile, abContent);265 oFile = TestFile(oParent, sFile, abContent); 262 266 self.aoFiles.append(oFile); 263 267 self.dPaths[sFile] = oFile; … … 273 277 # Create the root test dir. 274 278 # 275 sRoot = self.oTestVm.pathJoin(self.sBasePath, self.sSubDir);279 sRoot = pathutils.joinEx(self.fDosStyle, self.sBasePath, self.sSubDir); 276 280 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')); 283 287 self.oManyDir = oDir; 284 288 cManyFiles = self.oRandom.choice(self.oRngManyFiles); 285 289 for _ in xrange(cManyFiles): 286 290 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')); 293 297 uMaxDepth = self.oRandom.choice(self.oRngTreeDepth); 294 298 cMaxFiles = self.oRandom.choice(self.oRngTreeFiles); … … 302 306 # 0: Add a file: 303 307 if iAction == 0 and self.cTreeFiles < cMaxFiles and len(oDir.sPath) < 230 - 2: 304 sName = self.__createFilename(oDir, self.sFileCharset Common, 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)); 306 310 self.cTreeFiles += 1; 307 311 # 1: Add a subdirector and descend into it: 308 312 elif iAction == 1 and self.cTreeDirs < cMaxDirs and uDepth < uMaxDepth and len(oDir.sPath) < 220: 309 sName = self.__createFilename(oDir, self.sFileCharset Common, 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)); 311 315 self.cTreeDirs += 1; 312 316 uDepth += 1; … … 325 329 reporter.log('Creating tarball "%s" with test files for the guest...' % (sTarFileHst,)); 326 330 327 chOtherSlash = '\\' if self.oTestVm.isWindows() or self.oTestVm.isOS2() else '/'; 328 cchSkip = len(self.sBasePath) + 1; 331 cchSkip = len(self.sBasePath) + 1; 329 332 330 333 # Open the tarball: … … 336 339 # Directories: 337 340 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 + '/'); 339 345 oTarInfo.mode = 0o777; 340 346 oTarInfo.type = tarfile.DIRTYPE; … … 346 352 # Files: 347 353 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); 349 358 oTarInfo.size = len(oFile.abContent); 350 359 oFile.off = 0; … … 361 370 return True; 362 371 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 389 413 return True; 390 414 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)))]; 436 421 437 422 def chooseRandomDirFromTree(self, fLeaf = False, fNonEmpty = False): 438 423 """ 439 Returns a random directory rfrom the tree (self.oTreeDir).424 Returns a random directory from the tree (self.oTreeDir). 440 425 """ 441 426 while True: … … 446 431 if not fLeaf: 447 432 for oChild in oDir.aoChildren: 448 if isinstance(oChild, GstDir):433 if isinstance(oChild, TestDir): 449 434 continue; # skip it. 450 435 … … 456 441 oParent = oParent.oParent; 457 442 458 443 # 444 # Unit testing. 445 # 446 447 # pylint: disable=missing-docstring 448 # pylint: disable=undefined-variable 449 class 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 456 if __name__ == '__main__': 457 unittest.main(); 458 # not reached. 459 -
trunk/src/VBox/ValidationKit/testdriver/vboxtestfileset.py
r79182 r79185 4 4 5 5 """ 6 VirtualBoxTest File Set6 Test File Set 7 7 """ 8 8 … … 33 33 # Standard Python imports. 34 34 import os; 35 import random;36 import string;37 35 import sys; 38 import tarfile;39 36 40 37 # Validation Kit imports. 41 38 from common import utils; 42 39 from testdriver import reporter; 40 from testdriver import testfileset; 43 41 44 42 # Python 3 hacks: … … 47 45 48 46 47 class TestFileSet(testfileset.TestFileSet): 48 """ 49 A generated set of files and directories for uploading to a VM. 49 50 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. 98 53 99 54 Uploaded as a tarball and expanded via TXS (if new enough) or uploaded vts_tar 100 55 utility from the validation kit. 101 56 """ 102 103 ksReservedWinOS2 = '/\\"*:<>?|\t\v\n\r\f\a\b';104 ksReservedUnix = '/';105 ksReservedTrailingWinOS2 = ' .';106 ksReservedTrailingUnix = '';107 57 108 58 def __init__(self, oTestVm, sBasePath, sSubDir, # pylint: disable=too-many-arguments … … 113 63 oRngTreeDirs = xrange(2, 16), 114 64 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): 129 67 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); 149 72 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; 362 87 363 88 def __uploadFallback(self, oTxsSession, sTarFileGst, oTstDrv): … … 365 90 Fallback upload method. 366 91 """ 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 92 sVtsTarExe = 'vts_tar' + self.oTestVm.getGuestExeSuff(); 379 93 sVtsTarHst = os.path.join(oTstDrv.sVBoxValidationKit, self.oTestVm.getGuestOs(), … … 423 137 return True; 424 138 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 49 49 from testdriver import reporter; 50 50 from testdriver import base; 51 from testdriver import testfileset; 51 52 from testdriver import vbox; 52 53 from testdriver import vboxcon; … … 233 234 self.sDst = sDst; 234 235 self.fFlags = fFlags; 235 self.oSrc = oSrc # type: vboxtestfileset.GstFsObj236 self.oSrc = oSrc # type: testfileset.TestFsObj 236 237 if oSrc and not sSrc: 237 238 self.sSrc = oSrc.sPath; … … 1349 1350 return (fRc, cDirs, cFiles, cOthers); 1350 1351 1351 def gctrlReadDirTree2(self, oGuestSession, oDir): # type: ( vboxtestfileset.GstDir) -> bool1352 def gctrlReadDirTree2(self, oGuestSession, oDir): # type: (testfileset.TestDir) -> bool 1352 1353 """ 1353 1354 Helper function to recursively read a guest directory tree specified in the current test. … … 1404 1405 1405 1406 # Check type 1406 if isinstance(oFsObj, vboxtestfileset.GstDir):1407 if isinstance(oFsObj, testfileset.TestDir): 1407 1408 if eType != vboxcon.FsObjType_Directory: 1408 1409 fRc = reporter.error('%s: expected directory (%d), got eType=%d!' 1409 1410 % (oFsObj.sPath, vboxcon.FsObjType_Directory, eType,)); 1410 elif isinstance(oFsObj, vboxtestfileset.GstFile):1411 elif isinstance(oFsObj, testfileset.TestFile): 1411 1412 if eType != vboxcon.FsObjType_File: 1412 1413 fRc = reporter.error('%s: expected file (%d), got eType=%d!' … … 1420 1421 1421 1422 # 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: 1423 1424 fRc = reporter.error('%s: expected size %s, got %s instead!' % (oFsObj.sPath, oFsObj.cbContent, cbFile,)); 1424 1425 … … 1446 1447 # 1447 1448 for oFsObj in oDir.aoChildren: 1448 if isinstance(oFsObj, vboxtestfileset.GstDir):1449 if isinstance(oFsObj, testfileset.TestDir): 1449 1450 fRc = self.gctrlReadDirTree2(oGuestSession, oFsObj) and fRc; 1450 1451 … … 3575 3576 # 3576 3577 sScratchHst = os.path.join(self.oTstDrv.sScratchPath, "testGctrlCopyFrom"); 3577 oExistingFileGst = self.oTestFiles.chooseRandomFile FromTree();3578 oExistingFileGst = self.oTestFiles.chooseRandomFile(); 3578 3579 oNonEmptyDirGst = self.oTestFiles.chooseRandomDirFromTree(fNonEmpty = True); 3579 3580 oEmptyDirGst = self.oTestFiles.oEmptyDir;
Note:
See TracChangeset
for help on using the changeset viewer.