Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests: harness: Add kselftest harness selftest

Add a selftest for the kselftest harness itself so any changes can be
validated.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Reviewed-by: Muhammad Usama Anjum <usama.anjum@collabora.com>
Acked-by: Shuah Khan <skhan@linuxfoundation.org>
Link: https://lore.kernel.org/r/20250505-nolibc-kselftest-harness-v4-1-ee4dd5257135@linutronix.de
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>

authored by

Thomas Weißschuh and committed by
Thomas Weißschuh
df82ffc5 2011097c

+224
+1
MAINTAINERS
··· 21742 21742 F: include/uapi/linux/seccomp.h 21743 21743 F: kernel/seccomp.c 21744 21744 F: tools/testing/selftests/kselftest_harness.h 21745 + F: tools/testing/selftests/kselftest_harness/ 21745 21746 F: tools/testing/selftests/seccomp/* 21746 21747 K: \bsecure_computing 21747 21748 K: \bTIF_SECCOMP\b
+1
tools/testing/selftests/Makefile
··· 48 48 TARGETS += ir 49 49 TARGETS += kcmp 50 50 TARGETS += kexec 51 + TARGETS += kselftest_harness 51 52 TARGETS += kvm 52 53 TARGETS += landlock 53 54 TARGETS += lib
+2
tools/testing/selftests/kselftest_harness/.gitignore
··· 1 + /harness-selftest 2 + /harness-selftest.seen
+7
tools/testing/selftests/kselftest_harness/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + TEST_GEN_PROGS_EXTENDED := harness-selftest 4 + TEST_PROGS := harness-selftest.sh 5 + EXTRA_CLEAN := harness-selftest.seen 6 + 7 + include ../lib.mk
+136
tools/testing/selftests/kselftest_harness/harness-selftest.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <stdio.h> 4 + 5 + #include <sys/resource.h> 6 + #include <sys/prctl.h> 7 + 8 + /* Avoid any inconsistencies */ 9 + #define TH_LOG_STREAM stdout 10 + 11 + #include "../kselftest_harness.h" 12 + 13 + static void test_helper(struct __test_metadata *_metadata) 14 + { 15 + ASSERT_EQ(0, 0); 16 + } 17 + 18 + TEST(standalone_pass) { 19 + TH_LOG("before"); 20 + ASSERT_EQ(0, 0); 21 + EXPECT_EQ(0, 0); 22 + test_helper(_metadata); 23 + TH_LOG("after"); 24 + } 25 + 26 + TEST(standalone_fail) { 27 + TH_LOG("before"); 28 + EXPECT_EQ(0, 0); 29 + EXPECT_EQ(0, 1); 30 + ASSERT_EQ(0, 1); 31 + TH_LOG("after"); 32 + } 33 + 34 + TEST_SIGNAL(signal_pass, SIGUSR1) { 35 + TH_LOG("before"); 36 + ASSERT_EQ(0, 0); 37 + TH_LOG("after"); 38 + kill(getpid(), SIGUSR1); 39 + } 40 + 41 + TEST_SIGNAL(signal_fail, SIGUSR1) { 42 + TH_LOG("before"); 43 + ASSERT_EQ(0, 1); 44 + TH_LOG("after"); 45 + kill(getpid(), SIGUSR1); 46 + } 47 + 48 + FIXTURE(fixture) { 49 + pid_t testpid; 50 + }; 51 + 52 + FIXTURE_SETUP(fixture) { 53 + TH_LOG("setup"); 54 + self->testpid = getpid(); 55 + } 56 + 57 + FIXTURE_TEARDOWN(fixture) { 58 + TH_LOG("teardown same-process=%d", self->testpid == getpid()); 59 + } 60 + 61 + TEST_F(fixture, pass) { 62 + TH_LOG("before"); 63 + ASSERT_EQ(0, 0); 64 + test_helper(_metadata); 65 + standalone_pass(_metadata); 66 + TH_LOG("after"); 67 + } 68 + 69 + TEST_F(fixture, fail) { 70 + TH_LOG("before"); 71 + ASSERT_EQ(0, 1); 72 + fixture_pass(_metadata, self, variant); 73 + TH_LOG("after"); 74 + } 75 + 76 + TEST_F_TIMEOUT(fixture, timeout, 1) { 77 + TH_LOG("before"); 78 + sleep(2); 79 + TH_LOG("after"); 80 + } 81 + 82 + FIXTURE(fixture_parent) { 83 + pid_t testpid; 84 + }; 85 + 86 + FIXTURE_SETUP(fixture_parent) { 87 + TH_LOG("setup"); 88 + self->testpid = getpid(); 89 + } 90 + 91 + FIXTURE_TEARDOWN_PARENT(fixture_parent) { 92 + TH_LOG("teardown same-process=%d", self->testpid == getpid()); 93 + } 94 + 95 + TEST_F(fixture_parent, pass) { 96 + TH_LOG("before"); 97 + ASSERT_EQ(0, 0); 98 + TH_LOG("after"); 99 + } 100 + 101 + FIXTURE(fixture_setup_failure) { 102 + pid_t testpid; 103 + }; 104 + 105 + FIXTURE_SETUP(fixture_setup_failure) { 106 + TH_LOG("setup"); 107 + self->testpid = getpid(); 108 + ASSERT_EQ(0, 1); 109 + } 110 + 111 + FIXTURE_TEARDOWN(fixture_setup_failure) { 112 + TH_LOG("teardown same-process=%d", self->testpid == getpid()); 113 + } 114 + 115 + TEST_F(fixture_setup_failure, pass) { 116 + TH_LOG("before"); 117 + ASSERT_EQ(0, 0); 118 + TH_LOG("after"); 119 + } 120 + 121 + int main(int argc, char **argv) 122 + { 123 + /* 124 + * The harness uses abort() to signal assertion failures, which triggers coredumps. 125 + * This may be useful to debug real failures but not for this selftest, disable them. 126 + */ 127 + struct rlimit rlimit = { 128 + .rlim_cur = 0, 129 + .rlim_max = 0, 130 + }; 131 + 132 + prctl(PR_SET_DUMPABLE, 0, 0, 0, 0); 133 + setrlimit(RLIMIT_CORE, &rlimit); 134 + 135 + return test_harness_run(argc, argv); 136 + }
+64
tools/testing/selftests/kselftest_harness/harness-selftest.expected
··· 1 + TAP version 13 2 + 1..9 3 + # Starting 9 tests from 4 test cases. 4 + # RUN global.standalone_pass ... 5 + # harness-selftest.c:19:standalone_pass:before 6 + # harness-selftest.c:23:standalone_pass:after 7 + # OK global.standalone_pass 8 + ok 1 global.standalone_pass 9 + # RUN global.standalone_fail ... 10 + # harness-selftest.c:27:standalone_fail:before 11 + # harness-selftest.c:29:standalone_fail:Expected 0 (0) == 1 (1) 12 + # harness-selftest.c:30:standalone_fail:Expected 0 (0) == 1 (1) 13 + # standalone_fail: Test terminated by assertion 14 + # FAIL global.standalone_fail 15 + not ok 2 global.standalone_fail 16 + # RUN global.signal_pass ... 17 + # harness-selftest.c:35:signal_pass:before 18 + # harness-selftest.c:37:signal_pass:after 19 + # OK global.signal_pass 20 + ok 3 global.signal_pass 21 + # RUN global.signal_fail ... 22 + # harness-selftest.c:42:signal_fail:before 23 + # harness-selftest.c:43:signal_fail:Expected 0 (0) == 1 (1) 24 + # signal_fail: Test terminated by assertion 25 + # FAIL global.signal_fail 26 + not ok 4 global.signal_fail 27 + # RUN fixture.pass ... 28 + # harness-selftest.c:53:pass:setup 29 + # harness-selftest.c:62:pass:before 30 + # harness-selftest.c:19:pass:before 31 + # harness-selftest.c:23:pass:after 32 + # harness-selftest.c:66:pass:after 33 + # harness-selftest.c:58:pass:teardown same-process=1 34 + # OK fixture.pass 35 + ok 5 fixture.pass 36 + # RUN fixture.fail ... 37 + # harness-selftest.c:53:fail:setup 38 + # harness-selftest.c:70:fail:before 39 + # harness-selftest.c:71:fail:Expected 0 (0) == 1 (1) 40 + # harness-selftest.c:58:fail:teardown same-process=1 41 + # fail: Test terminated by assertion 42 + # FAIL fixture.fail 43 + not ok 6 fixture.fail 44 + # RUN fixture.timeout ... 45 + # harness-selftest.c:53:timeout:setup 46 + # harness-selftest.c:77:timeout:before 47 + # timeout: Test terminated by timeout 48 + # FAIL fixture.timeout 49 + not ok 7 fixture.timeout 50 + # RUN fixture_parent.pass ... 51 + # harness-selftest.c:87:pass:setup 52 + # harness-selftest.c:96:pass:before 53 + # harness-selftest.c:98:pass:after 54 + # harness-selftest.c:92:pass:teardown same-process=0 55 + # OK fixture_parent.pass 56 + ok 8 fixture_parent.pass 57 + # RUN fixture_setup_failure.pass ... 58 + # harness-selftest.c:106:pass:setup 59 + # harness-selftest.c:108:pass:Expected 0 (0) == 1 (1) 60 + # pass: Test terminated by assertion 61 + # FAIL fixture_setup_failure.pass 62 + not ok 9 fixture_setup_failure.pass 63 + # FAILED: 4 / 9 tests passed. 64 + # Totals: pass:4 fail:5 xfail:0 xpass:0 skip:0 error:0
+13
tools/testing/selftests/kselftest_harness/harness-selftest.sh
··· 1 + #!/bin/sh 2 + # SPDX-License-Identifier: GPL-2.0 3 + # 4 + # Selftest for kselftest_harness.h 5 + # 6 + 7 + set -e 8 + 9 + DIR="$(dirname $(readlink -f "$0"))" 10 + 11 + "$DIR"/harness-selftest > harness-selftest.seen || true 12 + 13 + diff -u "$DIR"/harness-selftest.expected harness-selftest.seen