]> git.lizzy.rs Git - rust.git/blob - tests/compiletest.rs
Merge pull request #283 from RalfJung/backtrace
[rust.git] / tests / compiletest.rs
1 #![feature(slice_concat_ext)]
2
3 extern crate compiletest_rs as compiletest;
4
5 use std::slice::SliceConcatExt;
6 use std::path::{PathBuf, Path};
7 use std::io::Write;
8
9 macro_rules! eprintln {
10     ($($arg:tt)*) => {
11         let stderr = std::io::stderr();
12         writeln!(stderr.lock(), $($arg)*).unwrap();
13     }
14 }
15
16 const MIRI_PATH: &'static str = concat!("target/", env!("PROFILE"), "/miri");
17
18 fn compile_fail(sysroot: &Path, path: &str, target: &str, host: &str, fullmir: bool) {
19     eprintln!("## Running compile-fail tests in {} against miri for target {}", path, target);
20     let mut config = compiletest::default_config();
21     config.mode = "compile-fail".parse().expect("Invalid mode");
22     config.rustc_path = MIRI_PATH.into();
23     let mut flags = Vec::new();
24     if fullmir {
25         if host != target {
26             // skip fullmir on nonhost
27             return;
28         }
29         let sysroot = Path::new(&std::env::var("HOME").unwrap()).join(".xargo").join("HOST");
30         config.target_rustcflags = Some(format!("--sysroot {}", sysroot.to_str().unwrap()));
31         config.src_base = PathBuf::from(path.to_string());
32     } else {
33         config.target_rustcflags = Some(format!("--sysroot {}", sysroot.to_str().unwrap()));
34         config.src_base = PathBuf::from(path.to_string());
35     }
36     flags.push("-Zmir-emit-validate=1".to_owned());
37     config.target_rustcflags = Some(flags.join(" "));
38     config.target = target.to_owned();
39     compiletest::run_tests(&config);
40 }
41
42 fn run_pass(path: &str) {
43     eprintln!("## Running run-pass tests in {} against rustc", path);
44     let mut config = compiletest::default_config();
45     config.mode = "run-pass".parse().expect("Invalid mode");
46     config.src_base = PathBuf::from(path);
47     config.target_rustcflags = Some("-Dwarnings".to_string());
48     config.host_rustcflags = Some("-Dwarnings".to_string());
49     compiletest::run_tests(&config);
50 }
51
52 fn miri_pass(path: &str, target: &str, host: &str, fullmir: bool, opt: bool) {
53     let opt_str = if opt {
54         " with optimizations"
55     } else {
56         ""
57     };
58     eprintln!("## Running run-pass tests in {} against miri for target {}{}", path, target, opt_str);
59     let mut config = compiletest::default_config();
60     config.mode = "mir-opt".parse().expect("Invalid mode");
61     config.src_base = PathBuf::from(path);
62     config.target = target.to_owned();
63     config.host = host.to_owned();
64     config.rustc_path = MIRI_PATH.into();
65     let mut flags = Vec::new();
66     if fullmir {
67         if host != target {
68             // skip fullmir on nonhost
69             return;
70         }
71         let sysroot = Path::new(&std::env::var("HOME").unwrap()).join(".xargo").join("HOST");
72         flags.push(format!("--sysroot {}", sysroot.to_str().unwrap()));
73     }
74     if opt {
75         flags.push("-Zmir-opt-level=3".to_owned());
76     } else {
77         flags.push("-Zmir-opt-level=0".to_owned());
78         // For now, only validate without optimizations.  Inlining breaks validation.
79         flags.push("-Zmir-emit-validate=1".to_owned());
80     }
81     config.target_rustcflags = Some(flags.join(" "));
82     // don't actually execute the final binary, it might be for other targets and we only care
83     // about running miri, not the binary.
84     config.runtool = Some("echo \"\" || ".to_owned());
85     if target == host {
86         std::env::set_var("MIRI_HOST_TARGET", "yes");
87     }
88     compiletest::run_tests(&config);
89     std::env::set_var("MIRI_HOST_TARGET", "");
90 }
91
92 fn is_target_dir<P: Into<PathBuf>>(path: P) -> bool {
93     let mut path = path.into();
94     path.push("lib");
95     path.metadata().map(|m| m.is_dir()).unwrap_or(false)
96 }
97
98 fn for_all_targets<F: FnMut(String)>(sysroot: &Path, mut f: F) {
99     let target_dir = sysroot.join("lib").join("rustlib");
100     for entry in std::fs::read_dir(target_dir).expect("invalid sysroot") {
101         let entry = entry.unwrap();
102         if !is_target_dir(entry.path()) { continue; }
103         let target = entry.file_name().into_string().unwrap();
104         f(target);
105     }
106 }
107
108 fn get_sysroot() -> PathBuf {
109     let sysroot = std::env::var("MIRI_SYSROOT").unwrap_or_else(|_| {
110         let sysroot = std::process::Command::new("rustc")
111             .arg("--print")
112             .arg("sysroot")
113             .output()
114             .expect("rustc not found")
115             .stdout;
116         String::from_utf8(sysroot).expect("sysroot is not utf8")
117     });
118     PathBuf::from(sysroot.trim())
119 }
120
121 fn get_host() -> String {
122     let host = std::process::Command::new("rustc")
123         .arg("-vV")
124         .output()
125         .expect("rustc not found for -vV")
126         .stdout;
127     let host = std::str::from_utf8(&host).expect("sysroot is not utf8");
128     let host = host.split("\nhost: ").nth(1).expect("no host: part in rustc -vV");
129     let host = host.split('\n').next().expect("no \n after host");
130     String::from(host)
131 }
132
133 #[test]
134 fn run_pass_miri() {
135     let sysroot = get_sysroot();
136     let host = get_host();
137
138     for &opt in [false, true].iter() {
139         for_all_targets(&sysroot, |target| {
140             miri_pass("tests/run-pass", &target, &host, false, opt);
141         });
142         miri_pass("tests/run-pass-fullmir", &host, &host, true, opt);
143     }
144 }
145
146 #[test]
147 fn run_pass_rustc() {
148     run_pass("tests/run-pass");
149     run_pass("tests/run-pass-fullmir");
150 }
151
152 #[test]
153 fn compile_fail_miri() {
154     let sysroot = get_sysroot();
155     let host = get_host();
156
157     for_all_targets(&sysroot, |target| {
158         compile_fail(&sysroot, "tests/compile-fail", &target, &host, false);
159     });
160     compile_fail(&sysroot, "tests/compile-fail-fullmir", &host, &host, true);
161 }