243 lines
6.5 KiB
ReStructuredText
243 lines
6.5 KiB
ReStructuredText
|
.. 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 the KUnit Wrapper
|
||
|
====================================
|
||
|
Included with KUnit is a simple Python wrapper which runs tests under User Mode
|
||
|
Linux, and formats the test results.
|
||
|
|
||
|
The wrapper can be run with:
|
||
|
|
||
|
.. code-block:: bash
|
||
|
|
||
|
./tools/testing/kunit/kunit.py run
|
||
|
|
||
|
For more information on this wrapper (also called kunit_tool) check out the
|
||
|
Documentation/dev-tools/kunit/kunit-tool.rst page.
|
||
|
|
||
|
Creating a .kunitconfig
|
||
|
-----------------------
|
||
|
If you want to run a specific set of tests (rather than those listed in the
|
||
|
KUnit defconfig), you can provide Kconfig options in the ``.kunitconfig`` file.
|
||
|
This file essentially contains the regular Kernel config, with the specific
|
||
|
test targets as well. The ``.kunitconfig`` should also contain any other config
|
||
|
options required by the tests.
|
||
|
|
||
|
A good starting point for a ``.kunitconfig`` is the KUnit defconfig:
|
||
|
|
||
|
.. code-block:: bash
|
||
|
|
||
|
cd $PATH_TO_LINUX_REPO
|
||
|
cp tools/testing/kunit/configs/default.config .kunitconfig
|
||
|
|
||
|
You can then add any other Kconfig options you wish, e.g.:
|
||
|
|
||
|
.. code-block:: none
|
||
|
|
||
|
CONFIG_LIST_KUNIT_TEST=y
|
||
|
|
||
|
:doc:`kunit_tool <kunit-tool>` will ensure that all config options set in
|
||
|
``.kunitconfig`` are set in the kernel ``.config`` before running the tests.
|
||
|
It'll warn you if you haven't included the dependencies of the options you're
|
||
|
using.
|
||
|
|
||
|
.. note::
|
||
|
Note that removing something from the ``.kunitconfig`` will not trigger a
|
||
|
rebuild of the ``.config`` file: the configuration is only updated if the
|
||
|
``.kunitconfig`` is not a subset of ``.config``. This means that you can use
|
||
|
other tools (such as make menuconfig) to adjust other config options.
|
||
|
|
||
|
|
||
|
Running the tests (KUnit Wrapper)
|
||
|
---------------------------------
|
||
|
|
||
|
To make sure that everything is set up correctly, simply invoke the Python
|
||
|
wrapper from your kernel repo:
|
||
|
|
||
|
.. code-block:: bash
|
||
|
|
||
|
./tools/testing/kunit/kunit.py run
|
||
|
|
||
|
.. note::
|
||
|
You may want to run ``make mrproper`` first.
|
||
|
|
||
|
If everything worked correctly, you should see the following:
|
||
|
|
||
|
.. code-block:: bash
|
||
|
|
||
|
Generating .config ...
|
||
|
Building KUnit Kernel ...
|
||
|
Starting KUnit Kernel ...
|
||
|
|
||
|
followed by a list of tests that are run. All of them should be passing.
|
||
|
|
||
|
.. note::
|
||
|
Because it is building a lot of sources for the first time, the
|
||
|
``Building KUnit kernel`` step may take a while.
|
||
|
|
||
|
Running tests without the KUnit Wrapper
|
||
|
=======================================
|
||
|
|
||
|
If you'd rather not use the KUnit Wrapper (if, for example, you need to
|
||
|
integrate with other systems, or use an architecture other than UML), KUnit can
|
||
|
be included in any kernel, and the results read out and parsed manually.
|
||
|
|
||
|
.. note::
|
||
|
KUnit is not designed for use in a production system, and it's possible that
|
||
|
tests may reduce the stability or security of the system.
|
||
|
|
||
|
|
||
|
|
||
|
Configuring the kernel
|
||
|
----------------------
|
||
|
|
||
|
In order to enable KUnit itself, you simply need to enable the ``CONFIG_KUNIT``
|
||
|
Kconfig option (it's under Kernel Hacking/Kernel Testing and Coverage in
|
||
|
menuconfig). From there, you can enable any KUnit tests you want: they usually
|
||
|
have config options ending in ``_KUNIT_TEST``.
|
||
|
|
||
|
KUnit and KUnit tests can be compiled as modules: in this case the tests in a
|
||
|
module will be run when the module is loaded.
|
||
|
|
||
|
|
||
|
Running the tests (w/o KUnit Wrapper)
|
||
|
-------------------------------------
|
||
|
|
||
|
Build and run your kernel as usual. Test output will be written to the kernel
|
||
|
log in `TAP <https://testanything.org/>`_ format.
|
||
|
|
||
|
.. note::
|
||
|
It's possible that there will be other lines and/or data interspersed in the
|
||
|
TAP output.
|
||
|
|
||
|
|
||
|
Writing your first test
|
||
|
=======================
|
||
|
|
||
|
In your kernel repo let's add some code that we can test. Create a file
|
||
|
``drivers/misc/example.h`` with the contents:
|
||
|
|
||
|
.. code-block:: c
|
||
|
|
||
|
int misc_example_add(int left, int right);
|
||
|
|
||
|
create a file ``drivers/misc/example.c``:
|
||
|
|
||
|
.. code-block:: c
|
||
|
|
||
|
#include <linux/errno.h>
|
||
|
|
||
|
#include "example.h"
|
||
|
|
||
|
int misc_example_add(int left, int right)
|
||
|
{
|
||
|
return left + right;
|
||
|
}
|
||
|
|
||
|
Now add the following lines to ``drivers/misc/Kconfig``:
|
||
|
|
||
|
.. code-block:: kconfig
|
||
|
|
||
|
config MISC_EXAMPLE
|
||
|
bool "My example"
|
||
|
|
||
|
and the following lines to ``drivers/misc/Makefile``:
|
||
|
|
||
|
.. code-block:: make
|
||
|
|
||
|
obj-$(CONFIG_MISC_EXAMPLE) += example.o
|
||
|
|
||
|
Now we are ready to write the test. The test will be in
|
||
|
``drivers/misc/example-test.c``:
|
||
|
|
||
|
.. code-block:: c
|
||
|
|
||
|
#include <kunit/test.h>
|
||
|
#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);
|
||
|
|
||
|
Now add the following 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
|
||
|
|
||
|
and the following to ``drivers/misc/Makefile``:
|
||
|
|
||
|
.. code-block:: make
|
||
|
|
||
|
obj-$(CONFIG_MISC_EXAMPLE_TEST) += example-test.o
|
||
|
|
||
|
Now add it to your ``.kunitconfig``:
|
||
|
|
||
|
.. code-block:: none
|
||
|
|
||
|
CONFIG_MISC_EXAMPLE=y
|
||
|
CONFIG_MISC_EXAMPLE_TEST=y
|
||
|
|
||
|
Now you can 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
|
||
|
==========
|
||
|
* Check out the Documentation/dev-tools/kunit/tips.rst page for tips on
|
||
|
writing idiomatic KUnit tests.
|
||
|
* Check out the :doc:`running_tips` page for tips on
|
||
|
how to make running KUnit tests easier.
|
||
|
* Optional: see the :doc:`usage` page for a more
|
||
|
in-depth explanation of KUnit.
|