1 use std::fs; 2 use std::process::Command; 3 use std::sync::Once; 4 setup()5pub 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) -> bool16pub 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("no_panic=target/debug/libno_panic.so") 38 .status() 39 .expect("failed to execute rustc"); 40 assert!(status.success()); 41 42 let asm = tempdir.path().join(format!("{}.s", name)); 43 let asm = fs::read_to_string(asm).unwrap(); 44 asm.contains("detected panic in function") 45 } 46 47 macro_rules! assert_no_panic { 48 ($(mod $name:ident { $($content:tt)* })*) => { 49 mod no_panic { 50 use crate::compiletest; 51 $( 52 #[test] 53 fn $name() { 54 compiletest::setup(); 55 let name = stringify!($name); 56 let content = stringify!($($content)*); 57 assert!(!compiletest::contains_panic(name, content)); 58 } 59 )* 60 } 61 }; 62 } 63 64 macro_rules! assert_link_error { 65 ($(mod $name:ident { $($content:tt)* })*) => { 66 mod link_error { 67 use crate::compiletest; 68 $( 69 #[test] 70 fn $name() { 71 compiletest::setup(); 72 let name = stringify!($name); 73 let content = stringify!($($content)*); 74 assert!(compiletest::contains_panic(name, content)); 75 } 76 )* 77 } 78 }; 79 } 80