Example #1
0
 def testIsChildProcess(self):
   """Test IsChildProcess with no name."""
   mock_pstree_output = 'a(1)-+-b(2)\n\t|-c(3)\n\t|-foo(4)-bar(5)'
   self.rc.AddCmdResult(partial_mock.Ignore(), output=mock_pstree_output)
   self.assertTrue(osutils.IsChildProcess(4))
   self.assertTrue(osutils.IsChildProcess(4, name='foo'))
   self.assertFalse(osutils.IsChildProcess(5, name='foo'))
 def testChangeUnitInsideChroot(self):
     self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
     self.rc.AddCmdResult(partial_mock.Ignore(), output=self.SAMPLE_CGPT)
     partitions = image_lib.GetImageDiskPartitionInfo('_ignored')
     part_dict = {p.name: p for p in partitions}
     self.assertEqual(part_dict['STATE'].start, 983564288)
     self.assertEqual(part_dict['STATE'].size, 1073741824)
 def testIgnoreMatching(self):
     """Deep matching of Ignore objects."""
     ignore = partial_mock.Ignore()
     self.mr.AddResultForParams((ignore, ignore),
                                1,
                                kwargs={'test': ignore})
     self.assertEquals(
         1, self.mr.LookupResult(('some', 'values'), {'test': 'bla'}))
 def testNormalPath(self):
     self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=False)
     self.rc.AddCmdResult(partial_mock.Ignore(), output=self.SAMPLE_PARTED)
     partitions = image_lib.GetImageDiskPartitionInfo('_ignored')
     part_dict = {p.name: p for p in partitions}
     self.assertEqual(12, len(partitions))
     self.assertEqual(1, part_dict['STATE'].number)
     self.assertEqual(2097152000, part_dict['ROOT-A'].size)
Example #5
0
    def setUp(self):
        self.chroot_path = os.path.join(self.tempdir, 'chroot')
        osutils.SafeMakedirsNonRoot(self.chroot_path)
        self.chroot_img = self.chroot_path + '.img'

        self._MOUNT = [
            'sudo', '--', 'mount', '-text4', '-onoatime',
            partial_mock.Ignore(), self.chroot_path
        ]
    def RunCommand(self, cmd, *args, **kwargs):
        result = self._results['RunCommand'].LookupResult(
            (cmd, ), hook_args=(cmd, ) + args, hook_kwargs=kwargs)

        popen_mock = PopenMock()
        popen_mock.AddCmdResult(partial_mock.Ignore(), result.returncode,
                                result.output, result.error)
        with popen_mock:
            return self.backup['RunCommand'](cmd, *args, **kwargs)
 def testKeyedByNumber(self):
     self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=False)
     self.rc.AddCmdResult(partial_mock.Ignore(), output=self.SAMPLE_PARTED)
     partitions = image_lib.GetImageDiskPartitionInfo('_ignored')
     part_dict = {p.number: p for p in partitions}
     self.assertEqual(12, len(part_dict))
     self.assertEqual('STATE', part_dict[1].name)
     self.assertEqual(2097152000, part_dict[3].size)
     self.assertEqual('reserved', part_dict[9].name)
     self.assertEqual('reserved', part_dict[10].name)
Example #8
0
    def testFetchGs(self):
        """Verify we fetch from Google Storage and save the result."""

        # pylint: disable=unused-argument
        def _Fetch(_ctx, cmd, capture_output):
            # Touch file we tried to copy too.
            osutils.Touch(cmd[-1])

        self.gs_mock.AddCmdResult(
            ['cp', '-v', '--',
             partial_mock.Ignore(),
             partial_mock.Ignore()],
            side_effect=_Fetch)

        key = ('gs', )
        url = 'gs://some.site.localdomain/file_go_boom'
        with self.cache.Lookup(key) as ref:
            self.assertFalse(ref.Exists())
            ref.Assign(url)
            self.assertTrue(ref.Exists())
Example #9
0
    def testGetDDPidNotFound(self):
        """Check that -1 is returned for _GetDDPid() if the pids aren't valid."""
        expected_pid = -1
        op = flash.UsbImagerOperation('foo')
        self.PatchObject(osutils, 'IsChildProcess', return_value=False)
        self.rc.AddCmdResult(partial_mock.Ignore(), output='5\n10\n')

        pid = op._GetDDPid()

        # Check that the correct pid was returned.
        self.assertEqual(pid, expected_pid)
