.. SPDX-License-Identifier: GPL-2.0 =============== Getting Started =============== Installing Dependencies ======================= KUnit has the same dependencies as the Linux kernel. As long as you can build the kernel, you can run KUnit. Running tests with kunit_tool ============================= kunit_tool is a Python script, which configures and builds a kernel, runs tests, and formats the test results. From the kernel repository, you can run kunit_tool: .. code-block:: bash ./tools/testing/kunit/kunit.py run For more information on this wrapper, see: Documentation/dev-tools/kunit/run_wrapper.rst. Creating a ``.kunitconfig`` --------------------------- By default, kunit_tool runs a selection of tests. However, you can specify which unit tests to run by creating a ``.kunitconfig`` file with kernel config options that enable only a specific set of tests and their dependencies. The ``.kunitconfig`` file contains a list of kconfig options which are required to run the desired targets. The ``.kunitconfig`` also contains any other test specific config options, such as test dependencies. For example: the ``FAT_FS`` tests - ``FAT_KUNIT_TEST``, depends on ``FAT_FS``. ``FAT_FS`` can be enabled by selecting either ``MSDOS_FS`` or ``VFAT_FS``. To run ``FAT_KUNIT_TEST``, the ``.kunitconfig`` has: .. code-block:: none CONFIG_KUNIT=y CONFIG_MSDOS_FS=y CONFIG_FAT_KUNIT_TEST=y 1. A good starting point for the ``.kunitconfig`` is the KUnit default config. You can generate it by running: .. code-block:: bash cd $PATH_TO_LINUX_REPO tools/testing/kunit/kunit.py config cat .kunit/.kunitconfig .. note :: ``.kunitconfig`` lives in the ``--build_dir`` used by kunit.py, which is ``.kunit`` by default. .. note :: You may want to remove CONFIG_KUNIT_ALL_TESTS from the ``.kunitconfig`` as it will enable a number of additional tests that you may not want. 2. You can then add any other Kconfig options, for example: .. code-block:: none CONFIG_LIST_KUNIT_TEST=y Before running the tests, kunit_tool ensures that all config options set in ``.kunitconfig`` are set in the kernel ``.config``. It will warn you if you have not included dependencies for the options used. .. note :: If you change the ``.kunitconfig``, kunit.py will trigger a rebuild of the ``.config`` file. But you can edit the ``.config`` file directly or with tools like ``make menuconfig O=.kunit``. As long as its a superset of ``.kunitconfig``, kunit.py won't overwrite your changes. Running Tests (KUnit Wrapper) ----------------------------- 1. To make sure that everything is set up correctly, invoke the Python wrapper from your kernel repository: .. code-block:: bash ./tools/testing/kunit/kunit.py run If everything worked correctly, you should see the following: .. code-block:: Generating .config ... Building KUnit Kernel ... Starting KUnit Kernel ... The tests will pass or fail. .. note :: Because it is building a lot of sources for the first time, the ``Building KUnit kernel`` may take a while. Running Tests without the KUnit Wrapper ======================================= If you do not want to use the KUnit Wrapper (for example: you want code under test to integrate with other systems, or use a different/ unsupported architecture or configuration), KUnit can be included in any kernel, and the results are read out and parsed manually. .. note :: ``CONFIG_KUNIT`` should not be enabled in a production environment. Enabling KUnit disables Kernel Address-Space Layout Randomization (KASLR), and tests may affect the state of the kernel in ways not suitable for production. Configuring the Kernel ---------------------- To enable KUnit itself, you need to enable the ``CONFIG_KUNIT`` Kconfig option (under Kernel Hacking/Kernel Testing and Coverage in ``menuconfig``). From there, you can enable any KUnit tests. They usually have config options ending in ``_KUNIT_TEST``. KUnit and KUnit tests can be compiled as modules. The tests in a module will run when the module is loaded. Running Tests (without KUnit Wrapper) ------------------------------------- Build and run your kernel. In the kernel log, the test output is printed out in the TAP format. This will only happen by default if KUnit/tests are built-in. Otherwise the module will need to be loaded. .. note :: Some lines and/or data may get interspersed in the TAP output. Writing Your First Test ======================= In your kernel repository, let's add some code that we can test. 1. Create a file ``drivers/misc/example.h``, which includes: .. code-block:: c int misc_example_add(int left, int right); 2. Create a file ``drivers/misc/example.c``, which includes: .. code-block:: c #include #include "example.h" int misc_example_add(int left, int right) { return left + right; } 3. Add the following lines to ``drivers/misc/Kconfig``: .. code-block:: kconfig config MISC_EXAMPLE bool "My example" 4. Add the following lines to ``drivers/misc/Makefile``: .. code-block:: make obj-$(CONFIG_MISC_EXAMPLE) += example.o Now we are ready to write the test cases. 1. Add the below test case in ``drivers/misc/example_test.c``: .. code-block:: c #include #include "example.h" /* Define the test cases. */ static void misc_example_add_test_basic(struct kunit *test) { KUNIT_EXPECT_EQ(test, 1, misc_example_add(1, 0)); KUNIT_EXPECT_EQ(test, 2, misc_example_add(1, 1)); KUNIT_EXPECT_EQ(test, 0, misc_example_add(-1, 1)); KUNIT_EXPECT_EQ(test, INT_MAX, misc_example_add(0, INT_MAX)); KUNIT_EXPECT_EQ(test, -1, misc_example_add(INT_MAX, INT_MIN)); } static void misc_example_test_failure(struct kunit *test) { KUNIT_FAIL(test, "This test never passes."); } static struct kunit_case misc_example_test_cases[] = { KUNIT_CASE(misc_example_add_test_basic), KUNIT_CASE(misc_example_test_failure), {} }; static struct kunit_suite misc_example_test_suite = { .name = "misc-example", .test_cases = misc_example_test_cases, }; kunit_test_suite(misc_example_test_suite); 2. Add the following lines to ``drivers/misc/Kconfig``: .. code-block:: kconfig config MISC_EXAMPLE_TEST tristate "Test for my example" if !KUNIT_ALL_TESTS depends on MISC_EXAMPLE && KUNIT=y default KUNIT_ALL_TESTS 3. Add the following lines to ``drivers/misc/Makefile``: .. code-block:: make obj-$(CONFIG_MISC_EXAMPLE_TEST) += example_test.o 4. Add the following lines to ``.kunitconfig``: .. code-block:: none CONFIG_MISC_EXAMPLE=y CONFIG_MISC_EXAMPLE_TEST=y 5. Run the test: .. code-block:: bash ./tools/testing/kunit/kunit.py run You should see the following failure: .. code-block:: none ... [16:08:57] [PASSED] misc-example:misc_example_add_test_basic [16:08:57] [FAILED] misc-example:misc_example_test_failure [16:08:57] EXPECTATION FAILED at drivers/misc/example-test.c:17 [16:08:57] This test never passes. ... Congrats! You just wrote your first KUnit test. Next Steps ========== * Documentation/dev-tools/kunit/architecture.rst - KUnit architecture. * Documentation/dev-tools/kunit/run_wrapper.rst - run kunit_tool. * Documentation/dev-tools/kunit/run_manual.rst - run tests without kunit_tool. * Documentation/dev-tools/kunit/usage.rst - write tests. * Documentation/dev-tools/kunit/tips.rst - best practices with examples. * Documentation/dev-tools/kunit/api/index.rst - KUnit APIs used for testing. * Documentation/dev-tools/kunit/kunit-tool.rst - kunit_tool helper script. * Documentation/dev-tools/kunit/faq.rst - KUnit common questions and answers.