Linux Kernel Selftest development
 help / color / mirror / Atom feed
* [PATCH v2 0/3] rust: kunit: support #[should_panic] and same test name with different #[cfg(...)]
@ 2026-10-29 16:59 Nicolás Antinori via B4 Relay
  2026-10-29 16:59 ` [PATCH v2 1/3] rust: kunit: add #[should_panic] support Nicolás Antinori via B4 Relay
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Nicolás Antinori via B4 Relay @ 2026-10-29 16:59 UTC (permalink / raw)
  To: Alice Ryhl, Benno Lossin, Boqun Feng, Brendan Higgins,
	Daniel Almeida, Danilo Krummrich, David Gow, Gary Guo,
	Miguel Ojeda, Onur Özkan
  Cc: Alexandre Courbot, Andreas Hindborg, Björn Roy Baron,
	Burak Emir, Rae Moar, Tamir Duberstein, Trevor Gross, Yury Norov,
	kunit-dev, linux-kernel, linux-kselftest, rust-for-linux,
	Nicolás Antinori

This patch series intends to implement two features for KUnit tests
written in Rust. The work is based on a TODO comment made in the
`bitmap.rs` module [1].

Changelog:

v2: 
- Added more tests in `rust/kernel/kunit.rs` testing Sashiko findings
  and changes.
- Solved Sashiko: "[Low] kunit: spurious "try faulted" error logs for
  successful #[should_panic] tests": Solved by adding
  `rust_should_panic` in `kunit_try_catch` C struct to check if the test
  is expected to panic and act accordingly. Dismissed what I first talked
  about in [3].
- Solved Sashiko: "[Medium] kunit: assert! macro in #[should_panic]
  tests causes unexpected failure": Solved by making `kunit_assert`
  macro aware if the test should panic and act accordingly. Dismissed what
  I first talked about in [3]
- Solved Sashiko: "[Low] kunit: missing diagnostic log for
  #[should_panic] tests that fail to panic": Added an error message when
  a test that was expected to panic do not
- Solved Sashiko: "[Low] kunit: dead_code error for test wrappers with
  inactive cfg": Solved by moving the #[cfg(..)] attributes on top of
  the wrapper functions
- Dismissed Sashiko: "[Medium] rust: bitmap: memory leak in
  owned_bitmap_out_of_bounds() test panic": Not sure if can be done
  anything. If I am not mistaken this is the same issue as stated here [4].

Sashiko report links: https://sashiko.dev/#/patchset/20260930-rust_kunit_v4-v1-0-e3b0d45311dd@gmail.com?part=1

v1:
- Removed 'stringification' of test names (to avoid clash of names for
  different configurations now a number is appended).
- Added bool `rust_should_panic` attribute to `kunit_attributes` C
  struct
- Removed #[panic_handler] in Rust side, checking for aborts in the C
  side (`kunit_run_case_catch_errors` function). This allow to catch
  panics triggered, for example in a Rust function that called a panicking
  C function.
- Now the tests that have an inactive #[cfg(..)] do not appear un the
  KUnit execution summary as ignored, they just do not run.
Link to v1: https://lore.kernel.org/all/20260930-rust_kunit_v4-v1-0-e3b0d45311dd@gmail.com/

- RFC patch: https://lore.kernel.org/rust-for-linux/cover.1789500084.git.nico.antinori.7@gmail.com/

1. Supporting `#[should_panic]` [2]:

KUnit tests in Rust follow the user-space syntax, but at the moment
`#[should_panic]` is not supported. The first patch of this series adds
support for the attribute (only in its basic form, `#[should_panic =
"message"]` is not supported yet).

The way it is supported is by adding a new boolean property called
`rust_should_panic` to `kunit_attributes` struct in kunit/test.h and in
`kunit_attributes` in kunit/try-catch.h and check for the
`try_catch->try_result` code and the named flag to detect if there was a
panic in `kunit_try_catch_run` function.

2. Allow same test name with different #[cfg(...)]:

When testing `#[should_panic]` in `bitmap.rs` (check the last patch of
the series) I found that the test that was supposed to panic had the
same name as another one, but they were run on different configurations.
This caused the following compilation error:

ERROR:root:error[E0428]: the name `kunit_rust_wrapper_owned_bitmap_out_of_bounds` is defined multiple times
   --> ../rust/kernel/bitmap.rs:503:1
    |
503 | #[macros::kunit_tests(rust_kernel_bitmap)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `kunit_rust_wrapper_owned_bitmap_out_of_bounds` redefined here
    |
    = note: `kunit_rust_wrapper_owned_bitmap_out_of_bounds` must be defined only once in the value namespace of this module
    = note: this error originates in the attribute macro `macros::kunit_tests` (in Nightly builds, run with -Z macro-backtrace for more info)

Now, only the tests with an active `#[cfg(...)]` will be executed by the
runner. Tests with an inactive `#[cfg(...)]` will not appear in the
report since they are not added to the TEST_CASES array.

[1] https://github.com/Rust-for-Linux/linux/blob/fd73f4a6659897191fa0d40695fe370925dd3780/rust/kernel/bitmap.rs#L592-L600
[2] https://doc.rust-lang.org/rust-by-example/testing/unit_testing.html#testing-panics
[3] https://lore.kernel.org/all/DM41PHVITKOG.3I6P2X8048BEP@gmail.com/
[4] https://github.com/Rust-for-Linux/linux/blob/fd73f4a6659897191fa0d40695fe370925dd3780/rust/kernel/kunit.rs#L129-L136

Signed-off-by: Nicolás Antinori <nico.antinori.7@gmail.com>
---
Nicolás Antinori (3):
      rust: kunit: add #[should_panic] support
      rust: kunit: allow same test name with different #[cfg(...)]
      rust: bitmap: kunit: uncomment owned_bitmap_out_of_bounds panic case

 include/kunit/test.h       |  1 +
 include/kunit/try-catch.h  |  3 ++
 lib/kunit/attributes.c     | 18 ++++++++++++
 lib/kunit/kunit-test.c     |  3 ++
 lib/kunit/test.c           |  2 ++
 lib/kunit/try-catch-impl.h |  2 ++
 lib/kunit/try-catch.c      | 14 +++++----
 rust/kernel/bitmap.rs      | 21 +++++++------
 rust/kernel/kunit.rs       | 73 ++++++++++++++++++++++++++++++++++++++++++++--
 rust/macros/kunit.rs       | 67 +++++++++++++++++++++++++++++-------------
 10 files changed, 164 insertions(+), 40 deletions(-)
---
base-commit: 65ba8f34ec886ec72b2c07ddc8cf3d815c32869d
change-id: 20261029-rust_kunit_v6_send-d0353c1615f9

Best regards,
-- 
Nicolás Antinori <nico.antinori.7@gmail.com>



^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v2 1/3] rust: kunit: add #[should_panic] support
  2026-10-29 16:59 [PATCH v2 0/3] rust: kunit: support #[should_panic] and same test name with different #[cfg(...)] Nicolás Antinori via B4 Relay
@ 2026-10-29 16:59 ` Nicolás Antinori via B4 Relay
  2026-11-02 14:58   ` Nicolás Antinori
  2026-11-03 14:46   ` David Gow
  2026-10-29 16:59 ` [PATCH v2 2/3] rust: kunit: allow same test name with different #[cfg(...)] Nicolás Antinori via B4 Relay
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 15+ messages in thread
From: Nicolás Antinori via B4 Relay @ 2026-10-29 16:59 UTC (permalink / raw)
  To: Alice Ryhl, Benno Lossin, Boqun Feng, Brendan Higgins,
	Daniel Almeida, Danilo Krummrich, David Gow, Gary Guo,
	Miguel Ojeda, Onur Özkan
  Cc: Alexandre Courbot, Andreas Hindborg, Björn Roy Baron,
	Burak Emir, Rae Moar, Tamir Duberstein, Trevor Gross, Yury Norov,
	kunit-dev, linux-kernel, linux-kselftest, rust-for-linux,
	Nicolás Antinori

From: Nicolás Antinori <nico.antinori.7@gmail.com>

KUnit tests in Rust are written using user-space like syntax. This patch
adds support for the `#[should_panic]` attribute, enabling the user to
test conditions that are expected to cause a panic and report the test
as successful.

Signed-off-by: Nicolás Antinori <nico.antinori.7@gmail.com>
---
 include/kunit/test.h       |  1 +
 include/kunit/try-catch.h  |  3 +++
 lib/kunit/attributes.c     | 18 ++++++++++++++++
 lib/kunit/kunit-test.c     |  3 +++
 lib/kunit/test.c           |  2 ++
 lib/kunit/try-catch-impl.h |  2 ++
 lib/kunit/try-catch.c      | 14 ++++++++-----
 rust/kernel/kunit.rs       | 51 +++++++++++++++++++++++++++++++++++++++++++---
 rust/macros/kunit.rs       | 35 ++++++++++++++++++++++++-------
 9 files changed, 114 insertions(+), 15 deletions(-)

diff --git a/include/kunit/test.h b/include/kunit/test.h
index 31d549578f8ec113bef9b5d72bc9355c07fce3c0..15bd020d83722163bfc3899f64247afb2c4cefa4 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -83,6 +83,7 @@ enum kunit_speed {
 /* Holds attributes for each test case and suite */
 struct kunit_attributes {
 	enum kunit_speed speed;
+	bool rust_should_panic;
 };
 
 /**
diff --git a/include/kunit/try-catch.h b/include/kunit/try-catch.h
index d4e1a5b98ed67e4f71ff1bcc71422d5bada54b75..197029e19d759dfeb2700af13cfc8fc246768bb9 100644
--- a/include/kunit/try-catch.h
+++ b/include/kunit/try-catch.h
@@ -22,6 +22,8 @@ struct kunit;
  * @try_result: Contains any errno obtained while running test case.
  * @try: The function, the test case, to attempt to run.
  * @catch: The function called if @try bails out.
+ * @rust_should_panic: Flag used to avoid printing spurious error logs when a
+ *	Rust test is annotated with #[should_panic].
  * @context: used to pass user data to the try and catch functions.
  *
  * kunit_try_catch provides a generic, architecture independent way to execute
@@ -48,6 +50,7 @@ struct kunit_try_catch {
 	kunit_try_catch_func_t try;
 	kunit_try_catch_func_t catch;
 	unsigned long timeout;
+	bool rust_should_panic;
 	void *context;
 };
 
diff --git a/lib/kunit/attributes.c b/lib/kunit/attributes.c
index 6d7a53af94a9acf3cf336409462059b972efeb22..8a9dc526b3cb2d363d42087f8666a03e9bc2bc4b 100644
--- a/lib/kunit/attributes.c
+++ b/lib/kunit/attributes.c
@@ -246,6 +246,16 @@ static void *attr_is_init_get(void *test_or_suite, bool is_test)
 		return ((void *) suite->is_init);
 }
 
+static void *attr_rust_should_panic_get(void *test_or_suite, bool is_test)
+{
+	struct kunit_case *test = is_test ? test_or_suite : NULL;
+
+	if (test)
+		return ((void *) test->attr.rust_should_panic);
+	else
+		return ((void *) NULL);
+}
+
 /* List of all Test Attributes */
 
 static struct kunit_attr kunit_attr_list[] = {
@@ -272,6 +282,14 @@ static struct kunit_attr kunit_attr_list[] = {
 		.filter = attr_bool_filter,
 		.attr_default = (void *)false,
 		.print = PRINT_SUITE,
+	},
+	{
+		.name = "rust_should_panic",
+		.get_attr = attr_rust_should_panic_get,
+		.to_string = attr_bool_to_string,
+		.filter = attr_bool_filter,
+		.attr_default = (void *)false,
+		.print = PRINT_NEVER,
 	}
 };
 
diff --git a/lib/kunit/kunit-test.c b/lib/kunit/kunit-test.c
index 126e30879dad652d5b236aeb13d4406a4ddbab00..7cca586767cc711f7a829cc4c3bdec17bd8c7d9c 100644
--- a/lib/kunit/kunit-test.c
+++ b/lib/kunit/kunit-test.c
@@ -45,6 +45,7 @@ static void kunit_test_try_catch_successful_try_no_catch(struct kunit *test)
 			     test,
 			     kunit_test_successful_try,
 			     kunit_test_no_catch,
+			     false,
 			     300 * msecs_to_jiffies(MSEC_PER_SEC));
 	kunit_try_catch_run(try_catch, test);
 
