Files
qdl/tests/meson.build
Igor Opaniuk b7fdbaecd2 tests: add cli argument parsing tests
With qdl_parse_args() in cli.c it is now unit testable. Cover the
option-to-struct mapping for valid inputs: the defaults, storage and
backend selection, --dry-run/--create-digests pinning the SIM backend
(and a later --backend being ignored), the skipblock mode, the flag
and value options, and that --help/--version report "done" while
too-few positional arguments report a usage error.

Invalid storage/backend/skipblock values errx() out of the process
and so are
left to the integration tests.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2026-10-01 10:54:22 +02:00

353 lines
9.3 KiB
Meson

# Test suite. The integration tests drive the built qdl binary through
# shell scripts; the unit tests are cmocka programs that pull in a few
# src/ translation units directly. Both reuse variables declared in the
# root and src/ meson.build (qdl_exe, inc, version_h, *_src, etc.).
# --- integration tests ---
# The scripts locate the qdl binary under the top-level build dir, so
# pass meson.project_build_root() rather than this subdir's build dir.
test(
'VIP table generation',
find_program('bash'),
args: [meson.current_source_dir() / 'test_vip_generation.sh', '--builddir', meson.project_build_root()],
depends: [qdl_exe],
suite: 'integration',
)
test(
'Sahara archive generation',
find_program('python3'),
args: [meson.current_source_dir() / 'test_sahara_archive.py', '--builddir', meson.project_build_root()],
depends: [qdl_exe],
suite: 'integration',
)
# --- hardware-in-the-loop tests ---
# Each step is a separate test in the "hil" suite. Run explicitly against an
# attached EDL device with:
# QDL_HIL_BUILD=... QDL_HIL_STORAGE=... meson test --suite hil
# Without that environment every step exits 77 (SKIP), so the suite is
# harmless if picked up by a plain "meson test" run.
#
# The steps are stateful (flash -> read -> erase -> write -> reset), so they
# must not overlap and must run in order: is_parallel:false serializes them
# and a descending priority fixes the order. Flashing a full build can take a
# while, hence the long timeout.
hil_steps = [
['list devices', 'list', 110],
['chipinfo via Sahara', 'chipinfo', 105],
['flash whole build', 'flash_full', 100],
['create-zip and flash', 'create_zip', 97],
['flash sparse build', 'sparse_flash', 96],
['read EFI partition', 'read_partition', 90],
['read GPT table', 'read_gpt', 80],
['read address P/S+L', 'read_addr_sectors', 70],
['read address P/name', 'read_addr_partname', 60],
['NAK on bad partition', 'nak_read', 55],
['flash skipblock sha256', 'flash_skipblock', 50],
['sha256 command', 'sha256', 40],
['sha256 by partition name', 'sha256_name', 35],
['erase EFI partition', 'erase', 30],
['write EFI partition', 'write_image', 20],
['write chunked', 'write_chunked', 18],
['verify write integrity', 'verify_write', 15],
['reset board', 'reset', 10],
]
foreach s : hil_steps
test(
'HIL ' + s[0],
find_program('bash'),
args: [meson.current_source_dir() / 'test_hil.sh',
'--builddir', meson.project_build_root(),
'--step', s[1]],
depends: [qdl_exe],
suite: 'hil',
is_parallel: false,
priority: s[2],
timeout: 1800,
)
endforeach
# VIP-mode suite for secured boards: list and chipinfo are reused from
# test_hil.sh; the sign-and-flash step lives in test_hil_vip.sh and
# additionally requires QDL_HIL_SECTOOLS/SECPROFILE/SECKEYS. Run with:
# meson test -C build --suite hil-vip
# The suites share the fail-fast sentinel, so run one suite at a time.
hil_vip_steps = [
['list devices', 'list', 'test_hil.sh', 110],
['chipinfo', 'chipinfo', 'test_hil.sh', 105],
['sign and flash', 'sign_flash', 'test_hil_vip.sh', 100],
]
foreach s : hil_vip_steps
test(
'HIL-VIP ' + s[0],
find_program('bash'),
args: [meson.current_source_dir() / s[2],
'--builddir', meson.project_build_root(),
'--step', s[1]],
depends: [qdl_exe],
suite: 'hil-vip',
is_parallel: false,
priority: s[3],
timeout: 1800,
)
endforeach
# --- unit tests (cmocka) ---
if cmocka_dep.found()
test_flashmap = executable('test_flashmap',
sources : [
'test_flashmap.c',
flashmap_src,
json_src,
],
dependencies : common_dep + [cmocka_dep],
include_directories : inc,
)
test(
'flashmap loading',
test_flashmap,
suite: 'unit',
protocol: 'tap',
env: ['CMOCKA_MESSAGE_OUTPUT=TAP'],
)
# test_firehose below relies on the linker discarding the unreferenced
# rest of firehose.c. GNU ld cannot reliably garbage-collect sections on
# PE/COFF - the surviving firehose internals then demand the whole
# device/vip/json surface as undefined symbols - so the target is
# skipped on Windows. The parsers are platform-independent, and stay
# covered by the ELF and Mach-O builds.
if host_machine.system() != 'windows'
# test_firehose.c #includes firehose.c to reach its static response
# parsers. The rest of firehose.c (and its device/vip/ufs dependencies)
# is unreferenced by the tests and stripped as dead code at link time,
# so only the ux_* logging stubs are required. GNU ld spells the
# stripping --gc-sections, Apple's ld64 spells it -dead_strip; ask the
# linker which one it supports.
gc_sections = meson.get_compiler('c').get_supported_link_arguments(
['-Wl,--gc-sections', '-Wl,-dead_strip'])
test_firehose = executable('test_firehose',
sources : [
'test_firehose.c',
],
dependencies : common_dep + [cmocka_dep],
include_directories : inc,
c_args : ['-ffunction-sections', '-fdata-sections'],
link_args : gc_sections,
)
test(
'firehose response parsers',
test_firehose,
suite: 'unit',
protocol: 'tap',
env: ['CMOCKA_MESSAGE_OUTPUT=TAP'],
)
endif
test_ufs = executable('test_ufs',
sources : [
'test_ufs.c',
'common.c',
ufs_src,
util_src,
],
dependencies : common_dep + [cmocka_dep],
include_directories : inc,
)
test_programmer = executable('test_programmer',
sources : [
'test_programmer.c',
programmer_src,
],
dependencies : common_dep + [cmocka_dep],
include_directories : inc,
)
test(
'programmer archive decoder',
test_programmer,
suite: 'unit',
protocol: 'tap',
env: ['CMOCKA_MESSAGE_OUTPUT=TAP'],
)
test(
'ufs provisioning loader',
test_ufs,
suite: 'unit',
protocol: 'tap',
env: ['CMOCKA_MESSAGE_OUTPUT=TAP'],
)
test_util = executable('test_util',
sources : [
'test_util.c',
util_src,
],
dependencies : common_dep + [cmocka_dep],
include_directories : inc,
)
test(
'util helpers',
test_util,
suite: 'unit',
protocol: 'tap',
env: ['CMOCKA_MESSAGE_OUTPUT=TAP'],
)
test_input_type = executable('test_input_type',
sources : [
'test_input_type.c',
'common.c',
input_type_src,
],
dependencies : common_dep + [cmocka_dep],
include_directories : inc,
)
test(
'input type detection',
test_input_type,
suite: 'unit',
protocol: 'tap',
env: ['CMOCKA_MESSAGE_OUTPUT=TAP'],
)
test_op_loaders = executable('test_op_loaders',
sources : [
'test_op_loaders.c',
'common.c',
read_src,
patch_src,
util_src,
],
dependencies : common_dep + [cmocka_dep],
include_directories : inc,
)
test(
'read/patch loaders',
test_op_loaders,
suite: 'unit',
protocol: 'tap',
env: ['CMOCKA_MESSAGE_OUTPUT=TAP'],
)
test_cli = executable('test_cli',
sources : [
'test_cli.c',
cli_src,
util_src,
],
dependencies : common_dep + [cmocka_dep],
include_directories : inc,
)
test(
'cli argument parsing',
test_cli,
suite: 'unit',
protocol: 'tap',
env: ['CMOCKA_MESSAGE_OUTPUT=TAP'],
)
test_program_load_xml = executable('test_program_load_xml',
sources : [
'test_program_load_xml.c',
'common.c',
pathbuf_src,
program_src,
util_src,
],
dependencies : common_dep + [cmocka_dep],
include_directories : inc,
c_args : ['-Daccess=mock_access'],
)
test(
'program_load_xml path resolution',
test_program_load_xml,
suite: 'unit',
protocol: 'tap',
env: ['CMOCKA_MESSAGE_OUTPUT=TAP'],
)
test_pathbuf = executable('test_pathbuf',
sources : [
'test_pathbuf.c',
pathbuf_src,
],
dependencies : common_dep + [cmocka_dep],
include_directories : inc,
)
test(
'pathbuf dirname behavior',
test_pathbuf,
suite: 'unit',
protocol: 'tap',
env: ['CMOCKA_MESSAGE_OUTPUT=TAP'],
)
test_contents_selectors = executable('test_contents_selectors',
sources : [
'test_contents_selectors.c',
pathbuf_src,
],
dependencies : common_dep + [cmocka_dep],
include_directories : inc,
)
test(
'contents selector resolution',
test_contents_selectors,
suite: 'unit',
protocol: 'tap',
env: ['CMOCKA_MESSAGE_OUTPUT=TAP'],
)
test_contents_xml = executable('test_contents_xml',
sources : [
'test_contents_xml.c',
'common.c',
pathbuf_src,
],
dependencies : common_dep + [cmocka_dep],
include_directories : inc,
)
test(
'contents XML parsing',
test_contents_xml,
suite: 'unit',
protocol: 'tap',
env: ['CMOCKA_MESSAGE_OUTPUT=TAP'],
)
test_oscompat = executable('test_oscompat',
sources : [
'test_oscompat.c',
],
dependencies : common_dep + [cmocka_dep],
include_directories : inc,
)
test(
'oscompat path helpers',
test_oscompat,
suite: 'unit',
protocol: 'tap',
env: ['CMOCKA_MESSAGE_OUTPUT=TAP'],
)
else
warning('cmocka not found; skipping unit tests')
endif