kiwi-el8/test/unit/iso_test.py
Marcus Schäfer 9cb7390af0 Fixup boot-load-size for efi loader in iso
Pass the real boot-load-size of the used loader as number
of 512byte blocks to the iso creation call. Related to
(bsc#939456)
2017-05-19 17:12:57 +02:00

383 lines
13 KiB
Python

from mock import call, patch
import mock
import struct
from .test_helper import raises, patch_open
import sys
from builtins import bytes
from kiwi.exceptions import (
KiwiIsoLoaderError,
KiwiIsoToolError,
KiwiIsoMetaDataError
)
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')
@patch('os.path.getsize')
def test_add_efi_loader_parameters(self, mock_getsize, mock_exists):
mock_getsize.return_value = 4096
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', '-boot-load-size', '8'
]
@patch('os.path.exists')
@patch('os.path.getsize')
def test_add_efi_loader_parameters_big_loader(
self, mock_getsize, mock_exists
):
mock_getsize.return_value = 33554432
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
)
]