| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- .. SPDX-License-Identifier: GPL-2.0
- ==================
- KUnit Architecture
- ==================
- The KUnit architecture is divided into two parts:
- - `In-Kernel Testing Framework`_
- - `kunit_tool (Command-line Test Harness)`_
- In-Kernel Testing Framework
- ===========================
- The kernel testing library supports KUnit tests written in C using
- KUnit. These KUnit tests are kernel code. KUnit performs the following
- tasks:
- - Organizes tests
- - Reports test results
- - Provides test utilities
- Test Cases
- ----------
- The test case is the fundamental unit in KUnit. KUnit test cases are organised
- into suites. A KUnit test case is a function with type signature
- ``void (*)(struct kunit *test)``. These test case functions are wrapped in a
- struct called struct kunit_case.
- .. note:
- ``generate_params`` is optional for non-parameterized tests.
- Each KUnit test case receives a ``struct kunit`` context object that tracks a
- running test. The KUnit assertion macros and other KUnit utilities use the
- ``struct kunit`` context object. As an exception, there are two fields:
- - ``->priv``: The setup functions can use it to store arbitrary test
- user data.
- - ``->param_value``: It contains the parameter value which can be
- retrieved in the parameterized tests.
- Test Suites
- -----------
- A KUnit suite includes a collection of test cases. The KUnit suites
- are represented by the ``struct kunit_suite``. For example:
- .. code-block:: c
- static struct kunit_case example_test_cases[] = {
- KUNIT_CASE(example_test_foo),
- KUNIT_CASE(example_test_bar),
- KUNIT_CASE(example_test_baz),
- {}
- };
- static struct kunit_suite example_test_suite = {
- .name = "example",
- .init = example_test_init,
- .exit = example_test_exit,
- .test_cases = example_test_cases,
- };
- kunit_test_suite(example_test_suite);
- In the above example, the test suite ``example_test_suite``, runs the
- test cases ``example_test_foo``, ``example_test_bar``, and
- ``example_test_baz``. Before running the test, the ``example_test_init``
- is called and after running the test, ``example_test_exit`` is called.
- The ``kunit_test_suite(example_test_suite)`` registers the test suite
- with the KUnit test framework.
- Executor
- --------
- The KUnit executor can list and run built-in KUnit tests on boot.
- The Test suites are stored in a linker section
- called ``.kunit_test_suites``. For the code, see ``KUNIT_TABLE()`` macro
- definition in
- `include/asm-generic/vmlinux.lds.h <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/asm-generic/vmlinux.lds.h?h=v6.0#n950>`_.
- The linker section consists of an array of pointers to
- ``struct kunit_suite``, and is populated by the ``kunit_test_suites()``
- macro. The KUnit executor iterates over the linker section array in order to
- run all the tests that are compiled into the kernel.
- .. kernel-figure:: kunit_suitememorydiagram.svg
- :alt: KUnit Suite Memory
- KUnit Suite Memory Diagram
- On the kernel boot, the KUnit executor uses the start and end addresses
- of this section to iterate over and run all tests. For the implementation of the
- executor, see
- `lib/kunit/executor.c <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/kunit/executor.c>`_.
- When built as a module, the ``kunit_test_suites()`` macro defines a
- ``module_init()`` function, which runs all the tests in the compilation
- unit instead of utilizing the executor.
- In KUnit tests, some error classes do not affect other tests
- or parts of the kernel, each KUnit case executes in a separate thread
- context. See the ``kunit_try_catch_run()`` function in
- `lib/kunit/try-catch.c <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/kunit/try-catch.c?h=v5.15#n58>`_.
- Assertion Macros
- ----------------
- KUnit tests verify state using expectations/assertions.
- All expectations/assertions are formatted as:
- ``KUNIT_{EXPECT|ASSERT}_<op>[_MSG](kunit, property[, message])``
- - ``{EXPECT|ASSERT}`` determines whether the check is an assertion or an
- expectation.
- In the event of a failure, the testing flow differs as follows:
- - For expectations, the test is marked as failed and the failure is logged.
- - Failing assertions, on the other hand, result in the test case being
- terminated immediately.
- - Assertions call the function:
- ``void __noreturn __kunit_abort(struct kunit *)``.
- - ``__kunit_abort`` calls the function:
- ``void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)``.
- - ``kunit_try_catch_throw`` calls the function:
- ``void kthread_complete_and_exit(struct completion *, long) __noreturn;``
- and terminates the special thread context.
- - ``<op>`` denotes a check with options: ``TRUE`` (supplied property
- has the boolean value "true"), ``EQ`` (two supplied properties are
- equal), ``NOT_ERR_OR_NULL`` (supplied pointer is not null and does not
- contain an "err" value).
- - ``[_MSG]`` prints a custom message on failure.
- Test Result Reporting
- ---------------------
- KUnit prints the test results in KTAP format. KTAP is based on TAP14, see
- Documentation/dev-tools/ktap.rst.
- KTAP works with KUnit and Kselftest. The KUnit executor prints KTAP results to
- dmesg, and debugfs (if configured).
- Parameterized Tests
- -------------------
- Each KUnit parameterized test is associated with a collection of
- parameters. The test is invoked multiple times, once for each parameter
- value and the parameter is stored in the ``param_value`` field.
- The test case includes a KUNIT_CASE_PARAM() macro that accepts a
- generator function. The generator function is passed the previous parameter
- and returns the next parameter. It also includes a macro for generating
- array-based common-case generators.
- kunit_tool (Command-line Test Harness)
- ======================================
- ``kunit_tool`` is a Python script, found in ``tools/testing/kunit/kunit.py``. It
- is used to configure, build, execute, parse test results and run all of the
- previous commands in correct order (i.e., configure, build, execute and parse).
- You have two options for running KUnit tests: either build the kernel with KUnit
- enabled and manually parse the results (see
- Documentation/dev-tools/kunit/run_manual.rst) or use ``kunit_tool``
- (see Documentation/dev-tools/kunit/run_wrapper.rst).
- - ``configure`` command generates the kernel ``.config`` from a
- ``.kunitconfig`` file (and any architecture-specific options).
- The Python scripts available in ``qemu_configs`` folder
- (for example, ``tools/testing/kunit/qemu configs/powerpc.py``) contains
- additional configuration options for specific architectures.
- It parses both the existing ``.config`` and the ``.kunitconfig`` files
- to ensure that ``.config`` is a superset of ``.kunitconfig``.
- If not, it will combine the two and run ``make olddefconfig`` to regenerate
- the ``.config`` file. It then checks to see if ``.config`` has become a superset.
- This verifies that all the Kconfig dependencies are correctly specified in the
- file ``.kunitconfig``. The ``kunit_config.py`` script contains the code for parsing
- Kconfigs. The code which runs ``make olddefconfig`` is part of the
- ``kunit_kernel.py`` script. You can invoke this command through:
- ``./tools/testing/kunit/kunit.py config`` and
- generate a ``.config`` file.
- - ``build`` runs ``make`` on the kernel tree with required options
- (depends on the architecture and some options, for example: build_dir)
- and reports any errors.
- To build a KUnit kernel from the current ``.config``, you can use the
- ``build`` argument: ``./tools/testing/kunit/kunit.py build``.
- - ``exec`` command executes kernel results either directly (using
- User-mode Linux configuration), or through an emulator such
- as QEMU. It reads results from the log using standard
- output (stdout), and passes them to ``parse`` to be parsed.
- If you already have built a kernel with built-in KUnit tests,
- you can run the kernel and display the test results with the ``exec``
- argument: ``./tools/testing/kunit/kunit.py exec``.
- - ``parse`` extracts the KTAP output from a kernel log, parses
- the test results, and prints a summary. For failed tests, any
- diagnostic output will be included.
|