Skip to content

Commit eebf4dd

Browse files
Tobin C. HardingShuah Khan
authored andcommitted
kselftest: Add test module framework header
kselftest runs as a userspace process. Sometimes we need to test things from kernel space. One way of doing this is by creating a test module. Currently doing so requires developers to write a bunch of boiler plate in the module if kselftest is to be used to run the tests. This means we currently have a load of duplicate code to achieve these ends. If we have a uniform method for implementing test modules then we can reduce code duplication, ensure uniformity in the test framework, ease code maintenance, and reduce the work required to create tests. This all helps to encourage developers to write and run tests. Add a C header file that can be included in test modules. This provides a single point for common test functions/macros. Implement a few macros that make up the start of the test framework. Add documentation for new kselftest header to kselftest documentation. Acked-by: Kees Cook <[email protected]> Signed-off-by: Tobin C. Harding <[email protected]> Signed-off-by: Shuah Khan <[email protected]>
1 parent d346052 commit eebf4dd

File tree

2 files changed

+140
-2
lines changed

2 files changed

+140
-2
lines changed

Documentation/dev-tools/kselftest.rst

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ in safe mode with a limited scope. In limited mode, cpu-hotplug test is
1414
run on a single cpu as opposed to all hotplug capable cpus, and memory
1515
hotplug test is run on 2% of hotplug capable memory instead of 10%.
1616

17+
kselftest runs as a userspace process. Tests that can be written/run in
18+
userspace may wish to use the `Test Harness`_. Tests that need to be
19+
run in kernel space may wish to use a `Test Module`_.
20+
1721
Running the selftests (hotplug tests are run in limited mode)
1822
=============================================================
1923

@@ -161,11 +165,97 @@ Contributing new tests (details)
161165

162166
e.g: tools/testing/selftests/android/config
163167

168+
Test Module
169+
===========
170+
171+
Kselftest tests the kernel from userspace. Sometimes things need
172+
testing from within the kernel, one method of doing this is to create a
173+
test module. We can tie the module into the kselftest framework by
174+
using a shell script test runner. ``kselftest_module.sh`` is designed
175+
to facilitate this process. There is also a header file provided to
176+
assist writing kernel modules that are for use with kselftest:
177+
178+
- ``tools/testing/kselftest/kselftest_module.h``
179+
- ``tools/testing/kselftest/kselftest_module.sh``
180+
181+
How to use
182+
----------
183+
184+
Here we show the typical steps to create a test module and tie it into
185+
kselftest. We use kselftests for lib/ as an example.
186+
187+
1. Create the test module
188+
189+
2. Create the test script that will run (load/unload) the module
190+
e.g. ``tools/testing/selftests/lib/printf.sh``
191+
192+
3. Add line to config file e.g. ``tools/testing/selftests/lib/config``
193+
194+
4. Add test script to makefile e.g. ``tools/testing/selftests/lib/Makefile``
195+
196+
5. Verify it works:
197+
198+
.. code-block:: sh
199+
200+
# Assumes you have booted a fresh build of this kernel tree
201+
cd /path/to/linux/tree
202+
make kselftest-merge
203+
make modules
204+
sudo make modules_install
205+
make TARGETS=lib kselftest
206+
207+
Example Module
208+
--------------
209+
210+
A bare bones test module might look like this:
211+
212+
.. code-block:: c
213+
214+
// SPDX-License-Identifier: GPL-2.0+
215+
216+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
217+
218+
#include "../tools/testing/selftests/kselftest_module.h"
219+
220+
KSTM_MODULE_GLOBALS();
221+
222+
/*
223+
* Kernel module for testing the foobinator
224+
*/
225+
226+
static int __init test_function()
227+
{
228+
...
229+
}
230+
231+
static void __init selftest(void)
232+
{
233+
KSTM_CHECK_ZERO(do_test_case("", 0));
234+
}
235+
236+
KSTM_MODULE_LOADERS(test_foo);
237+
MODULE_AUTHOR("John Developer <[email protected]>");
238+
MODULE_LICENSE("GPL");
239+
240+
Example test script
241+
-------------------
242+
243+
.. code-block:: sh
244+
245+
#!/bin/bash
246+
# SPDX-License-Identifier: GPL-2.0+
247+
$(dirname $0)/../kselftest_module.sh "foo" test_foo
248+
249+
164250
Test Harness
165251
============
166252

167-
The kselftest_harness.h file contains useful helpers to build tests. The tests
168-
from tools/testing/selftests/seccomp/seccomp_bpf.c can be used as example.
253+
The kselftest_harness.h file contains useful helpers to build tests. The
254+
test harness is for userspace testing, for kernel space testing see `Test
255+
Module`_ above.
256+
257+
The tests from tools/testing/selftests/seccomp/seccomp_bpf.c can be used as
258+
example.
169259

170260
Example
171261
-------
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/* SPDX-License-Identifier: GPL-2.0+ */
2+
#ifndef __KSELFTEST_MODULE_H
3+
#define __KSELFTEST_MODULE_H
4+
5+
#include <linux/module.h>
6+
7+
/*
8+
* Test framework for writing test modules to be loaded by kselftest.
9+
* See Documentation/dev-tools/kselftest.rst for an example test module.
10+
*/
11+
12+
#define KSTM_MODULE_GLOBALS() \
13+
static unsigned int total_tests __initdata; \
14+
static unsigned int failed_tests __initdata
15+
16+
#define KSTM_CHECK_ZERO(x) do { \
17+
total_tests++; \
18+
if (x) { \
19+
pr_warn("TC failed at %s:%d\n", __func__, __LINE__); \
20+
failed_tests++; \
21+
} \
22+
} while (0)
23+
24+
static inline int kstm_report(unsigned int total_tests, unsigned int failed_tests)
25+
{
26+
if (failed_tests == 0)
27+
pr_info("all %u tests passed\n", total_tests);
28+
else
29+
pr_warn("failed %u out of %u tests\n", failed_tests, total_tests);
30+
31+
return failed_tests ? -EINVAL : 0;
32+
}
33+
34+
#define KSTM_MODULE_LOADERS(__module) \
35+
static int __init __module##_init(void) \
36+
{ \
37+
pr_info("loaded.\n"); \
38+
selftest(); \
39+
return kstm_report(total_tests, failed_tests); \
40+
} \
41+
static void __exit __module##_exit(void) \
42+
{ \
43+
pr_info("unloaded.\n"); \
44+
} \
45+
module_init(__module##_init); \
46+
module_exit(__module##_exit)
47+
48+
#endif /* __KSELFTEST_MODULE_H */

0 commit comments

Comments
 (0)