Claudiu Belu c01a7a74f0 tests cleanup: Removes mock import checks
In Python 3, the mock module is now part of the unittest module.
We no longer support Python 2, so there's no reason for the import checks.

Change-Id: I7b4d68cba4b587ad9f0121058ba615a9bb0aec93
2024-06-03 16:11:09 +00:00

331 lines
12 KiB
Python

# Copyright 2014 Cloudbase Solutions Srl
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import importlib
import unittest
import unittest.mock as mock
from cloudbaseinit import exception
from cloudbaseinit.tests import testutils
class BaseTestDevice(unittest.TestCase):
def setUp(self):
self._ctypes_mock = mock.MagicMock()
_module_patcher = mock.patch.dict(
'sys.modules',
{'ctypes': self._ctypes_mock,
'ctypes.windll': mock.MagicMock(),
'ctypes.wintypes': mock.MagicMock(),
'winioctlcon': mock.MagicMock()})
_module_patcher.start()
self.addCleanup(_module_patcher.stop)
self.disk = importlib.import_module(
"cloudbaseinit.utils.windows.disk")
self.mock_dword = mock.Mock()
self._ctypes_mock.wintypes.DWORD = self.mock_dword
self.disk.kernel32 = mock.MagicMock()
self.geom = mock.Mock()
self.geom.MediaType = self.disk.Win32_DiskGeometry.FixedMedia = 12
self.geom.Cylinders = 2
self.geom.TracksPerCylinder = 5
self.geom.SectorsPerTrack = 512
self.geom.BytesPerSector = 512
class TestBaseDevice(BaseTestDevice, testutils.CloudbaseInitTestBase):
def setUp(self):
super(TestBaseDevice, self).setUp()
class FinalBaseDevice(self.disk.BaseDevice):
def size(self):
return 0
self.fake_path = mock.sentinel.fake_path
self._device_class = FinalBaseDevice(
path=self.fake_path)
self._device_class._sector_size = self.geom.BytesPerSector
self._device_class._disk_size = 2 * 5 * 512 * 512
def _test_open(self, exc):
if exc:
self.disk.kernel32.CreateFileW.return_value = \
self._device_class.INVALID_HANDLE_VALUE
with self.assert_raises_windows_message(
"Cannot open file: %r", 100):
self._device_class.open()
else:
self._device_class.open()
self.disk.kernel32.CreateFileW.assert_called_once_with(
self._ctypes_mock.c_wchar_p.return_value,
self._device_class.GENERIC_READ,
self._device_class.FILE_SHARE_READ,
0, self._device_class.OPEN_EXISTING,
self._device_class.FILE_ATTRIBUTE_READONLY, 0
)
self._ctypes_mock.c_wchar_p.assert_called_once_with(self.fake_path)
self.assertEqual(
self.disk.kernel32.CreateFileW.return_value,
self._device_class._handle)
def test_open(self):
self._test_open(exc=False)
def test_open_exception(self):
self._test_open(exc=True)
def test_close(self):
self._device_class._handle = mock.sentinel._handle
self._device_class.close()
self.disk.kernel32.CloseHandle.assert_called_once_with(
mock.sentinel._handle)
self.assertEqual(None, self._device_class._handle)
def _test_get_geometry(self, ret_val, last_error=None):
mock_disk_geom = self.disk.Win32_DiskGeometry
mock_disk_geom.side_effect = None
mock_disk_geom.return_value = self.geom
mock_DeviceIoControl = self.disk.kernel32.DeviceIoControl
expect_byref = [mock.call(self.geom),
mock.call(
self.mock_dword.return_value)]
self.disk.kernel32.DeviceIoControl.return_value = ret_val
if not ret_val:
with self.assert_raises_windows_message(
"Cannot get disk geometry: %r", last_error):
self._device_class._get_geometry()
else:
response = self._device_class._get_geometry()
self.mock_dword.assert_called_once_with()
mock_DeviceIoControl.assert_called_once_with(
self._device_class._handle,
self.disk.winioctlcon.IOCTL_DISK_GET_DRIVE_GEOMETRY, 0, 0,
self._ctypes_mock.byref.return_value,
self._ctypes_mock.sizeof.return_value,
self._ctypes_mock.byref.return_value, 0)
self.assertEqual(expect_byref,
self._ctypes_mock.byref.call_args_list)
self.assertEqual((self._device_class._sector_size,
self._device_class._disk_size, True),
response)
def test_get_geometry(self):
self._test_get_geometry(ret_val=mock.sentinel.ret_val)
def test_get_geometry_exception(self):
self._test_get_geometry(ret_val=0, last_error=100)
def _test__seek(self, exc):
expect_DWORD = [mock.call(0), mock.call(1)]
if exc:
self.disk.kernel32.SetFilePointer.return_value = \
self._device_class.INVALID_SET_FILE_POINTER
with self.assert_raises_windows_message(
"Seek error: %r", 100):
self._device_class._seek(1)
else:
self._device_class._seek(1)
self.disk.kernel32.SetFilePointer.assert_called_once_with(
self._device_class._handle,
self.mock_dword.return_value,
self._ctypes_mock.byref.return_value,
self._device_class.FILE_BEGIN)
self._ctypes_mock.byref.assert_called_once_with(
self.mock_dword.return_value)
self.assertEqual(expect_DWORD,
self.mock_dword.call_args_list)
def test__seek(self):
self._test__seek(exc=False)
def test__seek_exception(self):
self._test__seek(exc=True)
def test_seek(self):
offset = self._device_class.seek(1025)
self.assertEqual(1024, offset)
def _test__read(self, ret_val, last_error=None):
bytes_to_read = mock.sentinel.bytes_to_read
self.disk.kernel32.ReadFile.return_value = ret_val
if not ret_val:
with self.assert_raises_windows_message(
"Read exception: %r", last_error):
self._device_class._read(bytes_to_read)
else:
response = self._device_class._read(bytes_to_read)
mock_buffer = self._ctypes_mock.create_string_buffer
mock_buffer.assert_called_once_with(bytes_to_read)
self.mock_dword.assert_called_once_with()
self.disk.kernel32.ReadFile.assert_called_once_with(
self._device_class._handle,
mock_buffer.return_value,
bytes_to_read, self._ctypes_mock.byref.return_value, 0)
self._ctypes_mock.byref.assert_called_once_with(
self.mock_dword.return_value)
self.assertEqual(
mock_buffer.return_value.raw[
:self.mock_dword.return_value.value], response)
def test__read(self):
self._test__read(ret_val=mock.sentinel.ret_val)
def test__read_exception(self):
self._test__read(ret_val=None, last_error=100)
def test_read(self):
_read_func = mock.Mock()
mock_content = mock.MagicMock()
_read_func.return_value = mock_content
self._device_class._read = _read_func
response = self._device_class.read(512, 10)
self._device_class._read.assert_called_once_with(1024)
self.assertEqual(response, mock_content[10, 522])
class TestDisk(BaseTestDevice, testutils.CloudbaseInitTestBase):
def setUp(self):
super(TestDisk, self).setUp()
self.fake_disk_path = mock.sentinel.fake_disk_path
self._disk_class = self.disk.Disk(
path=self.fake_disk_path)
self._disk_class._disk_size = 2 * 5 * 512 * 512
@mock.patch("cloudbaseinit.utils.windows.disk"
".Win32_DRIVE_LAYOUT_INFORMATION_EX")
def _test_get_layout(self, mock_layout_struct, fail=False):
mock_layout = mock.Mock()
mock_layout_struct.return_value = mock_layout
mock_devio = self.disk.kernel32.DeviceIoControl
if fail:
mock_devio.return_value = 0
with self.assert_raises_windows_message(
"Cannot get disk layout: %r", 100):
self._disk_class._get_layout()
return
mock_devio.return_value = 1
response = self._disk_class._get_layout()
mock_devio.assert_called_once_with(
self._disk_class._handle,
self.disk.winioctlcon.IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
0,
0,
self._ctypes_mock.byref(mock_layout),
self._ctypes_mock.sizeof(mock_layout),
self._ctypes_mock.byref(self.mock_dword.return_value),
0)
self.assertEqual(mock_layout, response)
def test_get_layout_fail(self):
self._test_get_layout(fail=True)
def test_get_layout(self):
self._test_get_layout()
def _test_get_partition_indexes(self, fail=False, gpt=True):
layout = mock.MagicMock()
if fail:
with self.assertRaises(exception.CloudbaseInitException):
self._disk_class._get_partition_indexes(layout)
return
part_style = (self._disk_class.PARTITION_STYLE_GPT if gpt
else self._disk_class.PARTITION_STYLE_MBR)
layout.PartitionStyle = part_style
count = 8
layout.PartitionCount = count
if gpt:
expected = list(range(count))
else:
layout.PartitionEntry = [mock.Mock() for _ in range(count)]
layout.PartitionEntry[-1].Mbr.PartitionType = \
self._disk_class.PARTITION_ENTRY_UNUSED
expected = list(range(count - 1))
response = self._disk_class._get_partition_indexes(layout)
self.assertEqual(expected, response)
def test_get_partition_indexes_fail(self):
self._test_get_partition_indexes(fail=True)
def test_get_partition_indexes_gpt(self):
self._test_get_partition_indexes()
def test_get_partition_indexes_mbr(self):
self._test_get_partition_indexes(gpt=False)
@mock.patch("cloudbaseinit.utils.windows.disk"
".Partition")
@mock.patch("cloudbaseinit.utils.windows.disk"
".Disk._get_partition_indexes")
@mock.patch("cloudbaseinit.utils.windows.disk"
".Disk._get_layout")
def test_partitions(self, mock_get_layout, mock_get_partition_indexes,
mock_partition):
size = 512
layout = mock.MagicMock()
layout.PartitionEntry[0].PartitionLength = size
indexes = [0, 1, 2]
mock_get_layout.return_value = layout
mock_get_partition_indexes.return_value = indexes
self._disk_class._path = r"\\?\GLOBALROOT\Device\Harddisk0"
response = self._disk_class.partitions()
mock_get_layout.assert_called_once_with()
mock_get_partition_indexes.assert_called_once_with(layout)
paths = [r"\\?\GLOBALROOT\Device\Harddisk{}\Partition{}".format(
0, idx + 1) for idx in indexes]
calls = [mock.call(path, size) for path in paths]
mock_partition.assert_has_calls(calls)
expected = [mock_partition(path, size) for path in paths]
self.assertEqual(expected, response)
class TestPartition(unittest.TestCase):
def setUp(self):
_module_patcher = mock.patch.dict(
'sys.modules',
{'ctypes': mock.MagicMock(),
'winioctlcon': mock.MagicMock()})
_module_patcher.start()
self.addCleanup(_module_patcher.stop)
self.disk = importlib.import_module(
"cloudbaseinit.utils.windows.disk")
def test_size(self):
size = mock.sentinel.size
partition = self.disk.Partition(mock.Mock(), size)
self.assertEqual(size, partition.size)