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