There is no need to mock Path.which as isoinfo binary from the platform is needed to run the test, so better let the system look for it, note that the binray can be located in the alternate location (/usr/lib/genisoimage/) which is not part of the PATH. In that particular case the iso_test would fail if we mock Path.which.
365 lines
12 KiB
Python
365 lines
12 KiB
Python
from mock import call
|
|
import mock
|
|
import struct
|
|
from .test_helper import *
|
|
import sys
|
|
from builtins import bytes
|
|
|
|
from kiwi.exceptions import *
|
|
|
|
from kiwi.iso import Iso
|
|
from collections import namedtuple
|
|
from tempfile import NamedTemporaryFile
|
|
|
|
|
|
class TestIso(object):
|
|
@patch('kiwi.iso.NamedTemporaryFile')
|
|
@patch('platform.machine')
|
|
def setup(self, mock_machine, mock_tempfile):
|
|
temp_type = namedtuple(
|
|
'temp_type', ['name']
|
|
)
|
|
mock_machine.return_value = 'x86_64'
|
|
mock_tempfile.return_value = temp_type(
|
|
name='sortfile'
|
|
)
|
|
self.context_manager_mock = mock.Mock()
|
|
self.file_mock = mock.Mock()
|
|
self.enter_mock = mock.Mock()
|
|
self.exit_mock = mock.Mock()
|
|
self.enter_mock.return_value = self.file_mock
|
|
setattr(self.context_manager_mock, '__enter__', self.enter_mock)
|
|
setattr(self.context_manager_mock, '__exit__', self.exit_mock)
|
|
|
|
self.iso = Iso('source-dir')
|
|
|
|
@patch_open
|
|
@patch('os.path.exists')
|
|
@raises(KiwiIsoLoaderError)
|
|
def test_init_iso_creation_parameters_no_loader(
|
|
self, mock_exists, mock_open
|
|
):
|
|
mock_exists.return_value = False
|
|
self.iso.init_iso_creation_parameters()
|
|
|
|
@patch('kiwi.iso.NamedTemporaryFile')
|
|
@patch('platform.machine')
|
|
def test_init_for_ix86_platform(self, mock_machine, mock_tempfile):
|
|
mock_machine.return_value = 'i686'
|
|
iso = Iso('source-dir')
|
|
assert iso.arch == 'ix86'
|
|
|
|
@patch_open
|
|
@patch('kiwi.iso.Command.run')
|
|
@patch('os.path.exists')
|
|
@patch('os.walk')
|
|
def test_init_iso_creation_parameters(
|
|
self, mock_walk, mock_exists, mock_command, mock_open
|
|
):
|
|
mock_walk_results = [
|
|
[('source-dir', ('EFI',), ())],
|
|
[('source-dir', ('bar', 'baz'), ('efi', 'eggs'))]
|
|
]
|
|
|
|
def side_effect(arg):
|
|
return mock_walk_results.pop()
|
|
|
|
mock_walk.side_effect = side_effect
|
|
|
|
mock_exists.return_value = True
|
|
mock_open.return_value = self.context_manager_mock
|
|
|
|
self.iso.init_iso_creation_parameters(['custom_arg'])
|
|
|
|
print(self.file_mock.write.call_args_list)
|
|
assert self.file_mock.write.call_args_list == [
|
|
call('7984fc91-a43f-4e45-bf27-6d3aa08b24cf\n'),
|
|
call('source-dir/boot/x86_64/boot.catalog 3\n'),
|
|
call('source-dir/boot/x86_64/loader/isolinux.bin 2\n'),
|
|
call('source-dir/efi 1000001\n'),
|
|
call('source-dir/eggs 1\n'),
|
|
call('source-dir/bar 1\n'),
|
|
call('source-dir/baz 1\n'),
|
|
call('source-dir/EFI 1\n'),
|
|
call('source-dir/header_end 1000000\n')
|
|
]
|
|
assert self.iso.iso_parameters == [
|
|
'custom_arg', '-R', '-J', '-f', '-pad', '-joliet-long',
|
|
'-sort', 'sortfile', '-no-emul-boot', '-boot-load-size', '4',
|
|
'-boot-info-table',
|
|
'-hide', 'boot/x86_64/boot.catalog',
|
|
'-hide-joliet', 'boot/x86_64/boot.catalog',
|
|
]
|
|
assert self.iso.iso_loaders == [
|
|
'-b', 'boot/x86_64/loader/isolinux.bin',
|
|
'-c', 'boot/x86_64/boot.catalog'
|
|
]
|
|
mock_command.assert_called_once_with(
|
|
[
|
|
'isolinux-config', '--base', 'boot/x86_64/loader',
|
|
'source-dir/boot/x86_64/loader/isolinux.bin'
|
|
]
|
|
)
|
|
|
|
@patch_open
|
|
@patch('kiwi.iso.Command.run')
|
|
@patch('kiwi.iso.Path.create')
|
|
@patch('os.path.exists')
|
|
@patch('os.walk')
|
|
def test_init_iso_creation_parameters_failed_isolinux_config(
|
|
self, mock_walk, mock_exists, mock_path, mock_command, mock_open
|
|
):
|
|
mock_exists.return_value = True
|
|
mock_open.return_value = self.context_manager_mock
|
|
command_raises = [False, True]
|
|
|
|
def side_effect(arg):
|
|
if command_raises.pop():
|
|
raise Exception
|
|
|
|
mock_command.side_effect = side_effect
|
|
|
|
self.iso.init_iso_creation_parameters(['custom_arg'])
|
|
|
|
mock_path.assert_called_once_with('source-dir/isolinux')
|
|
assert mock_command.call_args_list[1] == call(
|
|
[
|
|
'bash', '-c',
|
|
'ln source-dir/boot/x86_64/loader/* source-dir/isolinux'
|
|
]
|
|
)
|
|
|
|
@patch('os.path.exists')
|
|
def test_add_efi_loader_parameters(self, mock_exists):
|
|
mock_exists.return_value = True
|
|
self.iso.add_efi_loader_parameters()
|
|
assert self.iso.iso_loaders == [
|
|
'-eltorito-alt-boot', '-b', 'boot/x86_64/efi',
|
|
'-no-emul-boot', '-joliet-long'
|
|
]
|
|
|
|
def test_get_iso_creation_parameters(self):
|
|
self.iso.iso_parameters = ['a']
|
|
self.iso.iso_loaders = ['b']
|
|
assert self.iso.get_iso_creation_parameters() == ['a', 'b']
|
|
|
|
@raises(KiwiIsoToolError)
|
|
@patch('os.path.exists')
|
|
def test_isols_no_tool_found(self, mock_exists):
|
|
mock_exists.return_value = False
|
|
self.iso.isols('some-iso')
|
|
|
|
@patch('os.path.exists')
|
|
@patch('kiwi.iso.Command.run')
|
|
@patch('kiwi.iso.Path.which')
|
|
@patch_open
|
|
def test_isols_usr_bin_isoinfo_used(
|
|
self, mock_open, mock_which, mock_command, mock_exists
|
|
):
|
|
mock_which.return_value = '/usr/bin/isoinfo'
|
|
exists_results = [False, True]
|
|
|
|
def side_effect(self):
|
|
return exists_results.pop()
|
|
|
|
mock_exists.side_effect = side_effect
|
|
self.iso.isols('some-iso')
|
|
mock_command.assert_called_once_with(
|
|
['/usr/bin/isoinfo', '-R', '-l', '-i', 'some-iso']
|
|
)
|
|
|
|
@patch('os.path.exists')
|
|
@patch('kiwi.iso.Command.run')
|
|
@patch('kiwi.iso.Path.which')
|
|
@patch_open
|
|
def test_isols_usr_lib_genisoimage_isoinfo_used(
|
|
self, mock_open, mock_which, mock_command, mock_exists
|
|
):
|
|
mock_which.return_value = '/usr/lib/genisoimage/isoinfo'
|
|
exists_results = [True, False]
|
|
|
|
def side_effect(self):
|
|
return exists_results.pop()
|
|
|
|
mock_exists.side_effect = side_effect
|
|
self.iso.isols('some-iso')
|
|
mock_command.assert_called_once_with(
|
|
['/usr/lib/genisoimage/isoinfo', '-R', '-l', '-i', 'some-iso']
|
|
)
|
|
|
|
@patch('kiwi.iso.Command.run')
|
|
@patch('os.path.exists')
|
|
def test_isols(self, mock_exists, mock_command):
|
|
mock_exists.return_value = True
|
|
output_type = namedtuple('output_type', ['output'])
|
|
output_data = ''
|
|
with open('../data/iso_listing.txt') as iso:
|
|
output_data = iso.read()
|
|
mock_command.return_value = output_type(output=output_data)
|
|
result = self.iso.isols('some-iso')
|
|
assert result[2158].name == 'header_end'
|
|
|
|
|
|
def test_create_header_end_block(self):
|
|
temp_file = NamedTemporaryFile()
|
|
self.iso.header_end_file = temp_file.name
|
|
assert self.iso.create_header_end_block(
|
|
'../data/iso_with_marker.iso'
|
|
) == 96
|
|
|
|
@raises(KiwiIsoLoaderError)
|
|
def test_create_header_end_block_raises(self):
|
|
temp_file = NamedTemporaryFile()
|
|
self.iso.header_end_file = temp_file.name
|
|
self.iso.create_header_end_block(
|
|
'../data/iso_no_marker.iso'
|
|
)
|
|
|
|
@patch('kiwi.iso.Command.run')
|
|
def test_create_hybrid(self, mock_command):
|
|
mbrid = mock.Mock()
|
|
mbrid.get_id = mock.Mock(
|
|
return_value='0x0815'
|
|
)
|
|
Iso.create_hybrid(42, mbrid, 'some-iso')
|
|
mock_command.assert_called_once_with(
|
|
[
|
|
'isohybrid', '--offset', '42',
|
|
'--id', '0x0815', '--type', '0x83',
|
|
'--uefi', 'some-iso'
|
|
]
|
|
)
|
|
|
|
@patch_open
|
|
@raises(KiwiIsoMetaDataError)
|
|
def test_iso_metadata_iso9660_invalid(self, mock_open):
|
|
mock_open.return_value = self.context_manager_mock
|
|
self.file_mock.read.return_value = bytes(b'bogus')
|
|
Iso.fix_boot_catalog('isofile')
|
|
|
|
@patch_open
|
|
@raises(KiwiIsoMetaDataError)
|
|
def test_iso_metadata_not_bootable(self, mock_open):
|
|
mock_open.return_value = self.context_manager_mock
|
|
self.file_mock.read.return_value = bytes(b'CD001')
|
|
Iso.fix_boot_catalog('isofile')
|
|
|
|
@patch_open
|
|
@raises(KiwiIsoMetaDataError)
|
|
def test_iso_metadata_path_table_sector_invalid(self, mock_open):
|
|
mock_open.return_value = self.context_manager_mock
|
|
read_results = [bytes(b'EL TORITO SPECIFICATION'), bytes(b'CD001')]
|
|
|
|
def side_effect(arg):
|
|
return read_results.pop()
|
|
|
|
self.file_mock.read.side_effect = side_effect
|
|
Iso.fix_boot_catalog('isofile')
|
|
|
|
@patch_open
|
|
@raises(KiwiIsoMetaDataError)
|
|
def test_iso_metadata_catalog_sector_invalid(self, mock_open):
|
|
mock_open.return_value = self.context_manager_mock
|
|
volume_descriptor = \
|
|
bytes(b'CD001') + bytes(b'_') * (0x08c - 0x5) + bytes(b'0x1d5f23a')
|
|
read_results = [bytes(b'EL TORITO SPECIFICATION'), volume_descriptor]
|
|
|
|
def side_effect(arg):
|
|
return read_results.pop()
|
|
|
|
self.file_mock.read.side_effect = side_effect
|
|
Iso.fix_boot_catalog('isofile')
|
|
|
|
@patch_open
|
|
@raises(KiwiIsoMetaDataError)
|
|
def test_iso_metadata_catalog_invalid(self, mock_open):
|
|
mock_open.return_value = self.context_manager_mock
|
|
volume_descriptor = \
|
|
bytes(b'CD001') + bytes(b'_') * (0x08c - 0x5) + bytes(b'0x1d5f23a')
|
|
eltorito_descriptor = \
|
|
bytes(b'EL TORITO SPECIFICATION') + bytes(b'_') * (0x47 - 0x17) + bytes(b'0x1d5f23a')
|
|
read_results = [eltorito_descriptor, volume_descriptor]
|
|
|
|
def side_effect(arg):
|
|
return read_results.pop()
|
|
|
|
self.file_mock.read.side_effect = side_effect
|
|
Iso.fix_boot_catalog('isofile')
|
|
|
|
@patch_open
|
|
def test_relocate_boot_catalog(self, mock_open):
|
|
mock_open.return_value = self.context_manager_mock
|
|
volume_descriptor = \
|
|
bytes(b'CD001') + bytes(b'_') * (0x08c - 0x5) + bytes(b'0x1d5f23a')
|
|
eltorito_descriptor = \
|
|
bytes(b'EL TORITO SPECIFICATION') + bytes(b'_') * (0x47 - 0x17) + bytes(b'0x1d5f23a')
|
|
new_volume_descriptor = \
|
|
bytes(b'bogus')
|
|
next_new_volume_descriptor = \
|
|
bytes(b'TEA01')
|
|
new_boot_catalog = bytes(b'\x00') * 0x800
|
|
read_results = [
|
|
new_boot_catalog,
|
|
next_new_volume_descriptor,
|
|
new_volume_descriptor,
|
|
bytes(b'catalog'),
|
|
eltorito_descriptor,
|
|
volume_descriptor
|
|
]
|
|
|
|
def side_effect(arg):
|
|
return read_results.pop()
|
|
|
|
self.file_mock.read.side_effect = side_effect
|
|
|
|
Iso.relocate_boot_catalog('isofile')
|
|
assert self.file_mock.write.call_args_list == [
|
|
call(bytes(b'catalog')),
|
|
call(
|
|
bytes(b'EL TORITO SPECIFICATION') +
|
|
bytes(b'_') * (0x47 - 0x17) + bytes(b'\x13\x00\x00\x005f23a')
|
|
)
|
|
]
|
|
|
|
@patch_open
|
|
def test_fix_boot_catalog(self, mock_open):
|
|
mock_open.return_value = self.context_manager_mock
|
|
volume_descriptor = \
|
|
bytes(b'CD001') + bytes(b'_') * (0x08c - 0x5) + bytes(b'0x1d5f23a')
|
|
eltorito_descriptor = \
|
|
bytes(b'EL TORITO SPECIFICATION') + bytes(b'_') * (0x47 - 0x17) + bytes(b'0x1d5f23a')
|
|
boot_catalog = bytes(b'_') * 64 + struct.pack('B', 0x88) + bytes(b'_') * 32
|
|
read_results = [
|
|
boot_catalog,
|
|
eltorito_descriptor,
|
|
volume_descriptor
|
|
]
|
|
|
|
def side_effect(arg):
|
|
return read_results.pop()
|
|
|
|
self.file_mock.read.side_effect = side_effect
|
|
|
|
Iso.fix_boot_catalog('isofile')
|
|
|
|
if sys.byteorder == 'big':
|
|
assert self.file_mock.write.call_args_list == [
|
|
call(
|
|
bytes(b'_') * 44 +
|
|
bytes(b'\x01Legacy (isolinux)\x00\x00\x91\xef\x00\x01') +
|
|
bytes(b'\x00') * 28 +
|
|
bytes(b'\x88___________\x01UEFI (grub)') +
|
|
bytes(b'\x00') * 8
|
|
)
|
|
]
|
|
else:
|
|
assert self.file_mock.write.call_args_list == [
|
|
call(
|
|
bytes(b'_') * 44 +
|
|
bytes(b'\x01Legacy (isolinux)\x00\x00\x91\xef\x01') +
|
|
bytes(b'\x00') * 29 +
|
|
bytes(b'\x88___________\x01UEFI (grub)') +
|
|
bytes(b'\x00') * 8
|
|
)
|
|
]
|