From 6c5db43d298f105c95e75e8d9b468f0e421c672c Mon Sep 17 00:00:00 2001 From: Joeri van Ruth Date: Tue, 16 Jul 2024 17:33:12 +0200 Subject: [PATCH 1/2] test: show data as text when io mock assert fails The asserts used to show the bytes as numbers, which is unnecessary hard to debug when the data is textual. It seems generally, though not universally more useful to show it as text when possible. --- tokio-test/Cargo.toml | 1 + tokio-test/src/io.rs | 28 +++++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/tokio-test/Cargo.toml b/tokio-test/Cargo.toml index 076f79bf5e8..833f2f95969 100644 --- a/tokio-test/Cargo.toml +++ b/tokio-test/Cargo.toml @@ -23,6 +23,7 @@ async-stream = "0.3.3" bytes = "1.0.0" futures-core = "0.3.0" +bstr = "1.6.2" [dev-dependencies] tokio = { version = "1.2.0", path = "../tokio", features = ["full"] } diff --git a/tokio-test/src/io.rs b/tokio-test/src/io.rs index c31d5be5de2..3bc9deef3a8 100644 --- a/tokio-test/src/io.rs +++ b/tokio-test/src/io.rs @@ -18,6 +18,7 @@ //! [`AsyncRead`]: tokio::io::AsyncRead //! [`AsyncWrite`]: tokio::io::AsyncWrite +use bstr::BStr; use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; use tokio::sync::mpsc; use tokio::time::{self, Duration, Instant, Sleep}; @@ -256,7 +257,7 @@ impl Inner { Action::Write(ref mut expect) => { let n = cmp::min(src.len(), expect.len()); - assert_eq!(&src[..n], &expect[..n]); + assert_eq!(ShowBytes(src, n), ShowBytes(expect, n)); // Drop data that was matched expect.drain(..n); @@ -475,8 +476,8 @@ impl Drop for Mock { } self.inner.actions.iter().for_each(|a| match a { - Action::Read(data) => assert!(data.is_empty(), "There is still data left to read."), - Action::Write(data) => assert!(data.is_empty(), "There is still data left to write."), + Action::Read(data) => assert!(data.is_empty(), "There is still data left to read: {:?}", ShowBytes(data, 10)), + Action::Write(data) => assert!(data.is_empty(), "There is still data left to write: {:?}", ShowBytes(data, 10)), _ => (), }); } @@ -508,3 +509,24 @@ impl fmt::Debug for Inner { write!(f, "Inner {{...}}") } } + +struct ShowBytes<'a>(&'a[u8], usize); + +impl<'a> fmt::Debug for ShowBytes<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let n = self.0.len(); + let limit = self.1; + if self.0.len() <= limit { + write!(f, "{:?}", BStr::new(self.0)) + } else { + let bytes = BStr::new(&self.0[..limit]); + write!(f, "{bytes:?} plus {} more bytes", n - limit) + } + } +} + +impl<'a> PartialEq for ShowBytes<'a> { + fn eq(&self, other: &Self) -> bool { + self.0[..self.1] == other.0[..other.1] + } +} From 9b796f042e383fd5e356226eeea3b20d719e7133 Mon Sep 17 00:00:00 2001 From: Joeri van Ruth Date: Tue, 16 Jul 2024 17:57:04 +0200 Subject: [PATCH 2/2] test: fix formatting --- tokio-test/src/io.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tokio-test/src/io.rs b/tokio-test/src/io.rs index 3bc9deef3a8..b9990b767d1 100644 --- a/tokio-test/src/io.rs +++ b/tokio-test/src/io.rs @@ -476,8 +476,16 @@ impl Drop for Mock { } self.inner.actions.iter().for_each(|a| match a { - Action::Read(data) => assert!(data.is_empty(), "There is still data left to read: {:?}", ShowBytes(data, 10)), - Action::Write(data) => assert!(data.is_empty(), "There is still data left to write: {:?}", ShowBytes(data, 10)), + Action::Read(data) => assert!( + data.is_empty(), + "There is still data left to read: {:?}", + ShowBytes(data, 10) + ), + Action::Write(data) => assert!( + data.is_empty(), + "There is still data left to write: {:?}", + ShowBytes(data, 10) + ), _ => (), }); } @@ -510,7 +518,7 @@ impl fmt::Debug for Inner { } } -struct ShowBytes<'a>(&'a[u8], usize); +struct ShowBytes<'a>(&'a [u8], usize); impl<'a> fmt::Debug for ShowBytes<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {