Skip to content

Commit bc145b3

Browse files
Harinder SinghJonathan Corbet
authored andcommitted
Documentation: KUnit: Added KUnit Architecture
Describe the components of KUnit and how the kernel mode parts interact with kunit_tool. Signed-off-by: Harinder Singh <[email protected]> Co-developed-by: Marco Elver <[email protected]> Signed-off-by: Marco Elver <[email protected]> Reviewed-by: Brendan Higgins <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jonathan Corbet <[email protected]>
1 parent c48b9ef commit bc145b3

File tree

4 files changed

+288
-0
lines changed

4 files changed

+288
-0
lines changed
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
.. SPDX-License-Identifier: GPL-2.0
2+
3+
==================
4+
KUnit Architecture
5+
==================
6+
7+
The KUnit architecture can be divided into two parts:
8+
9+
- Kernel testing library
10+
- kunit_tool (Command line test harness)
11+
12+
In-Kernel Testing Framework
13+
===========================
14+
15+
The kernel testing library supports KUnit tests written in C using
16+
KUnit. KUnit tests are kernel code. KUnit does several things:
17+
18+
- Organizes tests
19+
- Reports test results
20+
- Provides test utilities
21+
22+
Test Cases
23+
----------
24+
25+
The fundamental unit in KUnit is the test case. The KUnit test cases are
26+
grouped into KUnit suites. A KUnit test case is a function with type
27+
signature ``void (*)(struct kunit *test)``.
28+
These test case functions are wrapped in a struct called
29+
``struct kunit_case``. For code, see:
30+
31+
.. kernel-doc:: include/kunit/test.h
32+
:identifiers: kunit_case
33+
34+
.. note:
35+
``generate_params`` is optional for non-parameterized tests.
36+
37+
Each KUnit test case gets a ``struct kunit`` context
38+
object passed to it that tracks a running test. The KUnit assertion
39+
macros and other KUnit utilities use the ``struct kunit`` context
40+
object. As an exception, there are two fields:
41+
42+
- ``->priv``: The setup functions can use it to store arbitrary test
43+
user data.
44+
45+
- ``->param_value``: It contains the parameter value which can be
46+
retrieved in the parameterized tests.
47+
48+
Test Suites
49+
-----------
50+
51+
A KUnit suite includes a collection of test cases. The KUnit suites
52+
are represented by the ``struct kunit_suite``. For example:
53+
54+
.. code-block:: c
55+
56+
static struct kunit_case example_test_cases[] = {
57+
KUNIT_CASE(example_test_foo),
58+
KUNIT_CASE(example_test_bar),
59+
KUNIT_CASE(example_test_baz),
60+
{}
61+
};
62+
63+
static struct kunit_suite example_test_suite = {
64+
.name = "example",
65+
.init = example_test_init,
66+
.exit = example_test_exit,
67+
.test_cases = example_test_cases,
68+
};
69+
kunit_test_suite(example_test_suite);
70+
71+
In the above example, the test suite ``example_test_suite``, runs the
72+
test cases ``example_test_foo``, ``example_test_bar``, and
73+
``example_test_baz``. Before running the test, the ``example_test_init``
74+
is called and after running the test, ``example_test_exit`` is called.
75+
The ``kunit_test_suite(example_test_suite)`` registers the test suite
76+
with the KUnit test framework.
77+
78+
Executor
79+
--------
80+
81+
The KUnit executor can list and run built-in KUnit tests on boot.
82+
The Test suites are stored in a linker section
83+
called ``.kunit_test_suites``. For code, see:
84+
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/asm-generic/vmlinux.lds.h?h=v5.15#n945.
85+
The linker section consists of an array of pointers to
86+
``struct kunit_suite``, and is populated by the ``kunit_test_suites()``
87+
macro. To run all tests compiled into the kernel, the KUnit executor
88+
iterates over the linker section array.
89+
90+
.. kernel-figure:: kunit_suitememorydiagram.svg
91+
:alt: KUnit Suite Memory
92+
93+
KUnit Suite Memory Diagram
94+
95+
On the kernel boot, the KUnit executor uses the start and end addresses
96+
of this section to iterate over and run all tests. For code, see:
97+
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/kunit/executor.c
98+
99+
When built as a module, the ``kunit_test_suites()`` macro defines a
100+
``module_init()`` function, which runs all the tests in the compilation
101+
unit instead of utilizing the executor.
102+
103+
In KUnit tests, some error classes do not affect other tests
104+
or parts of the kernel, each KUnit case executes in a separate thread
105+
context. For code, see:
106+
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/kunit/try-catch.c?h=v5.15#n58
107+
108+
Assertion Macros
109+
----------------
110+
111+
KUnit tests verify state using expectations/assertions.
112+
All expectations/assertions are formatted as:
113+
``KUNIT_{EXPECT|ASSERT}_<op>[_MSG](kunit, property[, message])``
114+
115+
- ``{EXPECT|ASSERT}`` determines whether the check is an assertion or an
116+
expectation.
117+
118+
- For an expectation, if the check fails, marks the test as failed
119+
and logs the failure.
120+
121+
- An assertion, on failure, causes the test case to terminate
122+
immediately.
123+
124+
- Assertions call function:
125+
``void __noreturn kunit_abort(struct kunit *)``.
126+
127+
- ``kunit_abort`` calls function:
128+
``void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)``.
129+
130+
- ``kunit_try_catch_throw`` calls function:
131+
``void complete_and_exit(struct completion *, long) __noreturn;``
132+
and terminates the special thread context.
133+
134+
- ``<op>`` denotes a check with options: ``TRUE`` (supplied property
135+
has the boolean value “true”), ``EQ`` (two supplied properties are
136+
equal), ``NOT_ERR_OR_NULL`` (supplied pointer is not null and does not
137+
contain an “err” value).
138+
139+
- ``[_MSG]`` prints a custom message on failure.
140+
141+
Test Result Reporting
142+
---------------------
143+
KUnit prints test results in KTAP format. KTAP is based on TAP14, see:
144+
https://github.com/isaacs/testanything.github.io/blob/tap14/tap-version-14-specification.md.
145+
KTAP (yet to be standardized format) works with KUnit and Kselftest.
146+
The KUnit executor prints KTAP results to dmesg, and debugfs
147+
(if configured).
148+
149+
Parameterized Tests
150+
-------------------
151+
152+
Each KUnit parameterized test is associated with a collection of
153+
parameters. The test is invoked multiple times, once for each parameter
154+
value and the parameter is stored in the ``param_value`` field.
155+
The test case includes a ``KUNIT_CASE_PARAM()`` macro that accepts a
156+
generator function.
157+
The generator function is passed the previous parameter and returns the next
158+
parameter. It also provides a macro to generate common-case generators based on
159+
arrays.
160+
161+
For code, see:
162+
163+
.. kernel-doc:: include/kunit/test.h
164+
:identifiers: KUNIT_ARRAY_PARAM
165+
166+
167+
kunit_tool (Command Line Test Harness)
168+
======================================
169+
170+
kunit_tool is a Python script ``(tools/testing/kunit/kunit.py)``
171+
that can be used to configure, build, exec, parse and run (runs other
172+
commands in order) test results. You can either run KUnit tests using
173+
kunit_tool or can include KUnit in kernel and parse manually.
174+
175+
- ``configure`` command generates the kernel ``.config`` from a
176+
``.kunitconfig`` file (and any architecture-specific options).
177+
For some architectures, additional config options are specified in the
178+
``qemu_config`` Python script
179+
(For example: ``tools/testing/kunit/qemu_configs/powerpc.py``).
180+
It parses both the existing ``.config`` and the ``.kunitconfig`` files
181+
and ensures that ``.config`` is a superset of ``.kunitconfig``.
182+
If this is not the case, it will combine the two and run
183+
``make olddefconfig`` to regenerate the ``.config`` file. It then
184+
verifies that ``.config`` is now a superset. This checks if all
185+
Kconfig dependencies are correctly specified in ``.kunitconfig``.
186+
``kunit_config.py`` includes the parsing Kconfigs code. The code which
187+
runs ``make olddefconfig`` is a part of ``kunit_kernel.py``. You can
188+
invoke this command via: ``./tools/testing/kunit/kunit.py config`` and
189+
generate a ``.config`` file.
190+
- ``build`` runs ``make`` on the kernel tree with required options
191+
(depends on the architecture and some options, for example: build_dir)
192+
and reports any errors.
193+
To build a KUnit kernel from the current ``.config``, you can use the
194+
``build`` argument: ``./tools/testing/kunit/kunit.py build``.
195+
- ``exec`` command executes kernel results either directly (using
196+
User-mode Linux configuration), or via an emulator such
197+
as QEMU. It reads results from the log via standard
198+
output (stdout), and passes them to ``parse`` to be parsed.
199+
If you already have built a kernel with built-in KUnit tests,
200+
you can run the kernel and display the test results with the ``exec``
201+
argument: ``./tools/testing/kunit/kunit.py exec``.
202+
- ``parse`` extracts the KTAP output from a kernel log, parses
203+
the test results, and prints a summary. For failed tests, any
204+
diagnostic output will be included.

Documentation/dev-tools/kunit/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ KUnit - Linux Kernel Unit Testing
99
:caption: Contents:
1010

1111
start
12+
architecture
1213
usage
1314
kunit-tool
1415
api/index
@@ -96,6 +97,7 @@ How do I use it?
9697
================
9798

9899
* Documentation/dev-tools/kunit/start.rst - for KUnit new users.
100+
* Documentation/dev-tools/kunit/architecture.rst - KUnit architecture.
99101
* Documentation/dev-tools/kunit/usage.rst - KUnit features.
100102
* Documentation/dev-tools/kunit/tips.rst - best practices with
101103
examples.
Lines changed: 81 additions & 0 deletions
Loading

Documentation/dev-tools/kunit/start.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ Congrats! You just wrote your first KUnit test.
240240
Next Steps
241241
==========
242242

243+
* Documentation/dev-tools/kunit/architecture.rst - KUnit architecture.
243244
* Documentation/dev-tools/kunit/usage.rst - KUnit features.
244245
* Documentation/dev-tools/kunit/tips.rst - best practices with
245246
examples.

0 commit comments

Comments
 (0)