Index: trunk/src/VBox/ValidationKit/tests/api/tdApi1.py
===================================================================
--- trunk/src/VBox/ValidationKit/tests/api/tdApi1.py	(revision 70812)
+++ trunk/src/VBox/ValidationKit/tests/api/tdApi1.py	(revision 70812)
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# $Id$
+
+"""
+VirtualBox Validation Kit - API Test wrapper #1 combining all API sub-tests
+"""
+
+__copyright__ = \
+"""
+Copyright (C) 2010-2017 Oracle Corporation
+
+This file is part of VirtualBox Open Source Edition (OSE), as
+available from http://www.virtualbox.org. This file is free software;
+you can redistribute it and/or modify it under the terms of the GNU
+General Public License (GPL) as published by the Free Software
+Foundation, in version 2 as it comes in the "COPYING" file of the
+VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+The contents of this file may alternatively be used under the terms
+of the Common Development and Distribution License Version 1.0
+(CDDL) only, as it comes in the "COPYING.CDDL" file of the
+VirtualBox OSE distribution, in which case the provisions of the
+CDDL are applicable instead of those of the GPL.
+
+You may elect to license modified versions of this file under the
+terms and conditions of either the GPL or the CDDL or both.
+"""
+__version__ = "$Revision$"
+
+
+# Standard Python imports.
+import os
+import sys
+
+# Only the main script needs to modify the path.
+try:    __file__
+except: __file__ = sys.argv[0]
+g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+sys.path.append(g_ksValidationKitDir)
+
+# Validation Kit imports.
+from testdriver import vbox
+
+
+class tdApi1(vbox.TestDriver):
+    """
+    API Test wrapper #1.
+    """
+
+    def __init__(self, aoSubTestDrivers = None):
+        vbox.TestDriver.__init__(self)
+        self.asRsrcs            = None
+
+    #
+    # Overridden methods.
+    #
+
+    def actionConfig(self):
+        """
+        Import the API.
+        """
+        if not self.importVBoxApi():
+            return False
+        return True
+
+    def actionExecute(self):
+        """
+        Execute the testcase, i.e. all sub-tests.
+        """
+        fRc = True
+        for oSubTstDrv in self.aoSubTstDrvs:
+            fRc &= oSubTstDrv.testIt()
+        return fRc
+
+
+if __name__ == '__main__':
+    sys.path.append(os.path.dirname(os.path.abspath(__file__)))
+    oTstDrv = tdApi1()
+    from tdPython1 import SubTstDrvPython1
+    oTstDrv.addSubTestDriver(SubTstDrvPython1(oTstDrv))
+    from tdAppliance1 import SubTstDrvAppliance1
+    oTstDrv.addSubTestDriver(SubTstDrvAppliance1(oTstDrv))
+    from tdMoveMedium1 import SubTstDrvMoveMedium1
+    oTstDrv.addSubTestDriver(SubTstDrvMoveMedium1(oTstDrv))
+    from tdTreeDepth1 import SubTstDrvTreeDepth1
+    oTstDrv.addSubTestDriver(SubTstDrvTreeDepth1(oTstDrv))
+    sys.exit(oTstDrv.main(sys.argv))
+
Index: trunk/src/VBox/ValidationKit/tests/api/tdAppliance1.py
===================================================================
--- trunk/src/VBox/ValidationKit/tests/api/tdAppliance1.py	(revision 70797)
+++ trunk/src/VBox/ValidationKit/tests/api/tdAppliance1.py	(revision 70812)
@@ -38,42 +38,27 @@
 # Only the main script needs to modify the path.
 try:    __file__
-except: __file__ = sys.argv[0];
-g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))));
-sys.path.append(g_ksValidationKitDir);
+except: __file__ = sys.argv[0]
+g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+sys.path.append(g_ksValidationKitDir)
 
 # Validation Kit imports.
-from testdriver import reporter;
-from testdriver import base;
-from testdriver import vbox;
-from testdriver import vboxwrappers;
-
-
-class tdAppliance1(vbox.TestDriver):
+from testdriver import base
+from testdriver import reporter
+from testdriver import vboxwrappers
+
+
+class SubTstDrvAppliance1(base.SubTestDriverBase):
     """
-    IAppliance Test #1.
+    Sub-test driver for IAppliance Test #1.
     """
 
-    def __init__(self):
-        vbox.TestDriver.__init__(self);
-        self.asRsrcs            = None;
-
-
-    #
-    # Overridden methods.
-    #
-
-    def actionConfig(self):
-        """
-        Import the API.
-        """
-        if not self.importVBoxApi():
-            return False;
-        return True;
-
-    def actionExecute(self):
-        """
-        Execute the testcase.
-        """
-        fRc = True;
+    def __init__(self, oTstDrv):
+        base.SubTestDriverBase.__init__(self, 'appliance', oTstDrv)
+
+    def testIt(self):
+        """
+        Execute the sub-testcase.
+        """
+        fRc = True
 
         # Import a set of simple OVAs.