Example #10
0
 def testListBlockDevices(self):
   """Tests that we can list all block devices correctly."""
   self.rc.AddCmdResult(partial_mock.Ignore(), output=self.FULL_OUTPUT)
   devices = osutils.ListBlockDevices()
   self.assertEqual(devices[0].NAME, 'sda')
   self.assertEqual(devices[0].RM, '0')
   self.assertEqual(devices[0].TYPE, 'disk')
   self.assertEqual(devices[0].SIZE, '128G')
   self.assertEqual(devices[3].NAME, 'sdc')
   self.assertEqual(devices[3].RM, '1')
   self.assertEqual(devices[3].TYPE, 'disk')
   self.assertEqual(devices[3].SIZE, '7.4G')
Example #11
0
    def testGetDDPidFound(self):
        """Check that the expected pid is returned for _GetDDPid()."""
        expected_pid = 5
        op = flash.UsbImagerOperation('foo')
        self.PatchObject(osutils, 'IsChildProcess', return_value=True)
        self.rc.AddCmdResult(partial_mock.Ignore(),
                             output='%d\n10\n' % expected_pid)

        pid = op._GetDDPid()

        # Check that the correct pid was returned.
        self.assertEqual(pid, expected_pid)
  def RemoteSh(self, inst, cmd, *args, **kwargs):
    """Simulates a RemoteSh invocation."""
    result = self._results['RemoteSh'].LookupResult(
        (cmd,), hook_args=(inst, cmd,) + args, hook_kwargs=kwargs)

    # Run the real RemoteSh with RunCommand mocked out.
    rc_mock = cros_build_lib_unittest.RunCommandMock()
    rc_mock.AddCmdResult(
        partial_mock.Ignore(), result.returncode, result.output,
        result.error)

    with rc_mock:
      return self.backup['RemoteSh'](inst, cmd, *args, **kwargs)
 def testCgpt(self):
     """Tests that we can list all partitions with `cgpt` correctly."""
     self.PatchObject(cros_build_lib, 'IsInsideChroot', return_value=True)
     self.rc.AddCmdResult(partial_mock.Ignore(), output=self.SAMPLE_CGPT)
     partitions = image_lib.GetImageDiskPartitionInfo('...')
     part_dict = {p.name: p for p in partitions}
     self.assertEqual(part_dict['STATE'].start, 983564288)
     self.assertEqual(part_dict['STATE'].size, 1073741824)
     self.assertEqual(part_dict['STATE'].number, 1)
     self.assertEqual(part_dict['STATE'].name, 'STATE')
     self.assertEqual(part_dict['EFI-SYSTEM'].start, 249856 * 512)
     self.assertEqual(part_dict['EFI-SYSTEM'].size, 32768 * 512)
     self.assertEqual(part_dict['EFI-SYSTEM'].number, 12)
     self.assertEqual(part_dict['EFI-SYSTEM'].name, 'EFI-SYSTEM')
     self.assertEqual(12, len(partitions))
  def RemoteSh(self, inst, cmd, *args, **kwargs):
    """Simulates a RemoteSh invocation.

    Returns:
      A CommandResult object with an additional member |rc_mock| to
      enable examination of the underlying run() function call.
    """
    result = self._results['RemoteSh'].LookupResult(
        (cmd,), hook_args=(inst, cmd,) + args, hook_kwargs=kwargs)

    # Run the real RemoteSh with run mocked out.
    rc_mock = cros_test_lib.RunCommandMock()
    rc_mock.AddCmdResult(
        partial_mock.Ignore(), result.returncode, result.output, result.error)

    with rc_mock:
      result = self.backup['RemoteSh'](inst, cmd, *args, **kwargs)
    result.rc_mock = rc_mock
    return result
Example #15
0
 def testGetDeviceSize(self):
   """Tests that we can get the size of a device."""
   self.rc.AddCmdResult(partial_mock.Ignore(), output=self.PARTIAL_OUTPUT)
   self.assertEqual(osutils.GetDeviceSize('/dev/sdc'), '7.4G')
 def testIgnoreEquals(self):
     """Verify __eq__ functionality for Ignore."""
     obj1 = partial_mock.Ignore()
     obj2 = partial_mock.Ignore()
     self.assertEquals(obj1, obj2)
     self.assertFalse(obj1 != obj2)
 def testMultipleMatches(self):
     """Lookup matches mutilple results."""
     self.mr.AddResultForParams((partial_mock.Ignore(), ), 1)
     self.mr.AddResultForParams((partial_mock.In('test'), ), 2)
     self.assertRaises(AssertionError, self.mr.LookupResult, ('test', ))
