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