blob: 3b71c6eebbf48f03e7af388bb95b871d0fc9ce35 [file] [log] [blame]
use std::fs;
use std::io;
use std::process::Command;
use std::sync::Once;
pub fn setup() {
static BUILD: Once = Once::new();
BUILD.call_once(|| {
let status = Command::new("cargo")
.arg("build")
.status()
.expect("failed to build");
assert!(status.success());
});
}
pub fn contains_panic(name: &str, code: &str) -> bool {
let tempdir = scratch::path("no-panic").join(name);
match fs::create_dir(&tempdir) {
Ok(()) => {}
Err(err) if err.kind() == io::ErrorKind::AlreadyExists => {}
err @ Err(_) => err.unwrap(),
}
let prelude = stringify! {
use no_panic::no_panic;
};
let rs = tempdir.join(format!("{}.rs", name));
fs::write(&rs, format!("{}{}", prelude, code)).unwrap();
let status = Command::new("rustc")
.arg("--crate-name")
.arg(name)
.arg(rs)
.arg("--edition=2018")
.arg("-C")
.arg("opt-level=3")
.arg("--emit=asm")
.arg("--out-dir")
.arg(&tempdir)
.arg("--extern")
.arg(format!(
"no_panic=target/debug/{prefix}no_panic.{extension}",
prefix = std::env::consts::DLL_PREFIX,
extension = std::env::consts::DLL_EXTENSION,
))
.arg("-D")
.arg("warnings")
.status()
.expect("failed to execute rustc");
assert!(status.success());
let asm = tempdir.join(format!("{}.s", name));
let asm = fs::read_to_string(asm).unwrap();
asm.contains("detected panic in function")
}
macro_rules! assert_no_panic {
($(mod $name:ident { $($content:tt)* })*) => {
mod no_panic {
use crate::compiletest;
$(
#[test]
fn $name() {
compiletest::setup();
let name = stringify!($name);
let content = stringify!($($content)*);
assert!(!compiletest::contains_panic(name, content));
}
)*
}
};
}
macro_rules! assert_link_error {
($(mod $name:ident { $($content:tt)* })*) => {
mod link_error {
use crate::compiletest;
$(
#[test]
fn $name() {
compiletest::setup();
let name = stringify!($name);
let content = stringify!($($content)*);
assert!(compiletest::contains_panic(name, content));
}
)*
}
};
}