如何处理测试单元中的中止

问题描述

我想测试我的一个应该恐慌的函数,但我的 GitHub 操作 abort() 导致即使我的代码要求“仅”2**31 字节(在我的实际代码中,限制是 { {1}}) 我的电脑有,GitHub 操作没有这样的内存 :p.

libc::c_int::MAX

但这失败了:

#[test]
#[should_panic]
fn reserve_with_max() {
    Vec::with_capacity(usize::MAX);
}

这会停止测试并报告错误,即使这是我所期望的(恐慌或中止)。

我没有找到太多关于这个问题的信息:

我希望应该有一个 test tests::bad_fd ... ok test tests::create_true ... ok test tests::create_false ... ok test tests::create_with_one ... ok memory allocation of 25769803764 bytes Failed ,我该如何处理?

目前我显而易见的解决方案是#[should_abort]测试:

ignore

解决方法

你可以分叉测试,但有很多缺点:

  • 需要 nix(也许某处有一个与操作系统无关的 fork 板条箱......)
  • 测试代码变得复杂
  • 代码覆盖工具问题
  • 询问更多资源
  • 笨手笨脚的
#[test]
#[ignore = "Still ignored taupaulin doesn't like it too"]
fn create_with_max() {
    use nix::{
        sys::{
            signal::Signal,wait::{waitpid,WaitStatus},},unistd::{fork,ForkResult},};
    use std::panic;
    use std::process::abort;

    match unsafe { fork() } {
        Ok(ForkResult::Parent { child }) => match waitpid(child,None) {
            Ok(WaitStatus::Signaled(_,s,_)) => {
                if s != Signal::SIGABRT {
                    panic!("Didn't abort")
                }
            }
            o => panic!("Didn't expect: {:?}",o),Ok(ForkResult::Child) => {
            let result = panic::catch_unwind(|| {
                Vec::with_capacity(usize::MAX);
            });

            if let Err(_) = result {
                abort();
            }
        }
        Err(_) => panic!("Fork failed"),}
}

我不认为我会建议这样做。

,

有一个 RFC 2116 允许配置 rust 来解决内存崩溃而不是 abort()

[profile.dev]
oom = "panic"

[profile.release]
oom = "panic"

缺点:

  • 即使在每晚都没有实施#43596
  • 它适用于您的用例,因为它是一个 oom 中止,但它不是测试中句柄 abort() 的通用解决方案。