How to handle abort in test unit

Viewed 545

I want to test one of my function that should panic, but my GitHub action abort() cause even if my code is asking for "only" 2**31 bytes (In my real code the limit is libc::c_int::MAX) that my PC has, GitHub action don't have such memory :p.

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

But this fails with:

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

And this stops the testing and report an error, even if this what I expected (either panic or abort).

I didn't find much about this problem:

I expect there should be a #[should_abort], how could I handle this ?

For now my obvious solution is to ignore the test:

#[test]
#[should_panic]
#[ignore = "Ask too much memory"]
2 Answers

You could fork the test but there is a lot of cons:

  • need nix (maybe there is a OS agnostic fork crate somewhere...)
  • test code become complex
  • code coverage tool problem
  • ask more resource
  • hacky
#[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"),
    }
}

I don't think I would advice this.

There is an RFC 2116 that would allow to configure rust to make out of memory panic instead of abort():

[profile.dev]
oom = "panic"

[profile.release]
oom = "panic"

Cons:

  • Not implemented even on nightly #43596
  • It's will work for your use case cause it's an oom abort but it's not a general solution for handle abort() in test.
Related