[PATCH 2/3] rust: kunit: allow same test name with different #[cfg(...)]

From: Nicolás Antinori

Date: Tue Sep 29 2026 - 10:17:00 EST


Sometimes it is necessary to test the same code paths under different
configurations. The `#[cfg(...)]` macro can be used to check if specific
configurations are enabled and run tests accordingly.

Currently, defining multiple tests with the same name under different
`#[cfg(...)]` attributes results in a compilation error. This patch
removes that restriction, allowing identical test names across different
configurations.

Signed-off-by: Nicolás Antinori <nico.antinori.7@xxxxxxxxx>
---
rust/kernel/kunit.rs | 22 ++++++++++++++++++++++
rust/macros/kunit.rs | 20 +++++++++++++++-----
2 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
index 5fa4d994e0f7..5ff988ab76a4 100644
--- a/rust/kernel/kunit.rs
+++ b/rust/kernel/kunit.rs
@@ -347,6 +347,28 @@ fn rust_test_kunit_in_kunit_test() {
assert!(in_kunit_test());
}

+ // Tests with cfg have the same name on purpose because we are implicitly testing that
+ // tests with the same name but different configs do not throw a compilation error
+ #[test]
+ #[cfg(CONFIG_RUST_KUNIT_SELFTEST = "y")]
+ fn rust_test_kunit_run_only_active_cfg() {
+ assert!(in_kunit_test());
+ }
+
+ #[test]
+ #[cfg(CONFIG_RUST_KUNIT_SELFTEST = "n")]
+ fn rust_test_kunit_run_only_active_cfg() {
+ // This test should never run because of the `cfg`.
+ assert!(false)
+ }
+
+ #[test]
+ #[cfg(CONFIG_RUST_KUNIT_SELFTEST = "INVALID_VALUE")]
+ fn rust_test_kunit_run_only_active_cfg() {
+ // This test should never run because of the `cfg`.
+ assert!(false)
+ }
+
#[test]
#[should_panic]
fn rust_test_kunit_panic_in_kunit_test() {
diff --git a/rust/macros/kunit.rs b/rust/macros/kunit.rs
index f1d0210e6a49..18cfa463c8db 100644
--- a/rust/macros/kunit.rs
+++ b/rust/macros/kunit.rs
@@ -45,6 +45,8 @@ pub(crate) fn kunit_tests(test_suite: Ident, mut module: ItemMod) -> Result<Toke

let mut processed_items = Vec::new();
let mut test_cases = Vec::new();
+ let mut test_cases_cfgs = Vec::new();
+ let mut test_case_number: u32 = 1;

// Generate the test KUnit test suite and a test case for each `#[test]`.
//
@@ -135,7 +137,7 @@ macro_rules! assert_eq {
// Add back the test item.
processed_items.push(Item::Fn(f));

- let kunit_wrapper_fn_name = format_ident!("kunit_rust_wrapper_{test}");
+ let kunit_wrapper_fn_name = format_ident!("kunit_rust_wrapper_{test}_{test_case_number}");
let test_cstr = LitCStr::new(
&CString::new(test_str.as_str()).expect("identifier cannot contain NUL"),
test.span(),
@@ -172,15 +174,23 @@ macro_rules! assert_eq {
case.attr.rust_should_panic = #should_panic;
case
}));
+ test_cases_cfgs.push(cfg_attrs);
+ test_case_number += 1;
}

- let num_tests_plus_1 = test_cases.len() + 1;
+ // This dummy array is used to calculate the exact number of tests cases that are active
+ // depending on their #[cfg(...)] attribute.
+ processed_items.push(parse_quote!(
+ const TEST_CASES_COUNT: &[()] = &[#(#(#test_cases_cfgs)* (),)* ()];
+ ));
+
processed_items.push(parse_quote! {
- static mut TEST_CASES: [::kernel::bindings::kunit_case; #num_tests_plus_1] = [
- #(#test_cases,)*
- ::pin_init::zeroed(),
+ static mut TEST_CASES: [::kernel::bindings::kunit_case; TEST_CASES_COUNT.len()] = [
+ #(#(#test_cases_cfgs)* { #test_cases },)*
+ ::pin_init::zeroed()
];
});
+
processed_items.push(parse_quote! {
::kernel::kunit_unsafe_test_suite!(#test_suite, TEST_CASES);
});
--
2.47.3