1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10 pub use self::Mode::*;
11
12 use std::env;
13 use std::fmt;
14 use std::fs::{read_dir, remove_file};
15 use std::str::FromStr;
16 use std::path::PathBuf;
17 #[cfg(feature = "rustc")]
18 use rustc_session;
19
20 use test::ColorConfig;
21 use runtest::dylib_env_var;
22
23 #[derive(Clone, Copy, PartialEq, Debug)]
24 pub enum Mode {
25 CompileFail,
26 ParseFail,
27 RunFail,
28 RunPass,
29 RunPassValgrind,
30 Pretty,
31 DebugInfoGdb,
32 DebugInfoLldb,
33 Codegen,
34 Rustdoc,
35 CodegenUnits,
36 Incremental,
37 RunMake,
38 Ui,
39 MirOpt,
40 Assembly,
41 }
42
43 impl Mode {
disambiguator(self) -> &'static str44 pub fn disambiguator(self) -> &'static str {
45 // Run-pass and pretty run-pass tests could run concurrently, and if they do,
46 // they need to keep their output segregated. Same is true for debuginfo tests that
47 // can be run both on gdb and lldb.
48 match self {
49 Pretty => ".pretty",
50 DebugInfoGdb => ".gdb",
51 DebugInfoLldb => ".lldb",
52 _ => "",
53 }
54 }
55 }
56
57 impl FromStr for Mode {
58 type Err = ();
from_str(s: &str) -> Result<Mode, ()>59 fn from_str(s: &str) -> Result<Mode, ()> {
60 match s {
61 "compile-fail" => Ok(CompileFail),
62 "parse-fail" => Ok(ParseFail),
63 "run-fail" => Ok(RunFail),
64 "run-pass" => Ok(RunPass),
65 "run-pass-valgrind" => Ok(RunPassValgrind),
66 "pretty" => Ok(Pretty),
67 "debuginfo-lldb" => Ok(DebugInfoLldb),
68 "debuginfo-gdb" => Ok(DebugInfoGdb),
69 "codegen" => Ok(Codegen),
70 "rustdoc" => Ok(Rustdoc),
71 "codegen-units" => Ok(CodegenUnits),
72 "incremental" => Ok(Incremental),
73 "run-make" => Ok(RunMake),
74 "ui" => Ok(Ui),
75 "mir-opt" => Ok(MirOpt),
76 "assembly" => Ok(Assembly),
77 _ => Err(()),
78 }
79 }
80 }
81
82 impl fmt::Display for Mode {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result83 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
84 fmt::Display::fmt(match *self {
85 CompileFail => "compile-fail",
86 ParseFail => "parse-fail",
87 RunFail => "run-fail",
88 RunPass => "run-pass",
89 RunPassValgrind => "run-pass-valgrind",
90 Pretty => "pretty",
91 DebugInfoGdb => "debuginfo-gdb",
92 DebugInfoLldb => "debuginfo-lldb",
93 Codegen => "codegen",
94 Rustdoc => "rustdoc",
95 CodegenUnits => "codegen-units",
96 Incremental => "incremental",
97 RunMake => "run-make",
98 Ui => "ui",
99 MirOpt => "mir-opt",
100 Assembly => "assembly",
101 },
102 f)
103 }
104 }
105
106 #[derive(Clone)]
107 pub struct Config {
108 /// `true` to overwrite stderr/stdout/fixed files instead of complaining about changes in output.
109 pub bless: bool,
110
111 /// The library paths required for running the compiler
112 pub compile_lib_path: PathBuf,
113
114 /// The library paths required for running compiled programs
115 pub run_lib_path: PathBuf,
116
117 /// The rustc executable
118 pub rustc_path: PathBuf,
119
120 /// The rustdoc executable
121 pub rustdoc_path: Option<PathBuf>,
122
123 /// The python executable to use for LLDB
124 pub lldb_python: String,
125
126 /// The python executable to use for htmldocck
127 pub docck_python: String,
128
129 /// The llvm FileCheck binary path
130 pub llvm_filecheck: Option<PathBuf>,
131
132 /// The valgrind path
133 pub valgrind_path: Option<String>,
134
135 /// Whether to fail if we can't run run-pass-valgrind tests under valgrind
136 /// (or, alternatively, to silently run them like regular run-pass tests).
137 pub force_valgrind: bool,
138
139 /// The directory containing the tests to run
140 pub src_base: PathBuf,
141
142 /// The directory where programs should be built
143 pub build_base: PathBuf,
144
145 /// The name of the stage being built (stage1, etc)
146 pub stage_id: String,
147
148 /// The test mode, compile-fail, run-fail, run-pass
149 pub mode: Mode,
150
151 /// Run ignored tests
152 pub run_ignored: bool,
153
154 /// Only run tests that match these filters
155 pub filters: Vec<String>,
156
157 /// Exactly match the filter, rather than a substring
158 pub filter_exact: bool,
159
160 /// Write out a parseable log of tests that were run
161 pub logfile: Option<PathBuf>,
162
163 /// A command line to prefix program execution with,
164 /// for running under valgrind
165 pub runtool: Option<String>,
166
167 /// Flags to pass to the compiler when building for the host
168 pub host_rustcflags: Option<String>,
169
170 /// Flags to pass to the compiler when building for the target
171 pub target_rustcflags: Option<String>,
172
173 /// Target system to be tested
174 pub target: String,
175
176 /// Host triple for the compiler being invoked
177 pub host: String,
178
179 /// Path to / name of the GDB executable
180 pub gdb: Option<String>,
181
182 /// Version of GDB, encoded as ((major * 1000) + minor) * 1000 + patch
183 pub gdb_version: Option<u32>,
184
185 /// Whether GDB has native rust support
186 pub gdb_native_rust: bool,
187
188 /// Version of LLDB
189 pub lldb_version: Option<String>,
190
191 /// Version of LLVM
192 pub llvm_version: Option<String>,
193
194 /// Is LLVM a system LLVM
195 pub system_llvm: bool,
196
197 /// Path to the android tools
198 pub android_cross_path: PathBuf,
199
200 /// Extra parameter to run adb on arm-linux-androideabi
201 pub adb_path: String,
202
203 /// Extra parameter to run test suite on arm-linux-androideabi
204 pub adb_test_dir: String,
205
206 /// status whether android device available or not
207 pub adb_device_status: bool,
208
209 /// the path containing LLDB's Python module
210 pub lldb_python_dir: Option<String>,
211
212 /// Explain what's going on
213 pub verbose: bool,
214
215 /// Print one character per test instead of one line
216 pub quiet: bool,
217
218 /// Whether to use colors in test.
219 pub color: ColorConfig,
220
221 /// where to find the remote test client process, if we're using it
222 pub remote_test_client: Option<PathBuf>,
223
224 /// If true, this will generate a coverage file with UI test files that run `MachineApplicable`
225 /// diagnostics but are missing `run-rustfix` annotations. The generated coverage file is
226 /// created in `/<build_base>/rustfix_missing_coverage.txt`
227 pub rustfix_coverage: bool,
228
229 /// The default Rust edition
230 pub edition: Option<String>,
231
232 // Configuration for various run-make tests frobbing things like C compilers
233 // or querying about various LLVM component information.
234 pub cc: String,
235 pub cxx: String,
236 pub cflags: String,
237 pub ar: String,
238 pub linker: Option<String>,
239 pub llvm_components: String,
240 pub llvm_cxxflags: String,
241 pub nodejs: Option<String>,
242 }
243
244 #[derive(Clone)]
245 pub struct TestPaths {
246 pub file: PathBuf, // e.g., compile-test/foo/bar/baz.rs
247 pub base: PathBuf, // e.g., compile-test, auxiliary
248 pub relative_dir: PathBuf, // e.g., foo/bar
249 }
250
251 /// Used by `ui` tests to generate things like `foo.stderr` from `foo.rs`.
expected_output_path( testpaths: &TestPaths, revision: Option<&str>, kind: &str, ) -> PathBuf252 pub fn expected_output_path(
253 testpaths: &TestPaths,
254 revision: Option<&str>,
255 kind: &str,
256 ) -> PathBuf {
257 assert!(UI_EXTENSIONS.contains(&kind));
258 let mut parts = Vec::new();
259
260 if let Some(x) = revision {
261 parts.push(x);
262 }
263 parts.push(kind);
264
265 let extension = parts.join(".");
266 testpaths.file.with_extension(extension)
267 }
268
269 pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT, UI_FIXED];
270 pub const UI_STDERR: &str = "stderr";
271 pub const UI_STDOUT: &str = "stdout";
272 pub const UI_FIXED: &str = "fixed";
273
274 impl Config {
275 /// Add rustc flags to link with the crate's dependencies in addition to the crate itself
link_deps(&mut self)276 pub fn link_deps(&mut self) {
277 let varname = dylib_env_var();
278
279 // Dependencies can be found in the environment variable. Throw everything there into the
280 // link flags
281 let lib_paths = env::var(varname).unwrap_or_else(|err| match err {
282 env::VarError::NotPresent => String::new(),
283 err => panic!("can't get {} environment variable: {}", varname, err),
284 });
285
286 // Append to current flags if any are set, otherwise make new String
287 let mut flags = self.target_rustcflags.take().unwrap_or_else(String::new);
288 if !lib_paths.is_empty() {
289 for p in env::split_paths(&lib_paths) {
290 flags += " -L ";
291 flags += p.to_str().unwrap(); // Can't fail. We already know this is unicode
292 }
293 }
294
295 self.target_rustcflags = Some(flags);
296 }
297
298 /// Remove rmeta files from target `deps` directory
299 ///
300 /// These files are created by `cargo check`, and conflict with
301 /// `cargo build` rlib files, causing E0464 for tests which use
302 /// the parent crate.
clean_rmeta(&self)303 pub fn clean_rmeta(&self) {
304 if self.target_rustcflags.is_some() {
305 for directory in self.target_rustcflags
306 .as_ref()
307 .unwrap()
308 .split_whitespace()
309 .filter(|s| s.ends_with("/deps"))
310 {
311 if let Ok(mut entries) = read_dir(directory) {
312 while let Some(Ok(entry)) = entries.next() {
313 if entry.file_name().to_string_lossy().ends_with(".rmeta") {
314 let _ = remove_file(entry.path());
315 }
316 }
317 }
318 }
319 }
320 }
321
322 #[cfg(feature = "tmp")]
tempdir(mut self) -> ConfigWithTemp323 pub fn tempdir(mut self) -> ConfigWithTemp {
324 let tmp = tempfile::Builder::new().prefix("compiletest").tempdir()
325 .expect("failed to create temporary directory");
326 self.build_base = tmp.path().to_owned();
327 config_tempdir::ConfigWithTemp {
328 config: self,
329 tempdir: tmp,
330 }
331 }
332 }
333
334 #[cfg(feature = "tmp")]
335 mod config_tempdir {
336 use tempfile;
337 use std::ops;
338
339 pub struct ConfigWithTemp {
340 pub config: super::Config,
341 pub tempdir: tempfile::TempDir,
342 }
343
344 impl ops::Deref for ConfigWithTemp {
345 type Target = super::Config;
346
deref(&self) -> &Self::Target347 fn deref(&self) -> &Self::Target {
348 &self.config
349 }
350 }
351
352 impl ops::DerefMut for ConfigWithTemp {
deref_mut(&mut self) -> &mut Self::Target353 fn deref_mut(&mut self) -> &mut Self::Target {
354 &mut self.config
355 }
356 }
357 }
358
359 #[cfg(feature = "tmp")]
360 pub use self::config_tempdir::ConfigWithTemp;
361
362
363 impl Default for Config {
default() -> Config364 fn default() -> Config {
365 #[cfg(feature = "rustc")]
366 let platform = rustc_session::config::host_triple().to_string();
367
368 Config {
369 bless: false,
370 compile_lib_path: PathBuf::from(""),
371 run_lib_path: PathBuf::from(""),
372 rustc_path: PathBuf::from("rustc"),
373 rustdoc_path: None,
374 lldb_python: "python".to_owned(),
375 docck_python: "docck-python".to_owned(),
376 valgrind_path: None,
377 force_valgrind: false,
378 llvm_filecheck: None,
379 src_base: PathBuf::from("tests/run-pass"),
380 build_base: env::temp_dir(),
381 stage_id: "stage-id".to_owned(),
382 mode: Mode::RunPass,
383 run_ignored: false,
384 filters: vec![],
385 filter_exact: false,
386 logfile: None,
387 runtool: None,
388 host_rustcflags: None,
389 target_rustcflags: None,
390 #[cfg(feature = "rustc")]
391 target: platform.clone(),
392 #[cfg(not(feature = "rustc"))]
393 target: env!("TARGET").to_string(),
394 #[cfg(feature = "rustc")]
395 host: platform.clone(),
396 #[cfg(not(feature = "rustc"))]
397 host: env!("HOST").to_string(),
398 rustfix_coverage: false,
399 gdb: None,
400 gdb_version: None,
401 gdb_native_rust: false,
402 lldb_version: None,
403 llvm_version: None,
404 system_llvm: false,
405 android_cross_path: PathBuf::from("android-cross-path"),
406 adb_path: "adb-path".to_owned(),
407 adb_test_dir: "adb-test-dir/target".to_owned(),
408 adb_device_status: false,
409 lldb_python_dir: None,
410 verbose: false,
411 quiet: false,
412 color: ColorConfig::AutoColor,
413 remote_test_client: None,
414 cc: "cc".to_string(),
415 cxx: "cxx".to_string(),
416 cflags: "cflags".to_string(),
417 ar: "ar".to_string(),
418 linker: None,
419 llvm_components: "llvm-components".to_string(),
420 llvm_cxxflags: "llvm-cxxflags".to_string(),
421 nodejs: None,
422 edition: None,
423 }
424 }
425 }
426