VirtualBox

Changeset 99084 in vbox for trunk/src/VBox/ValidationKit


Ignore:
Timestamp:
Mar 21, 2023 11:39:58 AM (23 months ago)
Author:
vboxsync
Message:

ValidationKit/tests/api/tdTreeDepth1.py: Restructure the layout to be
more modular, break up the monolithic try/except blocks into small
segments which only wrap API calls, remove the random selection of the
type of cleanup mode to pass to Machine::unregister() to give better
test coverage since we always call unregister(UnregisterOnly), and most
importantly add a small delay after calling unregister(UnregisterOnly)
and dropping the reference count of the IMachine object ('oVM') to zero
so that Machine::uninit() will be called to close the attached media.
The delay addresses the intermittent test suite failures when the
subsequent check would complete before the Machine::uninit() call and
flag the discrepancy between the expected number of attached disks and
the actual number found.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/tests/api/tdTreeDepth1.py

    r98826 r99084  
    4545import sys
    4646import random
     47import time
    4748
    4849# Only the main script needs to modify the path.
     
    7172        """
    7273        return  self.testMediumTreeDepth() \
    73             and self.testSnapshotTreeDepth()
     74            and self.testSnapshotTreeDepth();
     75
     76    def getNumOfAttachedHDs(self, oVM, sController):
     77        """
     78        Helper routine for counting the hard disks, including differencing disks,
     79        attached to the specified countroller.
     80        """
     81        try:
     82            aoMediumAttachments = oVM.getMediumAttachmentsOfController(sController);
     83        except:
     84            reporter.errorXcpt('oVM.getMediumAttachmentsOfController("%s") failed' % (sController));
     85            return -1;
     86
     87        cDisks = 0;
     88        for oAttachment in aoMediumAttachments:
     89            oMedium = oAttachment.medium;
     90            if oMedium.deviceType is vboxcon.DeviceType_HardDisk:
     91                cDisks = cDisks + 1;
     92                reporter.log2('base medium = %s cDisks = %d' % (oMedium.location, cDisks));
     93                oParentMedium = oMedium.parent;
     94                while oParentMedium is not None:
     95                    cDisks = cDisks + 1;
     96                    reporter.log2('parent medium = %s cDisks = %d' % (oParentMedium.location, cDisks));
     97                    oParentMedium = oParentMedium.parent;
     98        return cDisks;
     99
     100    def unregisterVM(self, oVM, enmCleanupMode):
     101        """
     102        Helper routine to unregister the VM using the CleanupMode specified.
     103        """
     104        reporter.log('unregistering VM using %s' % enmCleanupMode);
     105        if enmCleanupMode == 'DetachAllReturnHardDisksOnly':
     106            try:
     107                aoHDs = oVM.unregister(vboxcon.CleanupMode_DetachAllReturnHardDisksOnly);
     108            except:
     109                return reporter.logXcpt('unregister(CleanupMode_DetachAllReturnHardDisksOnly) failed');
     110            for oHD in aoHDs:
     111                reporter.log2('closing medium = %s' % (oHD.location));
     112                oHD.close();
     113            aoHDs = None;
     114        elif enmCleanupMode == 'UnregisterOnly':
     115            try:
     116                aoHDs = oVM.unregister(vboxcon.CleanupMode_UnregisterOnly);
     117            except:
     118                return reporter.logXcpt('unregister(CleanupMode_UnregisterOnly) failed');
     119            if aoHDs:
     120                return reporter.error('unregister(CleanupMode_UnregisterOnly) failed: returned %d disks' %
     121                                      len(aoHDs));
     122        else:
     123            return reporter.error('unregisterVM: unexpected CleanupMode "%s"' % enmCleanupMode);
     124
     125        return True;
     126
     127    def openAndRegisterMachine(self, oVBox, sSettingsFile):
     128        """
     129        Helper routine which opens a VM and registers it.
     130        """
     131        reporter.log('opening VM using configuration file = %s, testing config reading' % (sSettingsFile));
     132        try:
     133            if self.oTstDrv.fpApiVer >= 7.0:
     134                # Needs a password parameter since 7.0.
     135                oVM = oVBox.openMachine(sSettingsFile, "");
     136            else:
     137                oVM = oVBox.openMachine(sSettingsFile);
     138        except:
     139            reporter.logXcpt('openMachine(%s) failed' % (sSettingsFile));
     140            return None;
     141
     142        if not oVM:
     143            return None;
     144
     145        try:
     146            oVBox.registerMachine(oVM);
     147        except:
     148            reporter.logXcpt('registerMachine(%s) failed' % (sSettingsFile));
     149            return None;
     150
     151        return oVM;
    74152
    75153    #
     
    83161        reporter.testStart('mediumTreeDepth')
    84162
    85         try:
    86             oVBox = self.oTstDrv.oVBoxMgr.getVirtualBox()
    87             oVM = self.oTstDrv.createTestVM('test-medium', 1, None, 4)
    88             assert oVM is not None
    89 
    90             # create chain with up to 64 disk images (medium tree depth limit)
    91             fRc = True
    92             oSession = self.oTstDrv.openSession(oVM)
    93             cImages = random.randrange(1, 64);
    94             reporter.log('Creating chain with %d disk images' % (cImages))
    95             for i in range(1, cImages + 1):
    96                 sHddPath = os.path.join(self.oTstDrv.sScratchPath, 'Test' + str(i) + '.vdi')
    97                 if i == 1:
    98                     oHd = oSession.createBaseHd(sHddPath, cb=1024*1024)
    99                 else:
    100                     oHd = oSession.createDiffHd(oHd, sHddPath)
    101                 if oHd is None:
    102                     fRc = False
    103                     break
    104 
    105             # modify the VM config, attach HDD
    106             fRc = fRc and oSession.attachHd(sHddPath, sController='SATA Controller', fImmutable=False, fForceResource=False)
    107             fRc = fRc and oSession.saveSettings()
    108             fRc = oSession.close() and fRc
    109             ## @todo r=klaus: count known hard disk images, should be cImages
    110 
    111             # unregister, making sure the images are closed
    112             sSettingsFile = oVM.settingsFilePath
    113             fDetachAll = random.choice([False, True])
    114             if fDetachAll:
    115                 reporter.log('unregistering VM, DetachAll style')
     163        oVM = self.oTstDrv.createTestVMOnly('test-medium', 'Other')
     164        if oVM is None:
     165            return False;
     166
     167        # Save the path to the VM's settings file while oVM is valid (needed for
     168        # openMachine() later when oVM is gone).
     169        sSettingsFile = oVM.settingsFilePath
     170
     171        oSession = self.oTstDrv.openSession(oVM)
     172        if oSession is None:
     173            return False;
     174
     175        # create chain with up to 64 disk images (medium tree depth limit)
     176        cImages = random.randrange(1, 64);
     177        reporter.log('Creating chain with %d disk images' % (cImages))
     178        for i in range(1, cImages + 1):
     179            sHddPath = os.path.join(self.oTstDrv.sScratchPath, 'Test' + str(i) + '.vdi')
     180            if i == 1:
     181                oHd = oSession.createBaseHd(sHddPath, cb=1024*1024)
    116182            else:
    117                 reporter.log('unregistering VM, UnregisterOnly style')
    118             self.oTstDrv.forgetTestMachine(oVM)
    119             if fDetachAll:
    120                 aoHDs = oVM.unregister(vboxcon.CleanupMode_DetachAllReturnHardDisksOnly)
    121                 for oHD in aoHDs:
    122                     oHD.close()
    123                 aoHDs = None
    124             else:
    125                 oVM.unregister(vboxcon.CleanupMode_UnregisterOnly)
    126             oVM = None
    127 
    128             # If there is no base image (expected) then there are no leftover
    129             # child images either. Can be changed later once the todos above
    130             # and below are resolved.
    131             cBaseImages = len(self.oTstDrv.oVBoxMgr.getArray(oVBox, 'hardDisks'))
    132             reporter.log('API reports %i base images' % (cBaseImages))
    133             fRc = fRc and cBaseImages == 0
    134             if cBaseImages != 0:
    135                 reporter.error('Got %d initial base images, expected %d' % (cBaseImages, 0));
    136 
    137             # re-register to test loading of settings
    138             reporter.log('opening VM %s, testing config reading' % (sSettingsFile))
    139             if self.oTstDrv.fpApiVer >= 7.0:
    140                 # Needs a password parameter since 7.0.
    141                 oVM = oVBox.openMachine(sSettingsFile, "")
    142             else:
    143                 oVM = oVBox.openMachine(sSettingsFile)
    144             oVBox.registerMachine(oVM);
    145             ## @todo r=klaus: count known hard disk images, should be cImages
    146 
    147             reporter.log('unregistering VM')
    148             oVM.unregister(vboxcon.CleanupMode_UnregisterOnly)
    149             oVM = None
    150 
    151             cBaseImages = len(self.oTstDrv.oVBoxMgr.getArray(oVBox, 'hardDisks'))
    152             reporter.log('API reports %i base images' % (cBaseImages))
    153             fRc = fRc and cBaseImages == 0
    154             if cBaseImages != 0:
    155                 reporter.error('Got %d base images after unregistering, expected %d' % (cBaseImages, 0));
    156 
    157         except:
    158             reporter.errorXcpt()
    159 
    160         return reporter.testDone()[1] == 0
     183                oHd = oSession.createDiffHd(oHd, sHddPath)
     184            if oHd is None:
     185                return False;
     186
     187        # modify the VM config, attach HDD
     188        sController='SATA Controller';
     189        fRc = oSession.attachHd(sHddPath, sController, fImmutable=False, fForceResource=False);
     190        if fRc:
     191            fRc = oSession.saveSettings(fClose=True);
     192        oSession = None;
     193        if not fRc:
     194            return False;
     195
     196        # Verify that the number of hard disks attached to the VM's only storage
     197        # controller equals the number of disks created above.
     198        cDisks = self.getNumOfAttachedHDs(oVM, sController);
     199        reporter.log('Initial state: Number of hard disks attached = %d (should equal disks created = %d)' % (cDisks, cImages));
     200        if cImages != cDisks:
     201            reporter.error('Created %d disk images but found %d disks attached' % (cImages, cDisks));
     202
     203        # unregister the VM using "DetachAllReturnHardDisksOnly" and confirm all
     204        # hard disks were returned and subsequently closed
     205        fRc = self.unregisterVM(oVM, 'DetachAllReturnHardDisksOnly');
     206        if not fRc:
     207            return False;
     208        oVM = None;
     209
     210        # If there is no base image (expected) then there are no leftover
     211        # child images either.
     212        oVBox = self.oTstDrv.oVBoxMgr.getVirtualBox();
     213        if oVBox is None:
     214            return False;
     215
     216        cBaseImages = len(self.oTstDrv.oVBoxMgr.getArray(oVBox, 'hardDisks'))
     217        reporter.log('After unregister(DetachAllReturnHardDisksOnly): API reports %d base images' % (cBaseImages));
     218        if cBaseImages != 0:
     219            reporter.error('Got %d initial base images, expected zero (0)' % (cBaseImages));
     220
     221        # re-register to test loading of settings
     222        oVM = self.openAndRegisterMachine(oVBox, sSettingsFile);
     223        if oVM is None:
     224            return False;
     225
     226        # Verify that the number of hard disks attached to the VM's only storage
     227        # controller equals the number of disks created above.
     228        cDisks = self.getNumOfAttachedHDs(oVM, sController);
     229        reporter.log('After openMachine()+registerMachine(): Number of hard disks attached = %d '
     230                     '(should equal disks created = %d)' % (cDisks, cImages));
     231        if cImages != cDisks:
     232            reporter.error('Created %d disk images but after openMachine()+registerMachine() found %d disks attached' %
     233                           (cImages, cDisks));
     234
     235        fRc = self.unregisterVM(oVM, 'UnregisterOnly');
     236        if not fRc:
     237            return False;
     238        oVM = None;
     239
     240        # Fudge factor: When unregistering a VM with CleanupMode_UnregisterOnly the
     241        # associated medium objects will be closed when the Machine object is
     242        # uninitialized so wait for that to complete.  Otherwise the check for
     243        # cBaseImages below will race with the VM uninitialization and depending on
     244        # which one wins can cause a test failure.
     245        reporter.log('Waiting five seconds for Machine::uninit() to be called to close the attached disks');
     246        time.sleep(5);
     247
     248        cBaseImages = len(self.oTstDrv.oVBoxMgr.getArray(oVBox, 'hardDisks'));
     249        reporter.log('After unregister(UnregisterOnly): API reports %d base images' % (cBaseImages));
     250        if cBaseImages != 0:
     251            reporter.error('Got %d base images after unregistering, expected zero (0)' % (cBaseImages));
     252
     253        return reporter.testDone()[1] == 0;
    161254
    162255    def testSnapshotTreeDepth(self):
     
    166259        reporter.testStart('snapshotTreeDepth')
    167260
    168         try:
    169             oVBox = self.oTstDrv.oVBoxMgr.getVirtualBox()
    170             oVM = self.oTstDrv.createTestVM('test-snap', 1, None, 4)
    171             assert oVM is not None
    172 
    173             # modify the VM config, create and attach empty HDD
    174             oSession = self.oTstDrv.openSession(oVM)
    175             sHddPath = os.path.join(self.oTstDrv.sScratchPath, 'TestSnapEmpty.vdi')
    176             fRc = True
    177             fRc = fRc and oSession.createAndAttachHd(sHddPath, cb=1024*1024, sController='SATA Controller', fImmutable=False)
    178             fRc = fRc and oSession.saveSettings()
    179 
    180             # take up to 200 snapshots (250 is the snapshot tree depth limit (settings.h:SETTINGS_SNAPSHOT_DEPTH_MAX))
    181             cSnapshots = random.randrange(1, 200);
    182             reporter.log('Taking %d snapshots' % (cSnapshots))
    183             for i in range(1, cSnapshots + 1):
    184                 fRc = fRc and oSession.takeSnapshot('Snapshot ' + str(i))
    185             fRc = oSession.close() and fRc
    186             oSession = None
    187             reporter.log('API reports %i snapshots' % (oVM.snapshotCount))
    188             fRc = fRc and oVM.snapshotCount == cSnapshots
    189             if oVM.snapshotCount != cSnapshots:
    190                 reporter.error('Got %d initial snapshots, expected %d' % (oVM.snapshotCount, cSnapshots));
    191 
    192             # unregister, making sure the images are closed
    193             sSettingsFile = oVM.settingsFilePath
    194             fDetachAll = random.choice([False, True])
    195             if fDetachAll:
    196                 reporter.log('unregistering VM, DetachAll style')
    197             else:
    198                 reporter.log('unregistering VM, UnregisterOnly style')
    199             self.oTstDrv.forgetTestMachine(oVM)
    200             if fDetachAll:
    201                 aoHDs = oVM.unregister(vboxcon.CleanupMode_DetachAllReturnHardDisksOnly)
    202                 for oHD in aoHDs:
    203                     oHD.close()
    204                 aoHDs = None
    205             else:
    206                 oVM.unregister(vboxcon.CleanupMode_UnregisterOnly)
    207             oVM = None
    208 
    209             # If there is no base image (expected) then there are no leftover
    210             # child images either. Can be changed later once the todos above
    211             # and below are resolved.
    212             cBaseImages = len(self.oTstDrv.oVBoxMgr.getArray(oVBox, 'hardDisks'))
    213             reporter.log('API reports %i base images' % (cBaseImages))
    214             fRc = fRc and cBaseImages == 0
    215             if cBaseImages != 0:
    216                 reporter.error('Got %d initial base images, expected %d' % (cBaseImages, 0));
    217 
    218             # re-register to test loading of settings
    219             reporter.log('opening VM %s, testing config reading' % (sSettingsFile))
    220             if self.oTstDrv.fpApiVer >= 7.0:
    221                 # Needs a password parameter since 7.0.
    222                 oVM = oVBox.openMachine(sSettingsFile, "")
    223             else:
    224                 oVM = oVBox.openMachine(sSettingsFile)
    225             oVBox.registerMachine(oVM);
    226             reporter.log('API reports %i snapshots' % (oVM.snapshotCount))
    227             fRc = fRc and oVM.snapshotCount == cSnapshots
    228             if oVM.snapshotCount != cSnapshots:
    229                 reporter.error('Got %d snapshots after re-registering, expected %d' % (oVM.snapshotCount, cSnapshots));
    230 
    231             reporter.log('unregistering VM')
    232             oVM.unregister(vboxcon.CleanupMode_UnregisterOnly)
    233             oVM = None
    234 
    235             cBaseImages = len(self.oTstDrv.oVBoxMgr.getArray(oVBox, 'hardDisks'))
    236             reporter.log('API reports %i base images' % (cBaseImages))
    237             fRc = fRc and cBaseImages == 0
    238             if cBaseImages != 0:
    239                 reporter.error('Got %d base images after unregistering, expected %d' % (cBaseImages, 0));
    240         except:
    241             reporter.errorXcpt()
     261        oVM = self.oTstDrv.createTestVMOnly('test-snap', 'Other');
     262        if oVM is None:
     263            return False;
     264
     265        # Save the path to the VM's settings file while oVM is valid (needed for
     266        # openMachine() later when oVM is gone).
     267        sSettingsFile = oVM.settingsFilePath
     268
     269        # modify the VM config, create and attach empty HDD
     270        oSession = self.oTstDrv.openSession(oVM)
     271        if oSession is None:
     272            return False;
     273        sHddPath = os.path.join(self.oTstDrv.sScratchPath, 'TestSnapEmpty.vdi')
     274        sController='SATA Controller';
     275        fRc = oSession.createAndAttachHd(sHddPath, cb=1024*1024, sController=sController, fImmutable=False);
     276        fRc = fRc and oSession.saveSettings();
     277        if not fRc:
     278            return False;
     279
     280        # take up to 200 snapshots (250 is the snapshot tree depth limit (settings.h:SETTINGS_SNAPSHOT_DEPTH_MAX))
     281        cSnapshots = random.randrange(1, 200);
     282        reporter.log('Taking %d snapshots' % (cSnapshots));
     283        for i in range(1, cSnapshots + 1):
     284            fRc = oSession.takeSnapshot('Snapshot ' + str(i));
     285            if not fRc:
     286                return False;
     287        fRc = oSession.close() and fRc and True;
     288        oSession = None;
     289        reporter.log('API reports %d snapshots (should equal snapshots created = %d)' % (oVM.snapshotCount, cSnapshots));
     290        if oVM.snapshotCount != cSnapshots:
     291            reporter.error('Got %d initial snapshots, expected %d' % (oVM.snapshotCount, cSnapshots));
     292
     293        # unregister the VM using "DetachAllReturnHardDisksOnly" and confirm all
     294        # hard disks were returned and subsequently closed
     295        fRc = self.unregisterVM(oVM, 'DetachAllReturnHardDisksOnly');
     296        if not fRc:
     297            return False;
     298        oVM = None;
     299
     300        # If there is no base image (expected) then there are no leftover
     301        # child images either.
     302        oVBox = self.oTstDrv.oVBoxMgr.getVirtualBox()
     303        if oVBox is None:
     304            return False;
     305
     306        cBaseImages = len(self.oTstDrv.oVBoxMgr.getArray(oVBox, 'hardDisks'))
     307        reporter.log('After unregister(DetachAllReturnHardDisksOnly): API reports %d base images' % (cBaseImages));
     308        fRc = fRc and cBaseImages == 0
     309        if cBaseImages != 0:
     310            reporter.error('Got %d initial base images, expected zero (0)' % (cBaseImages));
     311
     312        # re-register to test loading of settings
     313        oVM = self.openAndRegisterMachine(oVBox, sSettingsFile);
     314        if oVM is None:
     315            return False;
     316
     317        # Verify that the number of hard disks attached to the VM's only storage
     318        # controller equals the number of disks created above.
     319        reporter.log('After openMachine()+registerMachine(): Number of snapshots of VM = %d '
     320                     '(should equal snapshots created = %d)' % (oVM.snapshotCount, cSnapshots));
     321        if oVM.snapshotCount != cSnapshots:
     322            reporter.error('Created %d snapshots but after openMachine()+registerMachine() found %d snapshots' %
     323                           (cSnapshots, oVM.snapshotCount));
     324
     325        fRc = self.unregisterVM(oVM, 'UnregisterOnly');
     326        if not fRc:
     327            return False;
     328        oVM = None;
     329
     330        # Fudge factor: When unregistering a VM with CleanupMode_UnregisterOnly the
     331        # associated medium objects will be closed when the Machine object is
     332        # uninitialized so wait for that to complete.  Otherwise the check for
     333        # cBaseImages below will race with the VM uninitialization and depending on
     334        # which one wins can cause a test failure.
     335        reporter.log('Waiting five seconds for Machine::uninit() to be called to close the attached disks');
     336        time.sleep(5);
     337
     338        cBaseImages = len(self.oTstDrv.oVBoxMgr.getArray(oVBox, 'hardDisks'))
     339        reporter.log('After unregister(UnregisterOnly): API reports %d base images' % (cBaseImages));
     340        if cBaseImages != 0:
     341            reporter.error('Got %d base images after unregistering, expected zero (0)' % (cBaseImages));
    242342
    243343        return reporter.testDone()[1] == 0
Note: See TracChangeset for help on using the changeset viewer.

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