@@ -103,15 +88,15 @@
             'tdAppliance1-t7-bad-instance.ova',
             ):
-            reporter.testStart(sOva);
+            reporter.testStart(sOva)
             try:
-                fRc = self.testImportOva(os.path.join(g_ksValidationKitDir, 'tests', 'api', sOva)) and fRc;
-                fRc = self.testImportOvaAsOvf(os.path.join(g_ksValidationKitDir, 'tests', 'api', sOva)) and fRc;
+                fRc = self.testImportOva(os.path.join(g_ksValidationKitDir, 'tests', 'api', sOva)) and fRc
+                fRc = self.testImportOvaAsOvf(os.path.join(g_ksValidationKitDir, 'tests', 'api', sOva)) and fRc
             except:
-                reporter.errorXcpt();
-                fRc = False;
-            fRc = reporter.testDone() and fRc;
+                reporter.errorXcpt()
+                fRc = False
+            fRc = reporter.testDone() and fRc
 
         ## @todo more stuff
-        return fRc;
+        return fRc
 
     #
@@ -121,5 +106,5 @@
     def testImportOva(self, sOva):
         """ xxx """
-        oVirtualBox = self.oVBoxMgr.getVirtualBox();
+        oVirtualBox = self.oTstDrv.oVBoxMgr.getVirtualBox()
 
         #
@@ -127,31 +112,30 @@
         #
         try:
-            oAppliance = oVirtualBox.createAppliance();
-        except:
-            return reporter.errorXcpt('IVirtualBox::createAppliance failed');
-        print("oAppliance=%s" % (oAppliance,));
-
-        try:
-            oProgress = vboxwrappers.ProgressWrapper(oAppliance.read(sOva), self.oVBoxMgr, self, 'read "%s"' % (sOva,));
-        except:
-            return reporter.errorXcpt('IAppliance::read("%s") failed' % (sOva,));
-        oProgress.wait();
-        if oProgress.logResult() is False:
-            return False;
-
-        try:
-            oAppliance.interpret();
-        except:
-            return reporter.errorXcpt('IAppliance::interpret() failed on "%s"' % (sOva,));
+            oAppliance = oVirtualBox.createAppliance()
+        except:
+            return reporter.errorXcpt('IVirtualBox::createAppliance failed')
+
+        try:
+            oProgress = vboxwrappers.ProgressWrapper(oAppliance.read(sOva), self.oTstDrv.oVBoxMgr, self.oTstDrv, 'read "%s"' % (sOva,))
+        except:
+            return reporter.errorXcpt('IAppliance::read("%s") failed' % (sOva,))
+        oProgress.wait()
+        if oProgress.logResult() is False:
+            return False
+
+        try:
+            oAppliance.interpret()
+        except:
+            return reporter.errorXcpt('IAppliance::interpret() failed on "%s"' % (sOva,))
 
         #
         try:
             oProgress = vboxwrappers.ProgressWrapper(oAppliance.importMachines([]),
-                                                     self.oVBoxMgr, self, 'importMachines "%s"' % (sOva,));
-        except:
-            return reporter.errorXcpt('IAppliance::importMachines failed on "%s"' % (sOva,));
-        oProgress.wait();
-        if oProgress.logResult() is False:
-            return False;
+                                                     self.oTstDrv.oVBoxMgr, self.oTstDrv, 'importMachines "%s"' % (sOva,))
+        except:
+            return reporter.errorXcpt('IAppliance::importMachines failed on "%s"' % (sOva,))
+        oProgress.wait()
+        if oProgress.logResult() is False:
+            return False
 
         #
@@ -160,14 +144,14 @@
         ## @todo do more with this OVA. Like untaring it and loading it as an OVF.  Export it and import it again.
 
