Index: /trunk/src/VBox/ValidationKit/testdriver/vboxtestfileset.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testdriver/vboxtestfileset.py	(revision 79158)
+++ /trunk/src/VBox/ValidationKit/testdriver/vboxtestfileset.py	(revision 79159)
@@ -47,4 +47,48 @@
 
 
+
+class GstFsObj(object):
+    """ A file system object we created in the guest for test purposes. """
+    def __init__(self, oParent, sPath):
+        self.oParent   = oParent    # type: GstDir
+        self.sPath     = sPath      # type: str
+        self.sName     = sPath      # type: str
+        if oParent:
+            assert sPath.startswith(oParent.sPath);
+            self.sName = sPath[len(oParent.sPath) + 1:];
+            # Add to parent.
+            oParent.aoChildren.append(self);
+            oParent.dChildrenUpper[self.sName.upper()] = self;
+
+class GstFile(GstFsObj):
+    """ A file object in the guest. """
+    def __init__(self, oParent, sPath, abContent):
+        GstFsObj.__init__(self, oParent, sPath);
+        self.abContent = abContent          # type: bytearray
+        self.cbContent = len(abContent);
+        self.off       = 0;
+
+    def read(self, cbToRead):
+        assert self.off <= self.cbContent;
+        cbLeft = self.cbContent - self.off;
+        if cbLeft < cbToRead:
+            cbToRead = cbLeft;
+        abRet = self.abContent[self.off:(self.off + cbToRead)];
+        assert len(abRet) == cbToRead;
+        self.off += cbToRead;
+        return abRet;
+
+class GstDir(GstFsObj):
+    """ A file object in the guest. """
+    def __init__(self, oParent, sPath):
+        GstFsObj.__init__(self, oParent, sPath);
+        self.aoChildren     = []  # type: list(GsFsObj)
+        self.dChildrenUpper = {}  # type: dict(str,GsFsObj)
+
+    def contains(self, sName):
+        """ Checks if the directory contains the given name. """
+        return sName.upper() in self.dChildrenUpper
+
+
 class TestFileSet(object):
     """
@@ -54,47 +98,4 @@
     utility from the validation kit.
     """
-
-    class GstFsObj(object):
-        """ A file system object we created in the guest for test purposes. """
-        def __init__(self, oParent, sPath):
-            self.oParent   = oParent    # type: GstDir
-            self.sPath     = sPath      # type: str
-            self.sName     = sPath      # type: str
-            if oParent:
-                assert sPath.startswith(oParent.sPath);
-                self.sName = sPath[len(oParent.sPath) + 1:];
-                # Add to parent.
-                oParent.aoChildren.append(self);
-                oParent.dChildrenUpper[self.sName.upper()] = self;
-
-    class GstFile(GstFsObj):
-        """ A file object in the guest. """
-        def __init__(self, oParent, sPath, abContent):
-            TestFileSet.GstFsObj.__init__(self, oParent, sPath);
-            self.abContent = abContent          # type: bytearray
-            self.cbContent = len(abContent);
-            self.off       = 0;
-
-        def read(self, cbToRead):
-            assert self.off <= self.cbContent;
-            cbLeft = self.cbContent - self.off;
-            if cbLeft < cbToRead:
-                cbToRead = cbLeft;
-            abRet = self.abContent[self.off:(self.off + cbToRead)];
-            assert len(abRet) == cbToRead;
-            self.off += cbToRead;
-            return abRet;
-
-    class GstDir(GstFsObj):
-        """ A file object in the guest. """
-        def __init__(self, oParent, sPath):
-            TestFileSet.GstFsObj.__init__(self, oParent, sPath);
-            self.aoChildren     = []  # type: list(GsFsObj)
-            self.dChildrenUpper = {}  # type: dict(str,GsFsObj)
-
-        def contains(self, sName):
-            """ Checks if the directory contains the given name. """
-            return sName.upper() in self.dChildrenUpper
-
 
     ksReservedWinOS2         = '/\\"*:<>?|\t\v\n\r\f\a\b';
@@ -164,4 +165,6 @@
         ## Number of directories under oTreeDir.
         self.cTreeDirs  = 0;
+        ## Number of other file types under oTreeDir.
+        self.cTreeOthers = 0;
 
         ## All directories in creation order.
