KUnit Architecture

The KUnit architecture is divided into two parts:

In-Kernel Testing Framework

The kernel testing library supports KUnit tests written in C usingKUnit. These KUnit tests are kernel code. KUnit performs the followingtasks:

  • Organizes tests

  • Reports test results

  • Provides test utilities

Test Cases

The test case is the fundamental unit in KUnit. KUnit test cases are organisedinto suites. A KUnit test case is a function with type signaturevoid(*)(structkunit*test). These test case functions are wrapped in astructcalledstructkunit_case.

Each KUnit test case receives astructkunit context object that tracks arunning test. The KUnit assertion macros and other KUnit utilities use thestructkunit context object. As an exception, there are two fields:

  • ->priv: The setup functions can use it to store arbitrary testuser data.

  • ->param_value: It contains the parameter value which can beretrieved in the parameterized tests.

Test Suites

A KUnit suite includes a collection of test cases. The KUnit suitesare represented by thestructkunit_suite. For example:

staticstructkunit_caseexample_test_cases[]={KUNIT_CASE(example_test_foo),KUNIT_CASE(example_test_bar),KUNIT_CASE(example_test_baz),{}};staticstructkunit_suiteexample_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 suiteexample_test_suite, runs thetest casesexample_test_foo,example_test_bar, andexample_test_baz. Before running the test, theexample_test_initis called and after running the test,example_test_exit is called.Thekunit_test_suite(example_test_suite) registers the test suitewith 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 sectioncalled.kunit_test_suites. For the code, seeKUNIT_TABLE() macrodefinition ininclude/asm-generic/vmlinux.lds.h.The linker section consists of an array of pointers tostructkunit_suite, and is populated by thekunit_test_suites()macro. The KUnit executor iterates over the linker section array in order torun all the tests that are compiled into the kernel.

KUnit Suite Memory

KUnit Suite Memory Diagram

On the kernel boot, the KUnit executor uses the start and end addressesof this section to iterate over and run all tests. For the implementation of theexecutor, seelib/kunit/executor.c.When built as a module, thekunit_test_suites() macro defines amodule_init() function, which runs all the tests in the compilationunit instead of utilizing the executor.

In KUnit tests, some error classes do not affect other testsor parts of the kernel, each KUnit case executes in a separate threadcontext. See thekunit_try_catch_run() function inlib/kunit/try-catch.c.

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 anexpectation.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 beingterminated immediately.

      • Assertions call the function:void__noreturn__kunit_abort(structkunit*).

      • __kunit_abort calls the function:void__noreturnkunit_try_catch_throw(structkunit_try_catch*try_catch).

      • kunit_try_catch_throw calls the function:voidkthread_complete_and_exit(structcompletion*,long)__noreturn;and terminates the special thread context.

  • <op> denotes a check with options:TRUE (supplied propertyhas the boolean value “true”),EQ (two supplied properties areequal),NOT_ERR_OR_NULL (supplied pointer is not null and does notcontain 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, seeThe Kernel Test Anything Protocol (KTAP), version 1.KTAP works with KUnit and Kselftest. The KUnit executor prints KTAP results todmesg, and debugfs (if configured).

Parameterized Tests

Each KUnit parameterized test is associated with a collection ofparameters. The test is invoked multiple times, once for each parametervalue and the parameter is stored in theparam_value field.The test case includes aKUNIT_CASE_PARAM() macro that accepts agenerator function. The generator function is passed the previous parameterand returns the next parameter. It also includes a macro for generatingarray-based common-case generators.

kunit_tool (Command-line Test Harness)

kunit_tool is a Python script, found intools/testing/kunit/kunit.py. Itis used to configure, build, execute, parse test results and run all of theprevious commands in correct order (i.e., configure, build, execute and parse).You have two options for running KUnit tests: either build the kernel with KUnitenabled and manually parse the results (seeRun Tests without kunit_tool) or usekunit_tool(seeRunning tests with kunit_tool).

  • configure command generates the kernel.config from a.kunitconfig file (and any architecture-specific options).The Python scripts available inqemu_configs folder(for example,tools/testing/kunit/qemuconfigs/powerpc.py) containsadditional configuration options for specific architectures.It parses both the existing.config and the.kunitconfig filesto ensure that.config is a superset of.kunitconfig.If not, it will combine the two and runmakeolddefconfig to regeneratethe.config file. It then checks to see if.config has become a superset.This verifies that all the Kconfig dependencies are correctly specified in thefile.kunitconfig. Thekunit_config.py script contains the code for parsingKconfigs. The code which runsmakeolddefconfig is part of thekunit_kernel.py script. You can invoke this command through:./tools/testing/kunit/kunit.pyconfig andgenerate a.config file.

  • build runsmake 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 thebuild argument:./tools/testing/kunit/kunit.pybuild.

  • exec command executes kernel results either directly (usingUser-mode Linux configuration), or through an emulator suchas QEMU. It reads results from the log using standardoutput (stdout), and passes them toparse 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 theexecargument:./tools/testing/kunit/kunit.pyexec.

  • parse extracts the KTAP output from a kernel log, parsesthe test results, and prints a summary. For failed tests, anydiagnostic output will be included.