-        return True;
+        return True
 
     def testImportOvaAsOvf(self, sOva):
         """
-        Unpacts the OVA into a subdirectory in the scratch area and imports it as an OVF.
-        """
-        oVirtualBox = self.oVBoxMgr.getVirtualBox();
-
-        sTmpDir = os.path.join(self.sScratchPath, os.path.split(sOva)[1] + '-ovf');
-        sOvf    = os.path.join(sTmpDir, os.path.splitext(os.path.split(sOva)[1])[0] + '.ovf');
+        Unpacks the OVA into a subdirectory in the scratch area and imports it as an OVF.
+        """
+        oVirtualBox = self.oTstDrv.oVBoxMgr.getVirtualBox()
+
+        sTmpDir = os.path.join(self.oTstDrv.sScratchPath, os.path.split(sOva)[1] + '-ovf')
+        sOvf    = os.path.join(sTmpDir, os.path.splitext(os.path.split(sOva)[1])[0] + '.ovf')
 
         #
@@ -175,10 +159,10 @@
         #
         try:
-            os.mkdir(sTmpDir, 0o755);
-            oTarFile = tarfile.open(sOva, 'r:*');
-            oTarFile.extractall(sTmpDir);
-            oTarFile.close();
-        except:
-            return reporter.errorXcpt('Unpacking "%s" to "%s" for OVF style importing failed' % (sOvf, sTmpDir,));
+            os.mkdir(sTmpDir, 0o755)
+            oTarFile = tarfile.open(sOva, 'r:*')
+            oTarFile.extractall(sTmpDir)
+            oTarFile.close()
+        except:
+            return reporter.errorXcpt('Unpacking "%s" to "%s" for OVF style importing failed' % (sOvf, sTmpDir,))
 
         #
@@ -186,34 +170,37 @@
         #
         try:
-            oAppliance2 = oVirtualBox.createAppliance();
-        except:
-            return reporter.errorXcpt('IVirtualBox::createAppliance failed (#2)');
-        print("oAppliance2=%s" % (oAppliance2,));
-
-        try:
-            oProgress = vboxwrappers.ProgressWrapper(oAppliance2.read(sOvf), self.oVBoxMgr, self, 'read "%s"' % (sOvf,));
-        except:
-            return reporter.errorXcpt('IAppliance::read("%s") failed' % (sOvf,));
-        oProgress.wait();
-        if oProgress.logResult() is False:
-            return False;
-
-        try:
-            oAppliance2.interpret();
-        except:
-            return reporter.errorXcpt('IAppliance::interpret() failed on "%s"' % (sOvf,));
+            oAppliance2 = oVirtualBox.createAppliance()
+        except:
+            return reporter.errorXcpt('IVirtualBox::createAppliance failed (#2)')
+
+        try:
+            oProgress = vboxwrappers.ProgressWrapper(oAppliance2.read(sOvf), self.oTstDrv.oVBoxMgr, self.oTstDrv, 'read "%s"' % (sOvf,))
+        except:
+            return reporter.errorXcpt('IAppliance::read("%s") failed' % (sOvf,))
+        oProgress.wait()
+        if oProgress.logResult() is False:
+            return False
+
+        try:
+            oAppliance2.interpret()
+        except:
+            return reporter.errorXcpt('IAppliance::interpret() failed on "%s"' % (sOvf,))
 
         try:
             oProgress = vboxwrappers.ProgressWrapper(oAppliance2.importMachines([]),
-                                                     self.oVBoxMgr, self, 'importMachines "%s"' % (sOvf,));
-        except:
-            return reporter.errorXcpt('IAppliance::importMachines failed on "%s"' % (sOvf,));
-        oProgress.wait();
-        if oProgress.logResult() is False:
-            return False;
-
-        return True;
+                                                     self.oTstDrv.oVBoxMgr, self.oTstDrv, 'importMachines "%s"' % (sOvf,))
+        except:
+            return reporter.errorXcpt('IAppliance::importMachines failed on "%s"' % (sOvf,))
+        oProgress.wait()
+        if oProgress.logResult() is False:
+            return False
+
+        return True
 
 if __name__ == '__main__':
-    sys.exit(tdAppliance1().main(sys.argv));
-
+    sys.path.append(os.path.dirname(os.path.abspath(__file__)))
+    from tdApi1 import tdApi1
+    oTstDrv = tdApi1()
+    oTstDrv.addSubTestDriver(SubTstDrvAppliance1(oTstDrv))
+    sys.exit(oTstDrv.main(sys.argv))
+
Index: trunk/src/VBox/ValidationKit/tests/api/tdMoveMedium.py
===================================================================
--- trunk/src/VBox/ValidationKit/tests/api/tdMoveMedium.py	(revision 70797)
+++ 	(revision )
@@ -1,174 +1,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# $Id: tdMoveMedium.py
-
-"""
-VirtualBox Validation Kit - Medium Move Test
-"""
-
-__copyright__ = \
-"""
-Copyright (C) 2010-2017 Oracle Corporation
-
-This file is part of VirtualBox Open Source Edition (OSE), as
-available from http://www.virtualbox.org. This file is free software;
-you can redistribute it and/or modify it under the terms of the GNU
-General Public License (GPL) as published by the Free Software
-Foundation, in version 2 as it comes in the "COPYING" file of the
-VirtualBox OSE distribution. VirtualBox OSE is distributed in the
-hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-
-The contents of this file may alternatively be used under the terms
-of the Common Development and Distribution License Version 1.0
-(CDDL) only, as it comes in the "COPYING.CDDL" file of the
-VirtualBox OSE distribution, in which case the provisions of the
-CDDL are applicable instead of those of the GPL.
-
-You may elect to license modified versions of this file under the
-terms and conditions of either the GPL or the CDDL or both.
-"""
-__version__ = ""
-
-# Standard Python imports.
-import os
-import sys
-
-# Only the main script needs to modify the path.
-try:    __file__
-except: __file__ = sys.argv[0]
-g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-sys.path.append(g_ksValidationKitDir)
-
-# Validation Kit imports.
-from common     import utils
-from testdriver import reporter
-from testdriver import vbox
-from testdriver import vboxwrappers;
-
-class tdMoveMedium(vbox.TestDriver):
-    """
-    Medium moving Test.
-    """
-
-    # Suffix exclude list.
-    suffixes = [
-        '.vdi',
-    ];
-
-    def __init__(self):
-        vbox.TestDriver.__init__(self)
-        self.asRsrcs            = None
-
-    #
-    # Overridden methods.
-    #
-
-    def actionConfig(self):
-        """
-        Import the API.
-        """
-        if not self.importVBoxApi():
-            return False
-        return True
-
-    def actionExecute(self):
-        """
-        Execute the testcase.
-        """
-        return  self.testMediumMove()
-
-    #
-    # Test execution helpers.
-    #
-    def setLocation(self, sLocation, aListOfAttach):
-        for attachment in aListOfAttach:
-            try:
-                oMedium = attachment.medium;
-                reporter.log('Move medium ' + oMedium.name + ' to the ' + sLocation)
-            except:
-                reporter.errorXcpt('failed to get the medium from the IMediumAttachment "%s"' % (attachment));
-
-            try:
-                oProgress = vboxwrappers.ProgressWrapper(oMedium.setLocation(sLocation), self.oVBoxMgr, self, 'move "%s"' % (oMedium.name,));
-            except:
-                return reporter.errorXcpt('Medium::setLocation("%s") for medium "%s" failed' % (sLocation, oMedium.name,));
-
-            oProgress.wait();
-            if oProgress.logResult() is False:
-                return False;
-
-    # Test with VDI image
-    # move medium to a new location.
-    # case 1. Only path without file name
-    # case 2. Only path without file name without '\' or '/' at the end
-    # case 3. Path with file name
-    # case 4. Only file name
-    # case 5. Move snapshot
-
-    def testMediumMove(self):
-        """
-        Test medium moving.
-        """
-        reporter.testStart('medium moving')
-
-        try:
-            oVM = self.createTestVM('test-medium-move', 1, None, 4)
-            assert oVM is not None
-
-            # create virtual disk image vdi
-            fRc = True
-            c = 0
-            oSession = self.openSession(oVM)
-            for i in self.suffixes:
-                sHddPath = os.path.join(self.sScratchPath, 'Test' + str(c) + i)
-                oHd = oSession.createBaseHd(sHddPath, cb=1024*1024)
-                if oHd is None:
-                    fRc = False
-                    break
-
-                # attach HDD, IDE controller exists by default, but we use SATA just in case
-                sController='SATA Controller'
-                fRc = fRc and oSession.attachHd(sHddPath, sController, iPort = c, iDevice = 0, fImmutable=False, fForceResource=False)
-                fRc = fRc and oSession.saveSettings()
-
-            #create temporary subdirectory in the current working directory
-            sOrigLoc = self.sScratchPath
-            sNewLoc = os.path.join(sOrigLoc, 'newLocation/')
-
-            os.makedirs(sNewLoc, 0o775);
-
-            aListOfAttach = oVM.getMediumAttachmentsOfController(sController)
-            #case 1. Only path without file name
-            sLocation = sNewLoc
-            self.setLocation(sLocation, aListOfAttach)
-
-            #case 2. Only path without file name without '\' or '/' at the end
-            sLocation = sOrigLoc
-            self.setLocation(sLocation, aListOfAttach)
-
-            #case 3. Path with file name
-            sLocation = sNewLoc + 'newName.vdi'
-            self.setLocation(sLocation, aListOfAttach)
-
-            #case 4. Only file name
-            sLocation = 'onlyMediumName'
-            self.setLocation(sLocation, aListOfAttach)
-
-            #case 5. Move snapshot
-            fRc = fRc and oSession.takeSnapshot('Snapshot1')
-            sLocation = sOrigLoc
-            #get fresh attachments after snapshot
-            aListOfAttach = oVM.getMediumAttachmentsOfController(sController)
-            self.setLocation(sLocation, aListOfAttach)
-
-            fRc = oSession.close() and fRc
-
-            assert fRc is True
-        except:
-            reporter.errorXcpt()
-
-        return reporter.testDone()[1] == 0
-
-if __name__ == '__main__':
-    sys.exit(tdMoveMedium().main(sys.argv))
-
Index: trunk/src/VBox/ValidationKit/tests/api/tdMoveMedium1.py
===================================================================
--- trunk/src/VBox/ValidationKit/tests/api/tdMoveMedium1.py	(revision 70812)
+++ trunk/src/VBox/ValidationKit/tests/api/tdMoveMedium1.py	(revision 70812)
@@ -0,0 +1,168 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# $Id$
+
+"""
+VirtualBox Validation Kit - Medium Move Test #1
+"""
+
+__copyright__ = \
+"""
+Copyright (C) 2010-2017 Oracle Corporation
+
+This file is part of VirtualBox Open Source Edition (OSE), as
+available from http://www.virtualbox.org. This file is free software;
+you can redistribute it and/or modify it under the terms of the GNU
+General Public License (GPL) as published by the Free Software
+Foundation, in version 2 as it comes in the "COPYING" file of the
+VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+
+The contents of this file may alternatively be used under the terms
+of the Common Development and Distribution License Version 1.0
+(CDDL) only, as it comes in the "COPYING.CDDL" file of the
+VirtualBox OSE distribution, in which case the provisions of the
+CDDL are applicable instead of those of the GPL.
+
+You may elect to license modified versions of this file under the
+terms and conditions of either the GPL or the CDDL or both.
+"""
+__version__ = "$Revision$"
+
+
+# Standard Python imports.
+import os
+import sys
+
+# Only the main script needs to modify the path.
+try:    __file__
+except: __file__ = sys.argv[0]
+g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+sys.path.append(g_ksValidationKitDir)
+
+# Validation Kit imports.
+from testdriver import base
+from testdriver import reporter
+from testdriver import vboxwrappers
+
+
+class SubTstDrvMoveMedium1(base.SubTestDriverBase):
+    """
+    Sub-test driver for Medium Move Test #1.
+    """
+
+    # List of suffixes to append.
+    suffixes = [
+        '.vdi',
+    ]
+
+    def __init__(self, oTstDrv):
+        base.SubTestDriverBase.__init__(self, 'move-medium', oTstDrv)
+
+    def testIt(self):
+        """
+        Execute the sub-testcase.
+        """
+        return  self.testMediumMove()
+
+    #
+    # Test execution helpers.
+    #
+
+    def setLocation(self, sLocation, aListOfAttach):
+        for attachment in aListOfAttach:
+            try:
+                oMedium = attachment.medium
+                reporter.log('Move medium ' + oMedium.name + ' to the ' + sLocation)
+            except:
+                reporter.errorXcpt('failed to get the medium from the IMediumAttachment "%s"' % (attachment))
+
+            try:
+                oProgress = vboxwrappers.ProgressWrapper(oMedium.setLocation(sLocation), self.oTstDrv.oVBoxMgr, self.oTstDrv, 'move "%s"' % (oMedium.name,))
+            except:
+                return reporter.errorXcpt('Medium::setLocation("%s") for medium "%s" failed' % (sLocation, oMedium.name,))
+
+            oProgress.wait()
+            if oProgress.logResult() is False:
+                return False
+
+    # Test with VDI image
+    # move medium to a new location.
+    # case 1. Only path without file name
+    # case 2. Only path without file name without '\' or '/' at the end
+    # case 3. Path with file name
+    # case 4. Only file name
+    # case 5. Move snapshot
+
+    def testMediumMove(self):
+        """
+        Test medium moving.
+        """
+        reporter.testStart('medium moving')
+
+        try:
+            oVM = self.oTstDrv.createTestVM('test-medium-move', 1, None, 4)
+            assert oVM is not None
+
+            # create virtual disk image vdi
+            fRc = True
+            c = 0
+            oSession = self.oTstDrv.openSession(oVM)
+            for i in self.suffixes:
+                sHddPath = os.path.join(self.oTstDrv.sScratchPath, 'Test' + str(c) + i)
+                oHd = oSession.createBaseHd(sHddPath, cb=1024*1024)
+                if oHd is None:
+                    fRc = False
+                    break
+
+                # attach HDD, IDE controller exists by default, but we use SATA just in case
+                sController='SATA Controller'
+                fRc = fRc and oSession.attachHd(sHddPath, sController, iPort = c, iDevice = 0, fImmutable=False, fForceResource=False)
+                fRc = fRc and oSession.saveSettings()
+
+            #create temporary subdirectory in the current working directory
+            sOrigLoc = self.oTstDrv.sScratchPath
+            sNewLoc = os.path.join(sOrigLoc, 'newLocation/')
+
+            os.makedirs(sNewLoc, 0o775)
+
+            aListOfAttach = oVM.getMediumAttachmentsOfController(sController)
+            #case 1. Only path without file name
+            sLocation = sNewLoc
+            self.setLocation(sLocation, aListOfAttach)
+
+            #case 2. Only path without file name without '\' or '/' at the end
+            sLocation = sOrigLoc
+            self.setLocation(sLocation, aListOfAttach)
+
+            #case 3. Path with file name
+            sLocation = sNewLoc + 'newName.vdi'
+            self.setLocation(sLocation, aListOfAttach)
+
+            #case 4. Only file name
+            sLocation = 'onlyMediumName'
+            self.setLocation(sLocation, aListOfAttach)
+
+            #case 5. Move snapshot
+            fRc = fRc and oSession.takeSnapshot('Snapshot1')
+            sLocation = sOrigLoc
+            #get fresh attachments after snapshot
+            aListOfAttach = oVM.getMediumAttachmentsOfController(sController)
+            self.setLocation(sLocation, aListOfAttach)
+
+            fRc = oSession.close() and fRc
+
+            assert fRc is True
+        except:
+            reporter.errorXcpt()
+
+        return reporter.testDone()[1] == 0
+
+
+if __name__ == '__main__':
+    sys.path.append(os.path.dirname(os.path.abspath(__file__)))
+    from tdApi1 import tdApi1
+    oTstDrv = tdApi1()
+    oTstDrv.addSubTestDriver(SubTstDrvMoveMedium1(oTstDrv))
+    sys.exit(oTstDrv.main(sys.argv))
+
Index: trunk/src/VBox/ValidationKit/tests/api/tdPython1.py
===================================================================
--- trunk/src/VBox/ValidationKit/tests/api/tdPython1.py	(revision 70797)
+++ trunk/src/VBox/ValidationKit/tests/api/tdPython1.py	(revision 70812)
@@ -39,42 +39,27 @@
 # Only the main script needs to modify the path.
 try:    __file__
-except: __file__ = sys.argv[0];
-g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))));
-sys.path.append(g_ksValidationKitDir);
+except: __file__ = sys.argv[0]
+g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+sys.path.append(g_ksValidationKitDir)
 
 # Validation Kit imports.
-from testdriver import reporter;
-from testdriver import base;
-from testdriver import vbox;
-
-
-class tdPython1(vbox.TestDriver):
+from testdriver import base
+from testdriver import reporter
+
+
+class SubTstDrvPython1(base.SubTestDriverBase):
     """
