Testing The Rust Code In Linux Kernel
[rust
kernel
linux
software-development
]
In the Rust project under the Linux kernel, you can find three types of tests: KUnit tests, #[test] tests, and Kselftests, that have similar purposes but different scopes.
To know how to configure Rust in the Linux Kernel, check out this post.
KUnit tests
KUnit tests are documentation tests and typically examples of usage of any item, such as functions, structs, modules and so on. The examples in the Rust documentation are transformed into KUnit tests. These tests can be run via KUnit. For example via kunit_tool (kunit.py) on the command line:
$ ./tools/testing/kunit/kunit.py run --make_options LLVM=1 --arch x86_64 --kconfig_add CONFIG_RUST=y
[20:24:40] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=x86_64 O=.kunit olddefconfig LLVM=1
[20:24:46] Building KUnit Kernel ...
Populating config with:
$ make ARCH=x86_64 O=.kunit olddefconfig LLVM=1
Building with:
$ make all compile_commands.json ARCH=x86_64 O=.kunit --jobs=8 LLVM=1
[20:24:40] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=x86_64 O=.kunit olddefconfig LLVM=1
[20:24:46] Building KUnit Kernel ...
Populating config with:
$ make ARCH=x86_64 O=.kunit olddefconfig LLVM=1
Building with:
$ make all compile_commands.json ARCH=x86_64 O=.kunit --jobs=8 LLVM=1
vmlinux.o: warning: objtool: .text+0x10: unreachable instruction
vmlinux.o: warning: objtool: .text+0x14: unreachable instruction
vmlinux.o: warning: objtool: .text+0x1b: unreachable instruction
vmlinux.o: warning: objtool: .text+0x22: unreachable instruction
vmlinux.o: warning: objtool: .text+0x27: unreachable instruction
vmlinux.o: warning: objtool: .text+0x2e: unreachable instruction
[20:28:58] Starting KUnit Kernel (1/1)...
[20:28:58] ============================================================
Running tests with:
$ qemu-system-x86_64 -nodefaults -m 1024 -kernel .kunit/arch/x86/boot/bzImage -append 'kunit.enable=1 console=ttyS0 kunit_shutdown=reboot' -no-reboot -nographic -serial stdio
...
[20:29:14] ================= [PASSED] property-entry ==================
[20:29:14] ================= input_core (4 subtests) ==================
[20:29:14] [PASSED] input_test_polling
[20:29:14] [PASSED] input_test_timestamp
[20:29:14] [PASSED] input_test_match_device_id
[20:29:14] [PASSED] input_test_grab
[20:29:14] =================== [PASSED] input_core ====================
[20:29:14] ============================================================
[20:29:14] Testing complete. Ran 509 tests: passed: 464, skipped: 45
[20:29:14] Elapsed time: 273.790s total, 6.025s configuring, 252.367s building, 15.389s running
[test] tests
#[test] test can be run using the rusttest Make target:
make LLVM=1 rusttest
It requires the presence of the kernel .config file. It runs the #[test] tests on the host and is fairly limited in what these tests can test.
Here an exmaple of how to run and the expected output:
$ make LLVM=1 rusttest
...
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
RUSTDOC T rust/macros/lib.rs
running 13 tests
i............
test result: ok. 12 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.82s
RUSTC T rust/kernel/lib.rs
running 8 tests
........
test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
The Kselftests
Kselftests are small tests used in the Linux kernel to exercise individual code paths in the kernel. Those tests are also available for the Rust Linux Kernel fork in the tools/testing/selftests/rust folder and are intended to be run after building, installing and booting a kernel.
The kernel config options required for the tests are listed in the tools/testing/selftests/rust/config file, which contains the basic Rust configuration options and can be included with the merge_config.sh script:
./scripts/kconfig/merge_config.sh .config tools/testing/selftests/rust/config
Once a kernel matching the source tree has been installed and booted, the tests can be compiled and executed using the following command:
$ make TARGETS="rust" kselftest
Refer to Linux Kernel Selftests for the Kselftest documentation.
Troubleshooting
KUnit tests — Source tree not clean
$ ./tools/testing/kunit/kunit.py run --make_options LLVM=1 --arch x86_64 --kconfig_add CONFIG_RUST=y
[20:20:03] Configuring KUnit Kernel ...
Generating .config ...
Populating config with:
$ make ARCH=x86_64 O=.kunit olddefconfig LLVM=1
ERROR:root:make[1]: Entering directory '/home/alessandro/linux_work/rust/linux/.kunit'
***
*** The source tree is not clean, please run 'make ARCH=x86_64 mrproper'
*** in /home/alessandro/linux_work/rust/linux
***
make[2]: *** [/home/alessandro/linux_work/rust/linux/Makefile:638: outputmakefile] Error 1
make[1]: *** [/home/alessandro/linux_work/rust/linux/Makefile:224: __sub-make] Error 2
make[1]: Leaving directory '/home/alessandro/linux_work/rust/linux/.kunit'
make: *** [Makefile:224: __sub-make] Error 2
You need to clean your project tree, so run the command
$ make ARCH=x86_64 mrproper
Kselftests tests — rust_minimal not found
$ make TARGETS="rust" kselftest
make[3]: Entering directory '/home/alessandro/linux_work/rust/linux/tools/testing/selftests/rust'
make[3]: Nothing to be done for 'all'.
make[3]: Leaving directory '/home/alessandro/linux_work/rust/linux/tools/testing/selftests/rust'
make[3]: Entering directory '/home/alessandro/linux_work/rust/linux/tools/testing/selftests/rust'
TAP version 13
1..1
# timeout set to 45
# selftests: rust: test_probe_samples.sh
# TAP version 13
# 1..0 # SKIP module rust_minimal is not found in /lib/modules/6.8.0-49-generic
ok 1 selftests: rust: test_probe_samples.sh # SKIP
make[3]: Leaving directory '/home/alessandro/linux_work/rust/linux/tools/testing/selftests/rust'
This error is raised by the tools/testing/selftests/rust/test_probe_sample.sh file which doesn’t find the basic sample available by default.
You need to enable the rust samples, e.g. rust_minimal, from the make make menuconfig menu under the options below