test: Add fsetup fixture and prepare helper for FIT test

Create an 'fsetup' fixture which sets up files and parameters, and a
prepare() helper which builds a FIT with given parameter overrides.

Update check_equal() and check_not_equal() to look up filenames from a
params dict by key, reducing the number of local variables needed.

Split the single test_fit_operations() into individual test functions so
that each appears separately in the results.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass
2026-04-13 06:59:58 -06:00
committed by Tom Rini
parent cd6e1f6dbe
commit 06b12fba0c

View File

@@ -241,91 +241,70 @@ class TestFitImage:
pytest.fail("Expected '%s' but not found in output")
return '<no-match>'
def check_equal(self, expected_fname, actual_fname, failure_msg):
def check_equal(self, params, expected_key, actual_key, failure_msg):
"""Check that a file matches its expected contents
This is always used on out-buffers whose size is decided by the test
script anyway, which in some cases may be larger than what we're
actually looking for. So it's safe to truncate it to the size of the
expected data.
Args:
expected_fname (str): Filename containing expected contents
actual_fname (str): Filename containing actual contents
failure_msg (str): Message to print on failure
"""
expected_data = self.read_file(expected_fname)
actual_data = self.read_file(actual_fname)
expected_data = self.read_file(params[expected_key])
actual_data = self.read_file(params[actual_key])
if len(expected_data) < len(actual_data):
actual_data = actual_data[:len(expected_data)]
assert expected_data == actual_data, failure_msg
def check_not_equal(self, expected_fname, actual_fname, failure_msg):
"""Check that a file does not match its expected contents
Args:
expected_fname (str): Filename containing expected contents
actual_fname (str): Filename containing actual contents
failure_msg (str): Message to print on failure
"""
expected_data = self.read_file(expected_fname)
actual_data = self.read_file(actual_fname)
def check_not_equal(self, params, expected_key, actual_key, failure_msg):
"""Check that a file does not match its expected contents"""
expected_data = self.read_file(params[expected_key])
actual_data = self.read_file(params[actual_key])
assert expected_data != actual_data, failure_msg
def test_fit_operations(self, ubman):
"""Basic sanity check of FIT loading in U-Boot
This test covers various FIT configurations and verifies correct behavior.
Args:
ubman (ConsoleBase): U-Boot fixture
"""
@pytest.fixture()
def fsetup(self, ubman):
"""Set up files and default parameters for FIT tests"""
mkimage = os.path.join(ubman.config.build_dir, 'tools/mkimage')
# Set up invariant files
fdt_data = fit_util.make_dtb(ubman, BASE_FDT, 'u-boot')
kernel = fit_util.make_kernel(ubman, 'test-kernel.bin', 'kernel')
ramdisk = self.make_ramdisk(ubman, 'test-ramdisk.bin', 'ramdisk')
loadables1 = fit_util.make_kernel(ubman, 'test-loadables1.bin', 'lenrek')
loadables2 = self.make_ramdisk(ubman, 'test-loadables2.bin', 'ksidmar')
kernel_out = self.make_fname(ubman, 'kernel-out.bin')
fdt = self.make_fname(ubman, 'u-boot.dtb')
fdt_out = self.make_fname(ubman, 'fdt-out.dtb')
ramdisk_out = self.make_fname(ubman, 'ramdisk-out.bin')
loadables1_out = self.make_fname(ubman, 'loadables1-out.bin')
loadables2_out = self.make_fname(ubman, 'loadables2-out.bin')
loadables1 = fit_util.make_kernel(ubman, 'test-loadables1.bin',
'lenrek')
loadables2 = self.make_ramdisk(ubman, 'test-loadables2.bin',
'ksidmar')
# Set up basic parameters with default values
params = {
yield {
'mkimage' : mkimage,
'fit_addr' : 0x1000,
'kernel' : kernel,
'kernel_out' : kernel_out,
'kernel_out' : self.make_fname(ubman, 'kernel-out.bin'),
'kernel_addr' : 0x40000,
'kernel_size' : self.filesize(kernel),
'kernel_config' : 'kernel = "kernel-1";',
'fdt' : fdt,
'fdt_out' : fdt_out,
'fdt_data' : fdt_data,
'fdt' : self.make_fname(ubman, 'u-boot.dtb'),
'fdt_out' : self.make_fname(ubman, 'fdt-out.dtb'),
'fdt_addr' : 0x80000,
'fdt_size' : self.filesize(fdt_data),
'fdt_load' : '',
'ramdisk' : ramdisk,
'ramdisk_out' : ramdisk_out,
'ramdisk_out' : self.make_fname(ubman, 'ramdisk-out.bin'),
'ramdisk_addr' : 0xc0000,
'ramdisk_size' : self.filesize(ramdisk),
'ramdisk_load' : '',
'ramdisk_config' : '',
'loadables1' : loadables1,
'loadables1_out' : loadables1_out,
'loadables1_out' : self.make_fname(ubman, 'loadables1-out.bin'),
'loadables1_addr' : 0x100000,
'loadables1_size' : self.filesize(loadables1),
'loadables1_load' : '',
'loadables2' : loadables2,
'loadables2_out' : loadables2_out,
'loadables2_out' : self.make_fname(ubman, 'loadables2-out.bin'),
'loadables2_addr' : 0x140000,
'loadables2_size' : self.filesize(loadables2),
'loadables2_load' : '',
@@ -334,101 +313,128 @@ class TestFitImage:
'compression' : 'none',
}
# Make a basic FIT and a script to load it
fit = fit_util.make_fit(ubman, mkimage, BASE_ITS, params)
def prepare(self, ubman, fsetup, **kwargs):
"""Build a FIT with given overrides
Args:
ubman (ConsoleBase): U-Boot fixture
fsetup (dict): Default parameters from the fsetup fixture
kwargs: Parameter overrides for this particular test
Return:
tuple:
list of str: Commands to run for the test
dict: Parameters used by the test
str: Filename of the FIT that was created
"""
params = {**fsetup, **kwargs}
fit = fit_util.make_fit(ubman, params['mkimage'], BASE_ITS, params)
params['fit'] = fit
cmd = BASE_SCRIPT % params
cmds = (BASE_SCRIPT % params).splitlines()
return cmds, params, fit
# First check that we can load a kernel
# We could perhaps reduce duplication with some loss of readability
with ubman.log.section('Kernel load'):
output = ubman.run_command_list(cmd.splitlines())
self.check_equal(kernel, kernel_out, 'Kernel not loaded')
self.check_not_equal(fdt_data, fdt_out,
'FDT loaded but should be ignored')
self.check_not_equal(ramdisk, ramdisk_out,
'Ramdisk loaded but should not be')
def test_fit_kernel_load(self, ubman, fsetup):
"""Test loading a FIT image with only a kernel"""
cmds, params, fit = self.prepare(ubman, fsetup)
# Find out the offset in the FIT where U-Boot has found the FDT
line = self.find_matching(output, 'Booting using the fdt blob at ')
fit_offset = int(line, 16) - params['fit_addr']
fdt_magic = struct.pack('>L', 0xd00dfeed)
data = self.read_file(fit)
output = ubman.run_command_list(cmds)
self.check_equal(params, 'kernel', 'kernel_out', 'Kernel not loaded')
self.check_not_equal(params, 'fdt_data', 'fdt_out',
'FDT loaded but should be ignored')
self.check_not_equal(params, 'ramdisk', 'ramdisk_out',
'Ramdisk loaded but should not be')
# Now find where it actually is in the FIT (skip the first word)
real_fit_offset = data.find(fdt_magic, 4)
assert fit_offset == real_fit_offset, (
'U-Boot loaded FDT from offset %#x, FDT is actually at %#x' %
(fit_offset, real_fit_offset))
# Find out the offset in the FIT where U-Boot has found the FDT
line = self.find_matching(output, 'Booting using the fdt blob at ')
fit_offset = int(line, 16) - params['fit_addr']
fdt_magic = struct.pack('>L', 0xd00dfeed)
data = self.read_file(fit)
# Now find where it actually is in the FIT (skip the first word)
real_fit_offset = data.find(fdt_magic, 4)
assert fit_offset == real_fit_offset, (
'U-Boot loaded FDT from offset %#x, FDT is actually at %#x' %
(fit_offset, real_fit_offset))
# Check bootargs string substitution
output = ubman.run_command_list([
'env set bootargs \\"\'my_boot_var=${foo}\'\\"',
'env set foo bar',
'bootm prep',
'env print bootargs'])
assert 'bootargs="my_boot_var=bar"' in output, "Bootargs strings not substituted"
output = ubman.run_command_list([
'env set bootargs \\"\'my_boot_var=${foo}\'\\"',
'env set foo bar',
'bootm prep',
'env print bootargs'])
assert 'bootargs="my_boot_var=bar"' in output, \
"Bootargs strings not substituted"
# Now a kernel and an FDT
with ubman.log.section('Kernel + FDT load'):
params['fdt_load'] = 'load = <%#x>;' % params['fdt_addr']
fit = fit_util.make_fit(ubman, mkimage, BASE_ITS, params)
params['fit'] = fit
cmd = BASE_SCRIPT % params
output = ubman.run_command_list(cmd.splitlines())
self.check_equal(kernel, kernel_out, 'Kernel not loaded')
self.check_equal(fdt_data, fdt_out, 'FDT not loaded')
self.check_not_equal(ramdisk, ramdisk_out,
'Ramdisk loaded but should not be')
def test_fit_kernel_fdt_load(self, ubman, fsetup):
"""Test loading a FIT image with a kernel and FDT"""
cmds, params, _ = self.prepare(
ubman, fsetup,
fdt_load='load = <%#x>;' % fsetup['fdt_addr'])
# Try a ramdisk
with ubman.log.section('Kernel + FDT + Ramdisk load'):
params['ramdisk_config'] = 'ramdisk = "ramdisk-1";'
params['ramdisk_load'] = 'load = <%#x>;' % params['ramdisk_addr']
fit = fit_util.make_fit(ubman, mkimage, BASE_ITS, params)
params['fit'] = fit
cmd = BASE_SCRIPT % params
output = ubman.run_command_list(cmd.splitlines())
self.check_equal(ramdisk, ramdisk_out, 'Ramdisk not loaded')
ubman.run_command_list(cmds)
self.check_equal(params, 'kernel', 'kernel_out', 'Kernel not loaded')
self.check_equal(params, 'fdt_data', 'fdt_out', 'FDT not loaded')
self.check_not_equal(params, 'ramdisk', 'ramdisk_out',
'Ramdisk loaded but should not be')
# Configuration with some Loadables
with ubman.log.section('Kernel + FDT + Ramdisk load + Loadables'):
params['loadables_config'] = 'loadables = "kernel-2", "ramdisk-2";'
params['loadables1_load'] = ('load = <%#x>;' %
params['loadables1_addr'])
params['loadables2_load'] = ('load = <%#x>;' %
params['loadables2_addr'])
fit = fit_util.make_fit(ubman, mkimage, BASE_ITS, params)
params['fit'] = fit
cmd = BASE_SCRIPT % params
output = ubman.run_command_list(cmd.splitlines())
self.check_equal(loadables1, loadables1_out,
'Loadables1 (kernel) not loaded')
self.check_equal(loadables2, loadables2_out,
'Loadables2 (ramdisk) not loaded')
def test_fit_kernel_fdt_ramdisk_load(self, ubman, fsetup):
"""Test loading a FIT image with kernel, FDT, and ramdisk"""
cmds, params, _ = self.prepare(
ubman, fsetup,
fdt_load='load = <%#x>;' % fsetup['fdt_addr'],
ramdisk_config='ramdisk = "ramdisk-1";',
ramdisk_load='load = <%#x>;' % fsetup['ramdisk_addr'])
# Kernel, FDT and Ramdisk all compressed
with ubman.log.section('(Kernel + FDT + Ramdisk) compressed'):
params['compression'] = 'gzip'
params['kernel'] = self.make_compressed(ubman, kernel)
params['fdt'] = self.make_compressed(ubman, fdt)
params['ramdisk'] = self.make_compressed(ubman, ramdisk)
fit = fit_util.make_fit(ubman, mkimage, BASE_ITS, params)
params['fit'] = fit
cmd = BASE_SCRIPT % params
output = ubman.run_command_list(cmd.splitlines())
self.check_equal(kernel, kernel_out, 'Kernel not loaded')
self.check_equal(fdt_data, fdt_out, 'FDT not loaded')
self.check_not_equal(ramdisk, ramdisk_out, 'Ramdisk got decompressed?')
self.check_equal(ramdisk + '.gz', ramdisk_out, 'Ramdisk not loaded')
ubman.run_command_list(cmds)
self.check_equal(params, 'ramdisk', 'ramdisk_out',
'Ramdisk not loaded')
# Try without a kernel
with ubman.log.section('No kernel + FDT'):
params['kernel_config'] = ''
params['ramdisk_config'] = ''
params['ramdisk_load'] = ''
fit = fit_util.make_fit(ubman, mkimage, BASE_ITS, params)
params['fit'] = fit
cmd = BASE_SCRIPT % params
output = ubman.run_command_list(cmd.splitlines())
assert "can't get kernel image!" in '\n'.join(output)
def test_fit_loadables_load(self, ubman, fsetup):
"""Test a configuration with loadables"""
cmds, params, _ = self.prepare(
ubman, fsetup,
fdt_load='load = <%#x>;' % fsetup['fdt_addr'],
ramdisk_config='ramdisk = "ramdisk-1";',
ramdisk_load='load = <%#x>;' % fsetup['ramdisk_addr'],
loadables_config='loadables = "kernel-2", "ramdisk-2";',
loadables1_load='load = <%#x>;' % fsetup['loadables1_addr'],
loadables2_load='load = <%#x>;' % fsetup['loadables2_addr'])
ubman.run_command_list(cmds)
self.check_equal(params, 'loadables1', 'loadables1_out',
'Loadables1 (kernel) not loaded')
self.check_equal(params, 'loadables2', 'loadables2_out',
'Loadables2 (ramdisk) not loaded')
def test_fit_compressed_images_load(self, ubman, fsetup):
"""Test loading compressed kernel, FDT, and ramdisk images"""
cmds, params, _ = self.prepare(
ubman, fsetup,
fdt_load='load = <%#x>;' % fsetup['fdt_addr'],
ramdisk_config='ramdisk = "ramdisk-1";',
ramdisk_load='load = <%#x>;' % fsetup['ramdisk_addr'],
compression='gzip',
kernel=self.make_compressed(ubman, fsetup['kernel']),
fdt=self.make_compressed(ubman, fsetup['fdt']),
ramdisk=self.make_compressed(ubman, fsetup['ramdisk']))
ubman.run_command_list(cmds)
self.check_equal(fsetup, 'kernel', 'kernel_out',
'Kernel not loaded')
self.check_equal(fsetup, 'fdt_data', 'fdt_out', 'FDT not loaded')
self.check_not_equal(fsetup, 'ramdisk', 'ramdisk_out',
'Ramdisk got decompressed?')
self.check_equal(params, 'ramdisk', 'ramdisk_out',
'Ramdisk not loaded')
def test_fit_no_kernel_load(self, ubman, fsetup):
"""Test that bootm fails when no kernel is specified"""
cmds = self.prepare(
ubman, fsetup,
fdt_load='load = <%#x>;' % fsetup['fdt_addr'],
kernel_config='',
ramdisk_config='',
ramdisk_load='')[0]
output = ubman.run_command_list(cmds)
assert "can't get kernel image!" in '\n'.join(output)