use internal::dirs::corpus_directory_from_target;
use predicates::prelude::*;
use rlimit::Resource;
use std::fs::remove_dir_all;
use test_log::test;
use testing::{examples, retry};
const MEMORY_LIMIT: u64 = 1024 * 1024 * 1024;
const TIMEOUT: &str = "240";
#[derive(Clone, Copy)]
enum Object {
Crashes,
Hangs,
}
#[cfg_attr(
dylint_lib = "non_thread_safe_call_in_test",
allow(non_thread_safe_call_in_test)
)]
#[test]
fn replay_crashes() {
replay(
"alloc",
"target",
&[
"--run-until-crash",
"--",
"-m",
&format!("{}", MEMORY_LIMIT / 1024),
],
Object::Crashes,
r"(?m)\bmemory allocation of \d{10,} bytes failed$|\bcapacity overflow\b",
);
}
#[cfg_attr(
dylint_lib = "non_thread_safe_call_in_test",
allow(non_thread_safe_call_in_test)
)]
#[allow(clippy::trivial_regex)]
#[test]
fn replay_hangs() {
replay(
"parse_duration",
"parse",
&["--persistent", "--", "-V", TIMEOUT],
Object::Hangs,
r"(?m)\bTimeout$",
);
}
fn replay(krate: &str, target: &str, fuzz_args: &[&str], object: Object, re: &str) {
let corpus = corpus_directory_from_target(krate, target);
#[cfg_attr(
dylint_lib = "non_thread_safe_call_in_test",
allow(non_thread_safe_call_in_test)
)]
remove_dir_all(&corpus).unwrap_or_default();
examples::test(krate, "test").unwrap().assert().success();
examples::test_fuzz(krate, target)
.unwrap()
.args(&["--reset"])
.assert()
.success();
retry(3, || {
let mut args = vec!["--no-ui"];
args.extend_from_slice(fuzz_args);
examples::test_fuzz(krate, target)
.unwrap()
.args(args)
.assert()
.success();
Resource::DATA.set(MEMORY_LIMIT, MEMORY_LIMIT).unwrap();
let mut command = examples::test_fuzz(krate, target).unwrap();
command
.args(&[match object {
Object::Crashes => "--replay=crashes",
Object::Hangs => "--replay=hangs",
}])
.assert()
.success()
.try_stdout(predicate::str::is_match(re).unwrap())
})
.unwrap();
}