Index: trunk/src/VBox/ValidationKit/testdriver/testfileset.py
===================================================================
--- trunk/src/VBox/ValidationKit/testdriver/testfileset.py	(revision 79279)
+++ trunk/src/VBox/ValidationKit/testdriver/testfileset.py	(revision 79280)
@@ -154,4 +154,14 @@
         return sRet;
 
+    def checkRange(self, cbRange, offFile = 0):
+        """ Check if the specified range is entirely within the file or not. """
+        if offFile >= self.cbContent:
+            return reporter.error('buffer @ %s LB %s is beyond the end of the file (%s bytes)!'
+                                  % (offFile, cbRange, self.cbContent,));
+        if offFile + cbRange > self.cbContent:
+            return reporter.error('buffer @ %s LB %s is partially beyond the end of the file (%s bytes)!'
+                                  % (offFile, cbRange, self.cbContent,));
+        return True;
+
     def equalMemory(self, abBuf, offFile = 0):
         """
@@ -163,12 +173,14 @@
         if not abBuf:
             return True;
-        if offFile >= self.cbContent:
-            return reporter.error('buffer @ %s LB %s is beyond the end of the file (%s bytes)!'
-                                  % (offFile, len(abBuf), self.cbContent,));
-        if offFile + len(abBuf) > self.cbContent:
-            return reporter.error('buffer @ %s LB %s is partially beyond the end of the file (%s bytes)!'
-                                  % (offFile, len(abBuf), self.cbContent,));
-        if utils.areBytesEqual(abBuf, self.abContent[offFile:(offFile + len(abBuf))]):
-            return True;
+
+        if not self.checkRange(len(abBuf), offFile):
+            return False;
+
+        if sys.version_info[0] >= 3:
+            if utils.areBytesEqual(abBuf, self.abContent[offFile:(offFile + len(abBuf))]):
+                return True;
+        else:
+            if utils.areBytesEqual(abBuf, buffer(self.abContent, offFile, len(abBuf))): # pylint: disable=undefined-variable
+                return True;
 
         reporter.error('mismatch with buffer @ %s LB %s (cbContent=%s)!' % (offFile, len(abBuf), self.cbContent,));
@@ -201,4 +213,54 @@
 
 
+class TestFileZeroFilled(TestFile):
+    """
+    Zero filled test file.
+    """
+
+    def __init__(self, oParent, sPath, cbContent):
+        TestFile.__init__(self, oParent, sPath, bytearray(1));
+        self.cbContent = cbContent;
+
+    def read(self, cbToRead):
+        """ read() emulation. """
+        assert self.off <= self.cbContent;
+        cbLeft = self.cbContent - self.off;
+        if cbLeft < cbToRead:
+            cbToRead = cbLeft;
+        abRet = bytearray(cbToRead);
+        assert len(abRet) == cbToRead;
+        self.off += cbToRead;
+        if sys.version_info[0] < 3:
+            return bytes(abRet);
+        return abRet;
+
+    def equalFile(self, oFile):
+        _ = oFile;
+        assert False, "not implemented";
+        return False;
+
+    def equalMemory(self, abBuf, offFile = 0):
+        if not abBuf:
+            return True;
+
+        if not self.checkRange(len(abBuf), offFile):
+            return False;
+
+        if utils.areBytesEqual(abBuf, bytearray(len(abBuf))):
+            return True;
+
+        cErrors = 0;
+        offBuf = 0
+        while offBuf < len(abBuf):
+            bByte = abBuf[offBuf];
+            if not isinstance(bByte, int):
+                bByte = ord(bByte);
+            if bByte != 0:
+                reporter.error('Mismatch @ %s/%s: %#x, expected 0!' % (offFile, offBuf, bByte,));
+                cErrors += 1;
+                if cErrors > 32:
+                    return False;
+            offBuf += 1;
+        return cErrors == 0;
 
 
Index: trunk/src/VBox/ValidationKit/tests/additions/tdAddGuestCtrl.py
===================================================================
--- trunk/src/VBox/ValidationKit/tests/additions/tdAddGuestCtrl.py	(revision 79279)
+++ trunk/src/VBox/ValidationKit/tests/additions/tdAddGuestCtrl.py	(revision 79280)
@@ -3515,7 +3515,6 @@
 
         #
-        # Open and read all the files in the test file set.
-        #
-
+        # Do everything in one session.
+        #
         oTest = tdTestGuestCtrlBase();
         oTest.setEnvironment(oSession, oTxsSession, oTestVm);
@@ -3524,6 +3523,51 @@
             return (False, oTxsSession);
 
+        #
+        # Create a really big zero filled, up to 1 GiB, adding it to the list of
+        # files from the set.
+        #
+        # Note! This code sucks a bit because we don't have a working setSize nor
+        #       any way to figure out how much free space there is in the guest.
+        #
+        aoExtraFiles = [];
+        sBigName = self.oTestFiles.generateFilenameEx();
+        sBigPath = oTestVm.pathJoin(self.oTestFiles.oRoot.sPath, sBigName);
         fRc = True;
-        for oTestFile in self.oTestFiles.aoFiles: # type: testfileset.TestFile
+        try:
+            oFile = oGuestSession.fileOpenEx(sBigPath, vboxcon.FileAccessMode_ReadWrite, vboxcon.FileOpenAction_CreateOrReplace,
+                                             vboxcon.FileSharingMode_All, 0, []);
+        except:
+            fRc = reporter.errorXcpt('sBigName=%s' % (sBigPath,));
+        else:
+            cbBigFile = 0;
+            while cbBigFile < (1024 + 32)*1024*1024:
+                cbBigFile += 32*1024*1024;
+                try:
+                    oFile.seek(cbBigFile, vboxcon.FileSeekOrigin_Begin);
+                    oFile.write(bytearray(1), 60*1000);
+                except:
+                    reporter.logXcpt('cbBigFile=%s' % (sBigPath,));
+                    break;
+            try:
+                cbBigFile = oFile.seek(0, vboxcon.FileSeekOrigin_End);
+            except:
+                fRc = reporter.errorXcpt('sBigName=%s' % (sBigPath,));
+            try:
+                oFile.close();
+            except:
+                fRc = reporter.errorXcpt('sBigName=%s' % (sBigPath,));
+            if fRc is True:
+                reporter.log('Big file: %s bytes: %s' % (cbBigFile, sBigPath,));
+                aoExtraFiles.append(testfileset.TestFileZeroFilled(None, sBigPath, cbBigFile));
+            else:
+                try:
+                    oGuestSession.fsObjRemove(sBigPath);
+                except:
+                    reporter.errorXcpt('fsObjRemove(sBigName=%s)' % (sBigPath,));
+
+        #
+        # Open and read all the files in the test file set.
+        #
+        for oTestFile in aoExtraFiles + self.oTestFiles.aoFiles: # type: testfileset.TestFile
             reporter.log2('Test file: %s bytes, "%s" ...' % (oTestFile.cbContent, oTestFile.sPath,));
 
@@ -3545,10 +3589,14 @@
             elif oTestFile.cbContent < 1024:
                 acbChunks = (2048, 127, 63, 32, 29, 17, 16, 15, 9);
+            elif oTestFile.cbContent < 8*1024*1024:
+                acbChunks = (128*1024, 32*1024, 8191, 255);
             else:
-                acbChunks = (128 * 1024, 32 * 1024, 8192, 1024, 128);
+                acbChunks = (768*1024, 128*1024);
+
             for cbChunk in acbChunks:
                 # Read the whole file straight thru:
-                #reporter.log2('... cbChunk=%s' % (cbChunk,));
+                if oTestFile.cbContent >= 1024*1024: reporter.log2('... cbChunk=%s' % (cbChunk,));
                 offFile = 0;
+                cReads = 0;
                 while offFile <= oTestFile.cbContent:
                     try:
@@ -3569,4 +3617,7 @@
                         break;
                     offFile += cbRead;
+                    cReads  += 1;
+                    if cReads > 8192:
+                        break;
 
                 # Seek to start of file.
@@ -3583,10 +3634,8 @@
             # Random reads.
             #
-            for _ in xrange(16):
+            for _ in xrange(8):
                 offFile  = self.oTestFiles.oRandom.randrange(0, oTestFile.cbContent + 1024);
-                cbToRead = self.oTestFiles.oRandom.randrange(1, oTestFile.cbContent + 256);
-                if cbToRead > 1024*1024:
-                    cbToRead = 1024*1024;
-                #reporter.log2('... %s LB %s' % (offFile, cbToRead,));
+                cbToRead = self.oTestFiles.oRandom.randrange(1, min(oTestFile.cbContent + 256, 768*1024));
+                if oTestFile.cbContent >= 1024*1024: reporter.log2('... %s LB %s' % (offFile, cbToRead,));
 
                 try:
@@ -3632,10 +3681,8 @@
             # Random reads using readAt.
             #
-            for _ in xrange(16):
+            for _ in xrange(12):
                 offFile  = self.oTestFiles.oRandom.randrange(0, oTestFile.cbContent + 1024);
-                cbToRead = self.oTestFiles.oRandom.randrange(1, oTestFile.cbContent + 256);
-                if cbToRead > 1024*1024:
-                    cbToRead = 1024*1024;
-                #reporter.log2('... %s LB %s (readAt)' % (offFile, cbToRead,));
+                cbToRead = self.oTestFiles.oRandom.randrange(1, min(oTestFile.cbContent + 256, 768*1024));
+                if oTestFile.cbContent >= 1024*1024: reporter.log2('... %s LB %s (readAt)' % (offFile, cbToRead,));
 
                 try:
@@ -3646,10 +3693,5 @@
                 else:
                     cbRead = len(abRead);
-                    if offFile >= oTestFile.cbContent or offFile + cbRead > oTestFile.cbContent:
-                        if cbRead != 0:
-                            fRc = reporter.error('%s: Read returned data beyond end of file: %s + %s = %s vs cbContent=%s (#2)'
-                                                 % (oTestFile.sPath, offFile, cbRead, offFile + cbRead, oTestFile.cbContent,));
-                    if    offFile + cbRead <= oTestFile.cbContent \
-                      and not utils.areBytesEqual(abRead, oTestFile.abContent[offFile:(offFile + cbRead)]):
+                    if not oTestFile.equalMemory(abRead, offFile):
                         fRc = reporter.error('%s: random readAt mismatch @ %s LB %s' % (oTestFile.sPath, offFile, cbRead,));
 
@@ -3683,11 +3725,13 @@
             # A few negative things.
             #
+
+            # Zero byte reads -> E_INVALIDARG.
             try:
                 abRead = oFile.read(0, 30*1000);
             except Exception as oXcpt:
                 if vbox.ComError.notEqual(oXcpt, vbox.ComError.E_INVALIDARG):
-                    reporter.errorXcpt('read(0,30s) did not raise E_INVALIDARG as expected!');
+                    fRc = reporter.errorXcpt('read(0,30s) did not raise E_INVALIDARG as expected!');
             else:
-                reporter.error('read(0,30s) did not fail!');
+                fRc = reporter.error('read(0,30s) did not fail!');
 
             try:
@@ -3695,24 +3739,31 @@
             except Exception as oXcpt:
                 if vbox.ComError.notEqual(oXcpt, vbox.ComError.E_INVALIDARG):
-                    reporter.errorXcpt('readAt(0,0,30s) did not raise E_INVALIDARG as expected!');
+                    fRc = reporter.errorXcpt('readAt(0,0,30s) did not raise E_INVALIDARG as expected!');
             else:
-                reporter.error('readAt(0,0,30s) did not fail!');
-
-            if not self.fSkipKnownBugs: ## @todo Place a restriction on how much we permit being read in a single request.
-                try:                    ##       Document it in VirtualBox.xidl.
-                    abRead = oFile.read(1024*1024*1024, 30*1000);
-                except Exception as oXcpt:
-                    if vbox.ComError.notEqual(oXcpt, vbox.ComError.E_INVALIDARG):
-                        reporter.errorXcpt('read(1GiB,30s) did not raise E_INVALIDARG as expected!');
-                else:
-                    reporter.error('read(1GiB,30s) did not fail! len(abRead)=%s' % (len(abRead), ));
-
-                try:
-                    abRead = oFile.readAt(0, 1024*1024*1024, 30*1000);
-                except Exception as oXcpt:
-                    if vbox.ComError.notEqual(oXcpt, vbox.ComError.E_INVALIDARG):
-                        reporter.errorXcpt('readAt(0,1GiB,30s) did not raise E_INVALIDARG as expected!');
-                else:
-                    reporter.error('readAt(0,1GiB,30s) did not fail! len(abRead)=%s' % (len(abRead), ));
+                fRc = reporter.error('readAt(0,0,30s) did not fail!');
+
+            # See what happens when we read 1GiB.  We should get a max of 1MiB back.
+            ## @todo Document this behaviour in VirtualBox.xidl.
+            try:
+                oFile.seek(0, vboxcon.FileSeekOrigin_Begin);
+            except:
+                fRc = reporter.error('seek(0)');
+            try:
+                abRead = oFile.read(1024*1024*1024, 30*1000);
+            except:
+                fRc = reporter.errorXcpt('read(1GiB,30s)');
+            else:
+                if len(abRead) != min(oTestFile.cbContent, 1024*1024):
+                    fRc = reporter.error('Expected read(1GiB,30s) to return %s bytes, got %s bytes instead'
+                                         % (min(oTestFile.cbContent, 1024*1024), len(abRead),));
+
+            try:
+                abRead = oFile.readAt(0, 1024*1024*1024, 30*1000);
+            except:
+                fRc = reporter.errorXcpt('readAt(0,1GiB,30s)');
+            else:
+                if len(abRead) != min(oTestFile.cbContent, 1024*1024):
+                    reporter.error('Expected readAt(0, 1GiB,30s) to return %s bytes, got %s bytes instead'
+                                   % (min(oTestFile.cbContent, 1024*1024), len(abRead),));
 
             #
@@ -3758,5 +3809,5 @@
                                          % (oTestFile.sPath, cbFile, oTestFile.cbContent));
             if oTestFile.cbContent > 0:
-                for _ in xrange(12):
+                for _ in xrange(5):
                     offSeek = self.oTestFiles.oRandom.randrange(oTestFile.cbContent + 1);
                     try:
@@ -3778,5 +3829,15 @@
                 fRc = reporter.errorXcpt('%s: error closing the file' % (oTestFile.sPath,));
 
+        #
+        # Clean up.
+        #
+        for oTestFile in aoExtraFiles:
+            try:
+                oGuestSession.fsObjRemove(sBigPath);
+            except:
+                fRc = reporter.errorXcpt('fsObjRemove(%s)' % (sBigPath,));
+
         fRc = oTest.closeSession(True) and fRc;
+
         return (fRc, oTxsSession);
 
