1 use std::fs;
2 use std::process::Command;
3 use std::sync::Once;
4
setup()5 pub fn setup() {
6 static BUILD: Once = Once::new();
7 BUILD.call_once(|| {
8 let status = Command::new("cargo")
9 .arg("build")
10 .status()
11 .expect("failed to build");
12 assert!(status.success());
13 });
14 }
15
contains_panic(name: &str, code: &str) -> bool16 pub fn contains_panic(name: &str, code: &str) -> bool {
17 let tempdir = tempfile::tempdir().unwrap();
18
19 let prelude = stringify! {
20 use no_panic::no_panic;
21 };
22
23 let rs = tempdir.path().join(format!("{}.rs", name));
24 fs::write(&rs, format!("{}{}", prelude, code)).unwrap();
25
26 let status = Command::new("rustc")
27 .arg("--crate-name")
28 .arg(name)
29 .arg(rs)
30 .arg("--edition=2018")
31 .arg("-C")
32 .arg("opt-level=3")
33 .arg("--emit=asm")
34 .arg("--out-dir")
35 .arg(tempdir.path())
36 .arg("--extern")
37 .arg(format!(
38 "no_panic=target/debug/{prefix}no_panic.{extension}",
39 prefix = std::env::consts::DLL_PREFIX,
40 extension = std::env::consts::DLL_EXTENSION,
41 ))
42 .status()
43 .expect("failed to execute rustc");
44 assert!(status.success());
45
46 let asm = tempdir.path().join(format!("{}.s", name));
47 let asm = fs::read_to_string(asm).unwrap();
48 asm.contains("detected panic in function")
49 }
50
51 macro_rules! assert_no_panic {
52 ($(mod $name:ident { $($content:tt)* })*) => {
53 mod no_panic {
54 use crate::compiletest;
55 $(
56 #[test]
57 fn $name() {
58 compiletest::setup();
59 let name = stringify!($name);
60 let content = stringify!($($content)*);
61 assert!(!compiletest::contains_panic(name, content));
62 }
63 )*
64 }
65 };
66 }
67
68 macro_rules! assert_link_error {
69 ($(mod $name:ident { $($content:tt)* })*) => {
70 mod link_error {
71 use crate::compiletest;
72 $(
73 #[test]
74 fn $name() {
75 compiletest::setup();
76 let name = stringify!($name);
77 let content = stringify!($($content)*);
78 assert!(compiletest::contains_panic(name, content));
79 }
80 )*
81 }
82 };
83 }
84