@@ -242,5 +245,5 @@
         Creates a test directory.
         """
-        oDir = TestFileSet.GstDir(oParent, sDir);
+        oDir = GstDir(oParent, sDir);
         self.aoDirs.append(oDir);
         self.dPaths[sDir] = oDir;
@@ -254,5 +257,5 @@
         abContent = bytearray(self.oRandom.getrandbits(8) for _ in xrange(cbFile));
 
-        oFile = TestFileSet.GstFile(oParent, sFile, abContent);
+        oFile = GstFile(oParent, sFile, abContent);
         self.aoFiles.append(oFile);
         self.dPaths[sFile] = oFile;
@@ -418,3 +421,2 @@
         return True;
 
-
Index: /trunk/src/VBox/ValidationKit/tests/additions/tdAddGuestCtrl.py
===================================================================
--- /trunk/src/VBox/ValidationKit/tests/additions/tdAddGuestCtrl.py	(revision 79158)
+++ /trunk/src/VBox/ValidationKit/tests/additions/tdAddGuestCtrl.py	(revision 79159)
@@ -1298,4 +1298,106 @@
 
         return (fRc, cDirs, cFiles, cOthers);
+
+    def gctrlReadDirTree2(self, oGuestSession, oDir): # type: (vboxtestfileset.GstDir) -> bool
+        """
+        Helper function to recursively read a guest directory tree specified in the current test.
+        """
+
+        #
+        # Process the directory.
+        #
+
+        # Open the directory:
+        try:
+            oCurDir = oGuestSession.directoryOpen(oDir.sPath, '', None);
+        except:
+            return reporter.errorXcpt('sPath=%s' % (oDir.sPath,));
+
+        # Read the directory.
+        dLeftUpper = dict(oDir.dChildrenUpper);
+        cDot       = 0;
+        cDotDot    = 0;
+        fRc = True;
+        while True:
+            try:
+                oFsObjInfo = oCurDir.read();
+            except Exception as oXcpt:
+                if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND):
+                    fRc = reporter.errorXcpt('Error reading directory "%s":' % (oDir.sPath,));
+                break;
+
+            try:
+                sName  = oFsObjInfo.name;
+                eType  = oFsObjInfo.type;
+                cbFile = oFsObjInfo.objectSize;
+                ## @todo check further attributes.
+            except:
+                fRc = reporter.errorXcpt();
+                break;
+
+            # '.' and '..' entries are not present in oDir.aoChildren, so special treatment:
+            if sName in ('.', '..', ):
+                if eType != vboxcon.FsObjType_Directory:
+                    fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)'
+                                         % (sName, eType, vboxcon.FsObjType_Directory));
+                if sName == '.': cDot    += 1;
+                else:            cDotDot += 1;
+            else:
+                # Find the child and remove it from the dictionary.
+                sNameUpper = sName.upper();
+                oFsObj = dLeftUpper.get(sNameUpper);
+                if oFsObj is None:
+                    fRc = reporter.error('Unknown object "%s" found in "%s" (type %s, size %s)!'
+                                         % (sName, oDir.sPath, eType, cbFile,));
+                else:
+                    del dLeftUpper[sNameUpper];
+
+                    # Check type
+                    if isinstance(oFsObj, vboxtestfileset.GstDir):
+                        if eType != vboxcon.FsObjType_Directory:
+                            fRc = reporter.error('%s: expected directory (%d), got eType=%d!'
+                                                 % (oFsObj.sPath, vboxcon.FsObjType_Directory, eType,));
+                    elif isinstance(oFsObj, vboxtestfileset.GstFile):
+                        if eType != vboxcon.FsObjType_File:
+                            fRc = reporter.error('%s: expected file (%d), got eType=%d!'
+                                                 % (oFsObj.sPath, vboxcon.FsObjType_File, eType,));
+                    else:
+                        fRc = reporter.error('%s: WTF? type=%s' % (oFsObj.sPath, type(oFsObj),));
+
+                    # Check the name.
+                    if oFsObj.sName != sName:
+                        fRc = reporter.error('%s: expected name "%s", got "%s" instead!' % (oFsObj.sPath, oFsObj.sName, sName,));
+
+                    # Check the size if a file.
+                    if isinstance(oFsObj, vboxtestfileset.GstFile) and cbFile != oFsObj.cbContent:
+                        fRc = reporter.error('%s: expected size %s, got %s instead!' % (oFsObj.sPath, oFsObj.cbContent, cbFile,));
+
+                    ## @todo check timestamps and attributes.
+
+        # Close the directory
+        try:
+            oCurDir.close();
+        except:
+            fRc = reporter.errorXcpt('oDir.sPath=%s' % (oDir.sPath,));
+
+        # Any files left over?
+        for sKey in dLeftUpper:
+            oFsObj = dLeftUpper[sKey];
+            fRc = reporter.error('%s: Was not returned! (%s)' % (oFsObj.sPath, type(oFsObj),));
+
+        # Check the dot and dot-dot counts.
+        if cDot != 1:
+            fRc = reporter.error('%s: Found %s "." entries, expected exactly 1!' % (oDir.sPath, cDot,));
+        if cDotDot != 1:
+            fRc = reporter.error('%s: Found %s ".." entries, expected exactly 1!' % (oDir.sPath, cDotDot,));
+
+        #
+        # Recurse into subdirectories using info from oDir.
+        #
+        for oFsObj in oDir.aoChildren:
+            if isinstance(oFsObj, vboxtestfileset.GstDir):
+                fRc = self.gctrlReadDirTree2(oGuestSession, oFsObj) and fRc;
+
+        return fRc;
 
     def gctrlExecDoTest(self, i, oTest, oRes, oGuestSession):
@@ -2749,16 +2851,14 @@
         ## @todo trailing slash
 
-        ## @todo this is very very inflexible.
-        ## Would be better to create a dir tree using TXS and make sure we get it back exactly as expected.
-        if oTestVm.sVmName.startswith('tst-xpsp2'):
-            atTests.extend([
-                # Reading directories.
-                [ tdTestDirRead(sDirectory = '../../Windows/Media'),
-                  tdTestResultDirRead(fRc = True, cFiles = 38) ],
-                [ tdTestDirRead(sDirectory = 'C:\\Windows\\Help'),
-                  tdTestResultDirRead(fRc = True, cDirs = 13, cFiles = 574) ],
-                [ tdTestDirRead(sDirectory = 'C:\\Windows\\Web'),
-                  tdTestResultDirRead(fRc = True, cDirs = 3, cFiles = 49) ]
-            ]);
+        # Read from the test file set.
+        atTests.extend([
+            [ tdTestDirRead(sDirectory = self.oTestFiles.oEmptyDir.sPath),
+              tdTestResultDirRead(fRc = True, cFiles = 0, cDirs = 0, cOthers = 0) ],
+            [ tdTestDirRead(sDirectory = self.oTestFiles.oManyDir.sPath),
+              tdTestResultDirRead(fRc = True, cFiles = len(self.oTestFiles.oManyDir.aoChildren), cDirs = 0, cOthers = 0) ],
+            [ tdTestDirRead(sDirectory = self.oTestFiles.oTreeDir.sPath),
+              tdTestResultDirRead(fRc = True, cFiles = self.oTestFiles.cTreeFiles, cDirs = self.oTestFiles.cTreeDirs,
+                                  cOthers = self.oTestFiles.cTreeOthers) ],
+        ]);
 
 
@@ -2774,5 +2874,5 @@
                 break;
             (fRc2, cDirs, cFiles, cOthers) = self.gctrlReadDirTree(oCurTest, oCurGuestSession, oCurRes.fRc);
-            oCurTest.closeSession(True);
+            fRc = oCurTest.closeSession(True) and fRc;
 
             reporter.log2('Test #%d: Returned %d directories, %d files total' % (i, cDirs, cFiles));
@@ -2803,4 +2903,19 @@
             else:
                 fRc = reporter.error('Test #%d failed: Got %s, expected %s' % (i, fRc2, oCurRes.fRc));
+
+
+        #
+        # Go over a few directories in the test file set and compare names,
+        # types and sizes rather than just the counts like we did above.
+        #
+        if fRc is True:
+            oCurTest = tdTestDirRead();
+            oCurTest.setEnvironment(oSession, oTxsSession, oTestVm);
+            fRc, oCurGuestSession = oCurTest.createSession('testGuestCtrlDirRead: gctrlReadDirTree2', True);
+            if fRc is True:
+                for oDir in (self.oTestFiles.oEmptyDir, self.oTestFiles.oManyDir, self.oTestFiles.oTreeDir):
+                    reporter.log('Checking "%s" ...' % (oDir.sPath,));
+                    fRc = self.gctrlReadDirTree2(oCurGuestSession, oDir) and fRc;
+                fRc = oCurTest.closeSession(True) and fRc;
 
         return (fRc, oTxsSession);
