kiwi-el8/test/unit/system/root_bind_test.py
Marcus Schäfer 9c9250ebc4
Support nose and xunit style tests
The modifications in this commit allows the unit tests
to run on both, pytest 6.x (nose test layout) and the new
pytest 7.x (xunit test layout). This Fixes #2072 in a
much nicer way. Thanks much to @smarlowucf
2022-02-26 20:26:18 +01:00

247 lines
9.0 KiB
Python

import sys
import logging
from mock import (
patch, call, Mock
)
from pytest import (
raises, fixture
)
from ..test_helper import argv_kiwi_tests
from kiwi.system.root_bind import RootBind
from kiwi.exceptions import (
KiwiMountKernelFileSystemsError,
KiwiMountSharedDirectoryError,
KiwiSetupIntermediateConfigError
)
class TestRootBind:
@fixture(autouse=True)
def inject_fixtures(self, caplog):
self._caplog = caplog
def setup(self):
root = Mock()
root.root_dir = 'root-dir'
self.bind_root = RootBind(root)
# stub config files and bind locations
self.bind_root.config_files = ['/etc/sysconfig/proxy']
self.bind_root.bind_locations = ['/proc']
# stub files/dirs and mountpoints to cleanup
self.mount_manager = Mock()
self.bind_root.cleanup_files = ['/etc/sysconfig/proxy.kiwi']
self.bind_root.mount_stack = [self.mount_manager]
self.bind_root.dir_stack = ['/mountpoint']
def setup_method(self, cls):
self.setup()
def teardown(self):
sys.argv = argv_kiwi_tests
def teardown_method(self, cls):
self.teardown()
@patch('kiwi.system.root_bind.MountManager.bind_mount')
@patch('kiwi.system.root_bind.RootBind.cleanup')
@patch('os.path.exists')
def test_kernel_file_systems_raises_error(
self, mock_exists, mock_cleanup, mock_mount
):
mock_exists.return_value = True
mock_mount.side_effect = KiwiMountKernelFileSystemsError(
'mount-error'
)
with raises(KiwiMountKernelFileSystemsError):
self.bind_root.mount_kernel_file_systems()
mock_cleanup.assert_called_once_with()
@patch('kiwi.system.root_bind.MountManager.bind_mount')
@patch('kiwi.system.root_bind.Path.create')
@patch('kiwi.system.root_bind.RootBind.cleanup')
def test_shared_directory_raises_error(
self, mock_cleanup, mock_path, mock_mount
):
mock_mount.side_effect = KiwiMountSharedDirectoryError(
'mount-error'
)
with raises(KiwiMountSharedDirectoryError):
self.bind_root.mount_shared_directory()
mock_cleanup.assert_called_once_with()
@patch('kiwi.command.Command.run')
@patch('kiwi.system.root_bind.RootBind.cleanup')
@patch('os.path.exists')
def test_intermediate_config_raises_error(
self, mock_exists, mock_cleanup, mock_command
):
mock_exists.return_value = True
mock_command.side_effect = KiwiSetupIntermediateConfigError(
'config-error'
)
with raises(KiwiSetupIntermediateConfigError):
self.bind_root.setup_intermediate_config()
mock_cleanup.assert_called_once_with()
@patch('kiwi.system.root_bind.os.path.exists')
@patch('kiwi.system.root_bind.MountManager')
def test_mount_kernel_file_systems(self, mock_mount, mock_exists):
mock_exists.return_value = True
shared_mount = Mock()
mock_mount.return_value = shared_mount
assert self.bind_root.mount_kernel_file_systems() is None
assert mock_mount.call_args_list == [
call(device='root-dir', mountpoint='root-dir'),
call(device='/proc', mountpoint='root-dir/proc')
]
assert shared_mount.bind_mount.call_args_list == [
call(), call()
]
@patch('kiwi.system.root_bind.MountManager')
def test_umount_kernel_file_systems(self, mock_mount):
self.mount_manager.device = '/proc'
self.mount_manager.is_mounted = Mock(return_value=True)
assert self.bind_root.umount_kernel_file_systems() is None
self.mount_manager.umount_lazy.assert_called_once_with()
assert self.bind_root.mount_stack == []
@patch('kiwi.system.root_bind.MountManager')
def test_umount_kernel_file_systems_raises_error(self, mock_mount):
self.mount_manager.device = '/proc'
self.mount_manager.is_mounted = Mock(return_value=True)
self.mount_manager.umount_lazy = Mock(side_effect=Exception)
assert self.bind_root.umount_kernel_file_systems() is None
self.mount_manager.umount_lazy.assert_called_once_with()
assert self.bind_root.mount_stack == [self.mount_manager]
@patch('kiwi.system.root_bind.MountManager')
@patch('kiwi.system.root_bind.Path.create')
def test_mount_shared_directory(self, mock_path, mock_mount):
shared_mount = Mock()
mock_mount.return_value = shared_mount
assert self.bind_root.mount_shared_directory() is None
mock_path.call_args_list = [
call('root-dir/var/cache/kiwi'),
call('/var/cache/kiwi')
]
mock_mount.assert_called_once_with(
device='/var/cache/kiwi', mountpoint='root-dir/var/cache/kiwi'
)
shared_mount.bind_mount.assert_called_once_with()
@patch('kiwi.command.Command.run')
@patch('kiwi.system.root_bind.Checksum')
@patch('os.path.exists')
def test_intermediate_config(
self, mock_exists, mock_Checksum, mock_command
):
checksum = Mock()
mock_Checksum.return_value = checksum
mock_exists.return_value = True
with patch('builtins.open') as m_open:
assert self.bind_root.setup_intermediate_config() is None
m_open.assert_called_once_with(
'root-dir/etc/sysconfig/proxy.sha', 'w'
)
assert mock_command.call_args_list == [
call([
'cp', '/etc/sysconfig/proxy', 'root-dir/etc/sysconfig/proxy.kiwi'
]),
call([
'ln', '-s', '-f', 'proxy.kiwi', 'root-dir/etc/sysconfig/proxy'
])
]
checksum.sha256.assert_called_once_with()
@patch('textwrap.dedent')
@patch('kiwi.system.root_bind.Checksum')
@patch('kiwi.system.root_bind.MountManager.is_mounted')
@patch('kiwi.system.root_bind.Command.run')
@patch('kiwi.system.root_bind.Path.remove_hierarchy')
@patch('os.path.islink')
@patch('os.path.exists')
@patch('shutil.move')
def test_cleanup(
self, mock_move, mock_exists, mock_islink,
mock_remove_hierarchy, mock_command, mock_is_mounted,
mock_Checksum, mock_dedent
):
checksum = Mock()
checksum.matches.return_value = False
mock_Checksum.return_value = checksum
os_exists_return_values = [False, True, True, False]
def exists_side_effect(*args):
return os_exists_return_values.pop()
mock_is_mounted.return_value = False
mock_exists.side_effect = exists_side_effect
mock_islink.return_value = True
with self._caplog.at_level(logging.WARNING):
assert self.bind_root.cleanup() is None
self.mount_manager.umount_lazy.assert_called_once_with()
mock_remove_hierarchy.assert_called_once_with(
root='root-dir', path='/mountpoint'
)
assert mock_command.call_args_list == [
call(['rm', '-f', 'root-dir/etc/sysconfig/proxy']),
call(
[
'cp',
'root-dir/usr/share/fillup-templates/sysconfig.proxy',
'root-dir/etc/sysconfig/proxy'
]
),
call(
[
'rm', '-f', 'root-dir/etc/sysconfig/proxy.kiwi',
'root-dir/etc/sysconfig/proxy.sha'
]
)
]
mock_move.assert_called_once_with(
'root-dir/etc/sysconfig/proxy.rpmnew',
'root-dir/etc/sysconfig/proxy'
)
@patch('os.path.islink')
@patch('kiwi.command.Command.run')
@patch('kiwi.system.root_bind.Path.remove_hierarchy')
@patch('kiwi.system.root_bind.Checksum')
def test_cleanup_continue_on_error(
self, mock_Checksum, mock_remove_hierarchy,
mock_command, mock_islink
):
mock_islink.return_value = True
mock_remove_hierarchy.side_effect = Exception('rm')
mock_command.side_effect = Exception
self.mount_manager.umount_lazy.side_effect = Exception
with self._caplog.at_level(logging.WARNING):
self.bind_root.cleanup()
assert 'Image root directory root-dir not cleanly umounted:' in \
self._caplog.text
assert 'Failed to remove directory hierarchy '
'root-dir/mountpoint: rm' in self._caplog.text
assert 'Failed to cleanup intermediate config files' in \
self._caplog.text
@patch('kiwi.command.Command.run')
@patch('kiwi.system.root_bind.Path.remove_hierarchy')
@patch('kiwi.system.root_bind.Checksum')
def test_cleanup_nothing_mounted(
self, mock_Checksum, mock_remove_hierarchy, mock_command
):
self.mount_manager.is_mounted.return_value = False
self.mount_manager.mountpoint = '/mountpoint'
with self._caplog.at_level(logging.WARNING):
assert self.bind_root.cleanup() is None
assert 'Path /mountpoint not a mountpoint' in self._caplog.text