mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Nicolás Antinori via B4 Relay" <devnull+nico.antinori.7.gmail.com@kernel.org>
To: Alice Ryhl <aliceryhl@google.com>,
	Burak Emir <burak.emir@gmail.com>,
	 Brendan Higgins <brendan.higgins@linux.dev>,
	David Gow <david@davidgow.net>,  Miguel Ojeda <ojeda@kernel.org>
Cc: "Nicolás Antinori" <nico.antinori.7@gmail.com>,
	"Alexandre Courbot" <acourbot@nvidia.com>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Benno Lossin" <lossin@kernel.org>,
	"Björn Roy Baron" <bjorn1_gh@protonmail.com>,
	"Boqun Feng" <boqun@kernel.org>,
	"Brigham Campbell" <me@brighamcampbell.com>,
	"Daniel Almeida" <daniel.almeida@collabora.com>,
	"Danilo Krummrich" <dakr@kernel.org>,
	"Gary Guo" <gary@garyguo.net>,
	"Jori Koolstra" <jkoolstra@xs4all.nl>,
	"Onur Özkan" <work@onurozkan.dev>,
	"Rae Moar" <raemoar63@gmail.com>,
	"Shuah Khan" <skhan@linuxfoundation.org>,
	"Tamir Duberstein" <tamird@kernel.org>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Yury Norov" <yury.norov@gmail.com>,
	linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
	linux-kernel-mentees@lists.linux.dev
Subject: [PATCH 1/3] rust: kunit: add #[should_panic] support
Date: Wed, 30 Sep 2026 10:23:28 -0300	[thread overview]
Message-ID: <20260930-rust_kunit_v4-v1-1-e3b0d45311dd@gmail.com> (raw)
In-Reply-To: <20260930-rust_kunit_v4-v1-0-e3b0d45311dd@gmail.com>

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 +
 lib/kunit/attributes.c | 18 ++++++++++++++++++
 lib/kunit/test.c       |  5 +++++
 rust/kernel/kunit.rs   | 15 +++++++++++++++
 rust/macros/kunit.rs   | 28 +++++++++++++++++++++++-----
 5 files changed, 62 insertions(+), 5 deletions(-)

diff --git a/include/kunit/test.h b/include/kunit/test.h
index da5312e0dfa57f37a7e96c9e618b03b0947ede8b..f2c640718d12258c183817be08a091b8cf316d16 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/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/test.c b/lib/kunit/test.c
index 09e3dabfac0c945b2608feb88c1b1d46fb807edc..2140841b7dc9ca45346159683d8f2b85b6e11381 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -590,6 +590,11 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite,
 	context.test_case = test_case;
 	kunit_try_catch_run(try_catch, &context);
 
+	if (try_catch->try_result == -EINTR && test_case->attr.rust_should_panic) {
+		test->status = KUNIT_SUCCESS;
+		test_case->status = KUNIT_SUCCESS;
+	}
+
 	/* Now run the cleanup */
 	kunit_try_catch_init(try_catch,
 			     test,
diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
index 91eaff8c186afd09333a525bc106d39391d30a92..5fa4d994e0f7ebf5bbe5fd3571a372548cc8499b 100644
--- a/rust/kernel/kunit.rs
+++ b/rust/kernel/kunit.rs
@@ -207,6 +207,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,
@@ -282,6 +283,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(),
@@ -345,6 +347,19 @@ 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]
     #[cfg(not(all()))]
     fn rust_test_kunit_always_disabled_test() {
diff --git a/rust/macros/kunit.rs b/rust/macros/kunit.rs
index ae20ed6768f1564439acf0cadc72a787bada8473..f1d0210e6a49468876d69821cc559002ad12da50 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();
@@ -135,25 +140,38 @@ 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();
+                (*_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



  reply	other threads:[~2026-09-30 13:23 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-30 13:23 [PATCH 0/3] rust: kunit: support #[should_panic] and same test name with different #[cfg(...)] Nicolás Antinori via B4 Relay
2026-09-30 13:23 ` Nicolás Antinori via B4 Relay [this message]
2026-09-30 13:23 ` [PATCH 2/3] rust: kunit: allow " Nicolás Antinori via B4 Relay
2026-09-30 13:23 ` [PATCH 3/3] rust: bitmap: kunit: uncomment owned_bitmap_out_of_bounds panic case Nicolás Antinori via B4 Relay
2026-09-30 14:41 ` [PATCH 0/3] rust: kunit: support #[should_panic] and same test name with different #[cfg(...)] Miguel Ojeda
2026-09-30 14:54 ` Gary Guo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260930-rust_kunit_v4-v1-1-e3b0d45311dd@gmail.com \
    --to=devnull+nico.antinori.7.gmail.com@kernel.org \
    --cc=a.hindborg@kernel.org \
    --cc=acourbot@nvidia.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn1_gh@protonmail.com \
    --cc=boqun@kernel.org \
    --cc=brendan.higgins@linux.dev \
    --cc=burak.emir@gmail.com \
    --cc=dakr@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=david@davidgow.net \
    --cc=gary@garyguo.net \
    --cc=jkoolstra@xs4all.nl \
    --cc=linux-kernel-mentees@lists.linux.dev \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=me@brighamcampbell.com \
    --cc=nico.antinori.7@gmail.com \
    --cc=ojeda@kernel.org \
    --cc=raemoar63@gmail.com \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=skhan@linuxfoundation.org \
    --cc=tamird@kernel.org \
    --cc=tmgross@umich.edu \
    --cc=work@onurozkan.dev \
    --cc=yury.norov@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®