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