@@ -78,6 +79,7 @@ static void kunit_test_try_catch_unsuccessful_try_does_catch(struct kunit *test)
 			     test,
 			     kunit_test_unsuccessful_try,
 			     kunit_test_catch,
+			     false,
 			     300 * msecs_to_jiffies(MSEC_PER_SEC));
 	kunit_try_catch_run(try_catch, test);
 
@@ -133,6 +135,7 @@ static void kunit_test_fault_null_dereference(struct kunit *test)
 			     test,
 			     kunit_test_null_dereference,
 			     kunit_test_catch,
+			     false,
 			     300 * msecs_to_jiffies(MSEC_PER_SEC));
 	kunit_try_catch_run(try_catch, test);
 
diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index 09e3dabfac0c945b2608feb88c1b1d46fb807edc..8b0072c66e1710c7faa7de2df7ff8c4bf48b8e88 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -584,6 +584,7 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
 			     test,
 			     kunit_try_run_case,
 			     kunit_catch_run_case,
+			     test_case->attr.rust_should_panic,
 			     kunit_test_timeout(suite, test_case));
 	context.test = test;
 	context.suite = suite;
@@ -595,6 +596,7 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
 			     test,
 			     kunit_try_run_case_cleanup,
 			     kunit_catch_run_case_cleanup,
+			     false,
 			     kunit_test_timeout(suite, test_case));
 	kunit_try_catch_run(try_catch, &context);
 
diff --git a/lib/kunit/try-catch-impl.h b/lib/kunit/try-catch-impl.h
index 6f401b97cd0b9842e7533f1b828f72f884450f74..9abe69bb8b396185afb77cb11ca651ba4c9b6a59 100644
--- a/lib/kunit/try-catch-impl.h
+++ b/lib/kunit/try-catch-impl.h
@@ -18,11 +18,13 @@ static inline void kunit_try_catch_init(struct kunit_try_catch *try_catch,
 					struct kunit *test,
 					kunit_try_catch_func_t try,
 					kunit_try_catch_func_t catch,
+					bool rust_should_panic,
 					unsigned long timeout)
 {
 	try_catch->test = test;
 	try_catch->try = try;
 	try_catch->catch = catch;
+	try_catch->rust_should_panic = rust_should_panic;
 	try_catch->timeout = timeout;
 }
 
diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c
index d84a879f0a789f3625538735644910c84ac80e56..b9e29d4e7dd52d8d82d71a3f138f0313c772ee76 100644
--- a/lib/kunit/try-catch.c
+++ b/lib/kunit/try-catch.c
@@ -76,11 +76,15 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
 	if (exit_code == -EFAULT)
 		try_catch->try_result = 0;
 	else if (exit_code == -EINTR) {
-		if (test->last_seen.file)
-			kunit_err(test, "try faulted: last line seen %s:%d\n",
-				  test->last_seen.file, test->last_seen.line);
-		else
-			kunit_err(test, "try faulted\n");
+		if (try_catch->rust_should_panic) {
+			try_catch->try_result = 0;
+		} else {
+			if (test->last_seen.file)
+				kunit_err(test, "try faulted: last line seen %s:%d\n",
+					  test->last_seen.file, test->last_seen.line);
+			else
+				kunit_err(test, "try faulted\n");
+		}
 	} else if (exit_code == -ETIMEDOUT)
 		kunit_err(test, "try timed out\n");
 	else if (exit_code)
diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
index 25ff272d29b2b3f192a3968481c1d5417df4335b..5e688b743ee2152867e2f99c7f18b86e1b7fbe3d 100644
--- a/rust/kernel/kunit.rs
+++ b/rust/kernel/kunit.rs
@@ -58,7 +58,7 @@ pub fn info(args: fmt::Arguments<'_>) {
 #[doc(hidden)]
 #[macro_export]
 macro_rules! kunit_assert {
-    ($name:literal, $condition:expr $(,)?) => {
+    ($name:literal, $test_should_panic:expr, $condition:expr $(,)?) => {
         'out: {
             // Do nothing if the condition is `true`.
             if $condition {
@@ -93,6 +93,14 @@ macro_rules! kunit_assert {
                 ));
                 break 'out;
             }
+            // If condition fails but the test should panic, then we just abort.
+            else if $test_should_panic {
+                // SAFETY: FFI call. The `kunit_test` pointer is valid because we got it from
+                // `kunit_get_current_test()` and it was not null.
+                unsafe {
+                    $crate::bindings::__kunit_abort(kunit_test);
+                }
+            }
 
             #[repr(transparent)]
             struct Location($crate::bindings::kunit_loc);
@@ -166,10 +174,10 @@ unsafe impl Sync for UnaryAssert {}
 #[doc(hidden)]
 #[macro_export]
 macro_rules! kunit_assert_eq {
-    ($name:literal, $left:expr, $right:expr $(,)?) => {{
+    ($name:literal, $test_should_panic:expr, $left:expr, $right:expr $(,)?) => {{
         // For the moment, we just forward to the expression assert because, for binary asserts,
         // KUnit supports only a few types (e.g. integers).
-        $crate::kunit_assert!($name, $left == $right);
+        $crate::kunit_assert!($name, $test_should_panic, $left == $right);
     }};
 }
 
@@ -209,6 +217,7 @@ pub const fn kunit_case(
         name: kernel::str::as_char_ptr_in_const_context(name),
         attr: kernel::bindings::kunit_attributes {
             speed: kernel::bindings::kunit_speed_KUNIT_SPEED_NORMAL,
+            rust_should_panic: false,
         },
         generate_params: None,
         status: kernel::bindings::kunit_status_KUNIT_SUCCESS,
@@ -284,6 +293,7 @@ macro_rules! kunit_unsafe_test_suite {
                     exit: None,
                     attr: ::kernel::bindings::kunit_attributes {
                         speed: ::kernel::bindings::kunit_speed_KUNIT_SPEED_NORMAL,
+                        rust_should_panic: false,
                     },
                     status_comment: [0; 256usize],
                     debugfs: ::core::ptr::null_mut(),
@@ -337,6 +347,16 @@ pub fn in_kunit_test() -> bool {
 mod tests {
     use super::*;
 
+    struct TestStruct;
+
+    impl TestStruct {
+        // This assert does not get replaced with kunit_assert, since this is not a #[test]
+        // function.
+        pub(crate) fn escaped_assert() {
+            assert!(false);
+        }
+    }
+
     #[test]
     fn rust_test_kunit_example_test() {
         assert_eq!(1 + 1, 2);
@@ -347,6 +367,31 @@ fn rust_test_kunit_in_kunit_test() {
         assert!(in_kunit_test());
     }
 
+    #[test]
+    #[should_panic]
+    fn rust_test_kunit_panic_in_kunit_test() {
+        panic!("This test should panic and pass");
+    }
+
+    #[test]
+    #[should_panic]
+    fn rust_test_kunit_panic_in_kunit_test_bug() {
+        // The panic is produced in a C call. This should succeed.
+        unsafe { bindings::BUG() };
+    }
+
+    #[test]
+    #[should_panic]
+    fn rust_test_assert_false_success_with_should_panic() {
+        assert!(false)
+    }
+
+    #[test]
+    #[should_panic]
+    fn rust_test_should_panic_with_escaped_assert() {
+        TestStruct::escaped_assert();
+    }
+
     #[test]
     #[cfg(not(all()))]
     fn rust_test_kunit_always_disabled_test() {
diff --git a/rust/macros/kunit.rs b/rust/macros/kunit.rs
index e9152b9d51f9450b7e549e2e1629b5fc5f485a28..288b53d21c4e7c8d9b5148d50c1a833f73e53015 100644
--- a/rust/macros/kunit.rs
+++ b/rust/macros/kunit.rs
@@ -106,6 +106,11 @@ pub(crate) fn kunit_tests(test_suite: Ident, mut module: ItemMod) -> Result<Toke
             .cloned()
             .collect();
 
+        let should_panic = f
+            .attrs
+            .iter()
+            .any(|attr| attr.path().is_ident("should_panic"));
+
         // Before the test, override usual `assert!` and `assert_eq!` macros with ones that call
         // KUnit instead.
         let test_str = test.to_string();
@@ -113,7 +118,7 @@ pub(crate) fn kunit_tests(test_suite: Ident, mut module: ItemMod) -> Result<Toke
             #[allow(unused)]
             macro_rules! assert {
                 ($cond:expr $(,)?) => {{
-                    kernel::kunit_assert!(#test_str, $cond);
+                    kernel::kunit_assert!(#test_str, #should_panic, $cond);
                 }}
             }
         });
@@ -121,7 +126,7 @@ macro_rules! assert {
             #[allow(unused)]
             macro_rules! assert_eq {
                 ($left:expr, $right:expr $(,)?) => {{
-                    kernel::kunit_assert_eq!(#test_str, $left, $right);
+                    kernel::kunit_assert_eq!(#test_str, #should_panic, $left, $right);
                 }}
             }
         });
@@ -134,25 +139,41 @@ macro_rules! assert_eq {
             &CString::new(test_str.as_str()).expect("identifier cannot contain NUL"),
             test.span(),
         );
+        let assertion = if should_panic {
+            quote!(
+                let _ = #test();
+                ::kernel::kunit::err(::kernel::prelude::fmt!(
+                    "    Expected {} to panic\n", #test_str
+                ));
+                (*_test).status = ::kernel::bindings::kunit_status_KUNIT_FAILURE;
+            )
+        } else {
+            quote!(
+                use ::kernel::kunit::is_test_result_ok;
+                assert!(is_test_result_ok(#test()));
+            )
+        };
         processed_items.push(parse_quote! {
             unsafe extern "C" fn #kunit_wrapper_fn_name(_test: *mut ::kernel::bindings::kunit) {
                 (*_test).status = ::kernel::bindings::kunit_status_KUNIT_SKIPPED;
 
+
                 // Append any `cfg` attributes the user might have written on their tests so we
                 // don't attempt to call them when they are `cfg`'d out. An extra `use` is used
                 // here to reduce the length of the assert message.
                 #(#cfg_attrs)*
                 {
                     (*_test).status = ::kernel::bindings::kunit_status_KUNIT_SUCCESS;
-                    use ::kernel::kunit::is_test_result_ok;
-                    assert!(is_test_result_ok(#test()));
+                    #assertion
                 }
             }
         });
 
-        test_cases.push(quote!(
-            ::kernel::kunit::kunit_case(#test_cstr, #kunit_wrapper_fn_name)
-        ));
+        test_cases.push(quote!({
+            let mut case = ::kernel::kunit::kunit_case(#test_cstr, #kunit_wrapper_fn_name);
+            case.attr.rust_should_panic = #should_panic;
+            case
+        }));
     }
 
     let num_tests_plus_1 = test_cases.len() + 1;

-- 
2.47.3



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 2/3] rust: kunit: allow same test name with different #[cfg(...)]
  2026-10-29 16:59 [PATCH v2 0/3] rust: kunit: support #[should_panic] and same test name with different #[cfg(...)] Nicolás Antinori via B4 Relay
  2026-10-29 16:59 ` [PATCH v2 1/3] rust: kunit: add #[should_panic] support Nicolás Antinori via B4 Relay
@ 2026-10-29 16:59 ` Nicolás Antinori via B4 Relay
  2026-11-03 14:45   ` David Gow
  2026-10-29 16:59 ` [PATCH v2 3/3] rust: bitmap: kunit: uncomment owned_bitmap_out_of_bounds panic case Nicolás Antinori via B4 Relay
  2026-11-03 14:45 ` [PATCH v2 0/3] rust: kunit: support #[should_panic] and same test name with different #[cfg(...)] David Gow
  3 siblings, 1 reply; 15+ messages in thread
From: Nicolás Antinori via B4 Relay @ 2026-10-29 16:59 UTC (permalink / raw)
  To: Alice Ryhl, Benno Lossin, Boqun Feng, Brendan Higgins,
	Daniel Almeida, Danilo Krummrich, David Gow, Gary Guo,
	Miguel Ojeda, Onur Özkan
  Cc: Alexandre Courbot, Andreas Hindborg, Björn Roy Baron,
	Burak Emir, Rae Moar, Tamir Duberstein, Trevor Gross, Yury Norov,
	kunit-dev, linux-kernel, linux-kselftest, rust-for-linux,
	Nicolás Antinori

From: Nicolás Antinori <nico.antinori.7@gmail.com>

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@gmail.com>
---
 rust/kernel/kunit.rs | 22 ++++++++++++++++++++++
 rust/macros/kunit.rs | 36 ++++++++++++++++++++----------------
 2 files changed, 42 insertions(+), 16 deletions(-)

diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
index 5e688b743ee2152867e2f99c7f18b86e1b7fbe3d..ba3040d302b95af6d6e648a229ac8e9ea2c31a8c 100644
--- a/rust/kernel/kunit.rs
+++ b/rust/kernel/kunit.rs
@@ -367,6 +367,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 288b53d21c4e7c8d9b5148d50c1a833f73e53015..173792563ca8b42e39ec0a53798f7b3bb75bf9cf 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]`.
     //
@@ -134,7 +136,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(),
@@ -154,18 +156,12 @@ macro_rules! assert_eq {
             )
         };
         processed_items.push(parse_quote! {
+            // Prepend any `cfg` attributes before the function declaration to activate it only in
+            // cases the configs are on
+            #(#cfg_attrs)*
             unsafe extern "C" fn #kunit_wrapper_fn_name(_test: *mut ::kernel::bindings::kunit) {
-                (*_test).status = ::kernel::bindings::kunit_status_KUNIT_SKIPPED;
-
-
-                // Append any `cfg` attributes the user might have written on their tests so we
-                // don't attempt to call them when they are `cfg`'d out. An extra `use` is used
-                // here to reduce the length of the assert message.
-                #(#cfg_attrs)*
-                {
-                    (*_test).status = ::kernel::bindings::kunit_status_KUNIT_SUCCESS;
-                    #assertion
-                }
+                (*_test).status = ::kernel::bindings::kunit_status_KUNIT_SUCCESS;
+                #assertion
             }
         });
 
@@ -174,15 +170,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



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v2 3/3] rust: bitmap: kunit: uncomment owned_bitmap_out_of_bounds panic case
  2026-10-29 16:59 [PATCH v2 0/3] rust: kunit: support #[should_panic] and same test name with different #[cfg(...)] Nicolás Antinori via B4 Relay
  2026-10-29 16:59 ` [PATCH v2 1/3] rust: kunit: add #[should_panic] support Nicolás Antinori via B4 Relay
  2026-10-29 16:59 ` [PATCH v2 2/3] rust: kunit: allow same test name with different #[cfg(...)] Nicolás Antinori via B4 Relay
@ 2026-10-29 16:59 ` Nicolás Antinori via B4 Relay
  2026-11-03 14:46   ` David Gow
  2026-11-03 14:45 ` [PATCH v2 0/3] rust: kunit: support #[should_panic] and same test name with different #[cfg(...)] David Gow
  3 siblings, 1 reply; 15+ messages in thread
From: Nicolás Antinori via B4 Relay @ 2026-10-29 16:59 UTC (permalink / raw)
  To: Alice Ryhl, Benno Lossin, Boqun Feng, Brendan Higgins,
	Daniel Almeida, Danilo Krummrich, David Gow, Gary Guo,
	Miguel Ojeda, Onur Özkan
  Cc: Alexandre Courbot, Andreas Hindborg, Björn Roy Baron,
	Burak Emir, Rae Moar, Tamir Duberstein, Trevor Gross, Yury Norov,
	kunit-dev, linux-kernel, linux-kselftest, rust-for-linux,
	Nicolás Antinori

From: Nicolás Antinori <nico.antinori.7@gmail.com>

Rust KUnit tests now support `#[should_panic]` attribute. Uncomment the
test so it can be run when CONFIG_RUST_BITMAP_HARDENED=y.

Signed-off-by: Nicolás Antinori <nico.antinori.7@gmail.com>
---
 rust/kernel/bitmap.rs | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/rust/kernel/bitmap.rs b/rust/kernel/bitmap.rs
index 610d565535ccfba6af8f2ca4ac4028fa027a9644..8eecd669096713fc7f21431188959a921a1d5ca0 100644
--- a/rust/kernel/bitmap.rs
+++ b/rust/kernel/bitmap.rs
@@ -762,11 +762,10 @@ fn bitmap_set_clear_find() -> Result<(), AllocError> {
         Ok(())
     }
 
-    #[test]
     #[cfg(not(CONFIG_RUST_BITMAP_HARDENED))]
+    #[test]
     fn owned_bitmap_out_of_bounds() -> Result<(), AllocError> {
         let mut b = BitmapVec::new(128, GFP_KERNEL)?;
-
         b.set_bit(2048);
         b.set_bit_atomic(2048);
         b.clear_bit(2048);
@@ -777,15 +776,15 @@ fn owned_bitmap_out_of_bounds() -> Result<(), AllocError> {
         Ok(())
     }
 
-    // TODO: uncomment once kunit supports `#[should_panic]`.
-    // #[cfg(CONFIG_RUST_BITMAP_HARDENED)]
-    // #[test]
-    // #[should_panic]
-    // fn owned_bitmap_out_of_bounds() -> Result<(), AllocError> {
-    //     let mut b = BitmapVec::new(128, GFP_KERNEL)?;
-    //
-    //     b.set_bit(2048);
-    // }
+    #[cfg(CONFIG_RUST_BITMAP_HARDENED)]
+    #[test]
+    #[should_panic]
+    fn owned_bitmap_out_of_bounds() -> Result<(), AllocError> {
+        let mut b = BitmapVec::new(128, GFP_KERNEL)?;
+
+        b.set_bit(2048);
+        Ok(())
+    }
 
     #[test]
     fn bitmap_copy_and_extend() -> Result<(), AllocError> {

-- 
2.47.3



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/3] rust: kunit: add #[should_panic] support
  2026-10-29 16:59 ` [PATCH v2 1/3] rust: kunit: add #[should_panic] support Nicolás Antinori via B4 Relay
@ 2026-11-02 14:58   ` Nicolás Antinori
  2026-11-02 15:51     ` Miguel Ojeda
  2026-11-03 15:00     ` David Gow
  2026-11-03 14:46   ` David Gow
  1 sibling, 2 replies; 15+ messages in thread
From: Nicolás Antinori @ 2026-11-02 14:58 UTC (permalink / raw)
  To: nico.antinori.7, Alice Ryhl, Benno Lossin, Boqun Feng,
	Brendan Higgins, Daniel Almeida, Danilo Krummrich, David Gow,
	Gary Guo, Miguel Ojeda, Onur Özkan
  Cc: Alexandre Courbot, Andreas Hindborg, Björn Roy Baron,
	Burak Emir, Rae Moar, Tamir Duberstein, Trevor Gross, Yury Norov,
	kunit-dev, linux-kernel, linux-kselftest, rust-for-linux

On Thu Oct 29, 2026 at 1:59 PM -03, Nicolás Antinori via B4 Relay wrote:
> From: Nicolás Antinori <nico.antinori.7@gmail.com>
>
> KUnit tests in Rust are written using user-space like syntax. This patch
> adds support for the `#[should_panic]` attribute, enabling the user to
> test conditions that are expected to cause a panic and report the test
> as successful.
>
> Signed-off-by: Nicolás Antinori <nico.antinori.7@gmail.com>

Hello, Sashiko found two issues [1] with this patch:

> [Severity: High]
> Will these new selftests crash the kernel or hang when
> CONFIG_RUST_KUNIT_SELFTEST is enabled under CONFIG_UML=y,
> CONFIG_PANIC_ON_OOPS=y, or CONFIG_BUG=n?

This is true, I tested this with:

./tools/testing/kunit/kunit.py run \
	--make_options LLVM=1 \
	--kconfig_add CONFIG_RUST=y \
	--kconfig_add CONFIG_RUST_KUNIT_TESTS=y \
	--kconfig_add CONFIG_KUNIT=y \
	--kconfig_add CONFIG_UML=y \
	--arch=um rust_kernel_kunit

./tools/testing/kunit/kunit.py run \
	--make_options LLVM=1 \
	--kconfig_add CONFIG_RUST=y \
	--kconfig_add CONFIG_RUST_KUNIT_TESTS=y \
	--kconfig_add CONFIG_KUNIT=y \
	--kconfig_add CONFIG_PANIC_ON_OOPS=y \
	--arch=x86_64 rust_kernel_kunit

And some other configs using the configs causing problems.

To solve this I created a new config "RUST_KUNIT_SHOULD_PANIC_ATTRIBUTE"
that depends on !UML && !PANIC_ON_OOPS && BUG. If the test is annotated
with `#[should_panic]` and CONFIG_RUST_KUNIT_SHOULD_PANIC_ATTRIBUTE=n,
the test won't run and won't show up in the summary.

> [Severity: Medium]
> Does defining macro_rules! assert and macro_rules! assert_eq at module scope
> in kunit_tests() leak the preceding test's #should_panic value into helper
> functions or impl blocks defined later in the module?

This is also true, the solution was redefining the `assert!` and
`assert_eq!` macros inside the function's body (as Sashiko suggested).

I'll wait a bit in case there are any feedback on the current series and
send a v3 with these changes. 

Best Regards,
Nicolás 

[1] https://sashiko.dev/#/patchset/20261029-rust_kunit_v6_send-v2-0-5ce551efc48e@gmail.com?part=1

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/3] rust: kunit: add #[should_panic] support
  2026-11-02 14:58   ` Nicolás Antinori
@ 2026-11-02 15:51     ` Miguel Ojeda
  2026-11-02 20:53       ` Nicolás Antinori
  2026-11-03 15:00     ` David Gow
  1 sibling, 1 reply; 15+ messages in thread
From: Miguel Ojeda @ 2026-11-02 15:51 UTC (permalink / raw)
  To: Nicolás Antinori
  Cc: Alice Ryhl, Benno Lossin, Boqun Feng, Brendan Higgins,
	Daniel Almeida, Danilo Krummrich, David Gow, Gary Guo,
	Miguel Ojeda, Onur Özkan, Alexandre Courbot,
	Andreas Hindborg, Björn Roy Baron, Burak Emir, Rae Moar,
	Tamir Duberstein, Trevor Gross, Yury Norov, kunit-dev,
	linux-kernel, linux-kselftest, rust-for-linux

On Mon, Nov 2, 2026 at 3:58 PM Nicolás Antinori
<nico.antinori.7@gmail.com> wrote:
>
> To solve this I created a new config "RUST_KUNIT_SHOULD_PANIC_ATTRIBUTE"
> that depends on !UML && !PANIC_ON_OOPS && BUG. If the test is annotated
> with `#[should_panic]` and CONFIG_RUST_KUNIT_SHOULD_PANIC_ATTRIBUTE=n,
> the test won't run and won't show up in the summary.

I was wondering if we needed the flexibility, i.e. if we could just
simply disable them when the conditions are not satisfied, but I guess
given `CONFIG_KUNIT_FAULT_TEST`'s existing description, it may make
sense to have a new Kconfig symbol -- do the ones added here look
similar in the kernel log to those fault ones?

(And I was wondering because, in general, adding Kconfig symbols has a
price: users may get confused etc.).

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/3] rust: kunit: add #[should_panic] support
  2026-11-02 15:51     ` Miguel Ojeda
@ 2026-11-02 20:53       ` Nicolás Antinori
  2026-11-02 21:25         ` Miguel Ojeda
  0 siblings, 1 reply; 15+ messages in thread
From: Nicolás Antinori @ 2026-11-02 20:53 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Alice Ryhl, Benno Lossin, Boqun Feng, Brendan Higgins,
	Daniel Almeida, Danilo Krummrich, David Gow, Gary Guo,
	Miguel Ojeda, Onur Özkan, Alexandre Courbot,
	Andreas Hindborg, Björn Roy Baron, Burak Emir, Rae Moar,
	Tamir Duberstein, Trevor Gross, Yury Norov, kunit-dev,
	linux-kernel, linux-kselftest, rust-for-linux

On Mon Nov 2, 2026 at 12:51 PM -03, Miguel Ojeda wrote:
> On Mon, Nov 2, 2026 at 3:58 PM Nicolás Antinori
> <nico.antinori.7@gmail.com> wrote:
>>
>> To solve this I created a new config "RUST_KUNIT_SHOULD_PANIC_ATTRIBUTE"
>> that depends on !UML && !PANIC_ON_OOPS && BUG. If the test is annotated
>> with `#[should_panic]` and CONFIG_RUST_KUNIT_SHOULD_PANIC_ATTRIBUTE=n,
>> the test won't run and won't show up in the summary.
>
> I was wondering if we needed the flexibility, i.e. if we could just
> simply disable them when the conditions are not satisfied, but I guess
> given `CONFIG_KUNIT_FAULT_TEST`'s existing description, it may make
> sense to have a new Kconfig symbol 

I first thought of disabling `#[should_panic]` tests by directly
checking the conditions in the macro code. I ended up creating a new
config because I thought it would be cleaner codewise, if a new
constraint arises in the future, we just have to add it to the 
`depends on` clause instead of modifying the macro code.

> -- do the ones added here look
> similar in the kernel log to those fault ones?

Yes! they are pretty similar, for `KUNIT_FAULT_TEST`:

KTAP version 1
1..1
    KTAP version 1
    # Subtest: kunit_fault
    # module: kunit_test
    1..1
BUG: kernel NULL pointer dereference, address: 0000000000000000
#PF: supervisor write access in kernel mode
#PF: error_code(0x0002) - not-present page
PGD 0 P4D 0
Oops: Oops: 0002 [#1] SMP NOPTI
CPU: 0 UID: 0 PID: 30 Comm: kunit_try_catch Tainted: G                 N   7.3.0-18137-ga2943ba718b4-dirty #357 PREEMPT(lazy)
Tainted: [N]=TEST
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 0.1 11/11/2019

... <Registers and stack trace> ...

note: kunit_try_catch[30] exited with irqs disabled
    # kunit_test_fault_null_dereference: try faulted: last line seen lib/kunit/kunit-test.c:100
    ok 1 kunit_test_fault_null_dereference
ok 1 kunit_fault

For `RUST_KUNIT_TESTS` (left only one that panics to shrink the log, but
they are all pretty much the same):

KTAP version 1
1..1
    KTAP version 1
    # Subtest: rust_kernel_kunit
    # speed: normal
    1..1
rust_kernel: panicked at ../rust/kernel/kunit.rs:399:9:
This test should panic and pass
------------[ cut here ]------------
kernel BUG at rust/helpers/bug.c:7!
Oops: invalid opcode: 0000 [#1] SMP NOPTI
CPU: 0 UID: 0 PID: 29 Comm: kunit_try_catch Tainted: G                 N   7.3.0-18137-ga2943ba718b4-dirty #357 PREEMPT(lazy)
Tainted: [N]=TEST
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 0.1 11/11/2019

... <Registers and stack trace> ...

    # rust_test_kunit_panic_in_kunit_test.speed: normal
    ok 1 rust_test_kunit_panic_in_kunit_test
ok 1 rust_kernel_kunit

The only one that is different in `RUST_KUNIT_TESTS` is:

#[test]
#[should_panic]
fn rust_test_assert_false_success_with_should_panic() {
    assert!(false)
}

That logs:

KTAP version 1
1..1
    KTAP version 1
    # Subtest: rust_kernel_kunit
    # speed: normal
    1..1
    # rust_test_assert_false_success_with_should_panic.speed: normal
    ok 1 rust_test_assert_false_success_with_should_panic
ok 1 rust_kernel_kunit

Because a BUG() is never called, the failed assertion is catched in the
`kunit_assert!` macro and, if the test should panic, the KUnit thread is
aborted without throwing a failed asssertion.

>
> (And I was wondering because, in general, adding Kconfig symbols has a
> price: users may get confused etc.).

On top of the reasons I gave above, I tried to follow the same as
`CONFIG_RUST_BUG_KUNIT_TEST` or `CONFIG_KUNIT_FAULT_TEST` are doing, but
in this case in particular, the config is not for enabling a test suite
but for enabling a feature that can affect multiple suites (in this
patch series the ones behind `CONFIG_RUST_KUNIT_TESTS` and
`CONFIG_RUST_BITMAP_KUNIT_TESTS`).

If this is prone to causing confusion, I think I am going to check the
contraints direclty in the code. 

Thank you for the feedback!

>
> Cheers,
> Miguel


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/3] rust: kunit: add #[should_panic] support
  2026-11-02 20:53       ` Nicolás Antinori
@ 2026-11-02 21:25         ` Miguel Ojeda
  2026-11-03 15:05           ` David Gow
  0 siblings, 1 reply; 15+ messages in thread
From: Miguel Ojeda @ 2026-11-02 21:25 UTC (permalink / raw)
  To: Nicolás Antinori, David Gow
  Cc: Alice Ryhl, Benno Lossin, Boqun Feng, Brendan Higgins,
	Daniel Almeida, Danilo Krummrich, Gary Guo, Miguel Ojeda,
	Onur Özkan, Alexandre Courbot, Andreas Hindborg,
	Björn Roy Baron, Burak Emir, Rae Moar, Tamir Duberstein,
	Trevor Gross, Yury Norov, kunit-dev, linux-kernel,
	linux-kselftest, rust-for-linux

On Mon, Nov 2, 2026 at 9:53 PM Nicolás Antinori
<nico.antinori.7@gmail.com> wrote:
>
> I first thought of disabling `#[should_panic]` tests by directly
> checking the conditions in the macro code. I ended up creating a new
> config because I thought it would be cleaner codewise, if a new
> constraint arises in the future, we just have to add it to the
> `depends on` clause instead of modifying the macro code.

It depends on what we want: if it is meant to be configurable, then it
should be a visible Kconfig symbol; if not, then it should remain an
implementation detail (which could perhaps be a non-visible Kconfig
symbol).

> Yes! they are pretty similar, for `KUNIT_FAULT_TEST`:

Yeah, in that case, I think a new visible Kconfig symbol may be
justifiable -- please see below.

> The only one that is different in `RUST_KUNIT_TESTS` is:
>
> #[test]
> #[should_panic]
> fn rust_test_assert_false_success_with_should_panic() {
>     assert!(false)
> }

I guess it is reasonable to expect this test to pass, since `assert!`
doesn't return and actually panics in normal Rust.

Having said that, I would expect our `should_panic` tests to be
generally about non-`assert*!` panics.

> On top of the reasons I gave above, I tried to follow the same as
> `CONFIG_RUST_BUG_KUNIT_TEST` or `CONFIG_KUNIT_FAULT_TEST` are doing, but
> in this case in particular, the config is not for enabling a test suite
> but for enabling a feature that can affect multiple suites (in this
> patch series the ones behind `CONFIG_RUST_KUNIT_TESTS` and
> `CONFIG_RUST_BITMAP_KUNIT_TESTS`).

Yeah, it is a "mode" -- that is why originally I thought we would try
to just do the right thing automatically, i.e. enable them when
possible, but then when I saw the description of
`CONFIG_KUNIT_FAULT_TEST`:

    Enables fault handling tests for the KUnit framework. These tests may
    trigger a kernel BUG(), and the associated stack trace, even when they
    pass. If this conflicts with your test infrastrcture (or is confusing
    or annoying), they can be disabled by setting this to N.

and I thought it may be fair to have the Kconfig symbol, i.e. it could
also be annoying to see the traces or similar, and thus it may be that
someone needs to disable this.

Having said that, if nobody has asked, we could keep it simple for now
as well -- that may be fine too.

David: what do you think? Is it something that was discussed back then
for that one in C?

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 0/3] rust: kunit: support #[should_panic] and same test name with different #[cfg(...)]
  2026-10-29 16:59 [PATCH v2 0/3] rust: kunit: support #[should_panic] and same test name with different #[cfg(...)] Nicolás Antinori via B4 Relay
                   ` (2 preceding siblings ...)
  2026-10-29 16:59 ` [PATCH v2 3/3] rust: bitmap: kunit: uncomment owned_bitmap_out_of_bounds panic case Nicolás Antinori via B4 Relay
@ 2026-11-03 14:45 ` David Gow
  3 siblings, 0 replies; 15+ messages in thread
From: David Gow @ 2026-11-03 14:45 UTC (permalink / raw)
  To: nico.antinori.7, Alice Ryhl, Benno Lossin, Boqun Feng,
	Brendan Higgins, Daniel Almeida, Danilo Krummrich, Gary Guo,
	Miguel Ojeda, Onur Özkan
  Cc: Alexandre Courbot, Andreas Hindborg, Björn Roy Baron,
	Burak Emir, Rae Moar, Tamir Duberstein, Trevor Gross, Yury Norov,
	kunit-dev, linux-kernel, linux-kselftest, rust-for-linux

Thanks very much, Nicolás.

I've had a closer look at the new version of this, and have a few 
comments. Ultimately, I think a mix of this version and the original RFC 
is probably best, and in particular, using a panic_handler instead of 
modifying kunit_try_catch, and removing the special-case assert!() 
handling would be ideal.

Le 30/10/2026 à 00:59, Nicolás Antinori via B4 Relay a écrit :
> This patch series intends to implement two features for KUnit tests
> written in Rust. The work is based on a TODO comment made in the
> `bitmap.rs` module [1].
> 
> Changelog:
> 
> v2:
> - Added more tests in `rust/kernel/kunit.rs` testing Sashiko findings
>    and changes.
> - Solved Sashiko: "[Low] kunit: spurious "try faulted" error logs for
>    successful #[should_panic] tests": Solved by adding
>    `rust_should_panic` in `kunit_try_catch` C struct to check if the test
>    is expected to panic and act accordingly. Dismissed what I first talked
>    about in [3].

I think if we only handle Rust panics, this should go away, right?

> - Solved Sashiko: "[Medium] kunit: assert! macro in #[should_panic]
>    tests causes unexpected failure": Solved by making `kunit_assert`
>    macro aware if the test should panic and act accordingly. Dismissed what
>    I first talked about in [3]
> - Solved Sashiko: "[Low] kunit: missing diagnostic log for
>    #[should_panic] tests that fail to panic": Added an error message when
>    a test that was expected to panic do not
> - Solved Sashiko: "[Low] kunit: dead_code error for test wrappers with
>    inactive cfg": Solved by moving the #[cfg(..)] attributes on top of
>    the wrapper functions
> - Dismissed Sashiko: "[Medium] rust: bitmap: memory leak in
>    owned_bitmap_out_of_bounds() test panic": Not sure if can be done
>    anything. If I am not mistaken this is the same issue as stated here [4].

Yes, the issue in [4] (that tests exiting early is unsafe) is known and 
kind-of unfixable. It does mean that we'd want to avoid deliberately 
panic-ing if we at all can.

It's possible to avoid resource leaks by using the KUnit resource / 
defer functionality, but that's not readily exposed in Rust at the 
moment (and it's likely to be highly non-idiomatic).

> 
> Sashiko report links: https://sashiko.dev/#/patchset/20260930-rust_kunit_v4-v1-0-e3b0d45311dd@gmail.com?part=1
> 
> v1:
> - Removed 'stringification' of test names (to avoid clash of names for
>    different configurations now a number is appended).
> - Added bool `rust_should_panic` attribute to `kunit_attributes` C
>    struct

I like this, but if we're calling it 'rust_should_panic', it should only 
affect Rust panics.

> - Removed #[panic_handler] in Rust side, checking for aborts in the C
>    side (`kunit_run_case_catch_errors` function). This allow to catch
>    panics triggered, for example in a Rust function that called a panicking
>    C function.

Ultimately, I think that we probably want to restrict #[should_panic] to 
Rust panics at this stage, so using #[panic_handler] would work best.

This greatly simplifies the implementation, and makes it much more targeted.

If we do really want to support panics from C, then I think we want to 
build this on top of the warning suppression feature[1], and expose it 
from C as well as Rust. It only traps WARN(), rather than BUG(), though.

> - Now the tests that have an inactive #[cfg(..)] do not appear un the
>    KUnit execution summary as ignored, they just do not run.
> Link to v1: https://lore.kernel.org/all/20260930-rust_kunit_v4-v1-0-e3b0d45311dd@gmail.com/
> 
> - RFC patch: https://lore.kernel.org/rust-for-linux/cover.1789500084.git.nico.antinori.7@gmail.com/
> 
> 1. Supporting `#[should_panic]` [2]:
> 
> KUnit tests in Rust follow the user-space syntax, but at the moment
> `#[should_panic]` is not supported. The first patch of this series adds
> support for the attribute (only in its basic form, `#[should_panic =
> "message"]` is not supported yet).
> 
> The way it is supported is by adding a new boolean property called
> `rust_should_panic` to `kunit_attributes` struct in kunit/test.h and in
> `kunit_attributes` in kunit/try-catch.h and check for the
> `try_catch->try_result` code and the named flag to detect if there was a
> panic in `kunit_try_catch_run` function.

I think rust_should_panic as an attribute is good, but it should just be 
checked from a panic_handler. If it supports more than just rust panics, 
it probably shouldn't be called *rust_*should_panic (and again, should 
probably be based on the warning suppression instead).


> 2. Allow same test name with different #[cfg(...)]:
> 
> When testing `#[should_panic]` in `bitmap.rs` (check the last patch of
> the series) I found that the test that was supposed to panic had the
> same name as another one, but they were run on different configurations.
> This caused the following compilation error:
> 
> ERROR:root:error[E0428]: the name `kunit_rust_wrapper_owned_bitmap_out_of_bounds` is defined multiple times
>     --> ../rust/kernel/bitmap.rs:503:1
>      |
> 503 | #[macros::kunit_tests(rust_kernel_bitmap)]
>      | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `kunit_rust_wrapper_owned_bitmap_out_of_bounds` redefined here
>      |
>      = note: `kunit_rust_wrapper_owned_bitmap_out_of_bounds` must be defined only once in the value namespace of this module
>      = note: this error originates in the attribute macro `macros::kunit_tests` (in Nightly builds, run with -Z macro-backtrace for more info)
> 
> Now, only the tests with an active `#[cfg(...)]` will be executed by the
> runner. Tests with an inactive `#[cfg(...)]` will not appear in the
> report since they are not added to the TEST_CASES array.

This is great, thanks!

> 
> [1] https://github.com/Rust-for-Linux/linux/blob/fd73f4a6659897191fa0d40695fe370925dd3780/rust/kernel/bitmap.rs#L592-L600
> [2] https://doc.rust-lang.org/rust-by-example/testing/unit_testing.html#testing-panics
> [3] https://lore.kernel.org/all/DM41PHVITKOG.3I6P2X8048BEP@gmail.com/
> [4] https://github.com/Rust-for-Linux/linux/blob/fd73f4a6659897191fa0d40695fe370925dd3780/rust/kernel/kunit.rs#L129-L136
> 
> Signed-off-by: Nicolás Antinori <nico.antinori.7@gmail.com>
> ---

Cheers,
-- David

[1]: 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=85347718ab0dd7ede9c3e1dcff2d604c7073df05

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 2/3] rust: kunit: allow same test name with different #[cfg(...)]
  2026-10-29 16:59 ` [PATCH v2 2/3] rust: kunit: allow same test name with different #[cfg(...)] Nicolás Antinori via B4 Relay
@ 2026-11-03 14:45   ` David Gow
  0 siblings, 0 replies; 15+ messages in thread
From: David Gow @ 2026-11-03 14:45 UTC (permalink / raw)
  To: nico.antinori.7, Alice Ryhl, Benno Lossin, Boqun Feng,
	Brendan Higgins, Daniel Almeida, Danilo Krummrich, Gary Guo,
	Miguel Ojeda, Onur Özkan
  Cc: Alexandre Courbot, Andreas Hindborg, Björn Roy Baron,
	Burak Emir, Rae Moar, Tamir Duberstein, Trevor Gross, Yury Norov,
	kunit-dev, linux-kernel, linux-kselftest, rust-for-linux

Le 30/10/2026 à 00:59, Nicolás Antinori via B4 Relay a écrit :
> From: Nicolás Antinori <nico.antinori.7@gmail.com>
> 
> 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@gmail.com>
> ---

Thanks very much.

This is a great improvement over the old implementation, IMO.

Reviewed-by: David Gow <david@davidgow.net>

Cheers,
-- David

>   rust/kernel/kunit.rs | 22 ++++++++++++++++++++++
>   rust/macros/kunit.rs | 36 ++++++++++++++++++++----------------
>   2 files changed, 42 insertions(+), 16 deletions(-)
> 
> diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
> index 5e688b743ee2152867e2f99c7f18b86e1b7fbe3d..ba3040d302b95af6d6e648a229ac8e9ea2c31a8c 100644
> --- a/rust/kernel/kunit.rs
> +++ b/rust/kernel/kunit.rs
> @@ -367,6 +367,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 288b53d21c4e7c8d9b5148d50c1a833f73e53015..173792563ca8b42e39ec0a53798f7b3bb75bf9cf 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]`.
>       //
> @@ -134,7 +136,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(),
> @@ -154,18 +156,12 @@ macro_rules! assert_eq {
>               )
>           };
>           processed_items.push(parse_quote! {
> +            // Prepend any `cfg` attributes before the function declaration to activate it only in
> +            // cases the configs are on
> +            #(#cfg_attrs)*
>               unsafe extern "C" fn #kunit_wrapper_fn_name(_test: *mut ::kernel::bindings::kunit) {
> -                (*_test).status = ::kernel::bindings::kunit_status_KUNIT_SKIPPED;
> -
> -
> -                // Append any `cfg` attributes the user might have written on their tests so we
> -                // don't attempt to call them when they are `cfg`'d out. An extra `use` is used
> -                // here to reduce the length of the assert message.
> -                #(#cfg_attrs)*
> -                {
> -                    (*_test).status = ::kernel::bindings::kunit_status_KUNIT_SUCCESS;
> -                    #assertion
> -                }
> +                (*_test).status = ::kernel::bindings::kunit_status_KUNIT_SUCCESS;
> +                #assertion
>               }
>           });
>   
> @@ -174,15 +170,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);
>       });
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/3] rust: kunit: add #[should_panic] support
  2026-10-29 16:59 ` [PATCH v2 1/3] rust: kunit: add #[should_panic] support Nicolás Antinori via B4 Relay
  2026-11-02 14:58   ` Nicolás Antinori
@ 2026-11-03 14:46   ` David Gow
  2026-11-03 16:32     ` Miguel Ojeda
  1 sibling, 1 reply; 15+ messages in thread
From: David Gow @ 2026-11-03 14:46 UTC (permalink / raw)
  To: nico.antinori.7, Alice Ryhl, Benno Lossin, Boqun Feng,
	Brendan Higgins, Daniel Almeida, Danilo Krummrich, Gary Guo,
	Miguel Ojeda, Onur Özkan
  Cc: Alexandre Courbot, Andreas Hindborg, Björn Roy Baron,
	Burak Emir, Rae Moar, Tamir Duberstein, Trevor Gross, Yury Norov,
	kunit-dev, linux-kernel, linux-kselftest, rust-for-linux

Le 30/10/2026 à 00:59, Nicolás Antinori via B4 Relay a écrit :
> From: Nicolás Antinori <nico.antinori.7@gmail.com>
> 
> KUnit tests in Rust are written using user-space like syntax. This patch
> adds support for the `#[should_panic]` attribute, enabling the user to
> test conditions that are expected to cause a panic and report the test
> as successful.
> 
> Signed-off-by: Nicolás Antinori <nico.antinori.7@gmail.com>
> ---

Thanks very much.

I'm afraid I'd rather go back to the RFC's design of only triggering on 
Rust panic!(), rather than on failures in C. It's a much simpler 
implementation, and makes more sense for a rust-specific #[should_panic] 
to me.

If we really want to support C panics, then something which works with 
CONFIG_UML would be ideal. The warning suppression implementation here 
does this for WARN(), and exposing that to Rust might make more sense if 
that's something we'd need.

Secondly, I'm not convinced we want to alter the behaviour of 
assertions. At least KUNIT_ASSERT_* should still be useful in a test 
ensuring that the state of the system being tested makes sense before a 
deliberate panic!(), and arbitrarily reversing the meaning of assert!() 
feels confusing to me.

That being said, I understand if we want assert!() from _outside_ the 
test (i.e., an assert!() in the code being tested, not the test itself) 
to be considered a panic!().

A few small notes below, but it's mostly just re-iterating what I've 
just said.

Cheers,
-- David

>   include/kunit/test.h       |  1 +
>   include/kunit/try-catch.h  |  3 +++
>   lib/kunit/attributes.c     | 18 ++++++++++++++++
>   lib/kunit/kunit-test.c     |  3 +++
>   lib/kunit/test.c           |  2 ++
>   lib/kunit/try-catch-impl.h |  2 ++
>   lib/kunit/try-catch.c      | 14 ++++++++-----
>   rust/kernel/kunit.rs       | 51 +++++++++++++++++++++++++++++++++++++++++++---
>   rust/macros/kunit.rs       | 35 ++++++++++++++++++++++++-------
>   9 files changed, 114 insertions(+), 15 deletions(-)
> 
> diff --git a/include/kunit/test.h b/include/kunit/test.h
> index 31d549578f8ec113bef9b5d72bc9355c07fce3c0..15bd020d83722163bfc3899f64247afb2c4cefa4 100644
> --- a/include/kunit/test.h
> +++ b/include/kunit/test.h
> @@ -83,6 +83,7 @@ enum kunit_speed {
>   /* Holds attributes for each test case and suite */
>   struct kunit_attributes {
>   	enum kunit_speed speed;
> +	bool rust_should_panic;
>   };
>   
>   /**
> diff --git a/include/kunit/try-catch.h b/include/kunit/try-catch.h
> index d4e1a5b98ed67e4f71ff1bcc71422d5bada54b75..197029e19d759dfeb2700af13cfc8fc246768bb9 100644
> --- a/include/kunit/try-catch.h
> +++ b/include/kunit/try-catch.h
> @@ -22,6 +22,8 @@ struct kunit;
>    * @try_result: Contains any errno obtained while running test case.
>    * @try: The function, the test case, to attempt to run.
>    * @catch: The function called if @try bails out.
> + * @rust_should_panic: Flag used to avoid printing spurious error logs when a
> + *	Rust test is annotated with #[should_panic].

I don't think this is the right way to check for a panic. If we're only 
checking for Rust panics, a #[panic_handler] is better. If we're trying 
to trap other errors, then something like the warning suppression 
feature is better.

>    * @context: used to pass user data to the try and catch functions.
>    *
>    * kunit_try_catch provides a generic, architecture independent way to execute
> @@ -48,6 +50,7 @@ struct kunit_try_catch {
>   	kunit_try_catch_func_t try;
>   	kunit_try_catch_func_t catch;
>   	unsigned long timeout;
> +	bool rust_should_panic;
>   	void *context;
>   };
>   
> diff --git a/lib/kunit/attributes.c b/lib/kunit/attributes.c
> index 6d7a53af94a9acf3cf336409462059b972efeb22..8a9dc526b3cb2d363d42087f8666a03e9bc2bc4b 100644
> --- a/lib/kunit/attributes.c
> +++ b/lib/kunit/attributes.c
> @@ -246,6 +246,16 @@ static void *attr_is_init_get(void *test_or_suite, bool is_test)
>   		return ((void *) suite->is_init);
>   }
>   
> +static void *attr_rust_should_panic_get(void *test_or_suite, bool is_test)
> +{
> +	struct kunit_case *test = is_test ? test_or_suite : NULL;
> +
> +	if (test)
> +		return ((void *) test->attr.rust_should_panic);
> +	else
> +		return ((void *) NULL);
> +}
> +
>   /* List of all Test Attributes */
>   
>   static struct kunit_attr kunit_attr_list[] = {
> @@ -272,6 +282,14 @@ static struct kunit_attr kunit_attr_list[] = {
>   		.filter = attr_bool_filter,
>   		.attr_default = (void *)false,
>   		.print = PRINT_SUITE,
> +	},
> +	{
> +		.name = "rust_should_panic",
> +		.get_attr = attr_rust_should_panic_get,
> +		.to_string = attr_bool_to_string,
> +		.filter = attr_bool_filter,
> +		.attr_default = (void *)false,
> +		.print = PRINT_NEVER,
>   	}
>   };
>   
> diff --git a/lib/kunit/kunit-test.c b/lib/kunit/kunit-test.c
> index 126e30879dad652d5b236aeb13d4406a4ddbab00..7cca586767cc711f7a829cc4c3bdec17bd8c7d9c 100644
> --- a/lib/kunit/kunit-test.c
> +++ b/lib/kunit/kunit-test.c
> @@ -45,6 +45,7 @@ static void kunit_test_try_catch_successful_try_no_catch(struct kunit *test)
>   			     test,
>   			     kunit_test_successful_try,
>   			     kunit_test_no_catch,
> +			     false,
>   			     300 * msecs_to_jiffies(MSEC_PER_SEC));
>   	kunit_try_catch_run(try_catch, test);
>   
> @@ -78,6 +79,7 @@ static void kunit_test_try_catch_unsuccessful_try_does_catch(struct kunit *test)
>   			     test,
>   			     kunit_test_unsuccessful_try,
>   			     kunit_test_catch,
> +			     false,
>   			     300 * msecs_to_jiffies(MSEC_PER_SEC));
>   	kunit_try_catch_run(try_catch, test);
>   
> @@ -133,6 +135,7 @@ static void kunit_test_fault_null_dereference(struct kunit *test)
>   			     test,
>   			     kunit_test_null_dereference,
>   			     kunit_test_catch,
> +			     false,
>   			     300 * msecs_to_jiffies(MSEC_PER_SEC));
>   	kunit_try_catch_run(try_catch, test);
>   
> diff --git a/lib/kunit/test.c b/lib/kunit/test.c
> index 09e3dabfac0c945b2608feb88c1b1d46fb807edc..8b0072c66e1710c7faa7de2df7ff8c4bf48b8e88 100644
> --- a/lib/kunit/test.c
> +++ b/lib/kunit/test.c
> @@ -584,6 +584,7 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
>   			     test,
>   			     kunit_try_run_case,
>   			     kunit_catch_run_case,
> +			     test_case->attr.rust_should_panic,
>   			     kunit_test_timeout(suite, test_case));
>   	context.test = test;
>   	context.suite = suite;
> @@ -595,6 +596,7 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
>   			     test,
>   			     kunit_try_run_case_cleanup,
>   			     kunit_catch_run_case_cleanup,
> +			     false,
>   			     kunit_test_timeout(suite, test_case));
>   	kunit_try_catch_run(try_catch, &context);
>   
> diff --git a/lib/kunit/try-catch-impl.h b/lib/kunit/try-catch-impl.h
> index 6f401b97cd0b9842e7533f1b828f72f884450f74..9abe69bb8b396185afb77cb11ca651ba4c9b6a59 100644
> --- a/lib/kunit/try-catch-impl.h
> +++ b/lib/kunit/try-catch-impl.h
> @@ -18,11 +18,13 @@ static inline void kunit_try_catch_init(struct kunit_try_catch *try_catch,
>   					struct kunit *test,
>   					kunit_try_catch_func_t try,
>   					kunit_try_catch_func_t catch,
> +					bool rust_should_panic,
>   					unsigned long timeout)
>   {
>   	try_catch->test = test;
>   	try_catch->try = try;
>   	try_catch->catch = catch;
> +	try_catch->rust_should_panic = rust_should_panic;
>   	try_catch->timeout = timeout;
>   }
>   
> diff --git a/lib/kunit/try-catch.c b/lib/kunit/try-catch.c
> index d84a879f0a789f3625538735644910c84ac80e56..b9e29d4e7dd52d8d82d71a3f138f0313c772ee76 100644
> --- a/lib/kunit/try-catch.c
> +++ b/lib/kunit/try-catch.c
> @@ -76,11 +76,15 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
>   	if (exit_code == -EFAULT)
>   		try_catch->try_result = 0;
>   	else if (exit_code == -EINTR) {
> -		if (test->last_seen.file)
> -			kunit_err(test, "try faulted: last line seen %s:%d\n",
> -				  test->last_seen.file, test->last_seen.line);
> -		else
> -			kunit_err(test, "try faulted\n");
> +		if (try_catch->rust_should_panic) {
> +			try_catch->try_result = 0;
I'd rather us keep the error here, and just handle it if the 
rust_should_panic test attribute is set afterwards.

> +		} else {
> +			if (test->last_seen.file)
> +				kunit_err(test, "try faulted: last line seen %s:%d\n",
> +					  test->last_seen.file, test->last_seen.line);
> +			else
> +				kunit_err(test, "try faulted\n");
> +		}
>   	} else if (exit_code == -ETIMEDOUT)
>   		kunit_err(test, "try timed out\n");
>   	else if (exit_code)
> diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
> index 25ff272d29b2b3f192a3968481c1d5417df4335b..5e688b743ee2152867e2f99c7f18b86e1b7fbe3d 100644
> --- a/rust/kernel/kunit.rs
> +++ b/rust/kernel/kunit.rs
> @@ -58,7 +58,7 @@ pub fn info(args: fmt::Arguments<'_>) {
>   #[doc(hidden)]
>   #[macro_export]
>   macro_rules! kunit_assert {
> -    ($name:literal, $condition:expr $(,)?) => {
> +    ($name:literal, $test_should_panic:expr, $condition:expr $(,)?) => {
>           'out: {
>               // Do nothing if the condition is `true`.
>               if $condition {
> @@ -93,6 +93,14 @@ macro_rules! kunit_assert {
>                   ));
>                   break 'out;
>               }
> +            // If condition fails but the test should panic, then we just abort.
> +            else if $test_should_panic {
> +                // SAFETY: FFI call. The `kunit_test` pointer is valid because we got it from
> +                // `kunit_get_current_test()` and it was not null.
> +                unsafe {
> +                    $crate::bindings::__kunit_abort(kunit_test);
> +                }
> +            }

I'd rather us keep asserts working as normal: a failed KUnit assertion 
shouldn't be considered a panic. If normal Rust assertions (particularly 
those outside the test-specific code) compile down to a panic, though, 
that's okay.

>   
>               #[repr(transparent)]
>               struct Location($crate::bindings::kunit_loc);
> @@ -166,10 +174,10 @@ unsafe impl Sync for UnaryAssert {}
>   #[doc(hidden)]
>   #[macro_export]
>   macro_rules! kunit_assert_eq {
> -    ($name:literal, $left:expr, $right:expr $(,)?) => {{
> +    ($name:literal, $test_should_panic:expr, $left:expr, $right:expr $(,)?) => {{
>           // For the moment, we just forward to the expression assert because, for binary asserts,
>           // KUnit supports only a few types (e.g. integers).
> -        $crate::kunit_assert!($name, $left == $right);
> +        $crate::kunit_assert!($name, $test_should_panic, $left == $right);
>       }};
>   }
>   
> @@ -209,6 +217,7 @@ pub const fn kunit_case(
>           name: kernel::str::as_char_ptr_in_const_context(name),
>           attr: kernel::bindings::kunit_attributes {
>               speed: kernel::bindings::kunit_speed_KUNIT_SPEED_NORMAL,
> +            rust_should_panic: false,
>           },
>           generate_params: None,
>           status: kernel::bindings::kunit_status_KUNIT_SUCCESS,
> @@ -284,6 +293,7 @@ macro_rules! kunit_unsafe_test_suite {
>                       exit: None,
>                       attr: ::kernel::bindings::kunit_attributes {
>                           speed: ::kernel::bindings::kunit_speed_KUNIT_SPEED_NORMAL,
> +                        rust_should_panic: false,
>                       },
>                       status_comment: [0; 256usize],
>                       debugfs: ::core::ptr::null_mut(),
> @@ -337,6 +347,16 @@ pub fn in_kunit_test() -> bool {
>   mod tests {
>       use super::*;
>   
> +    struct TestStruct;
> +
> +    impl TestStruct {
> +        // This assert does not get replaced with kunit_assert, since this is not a #[test]
> +        // function.
> +        pub(crate) fn escaped_assert() {
> +            assert!(false);
> +        }
> +    }
> +
>       #[test]
>       fn rust_test_kunit_example_test() {
>           assert_eq!(1 + 1, 2);
> @@ -347,6 +367,31 @@ fn rust_test_kunit_in_kunit_test() {
>           assert!(in_kunit_test());
>       }
>   
> +    #[test]
> +    #[should_panic]
> +    fn rust_test_kunit_panic_in_kunit_test() {
> +        panic!("This test should panic and pass");
> +    }
> +
> +    #[test]
> +    #[should_panic]
> +    fn rust_test_kunit_panic_in_kunit_test_bug() {
> +        // The panic is produced in a C call. This should succeed.
> +        unsafe { bindings::BUG() };

I'd rather this not pass: I think if we want to support BUG() here, it 
should be a separate implementation.

> +    }
> +
> +    #[test]
> +    #[should_panic]
> +    fn rust_test_assert_false_success_with_should_panic() {
> +        assert!(false)

I'd rather this not pass, personally. I think that an assert!() within a 
test should work normally (i.e., it's possible to assert that the test 
state is normal, and a failing assert will fail the test).

I could be talked out of this if it's really unpleasantly different from 
non-kernel Rust, but in that case I think we'd want to make sure that 
kunit_assert!() within a test behaves like a normal assert even in a 
should_panic test.

> +    }
> +
> +    #[test]
> +    #[should_panic]
> +    fn rust_test_should_panic_with_escaped_assert() {
> +        TestStruct::escaped_assert();

I'm okay with this passing, though: an assert!() outside the test code 
can be considered a panic.

> +    }
> +
>       #[test]
>       #[cfg(not(all()))]
>       fn rust_test_kunit_always_disabled_test() {
> diff --git a/rust/macros/kunit.rs b/rust/macros/kunit.rs
> index e9152b9d51f9450b7e549e2e1629b5fc5f485a28..288b53d21c4e7c8d9b5148d50c1a833f73e53015 100644
> --- a/rust/macros/kunit.rs
> +++ b/rust/macros/kunit.rs
> @@ -106,6 +106,11 @@ pub(crate) fn kunit_tests(test_suite: Ident, mut module: ItemMod) -> Result<Toke
>               .cloned()
>               .collect();
>   
> +        let should_panic = f
> +            .attrs
> +            .iter()
> +            .any(|attr| attr.path().is_ident("should_panic"));
> +
>           // Before the test, override usual `assert!` and `assert_eq!` macros with ones that call
>           // KUnit instead.
>           let test_str = test.to_string();
> @@ -113,7 +118,7 @@ pub(crate) fn kunit_tests(test_suite: Ident, mut module: ItemMod) -> Result<Toke
>               #[allow(unused)]
>               macro_rules! assert {
>                   ($cond:expr $(,)?) => {{
> -                    kernel::kunit_assert!(#test_str, $cond);
> +                    kernel::kunit_assert!(#test_str, #should_panic, $cond);
>                   }}
>               }
>           });
> @@ -121,7 +126,7 @@ macro_rules! assert {
>               #[allow(unused)]
>               macro_rules! assert_eq {
>                   ($left:expr, $right:expr $(,)?) => {{
> -                    kernel::kunit_assert_eq!(#test_str, $left, $right);
> +                    kernel::kunit_assert_eq!(#test_str, #should_panic, $left, $right);
>                   }}
>               }
>           });
> @@ -134,25 +139,41 @@ macro_rules! assert_eq {
>               &CString::new(test_str.as_str()).expect("identifier cannot contain NUL"),
>               test.span(),
>           );
> +        let assertion = if should_panic {
> +            quote!(
> +                let _ = #test();
> +                ::kernel::kunit::err(::kernel::prelude::fmt!(
> +                    "    Expected {} to panic\n", #test_str
> +                ));
> +                (*_test).status = ::kernel::bindings::kunit_status_KUNIT_FAILURE;
> +            )
> +        } else {
> +            quote!(
> +                use ::kernel::kunit::is_test_result_ok;
> +                assert!(is_test_result_ok(#test()));
> +            )
> +        };

Again, I'd prefer assert!() not take should_panic into account, 
personally. It'd clean the patch up a lot to not pass it through each time.

>           processed_items.push(parse_quote! {
>               unsafe extern "C" fn #kunit_wrapper_fn_name(_test: *mut ::kernel::bindings::kunit) {
>                   (*_test).status = ::kernel::bindings::kunit_status_KUNIT_SKIPPED;
>   
> +
>                   // Append any `cfg` attributes the user might have written on their tests so we
>                   // don't attempt to call them when they are `cfg`'d out. An extra `use` is used
>                   // here to reduce the length of the assert message.
>                   #(#cfg_attrs)*
>                   {
>                       (*_test).status = ::kernel::bindings::kunit_status_KUNIT_SUCCESS;
> -                    use ::kernel::kunit::is_test_result_ok;
> -                    assert!(is_test_result_ok(#test()));
> +                    #assertion
>                   }
>               }
>           });
>   
> -        test_cases.push(quote!(
> -            ::kernel::kunit::kunit_case(#test_cstr, #kunit_wrapper_fn_name)
> -        ));
> +        test_cases.push(quote!({
> +            let mut case = ::kernel::kunit::kunit_case(#test_cstr, #kunit_wrapper_fn_name);
> +            case.attr.rust_should_panic = #should_panic;
> +            case
> +        }));
>       }
>   
>       let num_tests_plus_1 = test_cases.len() + 1;
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 3/3] rust: bitmap: kunit: uncomment owned_bitmap_out_of_bounds panic case
  2026-10-29 16:59 ` [PATCH v2 3/3] rust: bitmap: kunit: uncomment owned_bitmap_out_of_bounds panic case Nicolás Antinori via B4 Relay
@ 2026-11-03 14:46   ` David Gow
  0 siblings, 0 replies; 15+ messages in thread
From: David Gow @ 2026-11-03 14:46 UTC (permalink / raw)
  To: nico.antinori.7, Alice Ryhl, Benno Lossin, Boqun Feng,
	Brendan Higgins, Daniel Almeida, Danilo Krummrich, Gary Guo,
	Miguel Ojeda, Onur Özkan
  Cc: Alexandre Courbot, Andreas Hindborg, Björn Roy Baron,
	Burak Emir, Rae Moar, Tamir Duberstein, Trevor Gross, Yury Norov,
	kunit-dev, linux-kernel, linux-kselftest, rust-for-linux

Le 30/10/2026 à 00:59, Nicolás Antinori via B4 Relay a écrit :
> From: Nicolás Antinori <nico.antinori.7@gmail.com>
> 
> Rust KUnit tests now support `#[should_panic]` attribute. Uncomment the
> test so it can be run when CONFIG_RUST_BITMAP_HARDENED=y.
> 
> Signed-off-by: Nicolás Antinori <nico.antinori.7@gmail.com>
> ---

This works well on architectures should_panic is working on (but we'll 
want to fix UML support first).

Acked-by: David Gow <david@davidgow.net>

Cheers,
-- David

>   rust/kernel/bitmap.rs | 21 ++++++++++-----------
>   1 file changed, 10 insertions(+), 11 deletions(-)
> 
> diff --git a/rust/kernel/bitmap.rs b/rust/kernel/bitmap.rs
> index 610d565535ccfba6af8f2ca4ac4028fa027a9644..8eecd669096713fc7f21431188959a921a1d5ca0 100644
> --- a/rust/kernel/bitmap.rs
> +++ b/rust/kernel/bitmap.rs
> @@ -762,11 +762,10 @@ fn bitmap_set_clear_find() -> Result<(), AllocError> {
>           Ok(())
>       }
>   
> -    #[test]
>       #[cfg(not(CONFIG_RUST_BITMAP_HARDENED))]
> +    #[test]
>       fn owned_bitmap_out_of_bounds() -> Result<(), AllocError> {
>           let mut b = BitmapVec::new(128, GFP_KERNEL)?;
> -
>           b.set_bit(2048);
>           b.set_bit_atomic(2048);
>           b.clear_bit(2048);
> @@ -777,15 +776,15 @@ fn owned_bitmap_out_of_bounds() -> Result<(), AllocError> {
>           Ok(())
>       }
>   
> -    // TODO: uncomment once kunit supports `#[should_panic]`.
> -    // #[cfg(CONFIG_RUST_BITMAP_HARDENED)]
> -    // #[test]
> -    // #[should_panic]
> -    // fn owned_bitmap_out_of_bounds() -> Result<(), AllocError> {
> -    //     let mut b = BitmapVec::new(128, GFP_KERNEL)?;
> -    //
> -    //     b.set_bit(2048);
> -    // }
> +    #[cfg(CONFIG_RUST_BITMAP_HARDENED)]
> +    #[test]
> +    #[should_panic]
> +    fn owned_bitmap_out_of_bounds() -> Result<(), AllocError> {
> +        let mut b = BitmapVec::new(128, GFP_KERNEL)?;
> +
> +        b.set_bit(2048);
> +        Ok(())
> +    }
>   
>       #[test]
>       fn bitmap_copy_and_extend() -> Result<(), AllocError> {
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/3] rust: kunit: add #[should_panic] support
  2026-11-02 14:58   ` Nicolás Antinori
  2026-11-02 15:51     ` Miguel Ojeda
@ 2026-11-03 15:00     ` David Gow
  1 sibling, 0 replies; 15+ messages in thread
From: David Gow @ 2026-11-03 15:00 UTC (permalink / raw)
  To: Nicolás Antinori, Alice Ryhl, Benno Lossin, Boqun Feng,
	Brendan Higgins, Daniel Almeida, Danilo Krummrich, Gary Guo,
	Miguel Ojeda, Onur Özkan
  Cc: Alexandre Courbot, Andreas Hindborg, Björn Roy Baron,
	Burak Emir, Rae Moar, Tamir Duberstein, Trevor Gross, Yury Norov,
	kunit-dev, linux-kernel, linux-kselftest, rust-for-linux

Le 02/11/2026 à 22:58, Nicolás Antinori a écrit :
> On Thu Oct 29, 2026 at 1:59 PM -03, Nicolás Antinori via B4 Relay wrote:
>> From: Nicolás Antinori <nico.antinori.7@gmail.com>
>>
>> KUnit tests in Rust are written using user-space like syntax. This patch
>> adds support for the `#[should_panic]` attribute, enabling the user to
>> test conditions that are expected to cause a panic and report the test
>> as successful.
>>
>> Signed-off-by: Nicolás Antinori <nico.antinori.7@gmail.com>
> 
> Hello, Sashiko found two issues [1] with this patch:
> 
>> [Severity: High]
>> Will these new selftests crash the kernel or hang when
>> CONFIG_RUST_KUNIT_SELFTEST is enabled under CONFIG_UML=y,
>> CONFIG_PANIC_ON_OOPS=y, or CONFIG_BUG=n?
> 
> This is true, I tested this with:
> 
> ./tools/testing/kunit/kunit.py run \
> 	--make_options LLVM=1 \
> 	--kconfig_add CONFIG_RUST=y \
> 	--kconfig_add CONFIG_RUST_KUNIT_TESTS=y \
> 	--kconfig_add CONFIG_KUNIT=y \
> 	--kconfig_add CONFIG_UML=y \
> 	--arch=um rust_kernel_kunit
> 
> ./tools/testing/kunit/kunit.py run \
> 	--make_options LLVM=1 \
> 	--kconfig_add CONFIG_RUST=y \
> 	--kconfig_add CONFIG_RUST_KUNIT_TESTS=y \
> 	--kconfig_add CONFIG_KUNIT=y \
> 	--kconfig_add CONFIG_PANIC_ON_OOPS=y \
> 	--arch=x86_64 rust_kernel_kunit
> 
> And some other configs using the configs causing problems.
> 
> To solve this I created a new config "RUST_KUNIT_SHOULD_PANIC_ATTRIBUTE"
> that depends on !UML && !PANIC_ON_OOPS && BUG. If the test is annotated
> with `#[should_panic]` and CONFIG_RUST_KUNIT_SHOULD_PANIC_ATTRIBUTE=n,
> the test won't run and won't show up in the summary.
> 

This is failing on UML for me, too. I'd rather have an implementation 
which worked on UML (such as a panic_handler), rather than trying to 
intercept BUG().

If you do want to add a new config option, I'd probably call it 
something like HAVE_KUNIT_RUST_SHOULD_PANIC, and set it in the 
architecture configs, but piggy-backing on the existing 
CONFIG_KUNIT_FAULT_TEST is probably best. And if we do want to support 
non-Rust panics, then this probably shouldn't be a rust-specific option.

The RFC's panic_handler-based implementation worked fine for me on UML, 
so I'd stick with that.

And, of course, UML isn't the only architecture that can't handle faults 
(though it might be the only one Rust supports at the moment). e.g., 
SPARC also would fail here.

>> [Severity: Medium]
>> Does defining macro_rules! assert and macro_rules! assert_eq at module scope
>> in kunit_tests() leak the preceding test's #should_panic value into helper
>> functions or impl blocks defined later in the module?
> 
> This is also true, the solution was redefining the `assert!` and
> `assert_eq!` macros inside the function's body (as Sashiko suggested).
> 
> I'll wait a bit in case there are any feedback on the current series and
> send a v3 with these changes.
> 

As mentioned, I'm not a big fan of including should_panic in the 
assert!() macros, so if we can just do away with that, this should no 
longer be a problem.

> Best Regards,
> Nicolás
> 
> [1] https://sashiko.dev/#/patchset/20261029-rust_kunit_v6_send-v2-0-5ce551efc48e@gmail.com?part=1


Cheers,
-- David

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/3] rust: kunit: add #[should_panic] support
  2026-11-02 21:25         ` Miguel Ojeda
@ 2026-11-03 15:05           ` David Gow
  0 siblings, 0 replies; 15+ messages in thread
From: David Gow @ 2026-11-03 15:05 UTC (permalink / raw)
  To: Miguel Ojeda, Nicolás Antinori
  Cc: Alice Ryhl, Benno Lossin, Boqun Feng, Brendan Higgins,
	Daniel Almeida, Danilo Krummrich, Gary Guo, Miguel Ojeda,
	Onur Özkan, Alexandre Courbot, Andreas Hindborg,
	Björn Roy Baron, Burak Emir, Rae Moar, Tamir Duberstein,
	Trevor Gross, Yury Norov, kunit-dev, linux-kernel,
	linux-kselftest, rust-for-linux

Le 03/11/2026 à 05:25, Miguel Ojeda a écrit :
> On Mon, Nov 2, 2026 at 9:53 PM Nicolás Antinori
> <nico.antinori.7@gmail.com> wrote:
>>
>> I first thought of disabling `#[should_panic]` tests by directly
>> checking the conditions in the macro code. I ended up creating a new
>> config because I thought it would be cleaner codewise, if a new
>> constraint arises in the future, we just have to add it to the
>> `depends on` clause instead of modifying the macro code.
> 
> It depends on what we want: if it is meant to be configurable, then it
> should be a visible Kconfig symbol; if not, then it should remain an
> implementation detail (which could perhaps be a non-visible Kconfig
> symbol).
> 

The reason KUNIT_FAULT_TEST was user-configurable is that some test 
harnesses / CI systems would automatically mark a test failed if they 
saw a panic/WARN stacktrace in the kernel output.

>> Yes! they are pretty similar, for `KUNIT_FAULT_TEST`:
> 
> Yeah, in that case, I think a new visible Kconfig symbol may be
> justifiable -- please see below.
> 
>> The only one that is different in `RUST_KUNIT_TESTS` is:
>>
>> #[test]
>> #[should_panic]
>> fn rust_test_assert_false_success_with_should_panic() {
>>      assert!(false)
>> }
> 
> I guess it is reasonable to expect this test to pass, since `assert!`
> doesn't return and actually panics in normal Rust.
> 
> Having said that, I would expect our `should_panic` tests to be
> generally about non-`assert*!` panics.
> 

Yeah, I really don't like the way this effectively reverses what 
assert!() does. I'm sort-of okay with it in indirectly-called code (I 
want to check that this function panics if I pass an invalid input, and 
don't care whether it calls assert!() or panic!()), but it's really 
confusing from within the test function.

Plus there's a whole bunch of special-cased code to make kunit_assert!() 
behave this way in this patch, and if we could get rid of that, the 
whole thing would be much cleaner.

(Of course, that introduces an inconsistency depending on where the 
assert!() is, which isn't particularly nice, though I'd be prepared to 
tolerate it to make everything else behave as expected.)

>> On top of the reasons I gave above, I tried to follow the same as
>> `CONFIG_RUST_BUG_KUNIT_TEST` or `CONFIG_KUNIT_FAULT_TEST` are doing, but
>> in this case in particular, the config is not for enabling a test suite
>> but for enabling a feature that can affect multiple suites (in this
>> patch series the ones behind `CONFIG_RUST_KUNIT_TESTS` and
>> `CONFIG_RUST_BITMAP_KUNIT_TESTS`).
> 
> Yeah, it is a "mode" -- that is why originally I thought we would try
> to just do the right thing automatically, i.e. enable them when
> possible, but then when I saw the description of
> `CONFIG_KUNIT_FAULT_TEST`:
> 
>      Enables fault handling tests for the KUnit framework. These tests may
>      trigger a kernel BUG(), and the associated stack trace, even when they
>      pass. If this conflicts with your test infrastrcture (or is confusing
>      or annoying), they can be disabled by setting this to N.
> 
> and I thought it may be fair to have the Kconfig symbol, i.e. it could
> also be annoying to see the traces or similar, and thus it may be that
> someone needs to disable this.
> 
> Having said that, if nobody has asked, we could keep it simple for now
> as well -- that may be fine too.
> 
> David: what do you think? Is it something that was discussed back then
> for that one in C?
I've always thought of CONFIG_KUNIT_FAULT_TEST as being a more general 
switch for tests which can cause faults, but the name and description to 
imply it's more of a switch for just those tests. I'm happy to keep 
CONFIG_KUNIT_FAULT_TEST as the generic implementation here, but if we 
really want another one, they both probably should chain off a single 
CONFIG_HAVE_KUNIT_FAULT_HANDLER or similar.

That being said, I'd prefer we go back to the panic_handler 
implementation for should_panic, as I think we're asking for trouble 
with Rust tests which deliberately panic in C code. Ideally, Rust tests 
will only trigger Rust panics deliberately. The panic_handler-based 
imeplementation works fine on UML.


Cheers,
-- David

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v2 1/3] rust: kunit: add #[should_panic] support
  2026-11-03 14:46   ` David Gow
@ 2026-11-03 16:32     ` Miguel Ojeda
  0 siblings, 0 replies; 15+ messages in thread
From: Miguel Ojeda @ 2026-11-03 16:32 UTC (permalink / raw)
  To: David Gow
  Cc: nico.antinori.7, Alice Ryhl, Benno Lossin, Boqun Feng,
	Brendan Higgins, Daniel Almeida, Danilo Krummrich, Gary Guo,
	Miguel Ojeda, Onur Özkan, Alexandre Courbot,
	Andreas Hindborg, Björn Roy Baron, Burak Emir, Rae Moar,
	Tamir Duberstein, Trevor Gross, Yury Norov, kunit-dev,
	linux-kernel, linux-kselftest, rust-for-linux

On Tue, Nov 3, 2026 at 3:46 PM David Gow <david@davidgow.net> wrote:
>
> I'd rather this not pass, personally. I think that an assert!() within a
> test should work normally (i.e., it's possible to assert that the test
> state is normal, and a failing assert will fail the test).
>
> I could be talked out of this if it's really unpleasantly different from
> non-kernel Rust, but in that case I think we'd want to make sure that
> kunit_assert!() within a test behaves like a normal assert even in a
> should_panic test.

Yeah, it all boils down to what we mean by `assert!()`.

When I implemented it back then, I intended to allow people to write
the normal asserts they would write (which could help in case we were
to e.g. import code from elsewhere, like a vendored library), as if
would have "Rust-panicked", but not "kernel-panicked".

Viewed in that light, `BUG()` would not necessarily need to make
`should_panic` succeed or not [*], but an `assert!(false)` would need
to make the test succeed. And then we could have a
`should_kernel_panic` and maybe expose a public `kunit_assert!` etc.
to distinguish them and so on.

Having said that, I am not sure how many tests would actually rely on
such differences... I think the core requirement is that, as you say,
we are able to test for Rust panics in functions we call within the
test (and ideally also other Rust panics within the test body too,
when viewed in the light above). But if something simplifies
implementation significantly, then we can consider other things.

[*] I asked an LLM to test what happens in userspace Rust when one
aborts/traps/etc., and it differs in stable between a normal test and
a doctest (with the default `panic=unwind`): essentially, the former
dies, the latter succeeds -- it doesn't seem to be well-defined yet.
There is an issue for the doctest side of it:

  https://github.com/rust-lang/rust/issues/143009

and there is a bunch of discussion on the different linked PRs.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2026-11-03 16:32 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-29 16:59 [PATCH v2 0/3] rust: kunit: support #[should_panic] and same test name with different #[cfg(...)] Nicolás Antinori via B4 Relay
2026-10-29 16:59 ` [PATCH v2 1/3] rust: kunit: add #[should_panic] support Nicolás Antinori via B4 Relay
2026-11-02 14:58   ` Nicolás Antinori
2026-11-02 15:51     ` Miguel Ojeda
2026-11-02 20:53       ` Nicolás Antinori
2026-11-02 21:25         ` Miguel Ojeda
2026-11-03 15:05           ` David Gow
2026-11-03 15:00     ` David Gow
2026-11-03 14:46   ` David Gow
2026-11-03 16:32     ` Miguel Ojeda
2026-10-29 16:59 ` [PATCH v2 2/3] rust: kunit: allow same test name with different #[cfg(...)] Nicolás Antinori via B4 Relay
2026-11-03 14:45   ` David Gow
2026-10-29 16:59 ` [PATCH v2 3/3] rust: bitmap: kunit: uncomment owned_bitmap_out_of_bounds panic case Nicolás Antinori via B4 Relay
2026-11-03 14:46   ` David Gow
2026-11-03 14:45 ` [PATCH v2 0/3] rust: kunit: support #[should_panic] and same test name with different #[cfg(...)] David Gow

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox