在我的overflower_support箱子的测试中,我发现我收到很多关于已经使用std::panic::catch_unwind(_)
处理的恐慌的虚假报告。这有点不幸,因为它掩盖了可能发生的真实错误。消息如下:
thread 'safe' panicked at 'arithmetic overflow', src/lib.rs:56
为了平息那些分散注意力的消息,我引入了dont_panic(..)
函数,它劫持了恐慌处理程序,调用了一个闭包并在完成时重置了恐慌处理程序,返回了闭包结果。它看起来像这样:
fn dont_panic<F, A, R>(args: A, f: F) -> R
where F: Fn(A) -> R
{
let p = panic::take_hook();
panic::set_hook(Box::new(|_| ()));
let result = f(args);
panic::set_hook(p);
result
}
然而,在功能中使用此功能有点令人惊讶地不仅可以消除所需的消息,还可以快速检查错误输出,这对我来说显然很有价值。即使将测试限制在一个线程中也会发生这种情况。
#[test]
fn test_some_panic() {
fn check(x: usize) -> bool {
let expected = if x < 256 { Some(x) } else { None };
let actual = dont_panic(|| panic::catch_unwind(|| { assert!(x < 256); x }).ok());
expected == actual
}
quickcheck(check as fn(usize) -> bool);
}
如何在保持QuickCheck的恐慌可见的同时隐藏我的代码中的抓捕恐慌?
答案 0 :(得分:2)
默认的恐慌处理程序无条件地在stderr上打印恐慌信息。
答案 1 :(得分:2)
我遇到了同样的问题和其他一些问题,最后我写了一个箱子来解决它们:
有了它,您的示例可能会通过在“安静”的线程中运行来解决(假设您对专门使用catch_unwind
不感兴趣):
use panic_control::spawn_quiet;
#[test]
fn test_some_panic() {
fn check(x: usize) -> bool {
let expected = if x < 256 { Some(x) } else { None };
let h = spawn_quiet(|| { assert!(x < 256); x });
let actual = h.join().ok();
expected == actual
}
quickcheck(check as fn(usize) -> bool);
}
答案 2 :(得分:1)
我的方法存在两个问题:
-j 1
似乎无法平息恐慌信息。)set_hook(_)
压制)no
如果有catch_unwind(_)
,则无关紧要。然而,dpc.pw的想法是基于恐慌处理程序中的文件进行区分
发现。之前我改变了我的方法来调用install_handler()
函数
调用quickcheck(_)
,我在这里完整地重现:
use std::panic;
use std::sync::{Once, ONCE_INIT};
static HANDLER : Once = ONCE_INIT;
fn install_handler() {
HANDLER.call_once(|| {
let p = panic::take_hook();
panic::set_hook(Box::new(move|info| {
if info.location().map_or(false, |l| l.file() != "src/lib.rs" &&
!l.file().ends_with("/num/mod.rs")) {
p(info);
}
}));
})
}
如果恐慌来自src/lib.rs
,那将会平息恐慌信息
是我的overflower_support
代码)或/num/mod.rs
的某个地方(因为
Rust libcore
代码也可能会出现恐慌。
请注意,您可以省略Once
,但这会将处理程序多次添加
时间并且在加剧时大大增加堆栈轨迹的大小
测试表现。