From: wen.yang@linux.dev
To: Gabriele Monaco <gmonaco@redhat.com>
Cc: Nam Cao <namcao@linutronix.de>,
linux-trace-kernel@vger.kernel.org, linux-kernel@vger.kernel.org,
Wen Yang <wen.yang@linux.dev>
Subject: [PATCH 2/3] rv/reactors: add KUnit tests for reactor_printk
Date: Tue, 16 Jun 2026 00:44:49 +0800 [thread overview]
Message-ID: <690593305ad075539a804e0bf94493335354e6b9.1781541556.git.wen.yang@linux.dev> (raw)
In-Reply-To: <cover.1781541556.git.wen.yang@linux.dev>
From: Wen Yang <wen.yang@linux.dev>
Add KUnit tests for the printk reactor covering:
- Reactor registration and unregistration lifecycle
- React callback invocation via rv_react()
- Double registration rejection
- Multiple register/unregister cycles
The mock callback calls vprintk_deferred() — the same path as the real
reactor — then busy-waits to simulate I/O back-pressure, exercising the
LD_WAIT_FREE constraint of rv_react() under load.
Signed-off-by: Wen Yang <wen.yang@linux.dev>
---
kernel/trace/rv/Kconfig | 10 ++
kernel/trace/rv/Makefile | 1 +
kernel/trace/rv/reactor_printk_kunit.c | 123 +++++++++++++++++++++++++
3 files changed, 134 insertions(+)
create mode 100644 kernel/trace/rv/reactor_printk_kunit.c
diff --git a/kernel/trace/rv/Kconfig b/kernel/trace/rv/Kconfig
index 3884b14df375..ff47895c897f 100644
--- a/kernel/trace/rv/Kconfig
+++ b/kernel/trace/rv/Kconfig
@@ -104,6 +104,16 @@ config RV_REACT_PRINTK
Enables the printk reactor. The printk reactor emits a printk()
message if an exception is found.
+config RV_REACT_PRINTK_KUNIT
+ bool "KUnit tests for reactor_printk" if !KUNIT_ALL_TESTS
+ depends on RV_REACT_PRINTK && KUNIT
+ default KUNIT_ALL_TESTS
+ help
+ This builds KUnit tests for the printk reactor. These are only
+ for development and testing, not for regular kernel use cases.
+
+ If unsure, say N.
+
config RV_REACT_PANIC
bool "Panic reactor"
depends on RV_REACTORS
diff --git a/kernel/trace/rv/Makefile b/kernel/trace/rv/Makefile
index 94498da35b37..ef0a2dcb927c 100644
--- a/kernel/trace/rv/Makefile
+++ b/kernel/trace/rv/Makefile
@@ -23,4 +23,5 @@ obj-$(CONFIG_RV_MON_NOMISS) += monitors/nomiss/nomiss.o
# Add new monitors here
obj-$(CONFIG_RV_REACTORS) += rv_reactors.o
obj-$(CONFIG_RV_REACT_PRINTK) += reactor_printk.o
+obj-$(CONFIG_RV_REACT_PRINTK_KUNIT) += reactor_printk_kunit.o
obj-$(CONFIG_RV_REACT_PANIC) += reactor_panic.o
diff --git a/kernel/trace/rv/reactor_printk_kunit.c b/kernel/trace/rv/reactor_printk_kunit.c
new file mode 100644
index 000000000000..933aa5602226
--- /dev/null
+++ b/kernel/trace/rv/reactor_printk_kunit.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * KUnit tests for reactor_printk
+ *
+ */
+
+#include <kunit/test.h>
+#include <linux/rv.h>
+#include <linux/printk.h>
+#include <linux/sched/clock.h>
+#include <linux/processor.h>
+
+/*
+ * Simulated execution time for mock_printk_react (sched_clock units,
+ * nanoseconds). Models the time a real printk reactor callback may consume
+ * under I/O pressure, exercising the LD_WAIT_FREE constraint of rv_react().
+ */
+#define MOCK_REACT_DURATION_NS 5000000ULL
+
+/*
+ * Mock react callback mirroring rv_printk_reaction().
+ *
+ * Calls vprintk_deferred() — the same path as the real reactor — then holds
+ * the CPU for MOCK_REACT_DURATION_NS via a sched_clock() timed busy-loop,
+ * simulating a callback that is slow due to I/O back-pressure.
+ * sched_clock() is notrace and lock-free; no sleep or lock acquisition is
+ * performed, satisfying the LD_WAIT_FREE constraint of rv_react().
+ */
+__printf(1, 0) static void mock_printk_react(const char *msg, va_list args)
+{
+ u64 start = sched_clock();
+
+ vprintk_deferred(msg, args);
+
+ while (sched_clock() - start < MOCK_REACT_DURATION_NS)
+ cpu_relax();
+}
+
+static struct rv_reactor mock_printk_reactor = {
+ .name = "test_printk",
+ .description = "test printk reactor",
+ .react = mock_printk_react,
+};
+
+/* Test 1: register and unregister reactor */
+static void test_printk_register_unregister(struct kunit *test)
+{
+ int ret;
+
+ ret = rv_register_reactor(&mock_printk_reactor);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+ KUNIT_EXPECT_STREQ(test, mock_printk_reactor.name, "test_printk");
+
+ rv_unregister_reactor(&mock_printk_reactor);
+}
+
+/* Test 2: react callback is invoked via rv_react() */
+static void test_printk_react_called(struct kunit *test)
+{
+ struct rv_reactor reactor = {
+ .name = "printk_cb_test",
+ .react = mock_printk_react,
+ };
+ struct rv_monitor monitor = {
+ .name = "test_monitor",
+ .reactor = &reactor,
+ .react = mock_printk_react,
+ };
+
+ rv_react(&monitor, "printk violation message");
+}
+
+/* Test 3: double registration should fail */
+static void test_printk_double_register(struct kunit *test)
+{
+ int ret;
+
+ ret = rv_register_reactor(&mock_printk_reactor);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ ret = rv_register_reactor(&mock_printk_reactor);
+ KUNIT_EXPECT_NE(test, ret, 0);
+
+ rv_unregister_reactor(&mock_printk_reactor);
+}
+
+/* Test 4: register/unregister cycle */
+static void test_printk_register_cycle(struct kunit *test)
+{
+ int ret, i;
+
+ for (i = 0; i < 5; i++) {
+ ret = rv_register_reactor(&mock_printk_reactor);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+
+ rv_unregister_reactor(&mock_printk_reactor);
+ }
+}
+
+/* Test 5: react callback is not NULL (printk reactors must provide react) */
+static void test_printk_react_not_null(struct kunit *test)
+{
+ KUNIT_EXPECT_NOT_NULL(test, mock_printk_reactor.react);
+}
+
+static struct kunit_case reactor_printk_kunit_cases[] = {
+ KUNIT_CASE(test_printk_register_unregister),
+ KUNIT_CASE(test_printk_react_called),
+ KUNIT_CASE(test_printk_double_register),
+ KUNIT_CASE(test_printk_register_cycle),
+ KUNIT_CASE(test_printk_react_not_null),
+ {}
+};
+
+static struct kunit_suite reactor_printk_kunit_suite = {
+ .name = "rv_reactor_printk",
+ .test_cases = reactor_printk_kunit_cases,
+};
+
+kunit_test_suite(reactor_printk_kunit_suite);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("KUnit tests for reactor_printk");
--
2.25.1
next prev parent reply other threads:[~2026-06-15 16:45 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-15 16:44 [PATCH 0/3] rv/reactors: fix lockdep warning and add KUnit tests wen.yang
2026-06-15 16:44 ` [PATCH 1/3] rv/reactors: fix lockdep "Invalid wait context" in rv_react() wen.yang
2026-06-17 11:12 ` Nam Cao
2026-06-17 15:58 ` Nam Cao
2026-06-23 9:38 ` Thomas Weißschuh
2026-07-06 14:02 ` Gabriele Monaco
2026-07-08 15:47 ` Thomas Weißschuh
2026-07-09 16:37 ` Wen Yang
2026-07-09 18:07 ` Nam Cao
2026-07-14 17:39 ` Wen Yang
2026-06-15 16:44 ` wen.yang [this message]
2026-06-23 9:54 ` [PATCH 2/3] rv/reactors: add KUnit tests for reactor_printk Thomas Weißschuh
2026-07-06 14:41 ` Gabriele Monaco
2026-07-09 16:53 ` Wen Yang
2026-06-15 16:44 ` [PATCH 3/3] rv/reactors: add KUnit tests for reactor_panic wen.yang
2026-06-20 23:30 ` XIAO WU
2026-06-21 3:34 ` Wen Yang
2026-07-06 14:48 ` Gabriele Monaco
2026-07-06 15:00 ` Gabriele Monaco
2026-07-09 16:46 ` Wen Yang
2026-07-10 8:27 ` Gabriele Monaco
2026-06-17 15:41 ` [PATCH 0/3] rv/reactors: fix lockdep warning and add KUnit tests Gabriele Monaco
2026-06-17 15:52 ` Nam Cao
2026-06-17 16:14 ` Gabriele Monaco
2026-06-17 17:11 ` Wen Yang
2026-06-18 15:35 ` Gabriele Monaco
2026-06-20 9:13 ` Wen Yang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=690593305ad075539a804e0bf94493335354e6b9.1781541556.git.wen.yang@linux.dev \
--to=wen.yang@linux.dev \
--cc=gmonaco@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=namcao@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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®