-    Python Bindings Test #1.
+    Sub-test driver for Python Bindings Test #1.
     """
 
-    def __init__(self):
-        vbox.TestDriver.__init__(self);
-        self.asRsrcs            = None;
-
-
-    #
-    # Overridden methods.
-    #
-
-    def actionConfig(self):
-        """
-        Import the API.
-        """
-        if not self.importVBoxApi():
-            return False;
-        return True;
-
-    def actionExecute(self):
-        """
-        Execute the testcase.
+    def __init__(self, oTstDrv):
+        base.SubTestDriverBase.__init__(self, 'python-binding', oTstDrv)
+
+    def testIt(self):
+        """
+        Execute the sub-testcase.
         """
         return  self.testEventQueueWaiting() \
-            and self.testEventQueueInterrupt();
+            and self.testEventQueueInterrupt()
 
     #
@@ -85,9 +70,9 @@
         """ Thread procedure for checking that waitForEvents fails when not called by the main thread. """
         try:
-            rc2 = self.oVBoxMgr.waitForEvents(0);
+            rc2 = self.oTstDrv.oVBoxMgr.waitForEvents(0)
         except:
-            return True;
-        reporter.error('waitForEvents() returned "%s" when called on a worker thread, expected exception.' % (rc2,));
-        return False;
+            return True
+        reporter.error('waitForEvents() returned "%s" when called on a worker thread, expected exception.' % (rc2,))
+        return False
 
     def testEventQueueWaiting(self):