Example #18
0
class TestMountChroot(cros_test_lib.MockTempDirTestCase):
    """Tests various partial setups for MountChroot."""

    _VGS_LOOKUP = ['sudo', '--', 'vgs', partial_mock.Ignore()]
    _VGCREATE = [
        'sudo', '--', 'vgcreate', '-q',
        partial_mock.Ignore(),
        partial_mock.Ignore()
    ]
    _VGCHANGE = ['sudo', '--', 'vgchange', '-q', '-ay', partial_mock.Ignore()]
    _LVS_LOOKUP = ['sudo', '--', 'lvs', partial_mock.Ignore()]
    _LVCREATE = [
        'sudo', '--', 'lvcreate', '-q', '-L499G', '-T',
        partial_mock.Ignore(), '-V500G', '-n',
        partial_mock.Ignore()
    ]
    _MKE2FS = [
        'sudo', '--', 'mke2fs', '-q', '-m', '0', '-t', 'ext4',
        partial_mock.Ignore()
    ]
    _MOUNT = []  # Set correctly in setUp.
    _LVM_FAILURE_CODE = 5  # Shell exit code when lvm commands fail.
    _LVM_SUCCESS_CODE = 0  # Shell exit code when lvm commands succeed.

    def _makeImageFile(self, chroot_img):
        with open(chroot_img, 'w') as f:
            f.seek(2**30)
            f.write('\0')

    def _mockFindVolumeGroupForDevice(self):
        m = self.PatchObject(cros_sdk_lib, 'FindVolumeGroupForDevice')
        m.return_value = 'cros_test_chroot_000'
        return m

    def _mockAttachDeviceToFile(self, loop_dev='loop0'):
        m = self.PatchObject(cros_sdk_lib, '_AttachDeviceToFile')
        m.return_value = '/dev/%s' % loop_dev
        return m

    def _mockDeviceFromFile(self, dev):
        m = self.PatchObject(cros_sdk_lib, '_DeviceFromFile')
        m.return_value = dev
        return m

    def setUp(self):
        self.chroot_path = os.path.join(self.tempdir, 'chroot')
        osutils.SafeMakedirsNonRoot(self.chroot_path)
        self.chroot_img = self.chroot_path + '.img'

        self._MOUNT = [
            'sudo', '--', 'mount', '-text4', '-onoatime',
            partial_mock.Ignore(), self.chroot_path
        ]

    def testFromScratch(self):
        # Create the whole setup from nothing.
        # Should call losetup, vgs, vgcreate, lvs, lvcreate, mke2fs, mount
        m = self._mockFindVolumeGroupForDevice()
        m2 = self._mockAttachDeviceToFile()

        with cros_test_lib.RunCommandMock() as rc_mock:
            rc_mock.AddCmdResult(self._VGS_LOOKUP,
                                 returncode=self._LVM_FAILURE_CODE)
            rc_mock.AddCmdResult(self._VGCREATE, output='')
            rc_mock.AddCmdResult(self._LVS_LOOKUP,
                                 returncode=self._LVM_FAILURE_CODE)
            rc_mock.AddCmdResult(self._LVCREATE)
            rc_mock.AddCmdResult(self._MKE2FS)
            rc_mock.AddCmdResult(self._MOUNT)

            success = cros_sdk_lib.MountChroot(self.chroot_path)
            self.assertTrue(success)

        m.assert_called_with(self.chroot_path, '/dev/loop0')
        m2.assert_called_with(self.chroot_img)

    def testMissingMount(self):
        # Re-mount an image that has a loopback and VG active but isn't mounted.
        # This can happen if the person unmounts the chroot or calls
        # osutils.UmountTree() on the path.
        # Should call losetup, vgchange, lvs, mount
        self._makeImageFile(self.chroot_img)

        m = self._mockFindVolumeGroupForDevice()
        m2 = self._mockDeviceFromFile('/dev/loop1')

        with cros_test_lib.RunCommandMock() as rc_mock:
            rc_mock.AddCmdResult(self._VGS_LOOKUP,
                                 returncode=self._LVM_SUCCESS_CODE)
            rc_mock.AddCmdResult(self._VGCHANGE)
            rc_mock.AddCmdResult(self._LVS_LOOKUP,
                                 returncode=self._LVM_SUCCESS_CODE)
            rc_mock.AddCmdResult(self._MOUNT)

            success = cros_sdk_lib.MountChroot(self.chroot_path)
            self.assertTrue(success)

        m.assert_called_with(self.chroot_path, '/dev/loop1')
        m2.assert_called_with(self.chroot_img)

    def testImageAfterReboot(self):
        # Re-mount an image that has everything setup, but doesn't have anything
        # attached, e.g. after reboot.
        # Should call losetup -j, losetup -f, vgs, vgchange, lvs, lvchange, mount
        self._makeImageFile(self.chroot_img)

        m = self._mockFindVolumeGroupForDevice()
        m2 = self._mockDeviceFromFile('')
        m3 = self._mockAttachDeviceToFile('loop1')

        with cros_test_lib.RunCommandMock() as rc_mock:
            rc_mock.AddCmdResult(self._VGS_LOOKUP,
                                 returncode=self._LVM_SUCCESS_CODE)
            rc_mock.AddCmdResult(self._VGCHANGE)
            rc_mock.AddCmdResult(self._LVS_LOOKUP,
                                 returncode=self._LVM_SUCCESS_CODE)
            rc_mock.AddCmdResult(self._MOUNT)

            success = cros_sdk_lib.MountChroot(self.chroot_path)
            self.assertTrue(success)

        m.assert_called_with(self.chroot_path, '/dev/loop1')
        m2.assert_called_with(self.chroot_img)
        m3.assert_called_with(self.chroot_img)

    def testImagePresentNotSetup(self):
        # Mount an image that is present but doesn't have anything set up.  This
        # can't arise in normal usage, but could happen if cros_sdk crashes in the
        # middle of setup.
        # Should call losetup -j, losetup -f, vgs, vgcreate, lvs, lvcreate, mke2fs,
        # mount
        self._makeImageFile(self.chroot_img)

        m = self._mockFindVolumeGroupForDevice()
        m2 = self._mockAttachDeviceToFile()
        m3 = self._mockDeviceFromFile('')

        with cros_test_lib.RunCommandMock() as rc_mock:
            rc_mock.AddCmdResult(self._VGS_LOOKUP,
                                 returncode=self._LVM_FAILURE_CODE)
            rc_mock.AddCmdResult(self._VGCREATE)
            rc_mock.AddCmdResult(self._LVS_LOOKUP,
                                 returncode=self._LVM_FAILURE_CODE)
            rc_mock.AddCmdResult(self._LVCREATE)
            rc_mock.AddCmdResult(self._MKE2FS)
            rc_mock.AddCmdResult(self._MOUNT)

            success = cros_sdk_lib.MountChroot(self.chroot_path)
            self.assertTrue(success)

        m.assert_called_with(self.chroot_path, '/dev/loop0')
        m2.assert_called_with(self.chroot_img)
        m3.assert_called_with(self.chroot_img)

    def testImagePresentOnlyLoopbackSetup(self):
        # Mount an image that is present and attached to a loopback device, but
        # doesn't have anything else set up.  This can't arise in normal usage, but
        # could happen if cros_sdk crashes in the middle of setup.
        # Should call losetup, vgs, vgcreate, lvs, lvcreate, mke2fs, mount
        self._makeImageFile(self.chroot_img)

        m = self._mockFindVolumeGroupForDevice()
        m2 = self._mockDeviceFromFile('/dev/loop0')

        with cros_test_lib.RunCommandMock() as rc_mock:
            rc_mock.AddCmdResult(self._VGS_LOOKUP,
                                 returncode=self._LVM_FAILURE_CODE)
            rc_mock.AddCmdResult(self._VGCREATE)
            rc_mock.AddCmdResult(self._LVS_LOOKUP,
                                 returncode=self._LVM_FAILURE_CODE)
            rc_mock.AddCmdResult(self._LVCREATE)
            rc_mock.AddCmdResult(self._MKE2FS)
            rc_mock.AddCmdResult(self._MOUNT)

            success = cros_sdk_lib.MountChroot(self.chroot_path)
            self.assertTrue(success)

        m.assert_called_with(self.chroot_path, '/dev/loop0')
        m2.assert_called_with(self.chroot_img)

    def testImagePresentOnlyVgSetup(self):
        # Mount an image that is present, attached to a loopback device, and has a
        # VG, but doesn't have anything else set up.  This can't arise in normal
        # usage, but could happen if cros_sdk crashes in the middle of setup.
        # Should call losetup, vgs, vgchange, lvs, lvcreate, mke2fs, mount
        self._makeImageFile(self.chroot_img)

        m = self._mockFindVolumeGroupForDevice()
        m2 = self._mockDeviceFromFile('/dev/loop0')

        with cros_test_lib.RunCommandMock() as rc_mock:
            rc_mock.AddCmdResult(self._VGS_LOOKUP,
                                 returncode=self._LVM_SUCCESS_CODE)
            rc_mock.AddCmdResult(self._VGCHANGE)
            rc_mock.AddCmdResult(self._LVS_LOOKUP,
                                 returncode=self._LVM_FAILURE_CODE)
            rc_mock.AddCmdResult(self._LVCREATE)
            rc_mock.AddCmdResult(self._MKE2FS)
            rc_mock.AddCmdResult(self._MOUNT)

            success = cros_sdk_lib.MountChroot(self.chroot_path)
            self.assertTrue(success)

        m.assert_called_with(self.chroot_path, '/dev/loop0')
        m2.assert_called_with(self.chroot_img)

    def testMissingNoCreate(self):
        # Chroot image isn't present, but create is False.
        # Should return False without running any commands.
        success = cros_sdk_lib.MountChroot(self.chroot_path, create=False)
        self.assertFalse(success)

    def testExistingChroot(self):
        # Chroot version file exists in the chroot.
        # Should return True without running any commands.
        osutils.Touch(os.path.join(self.chroot_path, 'etc',
                                   'cros_chroot_version'),
                      makedirs=True)

        success = cros_sdk_lib.MountChroot(self.chroot_path, create=False)
        self.assertTrue(success)

        success = cros_sdk_lib.MountChroot(self.chroot_path, create=True)
        self.assertTrue(success)

    def testEmptyChroot(self):
        # Chroot mounted from proper image but without the version file present,
        # e.g. if cros_sdk fails in the middle of populating the chroot.
        # Should return True without running any commands.
        proc_mounts = os.path.join(self.tempdir, 'proc_mounts')
        with open(proc_mounts, 'w') as f:
            f.write('/dev/mapper/cros_test_000-chroot %s ext4 rw 0 0\n' %
                    self.chroot_path)

        success = cros_sdk_lib.MountChroot(self.chroot_path,
                                           create=False,
                                           proc_mounts=proc_mounts)
        self.assertTrue(success)

        success = cros_sdk_lib.MountChroot(self.chroot_path,
                                           create=True,
                                           proc_mounts=proc_mounts)
        self.assertTrue(success)

    def testBadMount(self):
        # Chroot with something else mounted on it.
        # Should return False without running any commands.
        proc_mounts = os.path.join(self.tempdir, 'proc_mounts')
        with open(proc_mounts, 'w') as f:
            f.write('/dev/sda1 %s ext4 rw 0 0\n' % self.chroot_path)

        success = cros_sdk_lib.MountChroot(self.chroot_path,
                                           create=False,
                                           proc_mounts=proc_mounts)
        self.assertFalse(success)

        success = cros_sdk_lib.MountChroot(self.chroot_path,
                                           create=True,
                                           proc_mounts=proc_mounts)
        self.assertFalse(success)
 def setUp(self):
   self.mock = cros_test_lib.RunCommandMock()
   self.mock.AddCmdResult(partial_mock.Ignore())
