如何在QuickCheck测试中默默捕捉恐慌? [英] How can I silently catch panics in QuickCheck tests?

查看:321
本文介绍了如何在QuickCheck测试中默默捕捉恐慌?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 overflower_support 板条箱的测试中,我发现有很多关于已使用std::panic::catch_unwind(_)处理的紧急情况.这有点不幸,因为它掩盖了可能发生的实际错误.消息如下:

In the tests of my overflower_support crate, I have found that I get a lot of spurious reports of panics which are already handled using std::panic::catch_unwind(_). This is a bit unfortunate, as it obscures the real errors that may happen. The messages look like:

thread 'safe' panicked at 'arithmetic overflow', src/lib.rs:56

为平息那些分散注意力的消息,我引入了dont_panic(..)函数,该函数劫持了应急处理程序,调用了一个闭包,并在完成后重置了应急处理程序,返回了闭包结果.看起来像这样:

To quell those distracting messages, I introduced the dont_panic(..) function, which hijacks the panic handler, calls a closure and resets the panic handler when done, returning the closures result. It looks like this:

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
}

但是,在函数中使用此函数进行一些令人惊讶的检查不仅可以平息所需的消息,还可以平息quickcheck的错误输出,这对我来说显然很有价值.即使将测试限制在一个线程中,也会发生这种情况.

However, using this function within the function to check somewhat surprisingly not only quells the desired messages, but also quickcheck's error output, which is obviously valuable to me. This occurs even when limiting tests to one thread.

#[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的恐慌可见的同时,从代码中隐藏捕获的恐慌?

How can I hide the caught panics from my code while keeping QuickCheck's panics visible?

推荐答案

我的方法存在两个问题:

There were two problems with my approach:

  1. 测试是并行运行的(而quickcheck似乎增加了 本身,因为-j 1似乎无法平息恐慌消息.)
  2. 消息被写入(或被set_hook(_)禁止显示)否 是否有catch_unwind(_)无关紧要.
  1. The tests run in parallel (and quickcheck appears to add some parallelism of its own, as -j 1 appears ineffective to quell the panic messages).
  2. The message gets written (or otherwise suppressed by set_hook(_)) no matter if there's a catch_unwind(_) or not.

但是,dpc.pw区分恐慌处理程序中文件的想法是 发现.我更改了方法,以在调用install_handler()函数之前 调用quickcheck(_),我将在此处完整复制:

However, dpc.pw's idea to distinguish based on files in the panic handler was spot-on. I changed my approach to call an install_handler() function before calling quickcheck(_), which I reproduce here in full:

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代码也可能会崩溃).

This will quell the panic messages if the panic came from src/lib.rs (which is my overflower_support code) or somewhere from /num/mod.rs (because the Rust libcore code may panic, too).

请注意,您可以省略Once,但这会为处理程序添加多个 并增加堆栈跟踪的大小,同时加剧 测试性能.

Note that you could omit the Once, but this would add the handler multiple times and increase the size of stack traces considerably while exacerbating test performance.

这篇关于如何在QuickCheck测试中默默捕捉恐慌?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