rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Boqun Feng <boqun.feng@gmail.com>
To: Miguel Ojeda <ojeda@kernel.org>
Cc: "David Gow" <davidgow@google.com>,
	"Brendan Higgins" <brendan.higgins@linux.dev>,
	"Wedson Almeida Filho" <wedsonaf@gmail.com>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <benno.lossin@proton.me>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Andreas Hindborg" <nmi@metaspace.dk>,
	"Philip Li" <philip.li@intel.com>,
	kunit-dev@googlegroups.com, linux-kselftest@vger.kernel.org,
	rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
	patches@lists.linux.dev
Subject: Re: [PATCH 0/6] KUnit integration for Rust doctests
Date: Wed, 14 Jun 2023 18:44:19 -0700	[thread overview]
Message-ID: <ZIps86MbJF/iGIzd@boqun-archlinux> (raw)
In-Reply-To: <20230614180837.630180-1-ojeda@kernel.org>

On Wed, Jun 14, 2023 at 08:08:24PM +0200, Miguel Ojeda wrote:
> This is the initial KUnit integration for running Rust documentation
> tests within the kernel.
> 
> Thank you to the KUnit team for all the input and feedback on this
> over the months, as well as the Intel LKP 0-Day team!
> 
> This may be merged through either the KUnit or the Rust trees. If
> the KUnit team wants to merge it, then that would be great.
> 
> Please see the message in the main commit for the details.
> 

Great work! I've played this for a while, and it's really useful ;-)

One thing though, maybe we can provide more clues for users to locate
the corresponding Doctests? For example, I did the following to trigger
an assertion:

	diff --git a/rust/kernel/sync/lock/spinlock.rs b/rust/kernel/sync/lock/spinlock.rs
	index 91eb2c9e9123..9ead152e2c7e 100644
	--- a/rust/kernel/sync/lock/spinlock.rs
	+++ b/rust/kernel/sync/lock/spinlock.rs
	@@ -58,7 +58,7 @@ macro_rules! new_spinlock {
	 ///
	 /// // Allocate a boxed `Example`.
	 /// let e = Box::pin_init(Example::new())?;
	-/// assert_eq!(e.c, 10);
	+/// assert_eq!(e.c, 11);
	 /// assert_eq!(e.d.lock().a, 20);
	 /// assert_eq!(e.d.lock().b, 30);
	 /// # Ok::<(), Error>(())

Originally I got:

	[..] # Doctest from line 35
	[..] # rust_doctest_kernel_sync_lock_spinlock_rs_0: ASSERTION FAILED at rust/doctests_kernel_generated.rs:2437
	[..] Expected e.c == 11 to be true, but is false
	[..] [FAILED] rust_doctest_kernel_sync_lock_spinlock_rs_0

The assertion warning only says line 35 but which file? Yes, the
".._sync_lock_spinlock_rs" name does provide the lead, however since we
generate the test code, so we actually know the line # for each real
test body, so I come up a way to give us the following:

	[..] # rust_doctest_kernel_sync_lock_spinlock_rs_0: ASSERTION FAILED at rust/kernel/sync/lock/spinlock.rs:61
	[..] Expected e.c == 11 to be true, but is false
	[..] [FAILED] rust_doctest_kernel_sync_lock_spinlock_rs_0

Thoughts?

Regards,
Boqun

----------------->8
diff --git a/rust/kernel/kunit.rs b/rust/kernel/kunit.rs
index 3c94efcd7f76..807fe3633567 100644
--- a/rust/kernel/kunit.rs
+++ b/rust/kernel/kunit.rs
@@ -49,15 +49,15 @@ pub fn info(args: fmt::Arguments<'_>) {
 #[doc(hidden)]
 #[macro_export]
 macro_rules! kunit_assert {
-    ($name:literal, $condition:expr $(,)?) => {
+    ($name:literal, $diff:expr, $file:expr, $condition:expr $(,)?) => {
         'out: {
             // Do nothing if the condition is `true`.
             if $condition {
                 break 'out;
             }
 
-            static LINE: i32 = core::line!() as i32;
-            static FILE: &'static $crate::str::CStr = $crate::c_str!(core::file!());
+            static LINE: i32 = core::line!() as i32 - $diff;
+            static FILE: &'static $crate::str::CStr = $crate::c_str!($file);
             static CONDITION: &'static $crate::str::CStr = $crate::c_str!(stringify!($condition));
 
             // SAFETY: FFI call without safety requirements.
@@ -148,9 +148,9 @@ unsafe impl Sync for UnaryAssert {}
 #[doc(hidden)]
 #[macro_export]
 macro_rules! kunit_assert_eq {
-    ($name:literal, $left:expr, $right:expr $(,)?) => {{
+    ($name:literal, $diff:expr, $file: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, $diff, $file, $left == $right);
     }};
 }
diff --git a/scripts/rustdoc_test_gen.rs b/scripts/rustdoc_test_gen.rs
index 793885c32c0d..4786a2ef0dc6 100644
--- a/scripts/rustdoc_test_gen.rs
+++ b/scripts/rustdoc_test_gen.rs
@@ -75,6 +75,11 @@ fn main() {
 
         let line = line.parse::<core::ffi::c_int>().unwrap();
 
+        let src_file = format!("rust/kernel/{}", file.replace("_rs", ".rs").replace("_", "/"));
+
+        // Calculate how many lines before `main` function (including the `main` function line).
+        let body_offset = body.lines().take_while(|l| !l.contains("fn main() {")).count() + 1;
+
         use std::fmt::Write;
         write!(
             rust_tests,
@@ -85,7 +90,7 @@ pub extern "C" fn {kunit_name}(__kunit_test: *mut kernel::bindings::kunit) {{
     #[allow(unused)]
     macro_rules! assert {{
         ($cond:expr $(,)?) => {{{{
-            kernel::kunit_assert!("{kunit_name}", $cond);
+            kernel::kunit_assert!("{kunit_name}", anchor - {line}, "{src_file}", $cond);
         }}}}
     }}
 
@@ -93,7 +98,7 @@ macro_rules! assert {{
     #[allow(unused)]
     macro_rules! assert_eq {{
         ($left:expr, $right:expr $(,)?) => {{{{
-            kernel::kunit_assert_eq!("{kunit_name}", $left, $right);
+            kernel::kunit_assert_eq!("{kunit_name}", anchor - {line}, "{src_file}", $left, $right);
         }}}}
     }}
 
@@ -101,9 +106,8 @@ macro_rules! assert_eq {{
     #[allow(unused)]
     use kernel::prelude::*;
 
-    // Display line number so that developers can map the test easily to the source code.
-    kernel::kunit::info(format_args!("    # Doctest from line {line}\n"));
-
+    // The anchor where the test code body starts.
+    static anchor: i32 = core::line!() as i32 + {body_offset} + 1;
     {{
         {body}
         main();

  parent reply	other threads:[~2023-06-15  1:44 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-14 18:08 [PATCH 0/6] KUnit integration for Rust doctests Miguel Ojeda
2023-06-14 18:08 ` [PATCH 1/6] rust: init: make doctests compilable/testable Miguel Ojeda
2023-06-14 20:32   ` Alice Ryhl
2023-06-15  1:03   ` Martin Rodriguez Reboredo
2023-06-15  9:31     ` Miguel Ojeda
2023-06-15 13:33       ` Martin Rodriguez Reboredo
2023-06-15 23:47   ` Vincenzo Palazzo
2023-06-16  4:51   ` David Gow
2023-06-16 11:12   ` Björn Roy Baron
2023-06-25 10:13   ` Benno Lossin
2023-06-14 18:08 ` [PATCH 2/6] rust: str: " Miguel Ojeda
2023-06-14 20:32   ` Alice Ryhl
2023-06-15  1:04   ` Martin Rodriguez Reboredo
2023-06-15 23:47   ` Vincenzo Palazzo
2023-06-16  4:51   ` David Gow
2023-06-16 11:13   ` Björn Roy Baron
2023-06-14 18:08 ` [PATCH 3/6] rust: sync: " Miguel Ojeda
2023-06-14 20:32   ` Alice Ryhl
2023-06-15  1:04   ` Martin Rodriguez Reboredo
2023-06-16  4:51   ` David Gow
2023-06-16 11:14   ` Björn Roy Baron
2023-06-14 18:08 ` [PATCH 4/6] rust: types: " Miguel Ojeda
2023-06-14 20:32   ` Alice Ryhl
2023-06-15  1:06   ` Martin Rodriguez Reboredo
2023-06-16  4:52   ` David Gow
2023-06-16 11:14   ` Björn Roy Baron
2023-06-14 18:08 ` [PATCH 5/6] rust: support running Rust documentation tests as KUnit ones Miguel Ojeda
2023-06-14 20:38   ` Alice Ryhl
2023-06-14 22:09     ` Miguel Ojeda
2023-06-14 22:09   ` Miguel Ojeda
2023-06-15  0:19   ` Matt Gilbride
2023-06-15  3:49   ` Martin Rodriguez Reboredo
2023-06-15  9:23     ` Miguel Ojeda
2023-06-15 13:50       ` Martin Rodriguez Reboredo
2023-06-15 23:53   ` Vincenzo Palazzo
2023-06-16  4:52   ` David Gow
2023-06-19 17:16   ` Sergio González Collado
2023-06-30 18:17   ` Boqun Feng
2023-06-14 18:08 ` [PATCH 6/6] MAINTAINERS: add Rust KUnit files to the KUnit entry Miguel Ojeda
2023-06-15  3:49   ` Martin Rodriguez Reboredo
2023-06-15 23:46   ` Vincenzo Palazzo
2023-06-16  4:53   ` David Gow
2023-06-15  1:44 ` Boqun Feng [this message]
2023-06-15  8:20   ` [PATCH 0/6] KUnit integration for Rust doctests Miguel Ojeda
2023-06-16  4:44     ` David Gow
2023-06-16  4:51 ` David Gow

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=ZIps86MbJF/iGIzd@boqun-archlinux \
    --to=boqun.feng@gmail.com \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=benno.lossin@proton.me \
    --cc=bjorn3_gh@protonmail.com \
    --cc=brendan.higgins@linux.dev \
    --cc=davidgow@google.com \
    --cc=gary@garyguo.net \
    --cc=kunit-dev@googlegroups.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=nmi@metaspace.dk \
    --cc=ojeda@kernel.org \
    --cc=patches@lists.linux.dev \
    --cc=philip.li@intel.com \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=wedsonaf@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;
as well as URLs for NNTP newsgroup(s).