@@ -95,56 +80,56 @@
         Test event queue waiting.
         """
-        reporter.testStart('waitForEvents');
+        reporter.testStart('waitForEvents')
 
         # Check return values and such.
         for cMsTimeout in (0, 1, 2, 3, 256, 1000, 0):
-            iLoop = 0;
+            iLoop = 0
             while True:
                 try:
-                    rc = self.oVBoxMgr.waitForEvents(cMsTimeout);
+                    rc = self.oTstDrv.oVBoxMgr.waitForEvents(cMsTimeout)
                 except:
-                    reporter.errorXcpt();
-                    break;
+                    reporter.errorXcpt()
+                    break
                 if not isinstance(rc, int):
-                    reporter.error('waitForEvents returns non-integer type');
-                    break;
+                    reporter.error('waitForEvents returns non-integer type')
+                    break
                 if rc == 1:
-                    break;
+                    break
                 if rc != 0:
-                    reporter.error('waitForEvents returns "%s", expected 0 or 1' % (rc,));
-                    break;
-                iLoop += 1;
+                    reporter.error('waitForEvents returns "%s", expected 0 or 1' % (rc,))
+                    break
+                iLoop += 1
                 if iLoop > 10240:
                     reporter.error('waitForEvents returns 0 (success) %u times. '
                                    'Expected 1 (timeout/interrupt) after a call or two.'
-                                   % (iLoop,));
-                    break;
+                                   % (iLoop,))
+                    break
             if reporter.testErrorCount() != 0:
-                break;
+                break
 
         # Check that we get an exception when trying to call the method from
         # a different thread.
         reporter.log('If running a debug build, you will see an ignored assertion now. Please ignore it.')
-        sVBoxAssertSaved = os.environ.get('VBOX_ASSERT', 'breakpoint');
-        os.environ['VBOX_ASSERT'] = 'ignore';
-        oThread = threading.Thread(target=self.testEventQueueWaitingThreadProc);
-        oThread.start();
-        oThread.join();
-        os.environ['VBOX_ASSERT'] = sVBoxAssertSaved;
-
-        return reporter.testDone()[1] == 0;
+        sVBoxAssertSaved = os.environ.get('VBOX_ASSERT', 'breakpoint')
+        os.environ['VBOX_ASSERT'] = 'ignore'
+        oThread = threading.Thread(target=self.testEventQueueWaitingThreadProc)
+        oThread.start()
+        oThread.join()
+        os.environ['VBOX_ASSERT'] = sVBoxAssertSaved
+
+        return reporter.testDone()[1] == 0
 
     def interruptWaitEventsThreadProc(self):
         """ Thread procedure that's used for waking up the main thread. """
