All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.