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