From: Adrian Freihofer Date: Mon, 27 Oct 2025 20:56:49 +0000 (+0100) Subject: oe-selftest: fitimage: test absent optional nodes in ITS files X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=90dbdacc7f22120b4a96aad2a89b363fdd944079;p=thirdparty%2Fopenembedded%2Fopenembedded-core.git oe-selftest: fitimage: test absent optional nodes in ITS files Extend the test framework to verify that certain optional nodes are properly absent from ITS files based on configuration. The _get_req_its_paths() method now returns a tuple containing both expected and not-expected paths, enabling negative testing of conditional components. Test improvements: - Add verification for absent bootscr, setup, and ramdisk image nodes when their respective features are disabled - Extend configuration node testing with proper kernel/fdt/ramdisk field validation based on device tree and initramfs settings Code cleanup: - Remove unused tempfile module import - Sort bb_vars keys alphabetically in _test_fitimage_py() - Add debug output for bb_vars overrides when debug logging is enabled - Remove trailing empty line - Fix DTB file ordering for consistent test results Signed-off-by: Adrian Freihofer Signed-off-by: Mathieu Dubois-Briand Signed-off-by: Richard Purdie --- diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index 9c2e10dd2b..8df5e92a34 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -9,7 +9,6 @@ import re import shlex import logging import pprint -import tempfile import oe.fitimage @@ -47,10 +46,11 @@ class FitImageTestCase(OESelftestTestCase): # Check if the its file contains the expected paths and attributes. # The _get_req_* functions are implemented by more specific chield classes. self._check_its_file() - req_its_paths = self._get_req_its_paths() + req_its_paths, not_req_its_paths = self._get_req_its_paths() req_sigvalues_config = self._get_req_sigvalues_config() req_sigvalues_image = self._get_req_sigvalues_image() - # Compare the its file against req_its_paths, req_sigvalues_config, req_sigvalues_image + # Compare the its file against req_its_paths, not_req_its_paths, + # req_sigvalues_config, req_sigvalues_image # Call the dumpimage utiliy and check that it prints all the expected paths and attributes # The _get_req_* functions are implemented by more specific chield classes. @@ -198,7 +198,7 @@ class FitImageTestCase(OESelftestTestCase): # Support only the test recipe which provides 1 devicetree and 1 devicetree overlay pref_prov_dtb = bb_vars.get('PREFERRED_PROVIDER_virtual/dtb') if pref_prov_dtb == "bbb-dtbs-as-ext": - all_dtbs += ["am335x-bonegreen-ext.dtb", "BBORG_RELAY-00A2.dtbo"] + all_dtbs += ["BBORG_RELAY-00A2.dtbo", "am335x-bonegreen-ext.dtb"] dtb_symlinks.append("am335x-bonegreen-ext-alias.dtb") return (all_dtbs, dtb_symlinks) @@ -234,8 +234,9 @@ class FitImageTestCase(OESelftestTestCase): self.logger.debug("its file: %s" % its_file.read()) # Generate a list of expected paths in the its file - req_its_paths = self._get_req_its_paths(bb_vars) + req_its_paths, not_req_its_paths = self._get_req_its_paths(bb_vars) self.logger.debug("req_its_paths:\n%s\n" % pprint.pformat(req_its_paths, indent=4)) + self.logger.debug("not_req_its_paths:\n%s\n" % pprint.pformat(not_req_its_paths, indent=4)) # Generate a dict of expected configuration signature nodes req_sigvalues_config = self._get_req_sigvalues_config(bb_vars) @@ -275,6 +276,11 @@ class FitImageTestCase(OESelftestTestCase): if not req_path in its_paths: self.fail('Missing path in its file: %s (%s)' % (req_path, its_file_path)) + # check if all not expected paths are absent in the its file + for not_req_path in not_req_its_paths: + if not_req_path in its_paths: + self.fail('Unexpected path found in its file: %s (%s)' % (not_req_path, its_file_path)) + # Check if all the expected singnature nodes (images and configurations) are found self.logger.debug("sigs:\n%s\n" % pprint.pformat(sigs, indent=4)) if req_sigvalues_config or req_sigvalues_image: @@ -353,7 +359,7 @@ class FitImageTestCase(OESelftestTestCase): def _get_req_its_paths(self, bb_vars): self.logger.error("This function needs to be implemented") - return [] + return ([], []) def _get_req_its_fields(self, bb_vars): self.logger.error("This function needs to be implemented") @@ -499,7 +505,7 @@ class KernelFitImageBase(FitImageTestCase): return (fitimage_its_path, fitimage_path) def _get_req_its_paths(self, bb_vars): - """Generate a list of expected paths in the its file + """Generate a list of expected and a list of not expected paths in the its file Example: [ @@ -515,15 +521,26 @@ class KernelFitImageBase(FitImageTestCase): uboot_sign_enable = bb_vars.get('UBOOT_SIGN_ENABLE') # image nodes - images = [ 'kernel-1' ] + images = ['kernel-1'] + not_images = [] + if dtb_files: images += [ 'fdt-' + dtb for dtb in dtb_files ] + if fit_uboot_env: images.append('bootscr-' + fit_uboot_env) + else: + not_images.append('bootscr-boot.cmd') + if bb_vars['MACHINE'] == "qemux86-64": # Not really the right if images.append('setup-1') + else: + not_images.append('setup-1') + if initramfs_image and initramfs_image_bundle != "1": images.append('ramdisk-1') + else: + not_images.append('ramdisk-1') # configuration nodes (one per DTB and also one per symlink) if dtb_files: @@ -541,7 +558,12 @@ class KernelFitImageBase(FitImageTestCase): req_its_paths.append(['/', 'configurations', configuration, 'hash-1']) if uboot_sign_enable == "1": req_its_paths.append(['/', 'configurations', configuration, 'signature-1']) - return req_its_paths + + not_req_its_paths = [] + for image in not_images: + not_req_its_paths.append(['/', 'images', image]) + + return (req_its_paths, not_req_its_paths) def _get_req_its_fields(self, bb_vars): initramfs_image = bb_vars['INITRAMFS_IMAGE'] @@ -572,10 +594,23 @@ class KernelFitImageBase(FitImageTestCase): fit_conf_prefix = bb_vars.get('FIT_CONF_PREFIX', "conf-") its_field_check.append('default = "' + fit_conf_prefix + fit_conf_default_dtb + '";') - its_field_check.append('kernel = "kernel-1";') + # configuration nodes (one per DTB and also one per symlink) + dtb_files, dtb_symlinks = FitImageTestCase._get_dtb_files(bb_vars) + if dtb_files: + for dtb in dtb_files: + its_field_check.append('kernel = "kernel-1";') + its_field_check.append('fdt = "fdt-%s";' % dtb) + for dtb in dtb_symlinks: + its_field_check.append('kernel = "kernel-1";') + # Works only for tests were the symlink is with -alias suffix + its_field_check.append('fdt = "fdt-%s";' % dtb.replace('-alias', '')) - if initramfs_image and initramfs_image_bundle != "1": - its_field_check.append('ramdisk = "ramdisk-1";') + if initramfs_image and initramfs_image_bundle != "1": + its_field_check.append('ramdisk = "ramdisk-1";') + else: + its_field_check.append('kernel = "kernel-1";') + if initramfs_image and initramfs_image_bundle != "1": + its_field_check.append('ramdisk = "ramdisk-1";') return its_field_check @@ -1032,20 +1067,21 @@ class FitImagePyTests(KernelFitImageBase): # Provide variables without calling bitbake bb_vars = { # image-fitimage.conf + 'FIT_ADDRESS_CELLS': "1", + 'FIT_CONF_DEFAULT_DTB': "", + 'FIT_CONF_PREFIX': "conf-", 'FIT_DESC': "Kernel fitImage for a dummy distro", - 'FIT_HASH_ALG': "sha256", - 'FIT_SIGN_ALG': "rsa2048", - 'FIT_PAD_ALG': "pkcs-1.5", 'FIT_GENERATE_KEYS': "0", - 'FIT_SIGN_NUMBITS': "2048", + 'FIT_HASH_ALG': "sha256", 'FIT_KEY_GENRSA_ARGS': "-F4", 'FIT_KEY_REQ_ARGS': "-batch -new", 'FIT_KEY_SIGN_PKCS': "-x509", + 'FIT_LINUX_BIN': "linux.bin", + 'FIT_PAD_ALG': "pkcs-1.5", + 'FIT_SIGN_ALG': "rsa2048", 'FIT_SIGN_INDIVIDUAL': "0", - 'FIT_CONF_PREFIX': "conf-", + 'FIT_SIGN_NUMBITS': "2048", 'FIT_SUPPORTED_INITRAMFS_FSTYPES': "cpio.lz4 cpio.lzo cpio.lzma cpio.xz cpio.zst cpio.gz ext2.gz cpio", - 'FIT_CONF_DEFAULT_DTB': "", - 'FIT_ADDRESS_CELLS': "1", 'FIT_UBOOT_ENV': "", # kernel.bbclass 'UBOOT_ENTRYPOINT': "0x20008000", @@ -1072,6 +1108,9 @@ class FitImagePyTests(KernelFitImageBase): } if bb_vars_overrides: bb_vars.update(bb_vars_overrides) + if logging.DEBUG >= self.logger.level: + debug_output = "\n".join([f"{key} = {value}" for key, value in bb_vars_overrides.items()]) + self.logger.debug("bb_vars overrides:\n%s" % debug_output) root_node = oe.fitimage.ItsNodeRootKernel( bb_vars["FIT_DESC"], bb_vars["FIT_ADDRESS_CELLS"], @@ -1204,7 +1243,7 @@ class UBootFitImageTests(FitImageTestCase): req_its_paths.append(['/', 'images', image, 'signature']) for configuration in configurations: req_its_paths.append(['/', 'configurations', configuration]) - return req_its_paths + return (req_its_paths, []) def _get_req_its_fields(self, bb_vars): loadables = ["uboot"] @@ -1730,4 +1769,3 @@ UBOOT_FIT_GENERATE_KEYS = "1" self.write_config(config) bb_vars = self._fit_get_bb_vars() self._test_fitimage(bb_vars) -