[PATCH rust-next v2] rust: fmt: rework pointer formatting tests

Ke Sun <[email protected]>
Newsgroups org.kernel.feeds.b4-sent,org.kernel.vger.linux-kernel,org.kernel.vger.rust-for-linux
Message-ID <[email protected]>
`test_ptr_formatting` depended on the `no_hash_pointers` setting and
skipped the remaining checks when the CRNG was not ready. Assert the
formatted variants against the plain `{:p}` output instead, and cover
the placeholder path.

Signed-off-by: Ke Sun <[email protected]>
---
This is a follow-up to the applied v15 series "rust: Add safe pointer
formatting support" (on rust-next), addressing the review feedback on
the KUnit tests.
---
Changes in v2:
- Fix the KUnit failure when the CRNG is not ready: `%p` emits the
  placeholder at a fixed length, ignoring width and zero-padding.
- Link to v1: https://lore.kernel.org/r/[email protected]
---
 rust/kernel/fmt.rs | 98 ++++++++++++++++++++----------------------------------
 1 file changed, 36 insertions(+), 62 deletions(-)

diff --git a/rust/kernel/fmt.rs b/rust/kernel/fmt.rs
index 29582b053ab1f..cbdca7183d54b 100644
--- a/rust/kernel/fmt.rs
+++ b/rust/kernel/fmt.rs
@@ -215,83 +215,57 @@ fn fmt(&self, f: &mut Formatter<'_>) -> Result {
 #[macros::kunit_tests(rust_kernel_fmt)]
 mod tests {
     use crate::{
-        bindings,
         prelude::fmt,
         str::CString, //
     };
 
+    // Placeholder used when the CRNG is not ready.
     #[cfg(CONFIG_64BIT)]
-    mod expected {
-        pub(super) const PTR_VALUE: usize = 0xffffffffdeadbeef;
-        pub(super) const PTR_VAL_NO_CRNG: &str = "(____ptrval____)";
-        pub(super) const HASHED_PREFIX: &str = "0x00000000";
-        pub(super) const RAW_POINTER: &str = "0xffffffffdeadbeef";
-        pub(super) const PADDED_RIGHT: &str = "      0xffffffffdeadbeef";
-        pub(super) const ZERO_PADDED: &str = "0x000000ffffffffdeadbeef";
-        pub(super) const HASHED_PADDED_RIGHT_PREFIX: &str = "      ";
-        pub(super) const HASHED_ZERO_PADDED_PREFIX: &str = "0x00000000000000";
-        pub(super) const CLAMPED: &str = "0x0000000000000ffffffffdeadbeef";
-    }
+    const PTR_VAL_NO_CRNG: &str = "(____ptrval____)";
 
     #[cfg(not(CONFIG_64BIT))]
-    mod expected {
-        pub(super) const PTR_VALUE: usize = 0xdeadbeef;
-        pub(super) const PTR_VAL_NO_CRNG: &str = "(ptrval)";
-        pub(super) const HASHED_PREFIX: &str = "0x";
-        pub(super) const RAW_POINTER: &str = "0xdeadbeef";
-        pub(super) const PADDED_RIGHT: &str = "              0xdeadbeef";
-        pub(super) const ZERO_PADDED: &str = "0x00000000000000deadbeef";
-        pub(super) const HASHED_PADDED_RIGHT_PREFIX: &str = "              ";
-        pub(super) const HASHED_ZERO_PADDED_PREFIX: &str = "0x00000000000000";
-        pub(super) const CLAMPED: &str = "0x0000000000000000000000deadbeef";
-    }
+    const PTR_VAL_NO_CRNG: &str = "(ptrval)";
+
+    #[cfg(CONFIG_64BIT)]
+    const PTR_VALUE: usize = 0xffffffffdeadbeef;
+
+    #[cfg(not(CONFIG_64BIT))]
+    const PTR_VALUE: usize = 0xdeadbeef;
 
     #[test]
     fn test_ptr_formatting() -> core::result::Result<(), crate::error::Error> {
-        let ptr: *const u8 = core::ptr::without_provenance(expected::PTR_VALUE);
+        let ptr: *const u8 = core::ptr::without_provenance(PTR_VALUE);
 
-        // SAFETY: `no_hash_pointers` is a global variable that is never concurrently modified —
-        // KUnit tests may run at boot (before `mark_readonly()`) or manually afterwards (when the
-        // variable is read-only). Reading is always safe.
-        let no_hash = unsafe { bindings::no_hash_pointers };
+        let cstr = CString::try_from_fmt(fmt!("{:p}", ptr))?;
+        let formatted = cstr.to_str()?;
 
-        if no_hash {
-            let cstr = CString::try_from_fmt(fmt!("{:p}", ptr))?;
-            assert_eq!(cstr.to_str()?, expected::RAW_POINTER);
+        // If the CRNG is not ready yet, `%p` emits the placeholder at a fixed
+        // length: `f.pad` still applies, zero-padding does not (see `ptr_to_id()`).
+        let (crng_ready, expected_suffix) = if let Some(suffix) = formatted.strip_prefix("0x") {
+            (true, suffix)
+        } else {
+            (false, formatted)
+        };
+        let (zero_padded_len, clamped_len) = if crng_ready {
+            (24, 31)
+        } else {
+            (PTR_VAL_NO_CRNG.len(), PTR_VAL_NO_CRNG.len())
+        };
 
-            let cstr = CString::try_from_fmt(fmt!("{:>24p}", ptr))?;
-            assert_eq!(cstr.to_str()?, expected::PADDED_RIGHT);
+        let cstr = CString::try_from_fmt(fmt!("{:>24p}", ptr))?;
+        let padded = cstr.to_str()?;
+        assert!(padded.ends_with(expected_suffix));
+        assert_eq!(padded.len(), 24);
 
-            let cstr = CString::try_from_fmt(fmt!("{:024p}", ptr))?;
-            assert_eq!(cstr.to_str()?, expected::ZERO_PADDED);
+        let cstr = CString::try_from_fmt(fmt!("{:024p}", ptr))?;
+        let zero_padded = cstr.to_str()?;
+        assert!(zero_padded.ends_with(expected_suffix));
+        assert_eq!(zero_padded.len(), zero_padded_len);
 
-            let cstr = CString::try_from_fmt(fmt!("{:0100p}", ptr))?;
-            assert_eq!(cstr.to_str()?, expected::CLAMPED);
-        } else {
-            let cstr = CString::try_from_fmt(fmt!("{:p}", ptr))?;
-            let formatted = cstr.to_str()?;
-            // If the RNG is not yet ready, `%p` falls back to a placeholder.
-            if formatted == expected::PTR_VAL_NO_CRNG {
-                return Ok(());
-            }
-            assert!(formatted.starts_with(expected::HASHED_PREFIX));
-            assert_ne!(formatted, expected::RAW_POINTER);
-
-            let cstr = CString::try_from_fmt(fmt!("{:>24p}", ptr))?;
-            assert!(cstr
-                .to_str()?
-                .starts_with(expected::HASHED_PADDED_RIGHT_PREFIX));
-
-            let cstr = CString::try_from_fmt(fmt!("{:024p}", ptr))?;
-            assert!(cstr
-                .to_str()?
-                .starts_with(expected::HASHED_ZERO_PADDED_PREFIX));
-
-            let cstr = CString::try_from_fmt(fmt!("{:0100p}", ptr))?;
-            let output = cstr.to_str()?;
-            assert!(output.starts_with("0x"));
-            assert!(!output[2..].chars().all(|c| c == '0'));
-        }
+        let cstr = CString::try_from_fmt(fmt!("{:0100p}", ptr))?;
+        let clamped = cstr.to_str()?;
+        assert!(clamped.ends_with(expected_suffix));
+        assert_eq!(clamped.len(), clamped_len);
 
         Ok(())
     }

---
base-commit: be387b625933ee12ed230b1c2af5e14f946c3040
change-id: 20260814-b4-hashedptr-followup-27a4d737f377

Best regards,
-- 
Ke Sun <[email protected]>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.