* [PATCH 00/12] kunit: Introduce UAPI testing framework
@ 2025-02-17 10:59 Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 01/12] kconfig: implement CONFIG_HEADERS_INSTALL for Usermode Linux Thomas Weißschuh
` (12 more replies)
0 siblings, 13 replies; 18+ messages in thread
From: Thomas Weißschuh @ 2025-02-17 10:59 UTC (permalink / raw)
To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Willy Tarreau, Thomas Weißschuh,
Brendan Higgins, David Gow, Rae Moar, Shuah Khan,
Jonathan Corbet
Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev,
linux-doc, Thomas Weißschuh
Currently testing of userspace and in-kernel API use two different
frameworks. kselftests for the userspace ones and Kunit for the
in-kernel ones. Besides their different scopes, both have different
strengths and limitations:
Kunit:
* Tests are normal kernel code.
* They use the regular kernel toolchain.
* They can be packaged and distributed as modules conveniently.
Kselftests:
* Tests are normal userspace code
* They need a userspace toolchain.
A kernel cross toolchain is likely not enough.
* A fair amout of userland is required to run the tests,
which means a full distro or handcrafted rootfs.
* There is no way to conveniently package and run kselftests with a
given kernel image.
* The kselftests makefiles are not as powerful as regular kbuild.
For example they are missing proper header dependency tracking or more
complex compiler option modifications.
Therefore kunit is much easier to run against different kernel
configurations and architectures.
This series aims to combine kselftests and kunit, avoiding both their
limitations. It works by compiling the userspace kselftests as part of
the regular kernel build, embedding them into the kunit kernel or module
and executing them from there. If the kernel toolchain is not fit to
produce userspace because of a missing libc, the kernel's own nolibc can
be used instead.
The structured TAP output from the kselftest is integrated into the
kunit KTAP output transparently, the kunit parser can parse the combined
logs together.
Further room for improvements:
* Call each test in its completely dedicated namespace
* Handle additional test files besides the test executable through
archives. CPIO, cramfs, etc.
* Compatibility with kselftest_harness.h (in progress)
* Expose the blobs in debugfs
* Provide some convience wrappers around compat userprogs
* Figure out a migration path/coexistence solution for
kunit UAPI and tools/testing/selftests/
Output from the kunit example testcase, note the output of
"example_uapi_tests".
$ ./tools/testing/kunit/kunit.py run --kunitconfig lib/kunit example
...
Running tests with:
$ .kunit/linux kunit.filter_glob=example kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[11:53:53] ================== example (10 subtests) ===================
[11:53:53] [PASSED] example_simple_test
[11:53:53] [SKIPPED] example_skip_test
[11:53:53] [SKIPPED] example_mark_skipped_test
[11:53:53] [PASSED] example_all_expect_macros_test
[11:53:53] [PASSED] example_static_stub_test
[11:53:53] [PASSED] example_static_stub_using_fn_ptr_test
[11:53:53] [PASSED] example_priv_test
[11:53:53] =================== example_params_test ===================
[11:53:53] [SKIPPED] example value 3
[11:53:53] [PASSED] example value 2
[11:53:53] [PASSED] example value 1
[11:53:53] [SKIPPED] example value 0
[11:53:53] =============== [PASSED] example_params_test ===============
[11:53:53] [PASSED] example_slow_test
[11:53:53] ======================= (4 subtests) =======================
[11:53:53] [PASSED] procfs
[11:53:53] [PASSED] userspace test 2
[11:53:53] [SKIPPED] userspace test 3: some reason
[11:53:53] [PASSED] userspace test 4
[11:53:53] ================ [PASSED] example_uapi_test ================
[11:53:53] ===================== [PASSED] example =====================
[11:53:53] ============================================================
[11:53:53] Testing complete. Ran 16 tests: passed: 11, skipped: 5
[11:53:53] Elapsed time: 67.543s total, 1.823s configuring, 65.655s building, 0.058s running
Based on v6.14-rc1 and the series
"tools/nolibc: compatibility with -Wmissing-prototypes" [0].
For compatibility with LLVM/clang another series is needed [1].
[0] https://lore.kernel.org/lkml/20250123-nolibc-prototype-v1-0-e1afc5c1999a@weissschuh.net/
[1] https://lore.kernel.org/lkml/20250213-kbuild-userprog-fixes-v1-0-f255fb477d98@linutronix.de/
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
Thomas Weißschuh (12):
kconfig: implement CONFIG_HEADERS_INSTALL for Usermode Linux
kconfig: introduce CONFIG_ARCH_HAS_NOLIBC
kbuild: userprogs: respect CONFIG_WERROR
kbuild: userprogs: add nolibc support
kbuild: introduce blob framework
kunit: tool: Add test for nested test result reporting
kunit: tool: Don't overwrite test status based on subtest counts
kunit: tool: Parse skipped tests from kselftest.h
kunit: Introduce UAPI testing framework
kunit: uapi: Add example for UAPI tests
kunit: uapi: Introduce preinit executable
kunit: uapi: Validate usability of /proc
Documentation/kbuild/makefiles.rst | 12 +
Makefile | 5 +-
include/kunit/uapi.h | 17 ++
include/linux/blob.h | 21 ++
init/Kconfig | 2 +
lib/Kconfig.debug | 1 -
lib/kunit/Kconfig | 9 +
lib/kunit/Makefile | 17 +-
lib/kunit/kunit-example-test.c | 17 ++
lib/kunit/kunit-uapi-example.c | 58 +++++
lib/kunit/uapi-preinit.c | 61 +++++
lib/kunit/uapi.c | 250 +++++++++++++++++++++
scripts/Makefile.blobs | 19 ++
scripts/Makefile.build | 6 +
scripts/Makefile.clean | 2 +-
scripts/Makefile.userprogs | 18 +-
scripts/blob-wrap.c | 27 +++
tools/include/nolibc/Kconfig.nolibc | 18 ++
tools/testing/kunit/kunit_parser.py | 13 +-
tools/testing/kunit/kunit_tool_test.py | 9 +
.../test_is_test_passed-failure-nested.log | 10 +
.../test_data/test_is_test_passed-kselftest.log | 3 +-
22 files changed, 584 insertions(+), 11 deletions(-)
---
base-commit: 20e952894066214a80793404c9578d72ef89c5e0
change-id: 20241015-kunit-kselftests-56273bc40442
Best regards,
--
Thomas Weißschuh <thomas.weissschuh@linutronix.de>
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 01/12] kconfig: implement CONFIG_HEADERS_INSTALL for Usermode Linux
2025-02-17 10:59 [PATCH 00/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
@ 2025-02-17 10:59 ` Thomas Weißschuh
2025-03-02 17:06 ` Masahiro Yamada
2025-03-04 19:23 ` Masahiro Yamada
2025-02-17 10:59 ` [PATCH 02/12] kconfig: introduce CONFIG_ARCH_HAS_NOLIBC Thomas Weißschuh
` (11 subsequent siblings)
12 siblings, 2 replies; 18+ messages in thread
From: Thomas Weißschuh @ 2025-02-17 10:59 UTC (permalink / raw)
To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Willy Tarreau, Thomas Weißschuh,
Brendan Higgins, David Gow, Rae Moar, Shuah Khan,
Jonathan Corbet
Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev,
linux-doc, Thomas Weißschuh
userprogs sometimes need access to UAPI headers.
This is currently not possible for Usermode Linux, as UM is only
a pseudo architecture built on top of a regular architecture and does
not have its own UAPI.
Instead use the UAPI headers from the underlying regular architecture.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
Makefile | 5 ++++-
lib/Kconfig.debug | 1 -
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index b4c208ae4041c1f4e32c2a158322422ce7353d06..275185d2ff5d3dc99bd7982abd1de85af0b9621a 100644
--- a/Makefile
+++ b/Makefile
@@ -1357,9 +1357,12 @@ hdr-inst := -f $(srctree)/scripts/Makefile.headersinst obj
PHONY += headers
headers: $(version_h) scripts_unifdef uapi-asm-generic archheaders archscripts
- $(if $(filter um, $(SRCARCH)), $(error Headers not exportable for UML))
+ifdef HEADER_ARCH
+ $(Q)$(MAKE) -f $(srctree)/Makefile HEADER_ARCH= SRCARCH=$(HEADER_ARCH) headers
+else
$(Q)$(MAKE) $(hdr-inst)=include/uapi
$(Q)$(MAKE) $(hdr-inst)=arch/$(SRCARCH)/include/uapi
+endif
ifdef CONFIG_HEADERS_INSTALL
prepare: headers
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 1af972a92d06f6e3f7beec4bd086c00b412c83ac..60026c8388db82c0055ccd8b8ac8789d6b939b62 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -473,7 +473,6 @@ config READABLE_ASM
config HEADERS_INSTALL
bool "Install uapi headers to usr/include"
- depends on !UML
help
This option will install uapi headers (headers exported to user-space)
into the usr/include directory for use during the kernel build.
--
2.48.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 02/12] kconfig: introduce CONFIG_ARCH_HAS_NOLIBC
2025-02-17 10:59 [PATCH 00/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 01/12] kconfig: implement CONFIG_HEADERS_INSTALL for Usermode Linux Thomas Weißschuh
@ 2025-02-17 10:59 ` Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 03/12] kbuild: userprogs: respect CONFIG_WERROR Thomas Weißschuh
` (10 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Thomas Weißschuh @ 2025-02-17 10:59 UTC (permalink / raw)
To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Willy Tarreau, Thomas Weißschuh,
Brendan Higgins, David Gow, Rae Moar, Shuah Khan,
Jonathan Corbet
Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev,
linux-doc, Thomas Weißschuh
Nolibc does not support all architectures.
Add a kconfig option, so users can know where it is available.
The new option is maintained inside tools/include/nolibc/ as only that
directory is responsible for nolibc's availability.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
init/Kconfig | 2 ++
tools/include/nolibc/Kconfig.nolibc | 18 ++++++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/init/Kconfig b/init/Kconfig
index d0d021b3fa3b3da5576421b4e1c63baf6c8afc09..794c9516d461ef7a3c5d399d982d3031199f0442 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -92,6 +92,8 @@ config CC_CAN_LINK_STATIC
default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(m64-flag) -static) if 64BIT
default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(m32-flag) -static)
+source "tools/include/nolibc/Kconfig.nolibc"
+
# Fixed in GCC 14, 13.3, 12.4 and 11.5
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113921
config GCC_ASM_GOTO_OUTPUT_BROKEN
diff --git a/tools/include/nolibc/Kconfig.nolibc b/tools/include/nolibc/Kconfig.nolibc
new file mode 100644
index 0000000000000000000000000000000000000000..a29825869d9b49a5502ae32d265b6f9c076f5713
--- /dev/null
+++ b/tools/include/nolibc/Kconfig.nolibc
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config ARCH_HAS_NOLIBC
+ def_bool n
+ help
+ Enabled if nolibc supports the current kernel architecture
+
+config ENABLE_ARCH_HAS_NOLIBC
+ def_bool y
+ select ARCH_HAS_NOLIBC if X86
+ select ARCH_HAS_NOLIBC if ARM
+ select ARCH_HAS_NOLIBC if ARM64
+ select ARCH_HAS_NOLIBC if PPC
+ select ARCH_HAS_NOLIBC if MIPS
+ select ARCH_HAS_NOLIBC if LOONGARCH
+ select ARCH_HAS_NOLIBC if RISCV
+ select ARCH_HAS_NOLIBC if S390
+ select ARCH_HAS_NOLIBC if UML && UML_X86
--
2.48.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 03/12] kbuild: userprogs: respect CONFIG_WERROR
2025-02-17 10:59 [PATCH 00/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 01/12] kconfig: implement CONFIG_HEADERS_INSTALL for Usermode Linux Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 02/12] kconfig: introduce CONFIG_ARCH_HAS_NOLIBC Thomas Weißschuh
@ 2025-02-17 10:59 ` Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 04/12] kbuild: userprogs: add nolibc support Thomas Weißschuh
` (9 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Thomas Weißschuh @ 2025-02-17 10:59 UTC (permalink / raw)
To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Willy Tarreau, Thomas Weißschuh,
Brendan Higgins, David Gow, Rae Moar, Shuah Khan,
Jonathan Corbet
Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev,
linux-doc, Thomas Weißschuh
Reuse the general CONFIG_WERROR to also apply to userprogs.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
scripts/Makefile.userprogs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/scripts/Makefile.userprogs b/scripts/Makefile.userprogs
index f3a7e1ef3753b54303718fae97f4b3c9d4eac07c..debbf083bcfa01c89c204a322a1b17e2bdbe95a1 100644
--- a/scripts/Makefile.userprogs
+++ b/scripts/Makefile.userprogs
@@ -21,6 +21,10 @@ user_ccflags = -Wp,-MMD,$(depfile) $(KBUILD_USERCFLAGS) $(userccflags) \
user_ldflags = $(KBUILD_USERLDFLAGS) $(userldflags) $($(target-stem)-userldflags)
user_ldlibs = $(userldlibs) $($(target-stem)-userldlibs)
+ifdef CONFIG_WERROR
+KBUILD_USERCFLAGS += -Werror
+endif
+
# Create an executable from a single .c file
quiet_cmd_user_cc_c = CC [U] $@
cmd_user_cc_c = $(CC) $(user_ccflags) $(user_ldflags) -o $@ $< \
--
2.48.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 04/12] kbuild: userprogs: add nolibc support
2025-02-17 10:59 [PATCH 00/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
` (2 preceding siblings ...)
2025-02-17 10:59 ` [PATCH 03/12] kbuild: userprogs: respect CONFIG_WERROR Thomas Weißschuh
@ 2025-02-17 10:59 ` Thomas Weißschuh
2025-02-22 9:44 ` Willy Tarreau
2025-02-17 10:59 ` [PATCH 05/12] kbuild: introduce blob framework Thomas Weißschuh
` (8 subsequent siblings)
12 siblings, 1 reply; 18+ messages in thread
From: Thomas Weißschuh @ 2025-02-17 10:59 UTC (permalink / raw)
To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Willy Tarreau, Thomas Weißschuh,
Brendan Higgins, David Gow, Rae Moar, Shuah Khan,
Jonathan Corbet
Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev,
linux-doc, Thomas Weißschuh
Userprogs are built with the regular kernel compiler $CC.
A kernel compiler does not necessarily contain a libc which is required
for a normal userspace application.
However the kernel tree does contain a minimal libc implementation
"nolibc" which can be used to build userspace applications.
Introduce support to build userprogs against nolibc instead of the
default C of the compiler, which may not exist.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
This could probably be moved out of the generic kbuild makefiles.
I think the ergonimics would suffer and this functionality could be
used by other users of userprogs.
---
Documentation/kbuild/makefiles.rst | 12 ++++++++++++
scripts/Makefile.userprogs | 14 +++++++++++---
2 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/Documentation/kbuild/makefiles.rst b/Documentation/kbuild/makefiles.rst
index d36519f194dc0d18b72a6f3ce7f3649f7c1b5637..cb859dc58b579def4995a5aa2efb45ab4ba3c93f 100644
--- a/Documentation/kbuild/makefiles.rst
+++ b/Documentation/kbuild/makefiles.rst
@@ -959,6 +959,18 @@ When linking bpfilter_umh, it will be passed the extra option -static.
From command line, :ref:`USERCFLAGS and USERLDFLAGS <userkbuildflags>` will also be used.
+Bulding userprogs against nolibc
+--------------------------------
+
+Not all kernel toolchains provide a libc.
+Simple userprogs can be built against a very simple libc call "nolibc" provided
+by the kernel source tree.
+
+Example::
+
+ # lib/kunit/Makefile
+ uapi-preinit-nolibc := $(CONFIG_ARCH_HAS_NOLIBC)
+
When userspace programs are actually built
------------------------------------------
diff --git a/scripts/Makefile.userprogs b/scripts/Makefile.userprogs
index debbf083bcfa01c89c204a322a1b17e2bdbe95a1..e94f3f2250f531dadbe00f5f5ee6f780bee22487 100644
--- a/scripts/Makefile.userprogs
+++ b/scripts/Makefile.userprogs
@@ -16,10 +16,18 @@ user-csingle := $(addprefix $(obj)/, $(user-csingle))
user-cmulti := $(addprefix $(obj)/, $(user-cmulti))
user-cobjs := $(addprefix $(obj)/, $(user-cobjs))
+user_nolibc_ccflags := -nostdlib -nostdinc -static -fno-ident -fno-asynchronous-unwind-tables \
+ -ffreestanding $(call cc-option,-mstack-protector-guard=global) \
+ -isystem $(objtree)/usr/include -include $(srctree)/tools/include/nolibc/nolibc.h -isystem $(srctree)/tools/include/nolibc/
+user_nolibc_ldflags := -nostdlib -nostdinc -static
+user_nolibc_ldlibs := $(call cc-option,-lgcc)
+
user_ccflags = -Wp,-MMD,$(depfile) $(KBUILD_USERCFLAGS) $(userccflags) \
- $($(target-stem)-userccflags)
-user_ldflags = $(KBUILD_USERLDFLAGS) $(userldflags) $($(target-stem)-userldflags)
-user_ldlibs = $(userldlibs) $($(target-stem)-userldlibs)
+ $($(target-stem)-userccflags) $(if $($(target-stem)-nolibc),$(user_nolibc_ccflags))
+user_ldflags = $(KBUILD_USERLDFLAGS) $(userldflags) $($(target-stem)-userldflags) \
+ $(if $($(target-stem)-nolibc),$(user_nolibc_ldflags))
+user_ldlibs = $(userldlibs) $($(target-stem)-userldlibs) \
+ $(if $($(target-stem)-nolibc),$(user_nolibc_ldlibs))
ifdef CONFIG_WERROR
KBUILD_USERCFLAGS += -Werror
--
2.48.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 05/12] kbuild: introduce blob framework
2025-02-17 10:59 [PATCH 00/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
` (3 preceding siblings ...)
2025-02-17 10:59 ` [PATCH 04/12] kbuild: userprogs: add nolibc support Thomas Weißschuh
@ 2025-02-17 10:59 ` Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 06/12] kunit: tool: Add test for nested test result reporting Thomas Weißschuh
` (7 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Thomas Weißschuh @ 2025-02-17 10:59 UTC (permalink / raw)
To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Willy Tarreau, Thomas Weißschuh,
Brendan Higgins, David Gow, Rae Moar, Shuah Khan,
Jonathan Corbet
Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev,
linux-doc, Thomas Weißschuh
Various subsystems embed non-code build artifacts into the kernel,
for example the initramfs, /proc/config.gz, vDSO image, etc.
Currently each user has their own implementation for that.
Add a common "blob" framework to provide this functionality.
It provides standard kbuild and C APIs to embed and later access non-code build
artifacts into the kernel image or modules.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
This is currently lacking a MAINTAINERS entry.
Due to its closeness to kbuild I would tend to add it there.
But I can also maintain it on its own.
---
include/linux/blob.h | 21 +++++++++++++++++++++
scripts/Makefile.blobs | 19 +++++++++++++++++++
scripts/Makefile.build | 6 ++++++
scripts/Makefile.clean | 2 +-
scripts/blob-wrap.c | 27 +++++++++++++++++++++++++++
5 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/include/linux/blob.h b/include/linux/blob.h
new file mode 100644
index 0000000000000000000000000000000000000000..5749c364f7e9c93eb32a6d8870621e3d6df0683c
--- /dev/null
+++ b/include/linux/blob.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_BLOB_H
+#define _LINUX_BLOB_H
+
+#include <linux/compiler_types.h>
+#include <linux/types.h>
+
+struct blob {
+ const char *const path;
+ const u8 *data;
+ const u8 __private *end;
+};
+
+#define DECLARE_BLOB(_symbol) extern const struct blob _symbol
+
+static inline size_t blob_size(const struct blob *blob)
+{
+ return ACCESS_PRIVATE(blob, end) - blob->data;
+}
+
+#endif /* _LINUX_BLOB_H */
diff --git a/scripts/Makefile.blobs b/scripts/Makefile.blobs
new file mode 100644
index 0000000000000000000000000000000000000000..fd20ebb41c1d6509750debf7896a08a143d28759
--- /dev/null
+++ b/scripts/Makefile.blobs
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Build linkable blobs
+#
+
+blobs := $(addprefix $(obj)/, $(blobs))
+
+blob-stem = $(subst -,_,$(subst .blob,,$(basename $(patsubst $(obj)/%,%,$@))))
+blob-symbol = $(or $($(target-stem)-symbol),$(blob-stem))
+
+blob-flags = -DBLOB_SYMBOL="$(blob-symbol)" -DBLOB_INPUT=$<
+
+quiet_cmd_blob = BLOB $@
+ cmd_blob = $(CC) $(c_flags) $(blob-flags) -c -o $@ $(srctree)/scripts/blob-wrap.c
+
+$(blobs): $(obj)/%.blob.o: $(obj)/% $(srctree)/scripts/blob-wrap.c FORCE
+ $(call if_changed_dep,blob)
+
+targets += $(blobs)
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 993708d1187459f3678d68ec81ef005e6f51d470..def9791523d718552617ef6ef752c1852d40d996 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -440,6 +440,12 @@ ifneq ($(need-dtbslist)$(dtb-y)$(dtb-)$(filter %.dtb %.dtb.o %.dtbo.o,$(targets)
include $(srctree)/scripts/Makefile.dtbs
endif
+# $(sort ...) is used here to remove duplicated words and excessive spaces.
+blobs := $(sort $(blobs))
+ifneq ($(blobs),)
+include $(srctree)/scripts/Makefile.blobs
+endif
+
# Build
# ---------------------------------------------------------------------------
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index 6ead00ec7313b3e4330a8de5f1342f2da1d6eb84..536972b0a528d117e17296da9936825c3903af6e 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -25,7 +25,7 @@ subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn))
# directory
__clean-files := \
- $(clean-files) $(targets) $(hostprogs) $(userprogs) \
+ $(clean-files) $(targets) $(hostprogs) $(userprogs) $(blobs) \
$(extra-y) $(extra-m) $(extra-) \
$(always-y) $(always-m) $(always-) \
$(hostprogs-always-y) $(hostprogs-always-m) $(hostprogs-always-) \
diff --git a/scripts/blob-wrap.c b/scripts/blob-wrap.c
new file mode 100644
index 0000000000000000000000000000000000000000..715d6981fa94bee309c693c2b937899c982e27b4
--- /dev/null
+++ b/scripts/blob-wrap.c
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/args.h>
+#include <linux/blob.h>
+#include <linux/stringify.h>
+
+#define BLOB_SYMBOL_DATA CONCATENATE(_blob_data_, BLOB_SYMBOL)
+#define BLOB_SYMBOL_END CONCATENATE(_blob_end_, BLOB_SYMBOL)
+
+asm (
+" .pushsection .rodata, \"a\" \n"
+" .global " __stringify(BLOB_SYMBOL_DATA) " \n"
+ __stringify(BLOB_SYMBOL_DATA) ": \n"
+" .incbin \"" __stringify(BLOB_INPUT) "\" \n"
+" .global " __stringify(BLOB_SYMBOL_END) " \n"
+ __stringify(BLOB_SYMBOL_END) ": \n"
+" .popsection \n"
+);
+
+extern const u8 BLOB_SYMBOL_DATA;
+extern const u8 BLOB_SYMBOL_END;
+
+const struct blob BLOB_SYMBOL = {
+ .path = __stringify(BLOB_INPUT),
+ .data = &BLOB_SYMBOL_DATA,
+ .end = &BLOB_SYMBOL_END,
+};
--
2.48.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 06/12] kunit: tool: Add test for nested test result reporting
2025-02-17 10:59 [PATCH 00/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
` (4 preceding siblings ...)
2025-02-17 10:59 ` [PATCH 05/12] kbuild: introduce blob framework Thomas Weißschuh
@ 2025-02-17 10:59 ` Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 07/12] kunit: tool: Don't overwrite test status based on subtest counts Thomas Weißschuh
` (6 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Thomas Weißschuh @ 2025-02-17 10:59 UTC (permalink / raw)
To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Willy Tarreau, Thomas Weißschuh,
Brendan Higgins, David Gow, Rae Moar, Shuah Khan,
Jonathan Corbet
Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev,
linux-doc, Thomas Weißschuh
Currently there is no test validating the result reporting from nested
tests. Add one, it will also be used to validate upcoming changes to the
nested test parsing.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
tools/testing/kunit/kunit_tool_test.py | 9 +++++++++
.../kunit/test_data/test_is_test_passed-failure-nested.log | 7 +++++++
2 files changed, 16 insertions(+)
diff --git a/tools/testing/kunit/kunit_tool_test.py b/tools/testing/kunit/kunit_tool_test.py
index 0bcb0cc002f8a7c24b119d59b3e996efc953c626..e71ce88682e137676be49ea9854a5ddaff0dc259 100755
--- a/tools/testing/kunit/kunit_tool_test.py
+++ b/tools/testing/kunit/kunit_tool_test.py
@@ -165,6 +165,15 @@ class KUnitParserTest(unittest.TestCase):
self.assertEqual(kunit_parser.TestStatus.FAILURE, result.status)
self.assertEqual(result.counts.errors, 0)
+ def test_parse_failed_nested_tests_log(self):
+ nested_log = test_data_path('test_is_test_passed-failure-nested.log')
+ with open(nested_log) as file:
+ result = kunit_parser.parse_run_tests(file.readlines(), stdout)
+ self.assertEqual(kunit_parser.TestStatus.FAILURE, result.status)
+ self.assertEqual(result.counts.failed, 2)
+ self.assertEqual(kunit_parser.TestStatus.FAILURE, result.subtests[0].status)
+ self.assertEqual(kunit_parser.TestStatus.FAILURE, result.subtests[1].status)
+
def test_no_header(self):
empty_log = test_data_path('test_is_test_passed-no_tests_run_no_header.log')
with open(empty_log) as file:
diff --git a/tools/testing/kunit/test_data/test_is_test_passed-failure-nested.log b/tools/testing/kunit/test_data/test_is_test_passed-failure-nested.log
new file mode 100644
index 0000000000000000000000000000000000000000..835816e0a07715a514f5f5afab1b6250037feaf4
--- /dev/null
+++ b/tools/testing/kunit/test_data/test_is_test_passed-failure-nested.log
@@ -0,0 +1,7 @@
+KTAP version 1
+1..2
+not ok 1 subtest 1
+ KTAP version 1
+ 1..1
+ not ok 1 test 1
+not ok 2 subtest 2
--
2.48.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 07/12] kunit: tool: Don't overwrite test status based on subtest counts
2025-02-17 10:59 [PATCH 00/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
` (5 preceding siblings ...)
2025-02-17 10:59 ` [PATCH 06/12] kunit: tool: Add test for nested test result reporting Thomas Weißschuh
@ 2025-02-17 10:59 ` Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 08/12] kunit: tool: Parse skipped tests from kselftest.h Thomas Weißschuh
` (5 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Thomas Weißschuh @ 2025-02-17 10:59 UTC (permalink / raw)
To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Willy Tarreau, Thomas Weißschuh,
Brendan Higgins, David Gow, Rae Moar, Shuah Khan,
Jonathan Corbet
Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev,
linux-doc, Thomas Weißschuh
If a subtest itself reports success, but the outer testcase fails,
the whole testcase should be reported as a failure.
However the status is recalculated based on the test counts,
overwriting the outer test result.
Synthesize a failed test in this case to make sure the failure is not
swallowed.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
tools/testing/kunit/kunit_parser.py | 5 +++++
tools/testing/kunit/kunit_tool_test.py | 2 +-
tools/testing/kunit/test_data/test_is_test_passed-failure-nested.log | 3 +++
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/tools/testing/kunit/kunit_parser.py b/tools/testing/kunit/kunit_parser.py
index 29fc27e8949bd4732448fdd96024624e5350a728..8f597a244b9866528ffb3850e876acb487f3bbd4 100644
--- a/tools/testing/kunit/kunit_parser.py
+++ b/tools/testing/kunit/kunit_parser.py
@@ -686,6 +686,11 @@ def bubble_up_test_results(test: Test) -> None:
counts.add_status(status)
elif test.counts.get_status() == TestStatus.TEST_CRASHED:
test.status = TestStatus.TEST_CRASHED
+ if not test.ok_status():
+ for t in subtests:
+ if not t.ok_status():
+ counts.add_status(t.status)
+ break
def parse_test(lines: LineStream, expected_num: int, log: List[str], is_subtest: bool, printer: Printer) -> Test:
"""
diff --git a/tools/testing/kunit/kunit_tool_test.py b/tools/testing/kunit/kunit_tool_test.py
index e71ce88682e137676be49ea9854a5ddaff0dc259..aab38aa0664655c84d633ab15e4818f818b0ce47 100755
--- a/tools/testing/kunit/kunit_tool_test.py
+++ b/tools/testing/kunit/kunit_tool_test.py
@@ -170,7 +170,7 @@ class KUnitParserTest(unittest.TestCase):
with open(nested_log) as file:
result = kunit_parser.parse_run_tests(file.readlines(), stdout)
self.assertEqual(kunit_parser.TestStatus.FAILURE, result.status)
- self.assertEqual(result.counts.failed, 2)
+ self.assertEqual(result.counts.failed, 3)
self.assertEqual(kunit_parser.TestStatus.FAILURE, result.subtests[0].status)
self.assertEqual(kunit_parser.TestStatus.FAILURE, result.subtests[1].status)
diff --git a/tools/testing/kunit/test_data/test_is_test_passed-failure-nested.log b/tools/testing/kunit/test_data/test_is_test_passed-failure-nested.log
index 835816e0a07715a514f5f5afab1b6250037feaf4..cd9033c464792e6294905a5676346684182874ad 100644
--- a/tools/testing/kunit/test_data/test_is_test_passed-failure-nested.log
+++ b/tools/testing/kunit/test_data/test_is_test_passed-failure-nested.log
@@ -1,5 +1,8 @@
KTAP version 1
1..2
+ KTAP version 1
+ 1..1
+ ok 1 test 1
not ok 1 subtest 1
KTAP version 1
1..1
--
2.48.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 08/12] kunit: tool: Parse skipped tests from kselftest.h
2025-02-17 10:59 [PATCH 00/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
` (6 preceding siblings ...)
2025-02-17 10:59 ` [PATCH 07/12] kunit: tool: Don't overwrite test status based on subtest counts Thomas Weißschuh
@ 2025-02-17 10:59 ` Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 09/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
` (4 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Thomas Weißschuh @ 2025-02-17 10:59 UTC (permalink / raw)
To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Willy Tarreau, Thomas Weißschuh,
Brendan Higgins, David Gow, Rae Moar, Shuah Khan,
Jonathan Corbet
Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev,
linux-doc, Thomas Weißschuh
Skipped tests reported by kselftest.h use a different format than KTAP,
there is no explicit test name. Normally the test name is part of the
free-form string after the SKIP keyword:
ok 3 # SKIP test: some reason
Extend the parser to handle those correctly. Use the free-form string as
test name instead.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
tools/testing/kunit/kunit_parser.py | 8 +++++---
tools/testing/kunit/test_data/test_is_test_passed-kselftest.log | 3 ++-
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/tools/testing/kunit/kunit_parser.py b/tools/testing/kunit/kunit_parser.py
index 8f597a244b9866528ffb3850e876acb487f3bbd4..096fe0c9740dd8ec528cbc3dabefcd5bc9b40e50 100644
--- a/tools/testing/kunit/kunit_parser.py
+++ b/tools/testing/kunit/kunit_parser.py
@@ -352,9 +352,9 @@ def parse_test_plan(lines: LineStream, test: Test) -> bool:
lines.pop()
return True
-TEST_RESULT = re.compile(r'^\s*(ok|not ok) ([0-9]+) (- )?([^#]*)( # .*)?$')
+TEST_RESULT = re.compile(r'^\s*(ok|not ok) ([0-9]+)? ?(- )?([^#]*)( # .*)?$')
-TEST_RESULT_SKIP = re.compile(r'^\s*(ok|not ok) ([0-9]+) (- )?(.*) # SKIP(.*)$')
+TEST_RESULT_SKIP = re.compile(r'^\s*(ok|not ok) ([0-9]+)? ?(- )?(.*) # SKIP ?(.*)$')
def peek_test_name_match(lines: LineStream, test: Test) -> bool:
"""
@@ -379,6 +379,8 @@ def peek_test_name_match(lines: LineStream, test: Test) -> bool:
if not match:
return False
name = match.group(4)
+ if not name:
+ return False
return name == test.name
def parse_test_result(lines: LineStream, test: Test,
@@ -416,7 +418,7 @@ def parse_test_result(lines: LineStream, test: Test,
# Set name of test object
if skip_match:
- test.name = skip_match.group(4)
+ test.name = skip_match.group(4) or skip_match.group(5)
else:
test.name = match.group(4)
diff --git a/tools/testing/kunit/test_data/test_is_test_passed-kselftest.log b/tools/testing/kunit/test_data/test_is_test_passed-kselftest.log
index 65d3f27feaf22a3f47ed831c4c24f6f11c625a92..30d9ef18bcec177067288d5242771236f29b7d56 100644
--- a/tools/testing/kunit/test_data/test_is_test_passed-kselftest.log
+++ b/tools/testing/kunit/test_data/test_is_test_passed-kselftest.log
@@ -1,5 +1,5 @@
TAP version 13
-1..2
+1..3
# selftests: membarrier: membarrier_test_single_thread
# TAP version 13
# 1..2
@@ -12,3 +12,4 @@ ok 1 selftests: membarrier: membarrier_test_single_thread
# ok 1 sys_membarrier available
# ok 2 sys membarrier invalid command test: command = -1, flags = 0, errno = 22. Failed as expected
ok 2 selftests: membarrier: membarrier_test_multi_thread
+ok 3 # SKIP selftests: membarrier: membarrier_test_multi_thread
--
2.48.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 09/12] kunit: Introduce UAPI testing framework
2025-02-17 10:59 [PATCH 00/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
` (7 preceding siblings ...)
2025-02-17 10:59 ` [PATCH 08/12] kunit: tool: Parse skipped tests from kselftest.h Thomas Weißschuh
@ 2025-02-17 10:59 ` Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 10/12] kunit: uapi: Add example for UAPI tests Thomas Weißschuh
` (3 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Thomas Weißschuh @ 2025-02-17 10:59 UTC (permalink / raw)
To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Willy Tarreau, Thomas Weißschuh,
Brendan Higgins, David Gow, Rae Moar, Shuah Khan,
Jonathan Corbet
Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev,
linux-doc, Thomas Weißschuh
Enable running UAPI tests as part of kunit.
The selftests are embedded into the kernel image and their output is
forwarded to kunit for unified reporting.
The implementation reuses parts of usermode drivers and usermode
helpers. However these frameworks are not used directly as they make it
impossible to retrieve a thread's exit code.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
include/kunit/uapi.h | 17 ++++
lib/kunit/Kconfig | 9 ++
lib/kunit/Makefile | 2 +
lib/kunit/uapi.c | 239 +++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 267 insertions(+)
diff --git a/include/kunit/uapi.h b/include/kunit/uapi.h
new file mode 100644
index 0000000000000000000000000000000000000000..760fad98884e12cbbec33155d3cc8ae083b0882b
--- /dev/null
+++ b/include/kunit/uapi.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * KUnit Userspace testing API.
+ *
+ * Copyright (C) 2025, Linuxtronix GmbH.
+ * Author: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
+ */
+
+#ifndef _KUNIT_UAPI_H
+#define _KUNIT_UAPI_H
+
+struct blob;
+struct kunit;
+
+void kunit_uapi_run_executable(struct kunit *test, const struct blob *blob);
+
+#endif /* _KUNIT_UAPI_H */
diff --git a/lib/kunit/Kconfig b/lib/kunit/Kconfig
index a97897edd9642f3e5df7fdd9dee26ee5cf00d6a4..e15b9a678a6ad2b37c898f8b4e17e06567eb7bb5 100644
--- a/lib/kunit/Kconfig
+++ b/lib/kunit/Kconfig
@@ -15,6 +15,15 @@ menuconfig KUNIT
if KUNIT
+config KUNIT_UAPI
+ def_bool y
+ depends on CC_CAN_LINK_STATIC || ARCH_HAS_NOLIBC
+ select HEADERS_INSTALL
+ select TMPFS
+ help
+ Enables support for build and running userspace selftests as part of kunit.
+ These tests should use kselftest.h for status reporting.
+
config KUNIT_DEBUGFS
bool "KUnit - Enable /sys/kernel/debug/kunit debugfs representation" if !KUNIT_ALL_TESTS
default KUNIT_ALL_TESTS
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 5aa51978e456ab3bb60c12071a26cf2bdcb1b508..2b68f9bd20137edb705dcd8cb2dc145f9684cf73 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -12,6 +12,8 @@ kunit-objs += test.o \
device.o \
platform.o
+obj-$(CONFIG_KUNIT_UAPI) += uapi.o
+
ifeq ($(CONFIG_KUNIT_DEBUGFS),y)
kunit-objs += debugfs.o
endif
diff --git a/lib/kunit/uapi.c b/lib/kunit/uapi.c
new file mode 100644
index 0000000000000000000000000000000000000000..9fbba13669e8e5cf349e596636f2cdc4adce4978
--- /dev/null
+++ b/lib/kunit/uapi.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit Userspace testing API.
+ *
+ * Copyright (C) 2025, Linuxtronix GmbH.
+ * Author: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
+ */
+
+#include <linux/binfmts.h>
+#include <linux/blob.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/fs_struct.h>
+#include <linux/pid.h>
+#include <linux/pipe_fs_i.h>
+#include <linux/sched/task.h>
+#include <linux/types.h>
+
+#include <kunit/test.h>
+#include <kunit/uapi.h>
+
+static struct vfsmount *kunit_uapi_mount_tmpfs(void)
+{
+ struct file_system_type *type;
+ struct vfsmount *mnt;
+
+ type = get_fs_type("tmpfs");
+ if (!type)
+ return ERR_PTR(-ENODEV);
+
+ /* FIXME
+ * The mount setup is supposed to look like this:
+ * kunit_uapi_mount_tmpfs() sets up a private mount,
+ * with nothing visible except the new tmpfs.
+ * Then each executable execution gets a new namespace on top of that
+ * on which it can mount whatever it needs.
+ * However I didn't manage to set this up, so keep everything simple
+ * for now and let somebody familiar with the VFS figure this out.
+ */
+
+ mnt = kern_mount(type);
+ put_filesystem(type);
+
+ return mnt;
+}
+
+static int kunit_uapi_write_file(struct vfsmount *mnt, const char *name, mode_t mode,
+ const u8 *data, size_t size)
+{
+ struct file *file;
+ ssize_t written;
+
+ file = file_open_root_mnt(mnt, name, O_CREAT | O_WRONLY, mode);
+ if (IS_ERR(file))
+ return PTR_ERR(file);
+
+ written = kernel_write(file, data, size, NULL);
+ filp_close(file, NULL);
+ if (written != size) {
+ if (written >= 0)
+ return -ENOMEM;
+ return written;
+ }
+
+ /* Flush delayed fput so exec can open the file read-only */
+ flush_delayed_fput();
+
+ return 0;
+}
+
+struct kunit_uapi_user_mode_thread_ctx {
+ const char *executable;
+
+ /* Signals mnt, out, pwd and tgid */
+ struct completion setup_done;
+ struct vfsmount *mnt;
+ struct file *out;
+ struct path pwd;
+ pid_t tgid;
+
+ /* Valid after wait(tgid) */
+ int exec_err;
+};
+
+static int kunit_uapi_user_mode_thread_init(void *data)
+{
+ struct kunit_uapi_user_mode_thread_ctx *ctx = data;
+ const char *const argv[] = {
+ ctx->executable,
+ NULL
+ };
+ struct file *out[2];
+ int err;
+
+ err = create_pipe_files(out, 0);
+ if (err)
+ return err;
+
+ err = replace_fd(1, out[1], 0);
+ if (err < 0) {
+ fput(out[1]);
+ return err;
+ }
+
+ err = replace_fd(2, out[1], 0);
+ if (err < 0) {
+ replace_fd(0, NULL, 0);
+ fput(out[1]);
+ return err;
+ }
+
+ fput(out[1]);
+
+ ctx->out = out[0];
+ ctx->tgid = current->tgid;
+
+ set_fs_pwd(current->fs, &ctx->pwd);
+ kernel_sigaction(SIGKILL, SIG_DFL);
+
+ complete(&ctx->setup_done);
+ ctx->exec_err = kernel_execve(ctx->executable, argv, NULL);
+ if (!ctx->exec_err)
+ return 0;
+ do_exit(0);
+}
+
+static size_t kunit_uapi_printk_subtest_lines(char *buf, size_t s)
+{
+ const char *ptr = buf, *newline;
+ size_t n;
+
+ while (s) {
+ newline = strnchr(ptr, s, '\n');
+ if (!newline)
+ break;
+
+ n = newline - ptr + 1;
+
+ pr_info(KUNIT_SUBSUBTEST_INDENT "%.*s", (int)n, ptr);
+ ptr += n;
+ s -= n;
+ }
+
+ memmove(buf, ptr, s);
+
+ return s;
+}
+
+static int kunit_uapi_forward_to_printk(struct file *output)
+{
+ char buf[512];
+ size_t s = 0;
+ ssize_t n;
+
+ while (1) {
+ n = kernel_read(output, buf + s, sizeof(buf) - s, NULL);
+ if (n <= 0)
+ return n;
+ s = kunit_uapi_printk_subtest_lines(buf, s + n);
+ }
+}
+
+static void kunit_uapi_kill_pid(pid_t pid)
+{
+ struct pid *p;
+
+ p = find_get_pid(pid);
+ kill_pid(p, SIGKILL, 1);
+ put_pid(p);
+}
+
+static int kunit_uapi_run_executable_in_mount(struct kunit *test, const char *executable,
+ struct vfsmount *mnt)
+{
+ struct kunit_uapi_user_mode_thread_ctx ctx = {
+ .setup_done = COMPLETION_INITIALIZER_ONSTACK(ctx.setup_done),
+ .executable = executable,
+ .pwd = {
+ .mnt = mnt,
+ .dentry = mnt->mnt_root,
+ },
+ };
+ int forward_err, wait_err, ret;
+ pid_t pid;
+
+ /* If SIGCHLD is ignored do_wait won't populate the status. */
+ kernel_sigaction(SIGCHLD, SIG_DFL);
+ pid = user_mode_thread(kunit_uapi_user_mode_thread_init, &ctx, SIGCHLD);
+ if (pid < 0) {
+ kernel_sigaction(SIGCHLD, SIG_IGN);
+ return pid;
+ }
+
+ wait_for_completion(&ctx.setup_done);
+
+ forward_err = kunit_uapi_forward_to_printk(ctx.out);
+ if (forward_err)
+ kunit_uapi_kill_pid(ctx.tgid);
+
+ wait_err = kernel_wait(ctx.tgid, &ret);
+
+ /* Restore default kernel sig handler */
+ kernel_sigaction(SIGCHLD, SIG_IGN);
+
+ if (ctx.exec_err)
+ return ctx.exec_err;
+ if (forward_err)
+ return forward_err;
+ if (wait_err < 0)
+ return wait_err;
+ return ret;
+}
+
+void kunit_uapi_run_executable(struct kunit *test, const struct blob *blob)
+{
+ const char *exe_name = kbasename(blob->path);
+ struct vfsmount *mnt;
+ int err;
+
+ mnt = kunit_uapi_mount_tmpfs();
+ KUNIT_EXPECT_FALSE_MSG(test, IS_ERR(mnt), "Could not mount tmpfs for test: %pe", mnt);
+ if (IS_ERR(mnt))
+ return;
+
+ err = kunit_uapi_write_file(mnt, exe_name, 0700, blob->data, blob_size(blob));
+ KUNIT_EXPECT_EQ_MSG(test, 0, err, "Could not add test executable: %pe", ERR_PTR(err));
+
+ if (!err) {
+ err = kunit_uapi_run_executable_in_mount(test, exe_name, mnt);
+ KUNIT_EXPECT_GE_MSG(test, err, 0, "Error when running executable: %pe\n",
+ ERR_PTR(err));
+ KUNIT_EXPECT_EQ_MSG(test, 0, err, "Executable signal/exitcode: %d/%d\n",
+ err & 0xff, err >> 8);
+ }
+
+ kern_unmount(mnt);
+
+}
+EXPORT_SYMBOL_GPL(kunit_uapi_run_executable);
--
2.48.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 10/12] kunit: uapi: Add example for UAPI tests
2025-02-17 10:59 [PATCH 00/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
` (8 preceding siblings ...)
2025-02-17 10:59 ` [PATCH 09/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
@ 2025-02-17 10:59 ` Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 11/12] kunit: uapi: Introduce preinit executable Thomas Weißschuh
` (2 subsequent siblings)
12 siblings, 0 replies; 18+ messages in thread
From: Thomas Weißschuh @ 2025-02-17 10:59 UTC (permalink / raw)
To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Willy Tarreau, Thomas Weißschuh,
Brendan Higgins, David Gow, Rae Moar, Shuah Khan,
Jonathan Corbet
Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev,
linux-doc, Thomas Weißschuh
Extend the example to show how to run a userspace executable.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
lib/kunit/Makefile | 8 +++++++-
lib/kunit/kunit-example-test.c | 17 +++++++++++++++++
lib/kunit/kunit-uapi-example.c | 20 ++++++++++++++++++++
3 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 2b68f9bd20137edb705dcd8cb2dc145f9684cf73..0d89b666fcad12a542d3e2ffacedd26b122c5449 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -30,4 +30,10 @@ obj-$(CONFIG_KUNIT_TEST) += string-stream-test.o
obj-$(CONFIG_KUNIT_TEST) += assert_test.o
endif
-obj-$(CONFIG_KUNIT_EXAMPLE_TEST) += kunit-example-test.o
+userprogs += kunit-uapi-example
+kunit-uapi-example-userccflags := -static
+kunit-uapi-example-nolibc := $(CONFIG_ARCH_HAS_NOLIBC)
+blobs += kunit-uapi-example.blob.o
+obj-$(CONFIG_KUNIT_EXAMPLE_TEST) += kunit-example-test-mod.o
+kunit-example-test-mod-y += kunit-example-test.o
+kunit-example-test-mod-$(CONFIG_KUNIT_UAPI) += kunit-uapi-example.blob.o
diff --git a/lib/kunit/kunit-example-test.c b/lib/kunit/kunit-example-test.c
index 3056d6bc705d0a8f196f0f4412e679dbb0e03114..c5b8b308ed7b10c6ec4f475965205f2ccc4b4ec5 100644
--- a/lib/kunit/kunit-example-test.c
+++ b/lib/kunit/kunit-example-test.c
@@ -6,8 +6,11 @@
* Author: Brendan Higgins <brendanhiggins@google.com>
*/
+#include <linux/blob.h>
+
#include <kunit/test.h>
#include <kunit/static_stub.h>
+#include <kunit/uapi.h>
/*
* This is the most fundamental element of KUnit, the test case. A test case
@@ -277,6 +280,19 @@ static void example_slow_test(struct kunit *test)
KUNIT_EXPECT_EQ(test, 1 + 1, 2);
}
+/*
+ * This test shows the usage of UAPI tests.
+ */
+static void example_uapi_test(struct kunit *test)
+{
+ DECLARE_BLOB(kunit_uapi_example);
+
+ if (IS_ENABLED(CONFIG_KUNIT_UAPI))
+ kunit_uapi_run_executable(test, &kunit_uapi_example);
+ else
+ kunit_skip(test, "CONFIG_KUNIT_UAPI not enabled");
+}
+
/*
* Here we make a list of all the test cases we want to add to the test suite
* below.
@@ -297,6 +313,7 @@ static struct kunit_case example_test_cases[] = {
KUNIT_CASE(example_priv_test),
KUNIT_CASE_PARAM(example_params_test, example_gen_params),
KUNIT_CASE_SLOW(example_slow_test),
+ KUNIT_CASE(example_uapi_test),
{}
};
diff --git a/lib/kunit/kunit-uapi-example.c b/lib/kunit/kunit-uapi-example.c
new file mode 100644
index 0000000000000000000000000000000000000000..4ec4b924f29b089cce9ca5b2b08a6ee0117b8ae9
--- /dev/null
+++ b/lib/kunit/kunit-uapi-example.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit Userspace example test.
+ *
+ * Copyright (C) 2025, Linuxtronix GmbH.
+ * Author: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
+ */
+
+#include "../../tools/testing/selftests/kselftest.h"
+
+int main(void)
+{
+ ksft_print_header();
+ ksft_set_plan(4);
+ ksft_test_result_pass("userspace test 1\n");
+ ksft_test_result_pass("userspace test 2\n");
+ ksft_test_result_skip("userspace test 3: some reason\n");
+ ksft_test_result_pass("userspace test 4\n");
+ ksft_finished();
+}
--
2.48.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 11/12] kunit: uapi: Introduce preinit executable
2025-02-17 10:59 [PATCH 00/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
` (9 preceding siblings ...)
2025-02-17 10:59 ` [PATCH 10/12] kunit: uapi: Add example for UAPI tests Thomas Weißschuh
@ 2025-02-17 10:59 ` Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 12/12] kunit: uapi: Validate usability of /proc Thomas Weißschuh
2025-02-18 8:20 ` [PATCH 00/12] kunit: Introduce UAPI testing framework David Gow
12 siblings, 0 replies; 18+ messages in thread
From: Thomas Weißschuh @ 2025-02-17 10:59 UTC (permalink / raw)
To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Willy Tarreau, Thomas Weißschuh,
Brendan Higgins, David Gow, Rae Moar, Shuah Khan,
Jonathan Corbet
Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev,
linux-doc, Thomas Weißschuh
UAPI selftests may expect a "normal" userspace environment.
For example the normal kernel API pseudo-filesystems should be mounted.
This could be done from kernel code but it is non-idiomatic.
Add a preinit userspace executable which performs these setup steps
before running the final test executable.
This preinit executable is only ever run from the kernel.
Give it access to autoconf.h and kconfig.h to adapt itself to the
tested kernel.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
lib/kunit/Makefile | 9 ++++++-
lib/kunit/uapi-preinit.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/kunit/uapi.c | 17 +++++++++++---
3 files changed, 83 insertions(+), 4 deletions(-)
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 0d89b666fcad12a542d3e2ffacedd26b122c5449..b1d9851f1a14ecd7fb48a20c5500058811259142 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -12,7 +12,14 @@ kunit-objs += test.o \
device.o \
platform.o
-obj-$(CONFIG_KUNIT_UAPI) += uapi.o
+userprogs += uapi-preinit
+uapi-preinit-nolibc := $(CONFIG_ARCH_HAS_NOLIBC)
+uapi-preinit-userccflags += -static \
+ -include include/generated/autoconf.h \
+ -include $(srctree)/tools/include/linux/kconfig.h
+blobs += uapi-preinit.blob.o
+uapi-preinit.blob-symbol := kunit_uapi_preinit
+obj-$(CONFIG_KUNIT_UAPI) += uapi.o uapi-preinit.blob.o
ifeq ($(CONFIG_KUNIT_DEBUGFS),y)
kunit-objs += debugfs.o
diff --git a/lib/kunit/uapi-preinit.c b/lib/kunit/uapi-preinit.c
new file mode 100644
index 0000000000000000000000000000000000000000..748599786aaa802982335e536ddae122f5cc2be5
--- /dev/null
+++ b/lib/kunit/uapi-preinit.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit Userspace environment setup.
+ *
+ * Copyright (C) 2025, Linuxtronix GmbH.
+ * Author: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
+ */
+
+#ifndef NOLIBC
+#include <sys/mount.h>
+#include <sys/stat.h>
+#endif
+
+#include "../../tools/testing/selftests/kselftest.h"
+
+static int setup_api_mount(const char *target, const char *fstype)
+{
+ int ret;
+
+ ret = mkdir(target, 0755);
+ if (ret && errno != EEXIST)
+ return -errno;
+
+ ret = mount("none", target, fstype, 0, NULL);
+ if (ret && errno != EBUSY)
+ return -errno;
+
+ return 0;
+}
+
+static void exit_failure(const char *stage, int err)
+{
+ /* If preinit fails synthesize a failed test report. */
+ ksft_print_header();
+ ksft_set_plan(1);
+ ksft_test_result_fail("Failed during test setup: %s: %s\n", stage, strerror(-err));
+ ksft_finished();
+}
+
+int main(int argc, char **argv, char **envp)
+{
+ int ret;
+
+ ret = setup_api_mount("/proc", "proc");
+ if (ret)
+ exit_failure("mount /proc", ret);
+ ret = setup_api_mount("/sys", "sysfs");
+ if (ret)
+ exit_failure("mount /sys", ret);
+ if (IS_ENABLED(CONFIG_DEVTMPFS)) {
+ ret = setup_api_mount("/dev", "devtmpfs");
+ if (ret)
+ exit_failure("mount /dev", ret);
+ }
+
+ ret = execve(argv[0], argv, envp);
+ if (ret)
+ exit_failure("execve", ret);
+
+ return 0;
+}
diff --git a/lib/kunit/uapi.c b/lib/kunit/uapi.c
index 9fbba13669e8e5cf349e596636f2cdc4adce4978..d43a1a1e5084ab1c7c4515e3c44fd3e819524737 100644
--- a/lib/kunit/uapi.c
+++ b/lib/kunit/uapi.c
@@ -19,6 +19,8 @@
#include <kunit/test.h>
#include <kunit/uapi.h>
+#define KUNIT_UAPI_PREINIT "preinit"
+
static struct vfsmount *kunit_uapi_mount_tmpfs(void)
{
struct file_system_type *type;
@@ -118,7 +120,7 @@ static int kunit_uapi_user_mode_thread_init(void *data)
kernel_sigaction(SIGKILL, SIG_DFL);
complete(&ctx->setup_done);
- ctx->exec_err = kernel_execve(ctx->executable, argv, NULL);
+ ctx->exec_err = kernel_execve(KUNIT_UAPI_PREINIT, argv, NULL);
if (!ctx->exec_err)
return 0;
do_exit(0);
@@ -213,6 +215,8 @@ static int kunit_uapi_run_executable_in_mount(struct kunit *test, const char *ex
void kunit_uapi_run_executable(struct kunit *test, const struct blob *blob)
{
+ DECLARE_BLOB(kunit_uapi_preinit);
+
const char *exe_name = kbasename(blob->path);
struct vfsmount *mnt;
int err;
@@ -222,8 +226,15 @@ void kunit_uapi_run_executable(struct kunit *test, const struct blob *blob)
if (IS_ERR(mnt))
return;
- err = kunit_uapi_write_file(mnt, exe_name, 0700, blob->data, blob_size(blob));
- KUNIT_EXPECT_EQ_MSG(test, 0, err, "Could not add test executable: %pe", ERR_PTR(err));
+ err = kunit_uapi_write_file(mnt, KUNIT_UAPI_PREINIT, 0755,
+ kunit_uapi_preinit.data, blob_size(&kunit_uapi_preinit));
+ KUNIT_EXPECT_EQ_MSG(test, 0, err, "Could not add preinit executable: %pe", ERR_PTR(err));
+
+ if (!err) {
+ err = kunit_uapi_write_file(mnt, exe_name, 0755, blob->data, blob_size(blob));
+ KUNIT_EXPECT_EQ_MSG(test, 0, err, "Could not add test executable: %pe",
+ ERR_PTR(err));
+ }
if (!err) {
err = kunit_uapi_run_executable_in_mount(test, exe_name, mnt);
--
2.48.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 12/12] kunit: uapi: Validate usability of /proc
2025-02-17 10:59 [PATCH 00/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
` (10 preceding siblings ...)
2025-02-17 10:59 ` [PATCH 11/12] kunit: uapi: Introduce preinit executable Thomas Weißschuh
@ 2025-02-17 10:59 ` Thomas Weißschuh
2025-02-18 8:20 ` [PATCH 00/12] kunit: Introduce UAPI testing framework David Gow
12 siblings, 0 replies; 18+ messages in thread
From: Thomas Weißschuh @ 2025-02-17 10:59 UTC (permalink / raw)
To: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Willy Tarreau, Thomas Weißschuh,
Brendan Higgins, David Gow, Rae Moar, Shuah Khan,
Jonathan Corbet
Cc: linux-kbuild, linux-kernel, linux-kselftest, kunit-dev,
linux-doc, Thomas Weißschuh
Show that the selftests are executed from a fairly "normal"
userspace context.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
lib/kunit/kunit-uapi-example.c | 40 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/lib/kunit/kunit-uapi-example.c b/lib/kunit/kunit-uapi-example.c
index 4ec4b924f29b089cce9ca5b2b08a6ee0117b8ae9..f7376e524b4c76a9c6d474e6ace80a8e2517b84b 100644
--- a/lib/kunit/kunit-uapi-example.c
+++ b/lib/kunit/kunit-uapi-example.c
@@ -6,13 +6,51 @@
* Author: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
*/
+#ifndef NOLIBC
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#endif
+
#include "../../tools/testing/selftests/kselftest.h"
+static void test_procfs(void)
+{
+ char buf[256];
+ ssize_t r;
+ int fd;
+
+ fd = open("/proc/self/comm", O_RDONLY);
+ if (fd == -1) {
+ ksft_test_result_fail("procfs: open() failed: %s\n", strerror(errno));
+ return;
+ }
+
+ r = read(fd, buf, sizeof(buf));
+ if (r == -1) {
+ close(fd);
+ ksft_test_result_fail("procfs: read() failed: %s\n", strerror(errno));
+ return;
+ }
+
+ close(fd);
+
+ if (r > 0 && buf[r - 1] == '\n')
+ buf[r - 1] = '\0';
+
+ if (strncmp("kunit-uapi-exam", buf, sizeof(buf)) != 0) {
+ ksft_test_result_fail("procfs: incorrect comm: %s\n", buf);
+ return;
+ }
+
+ ksft_test_result_pass("procfs\n");
+}
+
int main(void)
{
ksft_print_header();
ksft_set_plan(4);
- ksft_test_result_pass("userspace test 1\n");
+ test_procfs();
ksft_test_result_pass("userspace test 2\n");
ksft_test_result_skip("userspace test 3: some reason\n");
ksft_test_result_pass("userspace test 4\n");
--
2.48.1
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 00/12] kunit: Introduce UAPI testing framework
2025-02-17 10:59 [PATCH 00/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
` (11 preceding siblings ...)
2025-02-17 10:59 ` [PATCH 12/12] kunit: uapi: Validate usability of /proc Thomas Weißschuh
@ 2025-02-18 8:20 ` David Gow
2025-02-18 8:57 ` Thomas Weißschuh
12 siblings, 1 reply; 18+ messages in thread
From: David Gow @ 2025-02-18 8:20 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Willy Tarreau, Thomas Weißschuh,
Brendan Higgins, Rae Moar, Shuah Khan, Jonathan Corbet,
linux-kbuild, linux-kernel, linux-kselftest, kunit-dev,
linux-doc
[-- Attachment #1: Type: text/plain, Size: 8943 bytes --]
On Mon, 17 Feb 2025 at 19:00, Thomas Weißschuh
<thomas.weissschuh@linutronix.de> wrote:
>
> Currently testing of userspace and in-kernel API use two different
> frameworks. kselftests for the userspace ones and Kunit for the
> in-kernel ones. Besides their different scopes, both have different
> strengths and limitations:
>
> Kunit:
> * Tests are normal kernel code.
> * They use the regular kernel toolchain.
> * They can be packaged and distributed as modules conveniently.
>
> Kselftests:
> * Tests are normal userspace code
> * They need a userspace toolchain.
> A kernel cross toolchain is likely not enough.
> * A fair amout of userland is required to run the tests,
> which means a full distro or handcrafted rootfs.
> * There is no way to conveniently package and run kselftests with a
> given kernel image.
> * The kselftests makefiles are not as powerful as regular kbuild.
> For example they are missing proper header dependency tracking or more
> complex compiler option modifications.
>
> Therefore kunit is much easier to run against different kernel
> configurations and architectures.
> This series aims to combine kselftests and kunit, avoiding both their
> limitations. It works by compiling the userspace kselftests as part of
> the regular kernel build, embedding them into the kunit kernel or module
> and executing them from there. If the kernel toolchain is not fit to
> produce userspace because of a missing libc, the kernel's own nolibc can
> be used instead.
> The structured TAP output from the kselftest is integrated into the
> kunit KTAP output transparently, the kunit parser can parse the combined
> logs together.
Wow -- this is really neat! Thanks for putting this together.
I haven't had a chance to play with it in detail yet, but here are a
few initial / random thoughts:
- Having support for running things from userspace within a KUnit test
seems like it's something that could be really useful for testing
syscalls (and maybe other mm / exec code as well).
- I don't think we can totally combine kselftests and KUnit for all
tests (some of the selftests definitely require more complicated
dependencies than I think KUnit would want to reasonably support or
require).
- The in-kernel KUnit framework doesn't have any knowledge of the
structure or results of a uapi test. It'd be nice to at least be able
to get the process exit status, and bubble up a basic
'passed'/'skipped'/'failed' so that we're not reporting success for
failed tests (and so that simple test executables could run without
needing to output their own KTAP if they only run one test).
- Equally, for some selftests, it's probably a pain to have to write a
kernel module if there's nothing that needs to be done in the kernel.
Maybe such tests could still be built with nolibc and a kernel
toolchain, but be triggered directly from the python tooling (e.g. as
the 'init' process).
- There still seems to be some increased requirements over plain KUnit
at the moment: I'm definitely seeing issues from not having the right
libgcc installed for all architectures. (Though it's working for most
of them, which is very neat!)
- This is a great example of how having standardised result formats is useful!
- If this is going to change or blur the boundary between "this is a
ksefltest" and "this is a kunit test", we probably will need to update
Documentation/dev-tools/testing-overview.rst -- it probably needs some
clarifications there _anyway_, so this is probably a good point to
ensure everyone's on the same page.
Do you have a particular non-example test you'd like to either write
or port to use this? I think it'd be great to see some real-world
examples of where this'd be most useful.
Either way, I'll keep playing with this a bit over the next few days.
I'd love to hear what Shuah and Rae think, as well, as this involves
kselftest and KTAP a lot.
Cheers,
-- David
>
> Further room for improvements:
> * Call each test in its completely dedicated namespace
> * Handle additional test files besides the test executable through
> archives. CPIO, cramfs, etc.
> * Compatibility with kselftest_harness.h (in progress)
> * Expose the blobs in debugfs
> * Provide some convience wrappers around compat userprogs
> * Figure out a migration path/coexistence solution for
> kunit UAPI and tools/testing/selftests/
>
> Output from the kunit example testcase, note the output of
> "example_uapi_tests".
>
> $ ./tools/testing/kunit/kunit.py run --kunitconfig lib/kunit example
> ...
> Running tests with:
> $ .kunit/linux kunit.filter_glob=example kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
> [11:53:53] ================== example (10 subtests) ===================
> [11:53:53] [PASSED] example_simple_test
> [11:53:53] [SKIPPED] example_skip_test
> [11:53:53] [SKIPPED] example_mark_skipped_test
> [11:53:53] [PASSED] example_all_expect_macros_test
> [11:53:53] [PASSED] example_static_stub_test
> [11:53:53] [PASSED] example_static_stub_using_fn_ptr_test
> [11:53:53] [PASSED] example_priv_test
> [11:53:53] =================== example_params_test ===================
> [11:53:53] [SKIPPED] example value 3
> [11:53:53] [PASSED] example value 2
> [11:53:53] [PASSED] example value 1
> [11:53:53] [SKIPPED] example value 0
> [11:53:53] =============== [PASSED] example_params_test ===============
> [11:53:53] [PASSED] example_slow_test
> [11:53:53] ======================= (4 subtests) =======================
> [11:53:53] [PASSED] procfs
> [11:53:53] [PASSED] userspace test 2
> [11:53:53] [SKIPPED] userspace test 3: some reason
> [11:53:53] [PASSED] userspace test 4
> [11:53:53] ================ [PASSED] example_uapi_test ================
> [11:53:53] ===================== [PASSED] example =====================
> [11:53:53] ============================================================
> [11:53:53] Testing complete. Ran 16 tests: passed: 11, skipped: 5
> [11:53:53] Elapsed time: 67.543s total, 1.823s configuring, 65.655s building, 0.058s running
>
> Based on v6.14-rc1 and the series
> "tools/nolibc: compatibility with -Wmissing-prototypes" [0].
> For compatibility with LLVM/clang another series is needed [1].
>
> [0] https://lore.kernel.org/lkml/20250123-nolibc-prototype-v1-0-e1afc5c1999a@weissschuh.net/
> [1] https://lore.kernel.org/lkml/20250213-kbuild-userprog-fixes-v1-0-f255fb477d98@linutronix.de/
>
> Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
> ---
> Thomas Weißschuh (12):
> kconfig: implement CONFIG_HEADERS_INSTALL for Usermode Linux
> kconfig: introduce CONFIG_ARCH_HAS_NOLIBC
> kbuild: userprogs: respect CONFIG_WERROR
> kbuild: userprogs: add nolibc support
> kbuild: introduce blob framework
> kunit: tool: Add test for nested test result reporting
> kunit: tool: Don't overwrite test status based on subtest counts
> kunit: tool: Parse skipped tests from kselftest.h
> kunit: Introduce UAPI testing framework
> kunit: uapi: Add example for UAPI tests
> kunit: uapi: Introduce preinit executable
> kunit: uapi: Validate usability of /proc
>
> Documentation/kbuild/makefiles.rst | 12 +
> Makefile | 5 +-
> include/kunit/uapi.h | 17 ++
> include/linux/blob.h | 21 ++
> init/Kconfig | 2 +
> lib/Kconfig.debug | 1 -
> lib/kunit/Kconfig | 9 +
> lib/kunit/Makefile | 17 +-
> lib/kunit/kunit-example-test.c | 17 ++
> lib/kunit/kunit-uapi-example.c | 58 +++++
> lib/kunit/uapi-preinit.c | 61 +++++
> lib/kunit/uapi.c | 250 +++++++++++++++++++++
> scripts/Makefile.blobs | 19 ++
> scripts/Makefile.build | 6 +
> scripts/Makefile.clean | 2 +-
> scripts/Makefile.userprogs | 18 +-
> scripts/blob-wrap.c | 27 +++
> tools/include/nolibc/Kconfig.nolibc | 18 ++
> tools/testing/kunit/kunit_parser.py | 13 +-
> tools/testing/kunit/kunit_tool_test.py | 9 +
> .../test_is_test_passed-failure-nested.log | 10 +
> .../test_data/test_is_test_passed-kselftest.log | 3 +-
> 22 files changed, 584 insertions(+), 11 deletions(-)
> ---
> base-commit: 20e952894066214a80793404c9578d72ef89c5e0
> change-id: 20241015-kunit-kselftests-56273bc40442
>
> Best regards,
> --
> Thomas Weißschuh <thomas.weissschuh@linutronix.de>
>
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5294 bytes --]
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 00/12] kunit: Introduce UAPI testing framework
2025-02-18 8:20 ` [PATCH 00/12] kunit: Introduce UAPI testing framework David Gow
@ 2025-02-18 8:57 ` Thomas Weißschuh
0 siblings, 0 replies; 18+ messages in thread
From: Thomas Weißschuh @ 2025-02-18 8:57 UTC (permalink / raw)
To: David Gow
Cc: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Willy Tarreau, Thomas Weißschuh,
Brendan Higgins, Rae Moar, Shuah Khan, Jonathan Corbet,
linux-kbuild, linux-kernel, linux-kselftest, kunit-dev,
linux-doc
On Tue, Feb 18, 2025 at 04:20:06PM +0800, David Gow wrote:
> On Mon, 17 Feb 2025 at 19:00, Thomas Weißschuh
> <thomas.weissschuh@linutronix.de> wrote:
> >
> > Currently testing of userspace and in-kernel API use two different
> > frameworks. kselftests for the userspace ones and Kunit for the
> > in-kernel ones. Besides their different scopes, both have different
> > strengths and limitations:
> >
> > Kunit:
> > * Tests are normal kernel code.
> > * They use the regular kernel toolchain.
> > * They can be packaged and distributed as modules conveniently.
> >
> > Kselftests:
> > * Tests are normal userspace code
> > * They need a userspace toolchain.
> > A kernel cross toolchain is likely not enough.
> > * A fair amout of userland is required to run the tests,
> > which means a full distro or handcrafted rootfs.
> > * There is no way to conveniently package and run kselftests with a
> > given kernel image.
> > * The kselftests makefiles are not as powerful as regular kbuild.
> > For example they are missing proper header dependency tracking or more
> > complex compiler option modifications.
> >
> > Therefore kunit is much easier to run against different kernel
> > configurations and architectures.
> > This series aims to combine kselftests and kunit, avoiding both their
> > limitations. It works by compiling the userspace kselftests as part of
> > the regular kernel build, embedding them into the kunit kernel or module
> > and executing them from there. If the kernel toolchain is not fit to
> > produce userspace because of a missing libc, the kernel's own nolibc can
> > be used instead.
> > The structured TAP output from the kselftest is integrated into the
> > kunit KTAP output transparently, the kunit parser can parse the combined
> > logs together.
>
> Wow -- this is really neat! Thanks for putting this together.
>
> I haven't had a chance to play with it in detail yet, but here are a
> few initial / random thoughts:
> - Having support for running things from userspace within a KUnit test
> seems like it's something that could be really useful for testing
> syscalls (and maybe other mm / exec code as well).
That's the target :-)
I'm also looking for more descriptive naming ideas.
> - I don't think we can totally combine kselftests and KUnit for all
> tests (some of the selftests definitely require more complicated
> dependencies than I think KUnit would want to reasonably support or
> require).
Agreed, though I somewhat expect that some complex selftests would be
simplified to work with this scheme as it should improve test coverage
from the bots.
> - The in-kernel KUnit framework doesn't have any knowledge of the
> structure or results of a uapi test. It'd be nice to at least be able
> to get the process exit status, and bubble up a basic
> 'passed'/'skipped'/'failed' so that we're not reporting success for
> failed tests (and so that simple test executables could run without
> needing to output their own KTAP if they only run one test).
Currently any exitcode != 0 fails the test.
I'll add some proper handling for exit(KSFT_SKIP).
> - Equally, for some selftests, it's probably a pain to have to write a
> kernel module if there's nothing that needs to be done in the kernel.
> Maybe such tests could still be built with nolibc and a kernel
> toolchain, but be triggered directly from the python tooling (e.g. as
> the 'init' process).
Some autodiscovery based on linker sections could be done.
However that would not yet define how to group them into suites.
Having one explicit reference in a module makes everything easier
to understand. What about a helper macro for the test case definition:
KUNIT_CASE_UAPI(symbol)?
All UAPI tests of a subsystem can share the same module,
so the overhead should be limited.
I'd like to keep it usable without needing the python tooling.
Note in case it was not clear:
All test executables are available as normal files in the build directory
and can also be executed from there.
> - There still seems to be some increased requirements over plain KUnit
> at the moment: I'm definitely seeing issues from not having the right
> libgcc installed for all architectures. (Though it's working for most
> of them, which is very neat!)
I'll look into that.
> - This is a great example of how having standardised result formats is useful!
Indeed, it was surprisingly compatible.
> - If this is going to change or blur the boundary between "this is a
> ksefltest" and "this is a kunit test", we probably will need to update
> Documentation/dev-tools/testing-overview.rst -- it probably needs some
> clarifications there _anyway_, so this is probably a good point to
> ensure everyone's on the same page.
Agreed.
> Do you have a particular non-example test you'd like to either write
> or port to use this? I think it'd be great to see some real-world
> examples of where this'd be most useful.
I want to use it for the vDSO selftests.
To be usable for that another series is necessary[0].
I tested the whole thing locally with one selftest and promptly found
a bug in the selftests [1].
> Either way, I'll keep playing with this a bit over the next few days.
> I'd love to hear what Shuah and Rae think, as well, as this involves
> kselftest and KTAP a lot.
Thanks!
I'm also looking forward to their feedback.
Thomas
<snip>
[0] https://lore.kernel.org/lkml/20250203-parse_vdso-nolibc-v1-0-9cb6268d77be@linutronix.de/
[1] https://lore.kernel.org/lkml/20250217-selftests-vdso-s390-gnu-hash-v2-1-f6c2532ffe2a@linutronix.de/
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 04/12] kbuild: userprogs: add nolibc support
2025-02-17 10:59 ` [PATCH 04/12] kbuild: userprogs: add nolibc support Thomas Weißschuh
@ 2025-02-22 9:44 ` Willy Tarreau
0 siblings, 0 replies; 18+ messages in thread
From: Willy Tarreau @ 2025-02-22 9:44 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Masahiro Yamada, Nathan Chancellor, Nicolas Schier,
Andrew Morton, Thomas Weißschuh, Brendan Higgins, David Gow,
Rae Moar, Shuah Khan, Jonathan Corbet, linux-kbuild,
linux-kernel, linux-kselftest, kunit-dev, linux-doc
On Mon, Feb 17, 2025 at 11:59:24AM +0100, Thomas Weißschuh wrote:
> Userprogs are built with the regular kernel compiler $CC.
> A kernel compiler does not necessarily contain a libc which is required
> for a normal userspace application.
> However the kernel tree does contain a minimal libc implementation
> "nolibc" which can be used to build userspace applications.
>
> Introduce support to build userprogs against nolibc instead of the
> default C of the compiler, which may not exist.
^^^
"C library" or maybe "libc" I guess here.
Willy
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 01/12] kconfig: implement CONFIG_HEADERS_INSTALL for Usermode Linux
2025-02-17 10:59 ` [PATCH 01/12] kconfig: implement CONFIG_HEADERS_INSTALL for Usermode Linux Thomas Weißschuh
@ 2025-03-02 17:06 ` Masahiro Yamada
2025-03-04 19:23 ` Masahiro Yamada
1 sibling, 0 replies; 18+ messages in thread
From: Masahiro Yamada @ 2025-03-02 17:06 UTC (permalink / raw)
To: Thomas Weißschuh, Joe Perches
Cc: Nathan Chancellor, Nicolas Schier, Andrew Morton, Willy Tarreau,
Thomas Weißschuh, Brendan Higgins, David Gow, Rae Moar,
Shuah Khan, Jonathan Corbet, linux-kbuild, linux-kernel,
linux-kselftest, kunit-dev, linux-doc
To: Joe Perches for checkpatch.pl input
On Mon, Feb 17, 2025 at 8:00 PM Thomas Weißschuh
<thomas.weissschuh@linutronix.de> wrote:
>
> userprogs sometimes need access to UAPI headers.
> This is currently not possible for Usermode Linux, as UM is only
> a pseudo architecture built on top of a regular architecture and does
> not have its own UAPI.
> Instead use the UAPI headers from the underlying regular architecture.
>
> Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
> ---
> Makefile | 5 ++++-
> lib/Kconfig.debug | 1 -
> 2 files changed, 4 insertions(+), 2 deletions(-)
Can we add some checks to scripts/checkpatch.pl
for inappropriate commit subject prefixes?
I really want to see "kconfig:" used in the subject only
for changes under scripts/kconfig/.
I wonder if scripts/checkpatch.pl shows a warning
if "kconfig:" is used in the subject but nothing
under scripts/kconfig/ is changed.
People incorrectly use "kconfig:" prefix for random
"Kconfig" file changes. I am fed up with pointing out
this silly stuff.
Apparently, this patch is not related to Kconfig at all.
>
> diff --git a/Makefile b/Makefile
> index b4c208ae4041c1f4e32c2a158322422ce7353d06..275185d2ff5d3dc99bd7982abd1de85af0b9621a 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1357,9 +1357,12 @@ hdr-inst := -f $(srctree)/scripts/Makefile.headersinst obj
>
> PHONY += headers
> headers: $(version_h) scripts_unifdef uapi-asm-generic archheaders archscripts
> - $(if $(filter um, $(SRCARCH)), $(error Headers not exportable for UML))
> +ifdef HEADER_ARCH
> + $(Q)$(MAKE) -f $(srctree)/Makefile HEADER_ARCH= SRCARCH=$(HEADER_ARCH) headers
> +else
> $(Q)$(MAKE) $(hdr-inst)=include/uapi
> $(Q)$(MAKE) $(hdr-inst)=arch/$(SRCARCH)/include/uapi
> +endif
>
> ifdef CONFIG_HEADERS_INSTALL
> prepare: headers
> diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> index 1af972a92d06f6e3f7beec4bd086c00b412c83ac..60026c8388db82c0055ccd8b8ac8789d6b939b62 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -473,7 +473,6 @@ config READABLE_ASM
>
> config HEADERS_INSTALL
> bool "Install uapi headers to usr/include"
> - depends on !UML
> help
> This option will install uapi headers (headers exported to user-space)
> into the usr/include directory for use during the kernel build.
>
> --
> 2.48.1
>
--
Best Regards
Masahiro Yamada
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 01/12] kconfig: implement CONFIG_HEADERS_INSTALL for Usermode Linux
2025-02-17 10:59 ` [PATCH 01/12] kconfig: implement CONFIG_HEADERS_INSTALL for Usermode Linux Thomas Weißschuh
2025-03-02 17:06 ` Masahiro Yamada
@ 2025-03-04 19:23 ` Masahiro Yamada
1 sibling, 0 replies; 18+ messages in thread
From: Masahiro Yamada @ 2025-03-04 19:23 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Nathan Chancellor, Nicolas Schier, Andrew Morton, Willy Tarreau,
Thomas Weißschuh, Brendan Higgins, David Gow, Rae Moar,
Shuah Khan, Jonathan Corbet, linux-kbuild, linux-kernel,
linux-kselftest, kunit-dev, linux-doc
On Mon, Feb 17, 2025 at 8:00 PM Thomas Weißschuh
<thomas.weissschuh@linutronix.de> wrote:
>
> userprogs sometimes need access to UAPI headers.
> This is currently not possible for Usermode Linux, as UM is only
> a pseudo architecture built on top of a regular architecture and does
> not have its own UAPI.
> Instead use the UAPI headers from the underlying regular architecture.
>
> Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Applied to linux-kbuild with the subject prefix fixed.
What concerned me was that this patch creates
multiple paths to visit the same directory.
[1]
ARCH=um archheaders
-> ARCH=x86 archheaders
-> arch/x86/entry/syscalls/
[2]
ARCH=um headers
-> ARCH=x86 headers
-> depends on ARCH=x86 archheaders
-> arch/x86/entry/syscalls/
After carefully reviewing the code, I was convinced that
this is not a race condition.
(I am particularly cautious about race conditions in parallel builds
and try my best to avoid such code.)
--
Best Regards
Masahiro Yamada
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2025-03-04 19:24 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-02-17 10:59 [PATCH 00/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 01/12] kconfig: implement CONFIG_HEADERS_INSTALL for Usermode Linux Thomas Weißschuh
2025-03-02 17:06 ` Masahiro Yamada
2025-03-04 19:23 ` Masahiro Yamada
2025-02-17 10:59 ` [PATCH 02/12] kconfig: introduce CONFIG_ARCH_HAS_NOLIBC Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 03/12] kbuild: userprogs: respect CONFIG_WERROR Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 04/12] kbuild: userprogs: add nolibc support Thomas Weißschuh
2025-02-22 9:44 ` Willy Tarreau
2025-02-17 10:59 ` [PATCH 05/12] kbuild: introduce blob framework Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 06/12] kunit: tool: Add test for nested test result reporting Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 07/12] kunit: tool: Don't overwrite test status based on subtest counts Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 08/12] kunit: tool: Parse skipped tests from kselftest.h Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 09/12] kunit: Introduce UAPI testing framework Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 10/12] kunit: uapi: Add example for UAPI tests Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 11/12] kunit: uapi: Introduce preinit executable Thomas Weißschuh
2025-02-17 10:59 ` [PATCH 12/12] kunit: uapi: Validate usability of /proc Thomas Weißschuh
2025-02-18 8:20 ` [PATCH 00/12] kunit: Introduce UAPI testing framework David Gow
2025-02-18 8:57 ` Thomas Weißschuh
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®