浏览代码

test: loom tests only print traces from the failed iteration (#8)

This helps a *lot* when a test fails on the 300,000th iteration or
something; you don't have to wait for *every* previous iteration's trace
to be dumped to stdout.
Eliza Weisman 3 年之前
父节点
当前提交
79d9d88d5f
共有 2 个文件被更改,包括 75 次插入12 次删除
  1. 66 8
      src/loom.rs
  2. 9 4
      src/macros.rs

+ 66 - 8
src/loom.rs

@@ -6,19 +6,69 @@ mod inner {
         pub use loom::sync::atomic::*;
         pub use std::sync::atomic::Ordering;
     }
+
     pub(crate) use loom::{cell::UnsafeCell, future, hint, sync, thread};
+    use std::{cell::RefCell, fmt::Write};
+
+    std::thread_local! {
+        static TRACE_BUF: RefCell<String> = RefCell::new(String::new());
+    }
+
+    pub(crate) fn traceln(args: std::fmt::Arguments) {
+        let mut args = Some(args);
+        TRACE_BUF
+            .try_with(|buf| {
+                let mut buf = buf.borrow_mut();
+                let _ = buf.write_fmt(args.take().unwrap());
+                let _ = buf.write_char('\n');
+            })
+            .unwrap_or_else(|_| println!("{}", args.take().unwrap()))
+    }
+
+    pub(crate) fn run_builder(
+        builder: loom::model::Builder,
+        model: impl Fn() + Sync + Send + 'static,
+    ) {
+        use core::sync::atomic::{AtomicUsize, Ordering};
+        #[must_use]
+        struct Iteration(());
+
+        impl Drop for Iteration {
+            fn drop(&mut self) {
+                if std::thread::panicking() {
+                    TRACE_BUF
+                        .try_with(|buf| {
+                            if let Ok(buf) = buf.try_borrow() {
+                                eprintln!("{}", buf);
+                            } else {
+                                eprintln!("trace buf already borrowed!");
+                            }
+                        })
+                        .unwrap_or_else(|_| eprintln!("trace buf already torn down!"));
+                } else {
+                    TRACE_BUF.with(|buf| buf.borrow_mut().clear());
+                }
+            }
+        }
 
-    pub(crate) fn model(f: impl Fn() + Sync + Send + 'static) {
-        let iteration = core::sync::atomic::AtomicUsize::new(0);
-        loom::model(move || {
-            println!(
-                "\n---- iteration {} ----\n",
-                iteration.fetch_add(1, atomic::Ordering::Relaxed)
-            );
-            f();
+        let current_iteration = AtomicUsize::new(1);
+
+        builder.check(move || {
+            traceln(format_args!(
+                "\n---- {} iteration {} ----",
+                std::thread::current().name().unwrap_or("<unknown test>"),
+                current_iteration.fetch_add(1, Ordering::Relaxed)
+            ));
+            let _iter = Iteration(());
+
+            model();
         })
     }
 
+    pub(crate) fn model(model: impl Fn() + Sync + Send + 'static) {
+        run_builder(loom::model::Builder::default(), model)
+    }
+
     pub(crate) mod alloc {
         #![allow(dead_code)]
         use loom::alloc;
@@ -151,4 +201,12 @@ mod inner {
             }
         }
     }
+
+    #[cfg(feature = "std")]
+    pub(crate) fn traceln(args: std::fmt::Arguments) {
+        eprintln!("{}", args);
+    }
+
+    #[cfg(not(feature = "std"))]
+    pub(crate) fn traceln(_: core::fmt::Arguments) {}
 }

+ 9 - 4
src/macros.rs

@@ -1,17 +1,22 @@
 macro_rules! test_println {
     ($($arg:tt)*) => {
-        if cfg!(test) {
+        if cfg!(test) || cfg!(all(thingbuf_trace, feature = "std")) {
             if crate::util::panic::panicking() {
                 // getting the thread ID while panicking doesn't seem to play super nicely with loom's
                 // mock lazy_static...
-                println!("[PANIC {:>17}:{:<3}] {}", file!(), line!(), format_args!($($arg)*))
+                println!("[PANIC {:>30}:{:<3}] {}", file!(), line!(), format_args!($($arg)*))
             } else {
-                println!("[{:?} {:>17}:{:<3}] {}", crate::loom::thread::current().id(), file!(), line!(), format_args!($($arg)*))
+                crate::loom::traceln(format_args!(
+                    "[{:?} {:>30}:{:<3}] {}",
+                    crate::loom::thread::current().id(),
+                    file!(),
+                    line!(),
+                    format_args!($($arg)*),
+                ));
             }
         }
     }
 }
-
 macro_rules! test_dbg {
     ($e:expr) => {
         match $e {