Example #20
0
class TestCleanupChrootMount(cros_test_lib.MockTempDirTestCase):
    """Tests the CleanupChrootMount function."""

    _VGS_DEV_LOOKUP = [
        'sudo', '--', 'vgs', '-q', '--noheadings', '-o', 'pv_name',
        '--unbuffered',
        partial_mock.Ignore()
    ]
    _VGS_VG_LOOKUP = ['sudo', '--', 'vgs', partial_mock.Ignore()]
    _LOSETUP_FIND = ['sudo', '--', 'losetup', '-j', partial_mock.Ignore()]
    _LOSETUP_DETACH = ['sudo', '--', 'losetup', '-d', partial_mock.Ignore()]
    _VGCHANGE_N = ['sudo', '--', 'vgchange', '-an', partial_mock.Ignore()]
    _LVM_FAILURE_CODE = 5  # Shell exit code when lvm commands fail.
    _LVM_SUCCESS_CODE = 0  # Shell exit code when lvm commands succeed.

    def setUp(self):
        self.chroot_path = os.path.join(self.tempdir, 'chroot')
        osutils.SafeMakedirsNonRoot(self.chroot_path)
        self.chroot_img = self.chroot_path + '.img'

    def testMountedCleanup(self):
        m = self.PatchObject(osutils, 'UmountTree')
        m2 = self.PatchObject(cros_sdk_lib, '_RescanDeviceLvmMetadata')

        proc_mounts = os.path.join(self.tempdir, 'proc_mounts')
        with open(proc_mounts, 'w') as f:
            f.write('/dev/mapper/cros_vg_name-chroot %s ext4 rw 0 0\n' %
                    self.chroot_path)

        with cros_test_lib.RunCommandMock() as rc_mock:
            rc_mock.AddCmdResult(self._VGS_DEV_LOOKUP, output='  /dev/loop0')
            rc_mock.AddCmdResult(self._VGCHANGE_N)
            rc_mock.AddCmdResult(self._LOSETUP_DETACH)

            cros_sdk_lib.CleanupChrootMount(self.chroot_path,
                                            None,
                                            proc_mounts=proc_mounts)

        m.assert_called_with(self.chroot_path)
        m2.assert_called_with('/dev/loop0')

    def testMountedCleanupByBuildroot(self):
        m = self.PatchObject(osutils, 'UmountTree')
        m2 = self.PatchObject(cros_sdk_lib, '_RescanDeviceLvmMetadata')

        proc_mounts = os.path.join(self.tempdir, 'proc_mounts')
        with open(proc_mounts, 'w') as f:
            f.write('/dev/mapper/cros_vg_name-chroot %s ext4 rw 0 0\n' %
                    self.chroot_path)

        with cros_test_lib.RunCommandMock() as rc_mock:
            rc_mock.AddCmdResult(self._VGS_DEV_LOOKUP, output='  /dev/loop0')
            rc_mock.AddCmdResult(self._VGCHANGE_N)
            rc_mock.AddCmdResult(self._LOSETUP_DETACH)

            cros_sdk_lib.CleanupChrootMount(None,
                                            self.tempdir,
                                            proc_mounts=proc_mounts)

        m.assert_called_with(self.chroot_path)
        m2.assert_called_with('/dev/loop0')

    def testMountedCleanupWithDelete(self):
        m = self.PatchObject(osutils, 'UmountTree')
        m2 = self.PatchObject(osutils, 'SafeUnlink')
        m3 = self.PatchObject(osutils, 'RmDir')
        m4 = self.PatchObject(cros_sdk_lib, '_RescanDeviceLvmMetadata')

        proc_mounts = os.path.join(self.tempdir, 'proc_mounts')
        with open(proc_mounts, 'w') as f:
            f.write('/dev/mapper/cros_vg_name-chroot %s ext4 rw 0 0\n' %
                    self.chroot_path)

        with cros_test_lib.RunCommandMock() as rc_mock:
            rc_mock.AddCmdResult(self._VGS_DEV_LOOKUP, output='  /dev/loop0')
            rc_mock.AddCmdResult(self._VGCHANGE_N)
            rc_mock.AddCmdResult(self._LOSETUP_DETACH)

            cros_sdk_lib.CleanupChrootMount(self.chroot_path,
                                            None,
                                            delete=True,
                                            proc_mounts=proc_mounts)

        m.assert_called_with(self.chroot_path)
        m2.assert_called_with(self.chroot_img)
        m3.assert_called_with(self.chroot_path, ignore_missing=True, sudo=True)
        m4.assert_called_with('/dev/loop0')

    def testUnmountedCleanup(self):
        m = self.PatchObject(osutils, 'UmountTree')
        m2 = self.PatchObject(cros_sdk_lib, 'FindVolumeGroupForDevice')
        m2.return_value = 'cros_chroot_001'
        m3 = self.PatchObject(cros_sdk_lib, '_RescanDeviceLvmMetadata')

        proc_mounts = os.path.join(self.tempdir, 'proc_mounts')
        with open(proc_mounts, 'w') as f:
            f.write('sysfs /sys sysfs rw 0 0\n')

        with cros_test_lib.RunCommandMock() as rc_mock:
            rc_mock.AddCmdResult(self._LOSETUP_FIND, output='/dev/loop1')
            rc_mock.AddCmdResult(self._VGS_VG_LOOKUP,
                                 returncode=self._LVM_SUCCESS_CODE)
            rc_mock.AddCmdResult(self._VGCHANGE_N)
            rc_mock.AddCmdResult(self._LOSETUP_DETACH)

            cros_sdk_lib.CleanupChrootMount(self.chroot_path,
                                            None,
                                            proc_mounts=proc_mounts)

        m.assert_called_with(self.chroot_path)
        m2.assert_called_with(self.chroot_path, '/dev/loop1')
        m3.assert_called_with('/dev/loop1')

    def testDevOnlyCleanup(self):
        m = self.PatchObject(osutils, 'UmountTree')
        m2 = self.PatchObject(cros_sdk_lib, 'FindVolumeGroupForDevice')
        m2.return_value = 'cros_chroot_001'
        m3 = self.PatchObject(cros_sdk_lib, '_RescanDeviceLvmMetadata')

        proc_mounts = os.path.join(self.tempdir, 'proc_mounts')
        with open(proc_mounts, 'w') as f:
            f.write('sysfs /sys sysfs rw 0 0\n')

        with cros_test_lib.RunCommandMock() as rc_mock:
            rc_mock.AddCmdResult(self._LOSETUP_FIND, output='/dev/loop1')
            rc_mock.AddCmdResult(self._VGS_VG_LOOKUP,
                                 returncode=self._LVM_FAILURE_CODE)
            rc_mock.AddCmdResult(self._LOSETUP_DETACH)

            cros_sdk_lib.CleanupChrootMount(self.chroot_path,
                                            None,
                                            proc_mounts=proc_mounts)

        m.assert_called_with(self.chroot_path)
        m2.assert_called_with(self.chroot_path, '/dev/loop1')
        m3.assert_called_with('/dev/loop1')

    def testNothingCleanup(self):
        m = self.PatchObject(osutils, 'UmountTree')
        m2 = self.PatchObject(cros_sdk_lib, 'FindVolumeGroupForDevice')
        m2.return_value = 'cros_chroot_001'

        proc_mounts = os.path.join(self.tempdir, 'proc_mounts')
        with open(proc_mounts, 'w') as f:
            f.write('sysfs /sys sysfs rw 0 0\n')

        with cros_test_lib.RunCommandMock() as rc_mock:
            rc_mock.AddCmdResult(self._LOSETUP_FIND, returncode=1)
            rc_mock.AddCmdResult(self._VGS_VG_LOOKUP,
                                 returncode=self._LVM_FAILURE_CODE)

            cros_sdk_lib.CleanupChrootMount(self.chroot_path,
                                            None,
                                            proc_mounts=proc_mounts)

        m.assert_called_with(self.chroot_path)
        m2.assert_called_with(self.chroot_path, None)

    def testNothingCleanupWithDelete(self):
        m = self.PatchObject(osutils, 'UmountTree')
        m2 = self.PatchObject(cros_sdk_lib, 'FindVolumeGroupForDevice')
        m2.return_value = 'cros_chroot_001'
        m3 = self.PatchObject(osutils, 'SafeUnlink')
        m4 = self.PatchObject(osutils, 'RmDir')

        proc_mounts = os.path.join(self.tempdir, 'proc_mounts')
        with open(proc_mounts, 'w') as f:
            f.write('sysfs /sys sysfs rw 0 0\n')

        with cros_test_lib.RunCommandMock() as rc_mock:
            rc_mock.AddCmdResult(self._LOSETUP_FIND, returncode=1)
            rc_mock.AddCmdResult(self._VGS_VG_LOOKUP,
                                 returncode=self._LVM_FAILURE_CODE)

            cros_sdk_lib.CleanupChrootMount(self.chroot_path,
                                            None,
                                            delete=True,
                                            proc_mounts=proc_mounts)

        m.assert_called_with(self.chroot_path)
        m2.assert_called_with(self.chroot_path, None)
        m3.assert_called_with(self.chroot_img)
        m4.assert_called_with(self.chroot_path, ignore_missing=True, sudo=True)