doc: expo: Add documentation for writing and debugging tests

Add a new section covering how to write expo tests, including test
structure, memory checking, creating test expos, testing rendering
and input, building from devicetree, and using IDs.

Also add a debugging section with sandbox command-line options useful
for expo development. Add a bit more detail for --video_frames

Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
This commit is contained in:
Simon Glass
2025-12-07 05:45:03 -07:00
parent 632956e1ab
commit 30410f2817
3 changed files with 201 additions and 1 deletions

View File

@@ -253,7 +253,10 @@ available options. Some of these are described below:
Show console output from tests. Normally this is suppressed.
--video_frames <dir>
Write video frames to the specified directory for debugging purposes.
Write video frames to the specified directory for debugging purposes. Each
time video_compress_fb() is called, this writes a file called 'frame%d.bmp'
to the given directory where %d is the sequence number starting from 0. Note
that sandbox removes all 'frame%d.bmp' files in that directory on startup.
-V, --video_test <ms>
Enable video test mode with a delay (in milliseconds) between assertions. This

View File

@@ -605,6 +605,201 @@ These metrics help identify performance bottlenecks and verify that expo is
operating efficiently. The timing information is particularly useful when
optimizing display drivers or debugging slow rendering issues.
Writing expo tests
------------------
Expo has extensive tests in ``test/boot/expo.c`` and ``test/boot/cedit.c``.
These can be run under sandbox like any other test (see :doc:`testing`).
Test structure
~~~~~~~~~~~~~~
Each test function follows a standard pattern::
static int expo_my_test(struct unit_test_state *uts)
{
struct expo *exp;
/* Create expo and perform tests */
ut_assertok(expo_new("test", NULL, &exp));
/* ... test code ... */
expo_destroy(exp);
return 0;
}
BOOTSTD_TEST(expo_my_test, UTF_DM | UTF_SCAN_FDT);
The ``BOOTSTD_TEST()`` macro registers the test with the test framework.
Common flags include:
UTF_DM
Requires driver model to be enabled (most expo tests need this)
UTF_SCAN_FDT
Scans the device tree for devices (needed for video display)
UTF_CONSOLE
Test needs to record console output (needed for commands)
UTF_NO_SILENT
Don't silence console output (needed for tests that check rendering output
with user input)
Memory checking
~~~~~~~~~~~~~~~
Tests should verify that no memory is leaked::
ulong start_mem;
start_mem = ut_check_free();
/* ... create expo, test, destroy ... */
ut_assertok(ut_check_delta(start_mem));
For assertions, see :ref:`tests_writing_assertions`.
Creating test expos
~~~~~~~~~~~~~~~~~~~
A common pattern is to create a helper function that sets up an expo with
scenes and objects for testing. See ``create_test_expo()`` in
``test/boot/expo.c`` for an example::
static int create_test_expo(struct unit_test_state *uts, struct expo **expp,
struct scene **scnp, struct scene_obj_menu **menup,
...)
{
struct expo *exp;
struct scene *scn;
int id;
ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev));
ut_assertok(expo_new(EXPO_NAME, NULL, &exp));
id = scene_new(exp, SCENE_NAME1, SCENE1, &scn);
ut_assert(id > 0);
ut_assertok(expo_set_display(exp, dev));
/* Add objects to the scene */
id = scene_txt_str(scn, "text", OBJ_TEXT, STR_TEXT, "my string", NULL);
ut_assert(id > 0);
/* Return pointers */
*expp = exp;
*scnp = scn;
return 0;
}
Testing rendering
~~~~~~~~~~~~~~~~~
For graphical rendering tests, use ``video_compress_fb()`` to get a checksum
of the framebuffer::
ut_assertok(expo_render(exp));
ut_asserteq(expected_checksum, video_compress_fb(uts, dev, false));
For text-mode rendering, check console output lines::
expo_set_text_mode(exp, true);
ut_assertok(expo_render(exp));
ut_assert_nextline("Expected line");
ut_assert_console_end();
Testing input
~~~~~~~~~~~~~
To test keyboard input handling, use ``expo_send_key()``::
ut_assertok(expo_send_key(exp, BKEY_DOWN));
ut_assertok(expo_action_get(exp, &act));
ut_asserteq(EXPOACT_POINT_ITEM, act.type);
ut_asserteq(ITEM2, act.select.id);
To test mouse clicks, use ``scene_send_click()``::
ut_assertok(scene_send_click(scn, x, y, &act));
ut_asserteq(EXPOACT_SELECT, act.type);
Building from devicetree
~~~~~~~~~~~~~~~~~~~~~~~~
To test building an expo from a devicetree description::
ofnode node;
node = ofnode_path("/cedit");
ut_assert(ofnode_valid(node));
ut_assertok(expo_build(node, &exp));
The test devicetree is in ``test/boot/files/expo_layout.dts`` with IDs
defined in ``test/boot/files/expo_ids.h``. See ``setup_cedit_file()`` in
``test/py/img/cedit.py`` for how this is set up.
Using IDs
~~~~~~~~~
Define an enum for all object IDs at the top of the test file::
enum {
/* scenes */
SCENE1 = 7,
/* objects */
OBJ_LOGO,
OBJ_TEXT,
OBJ_MENU,
/* strings */
STR_TEXT,
STR_MENU_TITLE,
/* menu items */
ITEM1,
ITEM2,
};
Starting IDs from a value higher than ``EXPOID_BASE_ID`` avoids conflicts
with reserved expo IDs.
Debugging tests
~~~~~~~~~~~~~~~
Running tests directly (without pytest) makes debugging easier. See
:doc:`tests_sandbox` for details on running sandbox tests with gdb.
For example, to run a single expo test::
./u-boot -T -c "ut bootstd expo_render_image"
To debug with gdb::
gdb --args ./u-boot -T -c "ut bootstd expo_render_image"
(gdb) break expo_render_image
(gdb) run
IDEs such as Visual Studio Code can also be used.
Sandbox provides command-line options useful for debugging expo and video
tests, including ``-l`` (show LCD), ``-K`` (double LCD size), ``-V`` (video
test mode with delay), ``--video_frames`` (capture frames), ``-f`` (continue
after failure), and ``-F`` (skip flat-tree tests). See
:doc:`../arch/sandbox/sandbox` for full details.
For example, to watch an expo test render with a visible display::
./u-boot -T -l -V 500 --video_frames /tmp/good -c "ut bootstd expo_render_image"
This will write each asserted expo frame to ``/tmp/good/frame0.bmp``,
``/tmp/good/frame1.bmp``, etc.
API documentation
-----------------

View File

@@ -373,6 +373,8 @@ existing suite or creating a new one.
An example SPL test is spl_test_load().
.. _tests_writing_assertions:
Assertions
----------