1.. SPDX-License-Identifier: GPL-2.0
2
3===============
4Getting Started
5===============
6
7Installing dependencies
8=======================
9KUnit has the same dependencies as the Linux kernel. As long as you can build
10the kernel, you can run KUnit.
11
12Running tests with the KUnit Wrapper
13====================================
14Included with KUnit is a simple Python wrapper which runs tests under User Mode
15Linux, and formats the test results.
16
17The wrapper can be run with:
18
19.. code-block:: bash
20
21	./tools/testing/kunit/kunit.py run
22
23For more information on this wrapper (also called kunit_tool) check out the
24Documentation/dev-tools/kunit/kunit-tool.rst page.
25
26Creating a .kunitconfig
27-----------------------
28If you want to run a specific set of tests (rather than those listed in the
29KUnit defconfig), you can provide Kconfig options in the ``.kunitconfig`` file.
30This file essentially contains the regular Kernel config, with the specific
31test targets as well. The ``.kunitconfig`` should also contain any other config
32options required by the tests.
33
34A good starting point for a ``.kunitconfig`` is the KUnit defconfig:
35
36.. code-block:: bash
37
38	cd $PATH_TO_LINUX_REPO
39	cp tools/testing/kunit/configs/default.config .kunitconfig
40
41You can then add any other Kconfig options you wish, e.g.:
42
43.. code-block:: none
44
45	CONFIG_LIST_KUNIT_TEST=y
46
47:doc:`kunit_tool <kunit-tool>` will ensure that all config options set in
48``.kunitconfig`` are set in the kernel ``.config`` before running the tests.
49It'll warn you if you haven't included the dependencies of the options you're
50using.
51
52.. note::
53   Note that removing something from the ``.kunitconfig`` will not trigger a
54   rebuild of the ``.config`` file: the configuration is only updated if the
55   ``.kunitconfig`` is not a subset of ``.config``. This means that you can use
56   other tools (such as make menuconfig) to adjust other config options.
57
58
59Running the tests (KUnit Wrapper)
60---------------------------------
61
62To make sure that everything is set up correctly, simply invoke the Python
63wrapper from your kernel repo:
64
65.. code-block:: bash
66
67	./tools/testing/kunit/kunit.py run
68
69.. note::
70   You may want to run ``make mrproper`` first.
71
72If everything worked correctly, you should see the following:
73
74.. code-block:: bash
75
76	Generating .config ...
77	Building KUnit Kernel ...
78	Starting KUnit Kernel ...
79
80followed by a list of tests that are run. All of them should be passing.
81
82.. note::
83	Because it is building a lot of sources for the first time, the
84	``Building KUnit kernel`` step may take a while.
85
86Running tests without the KUnit Wrapper
87=======================================
88
89If you'd rather not use the KUnit Wrapper (if, for example, you need to
90integrate with other systems, or use an architecture other than UML), KUnit can
91be included in any kernel, and the results read out and parsed manually.
92
93.. note::
94   KUnit is not designed for use in a production system, and it's possible that
95   tests may reduce the stability or security of the system.
96
97
98
99Configuring the kernel
100----------------------
101
102In order to enable KUnit itself, you simply need to enable the ``CONFIG_KUNIT``
103Kconfig option (it's under Kernel Hacking/Kernel Testing and Coverage in
104menuconfig). From there, you can enable any KUnit tests you want: they usually
105have config options ending in ``_KUNIT_TEST``.
106
107KUnit and KUnit tests can be compiled as modules: in this case the tests in a
108module will be run when the module is loaded.
109
110
111Running the tests (w/o KUnit Wrapper)
112-------------------------------------
113
114Build and run your kernel as usual. Test output will be written to the kernel
115log in `TAP <https://testanything.org/>`_ format.
116
117.. note::
118   It's possible that there will be other lines and/or data interspersed in the
119   TAP output.
120
121
122Writing your first test
123=======================
124
125In your kernel repo let's add some code that we can test. Create a file
126``drivers/misc/example.h`` with the contents:
127
128.. code-block:: c
129
130	int misc_example_add(int left, int right);
131
132create a file ``drivers/misc/example.c``:
133
134.. code-block:: c
135
136	#include <linux/errno.h>
137
138	#include "example.h"
139
140	int misc_example_add(int left, int right)
141	{
142		return left + right;
143	}
144
145Now add the following lines to ``drivers/misc/Kconfig``:
146
147.. code-block:: kconfig
148
149	config MISC_EXAMPLE
150		bool "My example"
151
152and the following lines to ``drivers/misc/Makefile``:
153
154.. code-block:: make
155
156	obj-$(CONFIG_MISC_EXAMPLE) += example.o
157
158Now we are ready to write the test. The test will be in
159``drivers/misc/example-test.c``:
160
161.. code-block:: c
162
163	#include <kunit/test.h>
164	#include "example.h"
165
166	/* Define the test cases. */
167
168	static void misc_example_add_test_basic(struct kunit *test)
169	{
170		KUNIT_EXPECT_EQ(test, 1, misc_example_add(1, 0));
171		KUNIT_EXPECT_EQ(test, 2, misc_example_add(1, 1));
172		KUNIT_EXPECT_EQ(test, 0, misc_example_add(-1, 1));
173		KUNIT_EXPECT_EQ(test, INT_MAX, misc_example_add(0, INT_MAX));
174		KUNIT_EXPECT_EQ(test, -1, misc_example_add(INT_MAX, INT_MIN));
175	}
176
177	static void misc_example_test_failure(struct kunit *test)
178	{
179		KUNIT_FAIL(test, "This test never passes.");
180	}
181
182	static struct kunit_case misc_example_test_cases[] = {
183		KUNIT_CASE(misc_example_add_test_basic),
184		KUNIT_CASE(misc_example_test_failure),
185		{}
186	};
187
188	static struct kunit_suite misc_example_test_suite = {
189		.name = "misc-example",
190		.test_cases = misc_example_test_cases,
191	};
192	kunit_test_suite(misc_example_test_suite);
193
194Now add the following to ``drivers/misc/Kconfig``:
195
196.. code-block:: kconfig
197
198	config MISC_EXAMPLE_TEST
199		tristate "Test for my example" if !KUNIT_ALL_TESTS
200		depends on MISC_EXAMPLE && KUNIT=y
201		default KUNIT_ALL_TESTS
202
203and the following to ``drivers/misc/Makefile``:
204
205.. code-block:: make
206
207	obj-$(CONFIG_MISC_EXAMPLE_TEST) += example-test.o
208
209Now add it to your ``.kunitconfig``:
210
211.. code-block:: none
212
213	CONFIG_MISC_EXAMPLE=y
214	CONFIG_MISC_EXAMPLE_TEST=y
215
216Now you can run the test:
217
218.. code-block:: bash
219
220	./tools/testing/kunit/kunit.py run
221
222You should see the following failure:
223
224.. code-block:: none
225
226	...
227	[16:08:57] [PASSED] misc-example:misc_example_add_test_basic
228	[16:08:57] [FAILED] misc-example:misc_example_test_failure
229	[16:08:57] EXPECTATION FAILED at drivers/misc/example-test.c:17
230	[16:08:57] 	This test never passes.
231	...
232
233Congrats! You just wrote your first KUnit test!
234
235Next Steps
236==========
237*   Check out the Documentation/dev-tools/kunit/tips.rst page for tips on
238    writing idiomatic KUnit tests.
239*   Check out the :doc:`running_tips` page for tips on
240    how to make running KUnit tests easier.
241*   Optional: see the :doc:`usage` page for a more
242    in-depth explanation of KUnit.
243