33
44======= 
55
6- There are the tests that come from the examples in the Rust documentation
7- and get transformed into KUnit tests. These can be run via KUnit. For example
8- via ``kunit_tool `` (``kunit.py ``) on the command line::
6+ This document contains useful information how to test the Rust code in the
7+ kernel.
8+ 
9+ There are two sorts of tests:
10+ 
11+ - The KUnit tests.
12+ - The ``#[test] `` tests.
13+ 
14+ The KUnit tests
15+ --------------- 
16+ 
17+ These are the tests that come from the examples in the Rust documentation. They
18+ get transformed into KUnit tests.
19+ 
20+ Usage
21+ ***** 
22+ 
23+ These tests can be run via KUnit. For example via ``kunit_tool `` (``kunit.py ``)
24+ on the command line::
925
1026	./tools/testing/kunit/kunit.py run --make_options LLVM=1 --arch x86_64 --kconfig_add CONFIG_RUST=y 
1127
@@ -14,11 +30,106 @@ Documentation/dev-tools/kunit/index.rst for the general KUnit documentation
1430and Documentation/dev-tools/kunit/architecture.rst for the details of kernel
1531built-in vs. command line testing.
1632
17- Additionally, there are the ``#[test] `` tests. These can be run using
18- the ``rusttest `` Make target::
33+ To use these KUnit doctests, the following must be enabled::
34+ 
35+ 	CONFIG_KUNIT 
36+ 	   Kernel hacking -> Kernel Testing and Coverage -> KUnit - Enable support for unit tests 
37+ 	CONFIG_RUST_KERNEL_DOCTESTS 
38+ 	   Kernel hacking -> Rust hacking -> Doctests for the `kernel` crate 
39+ 
40+ in the kernel config system.
41+ 
42+ KUnit tests are documentation tests
43+ *********************************** 
44+ 
45+ These documentation tests are typically examples of usage of any item (e.g.
46+ function, struct, module...).
47+ 
48+ They are very convenient because they are just written alongside the
49+ documentation. For instance:
50+ 
51+ .. code-block :: rust 
52+ 
53+ 	/// Sums two numbers. 
54+ 	/// 
55+ 	/// ``` 
56+ 	/// assert_eq!(mymod::f(10, 20), 30); 
57+ 	/// ``` 
58+ 	pub fn f(a: i32, b: i32) -> i32 { 
59+ 	    a + b 
60+ 	} 
61+ 
62+ rustdoc ``. Using the tool
63+ as-is would be useful already, since it allows verifying that examples compile
64+ (thus enforcing they are kept in sync with the code they document) and as well
65+ as running those that do not depend on in-kernel APIs.
66+ 
67+ For the kernel, however, these tests get transformed into KUnit test suites.
68+ This means that doctests get compiled as Rust kernel objects, allowing them to
69+ run against a built kernel.
70+ 
71+ A benefit of this KUnit integration is that Rust doctests get to reuse existing
72+ testing facilities. For instance, the kernel log would look like::
73+ 
74+ 	KTAP version 1 
75+ 	1..1 
76+ 	    KTAP version 1 
77+ 	    # Subtest: rust_doctests_kernel 
78+ 	    1..59 
79+ 	    # rust_doctest_kernel_build_assert_rs_0.location: rust/kernel/build_assert.rs:13 
80+ 	    ok 1 rust_doctest_kernel_build_assert_rs_0 
81+ 	    # rust_doctest_kernel_build_assert_rs_1.location: rust/kernel/build_assert.rs:56 
82+ 	    ok 2 rust_doctest_kernel_build_assert_rs_1 
83+ 	    # rust_doctest_kernel_init_rs_0.location: rust/kernel/init.rs:122 
84+ 	    ok 3 rust_doctest_kernel_init_rs_0 
85+ 	    ... 
86+ 	    # rust_doctest_kernel_types_rs_2.location: rust/kernel/types.rs:150 
87+ 	    ok 59 rust_doctest_kernel_types_rs_2 
88+ 	# rust_doctests_kernel: pass:59 fail:0 skip:0 total:59 
89+ 	# Totals: pass:59 fail:0 skip:0 total:59 
90+ 	ok 1 rust_doctests_kernel 
91+ 
92+ Tests using the `?  <https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator >`_
93+ operator are also supported as usual, e.g.:
94+ 
95+ .. code-block :: rust 
96+ 
97+ 	/// ``` 
98+ 	/// # use kernel::{spawn_work_item, workqueue}; 
99+ 	/// spawn_work_item!(workqueue::system(), || pr_info!("x"))?; 
100+ 	/// # Ok::<(), Error>(()) 
101+ 	/// ``` 
102+ 
103+ CLIPPY=1 ``, just like normal
104+ code, thus also benefitting from extra linting.
105+ 
106+ In order for developers to easily see which line of doctest code caused a
107+ failure, a KTAP diagnostic line is printed to the log. This contains the
108+ location (file and line) of the original test (i.e. instead of the location in
109+ the generated Rust file)::
110+ 
111+ 	# rust_doctest_kernel_types_rs_2.location: rust/kernel/types.rs:150 
112+ 
113+ Rust tests appear to assert using the usual ``assert! `` and ``assert_eq! ``
114+ macros from the Rust standard library (``core ``). We provide a custom version
115+ that forwards the call to KUnit instead. Importantly, these macros do not
116+ require passing context, unlike those for KUnit testing (i.e.
117+ ``struct kunit * ``). This makes them easier to use, and readers of the
118+ documentation do not need to care about which testing framework is used. In
119+ addition, it may allow us to test third-party code more easily in the future.
120+ 
121+ A current limitation is that KUnit does not support assertions in other tasks.
122+ Thus, we presently simply print an error to the kernel log if an assertion
123+ actually failed. Additionally, doctests are not run for nonpublic functions.
124+ 
125+ The ``#[test] `` tests
126+ --------------------- 
127+ 
128+ Additionally, there are the ``#[test] `` tests. These can be run using the
129+ ``rusttest `` Make target::
19130
20131	make LLVM=1 rusttest 
21132
22- This requires the kernel ``.config `` and downloads external repositories.
23- It  runs the ``#[test] `` tests on the host (currently) and thus is fairly
24- limited in  what these tests can test.
133+ This requires the kernel ``.config `` and downloads external repositories. It 
134+ runs the ``#[test] `` tests on the host (currently) and thus is fairly limited in 
135+ what these tests can test.
0 commit comments