Вот быстрый и грязный обходной путь.
Он работает, отправляя сообщения получателю, принадлежащему структуре в основном потоке.Приемник печатает все накопленные сообщения при его отбрасывании - это важно, чтобы паника, вызванная ошибочными утверждениями, не помешала печати.
use std::sync::mpsc::{channel, Sender, Receiver};
struct TestPrinter {
receiver: Receiver<String>,
sender: Sender<String>,
}
impl TestPrinter {
fn new() -> TestPrinter {
let (sender, receiver) = channel();
TestPrinter { receiver, sender }
}
fn sender(&self) -> Sender<String> {
self.sender.clone()
}
}
impl Drop for TestPrinter {
fn drop(&mut self) {
while let Some(v) = self.receiver.try_recv().ok() {
println!("later: {}", v);
}
}
}
И вспомогательный макрос, поэтому он больше похож на вызов println!
:
macro_rules! myprint {
($send: expr, $($arg:tt)*) => {
(*&$send).send(format!($($arg)*));
};
}
Для отправки сообщений на печать вы получаете sender
для каждой нити:
#[test]
fn multi_thread_test() {
use std::thread;
let mut threads = vec![];
let printer = TestPrinter::new();
for _ in 0..100 {
let sender = printer.sender();
let t = thread::spawn(move || {
myprint!(sender, "from thread");
});
threads.push(t);
}
for thread in threads {
thread.join().unwrap();
}
}
Фактическая печать происходит, когда printer
выходит из строяобласти видимостиОн находится в главном потоке, поэтому он не будет печататься во время успешных тестов, если не указано --nocapture
.