-        time.sleep(2);
+        time.sleep(2)
         try:
-            rc2 = self.oVBoxMgr.interruptWaitEvents();
+            rc2 = self.oTstDrv.oVBoxMgr.interruptWaitEvents()
         except:
-            reporter.errorXcpt();
+            reporter.errorXcpt()
         else:
             if rc2 is True:
-                return True;
-            reporter.error('interruptWaitEvents returned "%s" when called from other thread, expected True' % (rc2,));
-        return False;
+                return True
+            reporter.error('interruptWaitEvents returned "%s" when called from other thread, expected True' % (rc2,))
+        return False
 
     def testEventQueueInterrupt(self):
@@ -152,15 +137,15 @@
         Test interrupting an event queue wait.
         """
-        reporter.testStart('interruptWait');
+        reporter.testStart('interruptWait')
 
         # interrupt ourselves first and check the return value.
         for i in range(0, 10):
             try:
-                rc = self.oVBoxMgr.interruptWaitEvents();
+                rc = self.oTstDrv.oVBoxMgr.interruptWaitEvents()
             except:
-                reporter.errorXcpt();
-                break;
+                reporter.errorXcpt()
+                break
             if rc is not True:
-                reporter.error('interruptWaitEvents returned "%s" expected True' % (rc,));
+                reporter.error('interruptWaitEvents returned "%s" expected True' % (rc,))
                 break
 
@@ -176,49 +161,53 @@
                 # Try quiesce the event queue.
                 for _ in range(1, 100):
-                    self.oVBoxMgr.waitForEvents(0);
+                    self.oTstDrv.oVBoxMgr.waitForEvents(0)
 
                 # Create a thread that will interrupt us in 2 seconds.
                 try:
-                    oThread = threading.Thread(target=self.interruptWaitEventsThreadProc);
-                    oThread.setDaemon(False);
+                    oThread = threading.Thread(target=self.interruptWaitEventsThreadProc)
+                    oThread.setDaemon(False)
                 except:
-                    reporter.errorXcpt();
-                    break;
-
-                cMsTimeout = 20000;
+                    reporter.errorXcpt()
+                    break
+
+                cMsTimeout = 20000
                 if i == 2:
-                    cMsTimeout = -1;
+                    cMsTimeout = -1
                 elif i == 3:
-                    cMsTimeout = -999999;
+                    cMsTimeout = -999999
 
                 # Do the wait.
-                oThread.start();
-                msNow = base.timestampMilli();
+                oThread.start()
+                msNow = base.timestampMilli()
                 try:
-                    rc = self.oVBoxMgr.waitForEvents(cMsTimeout);
+                    rc = self.oTstDrv.oVBoxMgr.waitForEvents(cMsTimeout)
                 except:
-                    reporter.errorXcpt();
+                    reporter.errorXcpt()
                 else:
-                    msElapsed = base.timestampMilli() - msNow;
+                    msElapsed = base.timestampMilli() - msNow
 
                     # Check the return code and elapsed time.
                     if not isinstance(rc, int):
-                        reporter.error('waitForEvents returns non-integer type after %u ms, expected 1' % (msElapsed,));
+                        reporter.error('waitForEvents returns non-integer type after %u ms, expected 1' % (msElapsed,))
                     elif rc != 1:
-                        reporter.error('waitForEvents returned "%s" after %u ms, expected 1' % (rc, msElapsed));
+                        reporter.error('waitForEvents returned "%s" after %u ms, expected 1' % (rc, msElapsed))
                     if msElapsed > 15000:
-                        reporter.error('waitForEvents after %u ms, expected just above 2-3 seconds' % (msElapsed,));
+                        reporter.error('waitForEvents after %u ms, expected just above 2-3 seconds' % (msElapsed,))
                     elif msElapsed < 100:
-                        reporter.error('waitForEvents after %u ms, expected more than 100 ms.' % (msElapsed,));
-
-                oThread.join();
-                oThread = None;
+                        reporter.error('waitForEvents after %u ms, expected more than 100 ms.' % (msElapsed,))
+
+                oThread.join()
+                oThread = None
                 if reporter.testErrorCount() != 0:
-                    break;
-                reporter.log('Iteration %u was successful...' % (i + 1,));
-        return reporter.testDone()[1] == 0;
+                    break
+                reporter.log('Iteration %u was successful...' % (i + 1,))
+        return reporter.testDone()[1] == 0
 
 
 if __name__ == '__main__':
-    sys.exit(tdPython1().main(sys.argv));
-
+    sys.path.append(os.path.dirname(os.path.abspath(__file__)))
+    from tdApi1 import tdApi1
+    oTstDrv = tdApi1()
+    oTstDrv.addSubTestDriver(SubTstDrvPython1(oTstDrv))
+    sys.exit(oTstDrv.main(sys.argv))
+
Index: trunk/src/VBox/ValidationKit/tests/api/tdTreeDepth1.py
===================================================================
--- trunk/src/VBox/ValidationKit/tests/api/tdTreeDepth1.py	(revision 70797)
+++ trunk/src/VBox/ValidationKit/tests/api/tdTreeDepth1.py	(revision 70812)
@@ -42,34 +42,20 @@
 
 # Validation Kit imports.
+from testdriver import base
 from testdriver import reporter
-from testdriver import vbox
 from testdriver import vboxcon
 
 
-class tdTreeDepth1(vbox.TestDriver):
+class SubTstDrvTreeDepth1(base.SubTestDriverBase):
     """
-    Medium and Snapshot Tree Depth Test #1.
+    Sub-test driver for Medium and Snapshot Tree Depth Test #1.
     """
 
-    def __init__(self):
-        vbox.TestDriver.__init__(self)
-        self.asRsrcs            = None
+    def __init__(self, oTstDrv):
+        base.SubTestDriverBase.__init__(self, 'tree-depth', oTstDrv)
 
-
-    #
-    # Overridden methods.
-    #
-
-    def actionConfig(self):
+    def testIt(self):
         """
-        Import the API.
-        """
-        if not self.importVBoxApi():
-            return False
-        return True
-
-    def actionExecute(self):
-        """
-        Execute the testcase.
+        Execute the sub-testcase.
         """
         return  self.testMediumTreeDepth() \
@@ -87,12 +73,12 @@
 
         try:
-            oVM = self.createTestVM('test-medium', 1, None, 4)
+            oVM = self.oTstDrv.createTestVM('test-medium', 1, None, 4)
             assert oVM is not None
 
             # create chain with 300 disk images (medium tree depth limit)
             fRc = True
-            oSession = self.openSession(oVM)
+            oSession = self.oTstDrv.openSession(oVM)
             for i in range(1, 301):
-                sHddPath = os.path.join(self.sScratchPath, 'Test' + str(i) + '.vdi')
+                sHddPath = os.path.join(self.oTstDrv.sScratchPath, 'Test' + str(i) + '.vdi')
                 if i is 1:
                     oHd = oSession.createBaseHd(sHddPath, cb=1024*1024)
@@ -112,5 +98,5 @@
             reporter.log('unregistering VM')
             oVM.unregister(vboxcon.CleanupMode_DetachAllReturnNone)
-            oVBox = self.oVBoxMgr.getVirtualBox()
+            oVBox = self.oTstDrv.oVBoxMgr.getVirtualBox()
             reporter.log('opening VM %s, testing config reading' % (sSettingsFile))
             oVM = oVBox.openMachine(sSettingsFile)
@@ -129,10 +115,10 @@
 
         try:
-            oVM = self.createTestVM('test-snap', 1, None, 4)
+            oVM = self.oTstDrv.createTestVM('test-snap', 1, None, 4)
             assert oVM is not None
 
             # modify the VM config, create and attach empty HDD
-            oSession = self.openSession(oVM)
-            sHddPath = os.path.join(self.sScratchPath, 'TestSnapEmpty.vdi')
+            oSession = self.oTstDrv.openSession(oVM)
+            sHddPath = os.path.join(self.oTstDrv.sScratchPath, 'TestSnapEmpty.vdi')
             fRc = True
             fRc = fRc and oSession.createAndAttachHd(sHddPath, cb=1024*1024, sController='SATA Controller', fImmutable=False)
@@ -148,5 +134,5 @@
             reporter.log('unregistering VM')
             oVM.unregister(vboxcon.CleanupMode_DetachAllReturnNone)
-            oVBox = self.oVBoxMgr.getVirtualBox()
+            oVBox = self.oTstDrv.oVBoxMgr.getVirtualBox()
             reporter.log('opening VM %s, testing config reading' % (sSettingsFile))
             oVM = oVBox.openMachine(sSettingsFile)
@@ -160,4 +146,8 @@
 
 if __name__ == '__main__':
-    sys.exit(tdTreeDepth1().main(sys.argv))
+    sys.path.append(os.path.dirname(os.path.abspath(__file__)))
+    from tdApi1 import tdApi1
+    oTstDrv = tdApi1()
+    oTstDrv.addSubTestDriver(SubTstDrvTreeDepth1(oTstDrv))
+    sys.exit(oTstDrv.main(sys.argv))
 
