Files
qdl/tests/meson.build
T
Igor Opaniuk 4ef8df7db2 tests: extend HIL test suite
Extend the hardware-in-the-loop suite with self-contained steps that
fit the existing round-trip model:

- list devices: enumerate the attached EDL device with the list verb
  and require a vid:pid line in the output, covering device discovery
  over real USB.

- chipinfo via Sahara: read the chip identity (serial number, HW ID
  and OEM PK hash) with the chipinfo verb. The step runs before the
  programmer upload because chip identity is only available while the
  device still speaks Sahara; the verb switches the device back to
  image-transfer mode on exit, so the subsequent flash still gets its
  Sahara HELLO. SKIPs when a programmer is already running.

- create-zip and flash: package a build from a contents.xml with the
  create-zip verb, then flash the produced zip, covering the zip
  writer and the zip flashing path end to end. Gated on
  QDL_HIL_CONTENTS.

- flash sparse build: flash a bundle that uses Android sparse images,
  covering the sparse decoding path against real storage. Gated on
  QDL_HIL_SPARSE.

- NAK on bad partition: a read of a nonexistent physical partition
  must fail, verifying that a device NAK is reported as an error
  instead of silently succeeding.

- sha256 by partition name: digest a partition addressed by its GPT
  name rather than by partition and sector numbers, covering GPT name
  resolution against the device.

- write chunked: rewrite the partition image with an overridden
  --out-chunk-size=16384, covering the chunked transfer path.

- verify write integrity: compare the device-computed partition
  digest against a local sha256 of the previously read-back and
  rewritten image, proving the read/write round trip is bit-exact.

- reset board: switch the final step to the new reset verb, covering
  the explicit device-reset path instead of relying on the implicit
  reset after a dummy 1-sector read.

The two gated steps SKIP when their environment variable is unset,
and every step SKIPs without hardware, so a plain meson test stays
green.

Example invocation against an attached EDL device:

  D=<path_to_build>
  QDL_HIL_BUILD=$D QDL_HIL_CONTENTS=$D/contents.xml \
    QDL_HIL_STORAGE=ufs meson test -C build --suite=hil

   1/18 hil - qdl:HIL list devices             OK          0.05s
   2/18 hil - qdl:HIL chipinfo via Sahara      OK          0.4s
   3/18 hil - qdl:HIL flash whole build        OK         29.03s
   4/18 hil - qdl:HIL create-zip and flash     OK         79.62s
   5/18 hil - qdl:HIL flash sparse build       SKIP        0.02s
  ...
  18/18 hil - qdl:HIL reset board              OK          3.68s

  Ok:                17
  Fail:              0
  Skipped:           1

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
2026-07-16 17:15:34 -05:00

176 lines
4.9 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',
)
# --- 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
# --- 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_program_load_xml = executable('test_program_load_xml',
sources : [
'test_program_load_xml.c',
'common.c',
pathbuf_src,
program_src,
util_src,
version_h,
],
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