rust: bug: add a KUnit test for warn_on!

The test runs warn_on!(false) and warn_on!(true) inside a KUnit warning
suppression block, then checks that one warning was counted. The counter
is incremented by the kernel warning path, not by warn_on! itself, so a
count of one means the warning was really reported.

warn_flags! has a different definition per architecture. The test does not
look at any of them, so it runs on every architecture that supports Rust.

The new CONFIG_RUST_BUG_KUNIT_TEST depends on BUG. With CONFIG_BUG=n,
warn_on! does nothing and no warning is counted.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
Link: https://patch.msgid.link/20260916140952.3290924-1-tomo@flapping.org
[ Added newlines for clarity. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
This commit is contained in:
FUJITA Tomonori 2026-09-16 23:09:52 +09:00 committed by Miguel Ojeda
parent 951d09ca45
commit cd56a1c858
2 changed files with 41 additions and 0 deletions

View File

@ -83,4 +83,15 @@ config RUST_BITFIELD_KUNIT_TEST
If unsure, say N.
config RUST_BUG_KUNIT_TEST
bool "KUnit tests for the Rust BUG/WARN functionality" if !KUNIT_ALL_TESTS
depends on BUG
default KUNIT_ALL_TESTS
help
This option enables KUnit tests for the Rust BUG/WARN functionality.
These are only for development and testing, not for regular
kernel use cases.
If unsure, say N.
endif

View File

@ -153,3 +153,33 @@ macro_rules! warn_on {
cond
}};
}
#[cfg(CONFIG_RUST_BUG_KUNIT_TEST)]
#[macros::kunit_tests(rust_kernel_bug)]
mod tests {
// The counter is incremented by the kernel warning path, not by `warn_on!`
// itself. A count of one means the warning was really reported.
#[test]
fn test_warn_on() {
// SAFETY: `kunit_get_current_test()` is always safe to call (it has
// fallbacks for when no KUnit test is running).
let test = unsafe { bindings::kunit_get_current_test() };
// SAFETY: This function runs only as a KUnit test case, so `test` is a
// valid pointer to the running test.
let handle = unsafe { bindings::kunit_start_suppress_warning(test) };
assert!(!warn_on!(false));
assert!(warn_on!(true));
// SAFETY: `kunit_suppressed_warning_count()` accepts any value returned by
// `kunit_start_suppress_warning()`.
let suppressed_count = unsafe { bindings::kunit_suppressed_warning_count(handle) };
// SAFETY: `test` is valid as above. `kunit_end_suppress_warning()` accepts any
// value returned by `kunit_start_suppress_warning()`.
unsafe { bindings::kunit_end_suppress_warning(test, handle) };
assert_eq!(suppressed_count, 1);
}
}