Skip to content

[RFC] Introduce unit tests#207

Open
igoropaniuk wants to merge 6 commits intolinux-msm:masterfrom
igoropaniuk:feat/unit_tests
Open

[RFC] Introduce unit tests#207
igoropaniuk wants to merge 6 commits intolinux-msm:masterfrom
igoropaniuk:feat/unit_tests

Conversation

@igoropaniuk
Copy link
Copy Markdown
Contributor

Introduce test suite for the patch module.

The library had no unit tests because there was no way to link just the protocol logic without pulling in main(), no way to silence its output, and no way to reset per-module state between test cases.

All three of those blockers are removed here:

  • sources are collected into a static archive so a test binary can link them without a CLI entry point
  • output is routed through a pluggable vtable so tests can install a no-op backend
  • the patch module's file-scoped globals are moved into struct qdl_device so each test case gets a clean instance.

With those foundations in place the first real test suite is added for the patch module, and CI is updated to install cmocka so the tests run on every platform automatically.

All protocol logic, utilities, and headers are mixed with CLI entry
points in a flat directory, making it hard to draw a boundary between
reusable library code and tool-specific glue. This blocks any future
unit test harness from linking just the library without pulling
in main() symbols.

Move all non-CLI sources and headers into lib/, including the USB
transport (usb.c) which implements the same qdl_device vtable as the
simulator. The CLI entry points (qdl.c, ramdump.c, ks.c) stay at the
top level. Add -Ilib to CFLAGS so all #include "foo.h" directives
resolve without any source file changes.

This is a pure rename -- no code changes, no behavior changes.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
The three binaries (qdl, qdl-ramdump, ks) share many of the same source
files but each compiles them independently, wasting build time and
making it impossible for a test harness to link the protocol logic
without also pulling in a main() symbol.

Collect all lib/ sources into a static archive (lib/libqdl.a) and link
each binary against it. Each binary's own source list is now just its
CLI entry point. Shared objects are compiled once instead of up to three
times, and a future test binary can link libqdl.a directly.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
libxml2 prints warnings and errors directly to stderr before the caller
gets a chance to handle them. This leaks raw parser diagnostics into
both test output and user-facing output when a patch file is missing or
malformed. patch_load() already checks the return value and reports the
failure through ux_err(), so the extra stderr output is redundant noise.

Pass XML_PARSE_NOWARNING | XML_PARSE_NOERROR to xmlReadFile() so all
error reporting goes through our own output layer.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
The ux_*() functions write directly to stdout/stderr with terminal width
detection, making it impossible for tests or embedded consumers to
capture, redirect, or suppress library output. A test harness that links
libqdl.a inherits terminal I/O it cannot control, and a GUI or daemon
has no way to route messages to its own logging framework.

Introduce struct qdl_ux_ops with function pointers for err, info, log,
debug, and progress. The library dispatches all output through this
vtable. The existing terminal implementation becomes the default backend
and is installed when the caller passes NULL to qdl_ux_set_ops().

The qdl_debug check for log/debug verbosity stays in the dispatch layer
so backends do not need to filter by verbosity themselves.

CLI entry points (qdl.c, ramdump.c) replace ux_init() with
qdl_ux_set_ops(NULL) which initializes the terminal backend with width
detection. Test harnesses can supply a no-op or capture implementation.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
The patch module stored its state in file-scoped static variables
(patches list, loaded flag), making it impossible to run two independent
patch sessions or to test the module without hidden side effects leaking
between test cases.

Introduce struct patch_ctx to hold the patch list and loaded flag. Embed
it in struct qdl_device so that each device instance carries its own
patch state. All public functions take struct qdl_device as the first
argument and access the embedded context internally, keeping the API
consistent with the rest of the library.

This is the first step toward eliminating global singletons from the
library modules, enabling proper unit testing.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
The patch module had no test coverage, making it easy for regressions
in XML parsing or execution logic to go unnoticed until a real flash
session fails.

Add 14 cmocka-based tests covering:
- Context lifecycle: init, free, reuse after free
- Loading: single patch, multiple patches, empty file, missing file,
  malformed XML, missing attributes, unknown tags
- Execution: apply callback invocation for DISK patches, non-DISK
  filtering, error propagation from apply, no-op when not loaded

The tests link against libqdl.a with a no-op ux backend, requiring no
device or USB connection.

Signed-off-by: Igor Opaniuk <igor.opaniuk@oss.qualcomm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant