Info
This post is auto-generated from RSS feed The Rust Programming Language Forum - Latest topics. Source: Can I resume panics on different threads or how to capture test output
Currently test runtime in Rust spawns a new thread for every single test.
In my case this is problematic, since I am writing tests to a C++ library, which really doesn't want to be reinitialized on other threads.
So instead I use LazyStatic
to spawn a single thread to which Rust tests will be sending tasks to:
pub static WORKER: LazyLock<Mutex<Worker>> = LazyLock::new(|| {
let (task_tx, task_rx) = mpsc::channel();
std::thread::spawn(move || {
while let Ok(Task { task, result_tx }) = task_rx.recv() {
let env = unsafe { environment::TestEnvironment::build() };
let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
env.run(task);
}));
std::mem::drop(env);
_ = result_tx.send(result);
}
});
Mutex::new(Worker { task_tx })
});
The problem is that there are tests which can panic.
To deal with this I call resume_unwind
inside tests:
let worker = loop {
match worker::WORKER.lock() {
Ok(guard) => break guard,
Err(_) => worker::WORKER.clear_poison(),
}
};
let (result_tx, result_rx) = mpsc::channel();
worker
.task_tx
.send(worker::Task {
task: Box::new(task),
result_tx,
})
.expect("Worker thread cannot fail");
let result = result_rx.recv().expect("Worker thread cannot fail");
std::mem::drop(worker);
match result {
Ok(result) => result,
Err(panic) => std::panic::resume_unwind(panic),
}
This works, however, if the test fails for whatever reason the output is empty:
#[lib::test]
fn example_test() {
panic!("Explicitly fail")
}
running 1 test
test example_test... FAILED
failures:
failures:
example_test
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.90s
If I pass --nocapture
to tests I can see the actual error message, but this is bad UX:
running 1 test
thread '<unnamed>' panicked at tests\test_utils.rs:113:7:
Explicitly fail
test example_test... FAILED
failures:
failures:
example_test
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 3.90s
Anything I can do to make test runtime capture this output?
Instead of resume_unwind
I can extract the string out of the Box<dyn Any>
and panic with it, but this looses the error location.
2 posts - 1 participant
🏷️ Rust_feed