| // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT |
| // file at the top-level directory of this distribution and at |
| // http://rust-lang.org/COPYRIGHT. |
| // |
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
| // option. This file may not be copied, modified, or distributed |
| // except according to those terms. |
| pub use self::Mode::*; |
| |
| use std::env; |
| use std::fmt; |
| use std::fs::{read_dir, remove_file}; |
| use std::str::FromStr; |
| use std::path::PathBuf; |
| #[cfg(feature = "rustc")] |
| use rustc_session; |
| |
| use test::ColorConfig; |
| use runtest::dylib_env_var; |
| |
| #[derive(Clone, Copy, PartialEq, Debug)] |
| pub enum Mode { |
| CompileFail, |
| ParseFail, |
| RunFail, |
| RunPass, |
| RunPassValgrind, |
| Pretty, |
| DebugInfoGdb, |
| DebugInfoLldb, |
| Codegen, |
| Rustdoc, |
| CodegenUnits, |
| Incremental, |
| RunMake, |
| Ui, |
| MirOpt, |
| } |
| |
| impl Mode { |
| pub fn disambiguator(self) -> &'static str { |
| // Run-pass and pretty run-pass tests could run concurrently, and if they do, |
| // they need to keep their output segregated. Same is true for debuginfo tests that |
| // can be run both on gdb and lldb. |
| match self { |
| Pretty => ".pretty", |
| DebugInfoGdb => ".gdb", |
| DebugInfoLldb => ".lldb", |
| _ => "", |
| } |
| } |
| } |
| |
| impl FromStr for Mode { |
| type Err = (); |
| fn from_str(s: &str) -> Result<Mode, ()> { |
| match s { |
| "compile-fail" => Ok(CompileFail), |
| "parse-fail" => Ok(ParseFail), |
| "run-fail" => Ok(RunFail), |
| "run-pass" => Ok(RunPass), |
| "run-pass-valgrind" => Ok(RunPassValgrind), |
| "pretty" => Ok(Pretty), |
| "debuginfo-lldb" => Ok(DebugInfoLldb), |
| "debuginfo-gdb" => Ok(DebugInfoGdb), |
| "codegen" => Ok(Codegen), |
| "rustdoc" => Ok(Rustdoc), |
| "codegen-units" => Ok(CodegenUnits), |
| "incremental" => Ok(Incremental), |
| "run-make" => Ok(RunMake), |
| "ui" => Ok(Ui), |
| "mir-opt" => Ok(MirOpt), |
| _ => Err(()), |
| } |
| } |
| } |
| |
| impl fmt::Display for Mode { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| fmt::Display::fmt(match *self { |
| CompileFail => "compile-fail", |
| ParseFail => "parse-fail", |
| RunFail => "run-fail", |
| RunPass => "run-pass", |
| RunPassValgrind => "run-pass-valgrind", |
| Pretty => "pretty", |
| DebugInfoGdb => "debuginfo-gdb", |
| DebugInfoLldb => "debuginfo-lldb", |
| Codegen => "codegen", |
| Rustdoc => "rustdoc", |
| CodegenUnits => "codegen-units", |
| Incremental => "incremental", |
| RunMake => "run-make", |
| Ui => "ui", |
| MirOpt => "mir-opt", |
| }, |
| f) |
| } |
| } |
| |
| #[derive(Clone)] |
| pub struct Config { |
| /// The library paths required for running the compiler |
| pub compile_lib_path: PathBuf, |
| |
| /// The library paths required for running compiled programs |
| pub run_lib_path: PathBuf, |
| |
| /// The rustc executable |
| pub rustc_path: PathBuf, |
| |
| /// The rustdoc executable |
| pub rustdoc_path: Option<PathBuf>, |
| |
| /// The python executable to use for LLDB |
| pub lldb_python: String, |
| |
| /// The python executable to use for htmldocck |
| pub docck_python: String, |
| |
| /// The llvm FileCheck binary path |
| pub llvm_filecheck: Option<PathBuf>, |
| |
| /// The valgrind path |
| pub valgrind_path: Option<String>, |
| |
| /// Whether to fail if we can't run run-pass-valgrind tests under valgrind |
| /// (or, alternatively, to silently run them like regular run-pass tests). |
| pub force_valgrind: bool, |
| |
| /// The directory containing the tests to run |
| pub src_base: PathBuf, |
| |
| /// The directory where programs should be built |
| pub build_base: PathBuf, |
| |
| /// The name of the stage being built (stage1, etc) |
| pub stage_id: String, |
| |
| /// The test mode, compile-fail, run-fail, run-pass |
| pub mode: Mode, |
| |
| /// Run ignored tests |
| pub run_ignored: bool, |
| |
| /// Only run tests that match this filter |
| pub filter: Option<String>, |
| |
| /// Exactly match the filter, rather than a substring |
| pub filter_exact: bool, |
| |
| /// Write out a parseable log of tests that were run |
| pub logfile: Option<PathBuf>, |
| |
| /// A command line to prefix program execution with, |
| /// for running under valgrind |
| pub runtool: Option<String>, |
| |
| /// Flags to pass to the compiler when building for the host |
| pub host_rustcflags: Option<String>, |
| |
| /// Flags to pass to the compiler when building for the target |
| pub target_rustcflags: Option<String>, |
| |
| /// Target system to be tested |
| pub target: String, |
| |
| /// Host triple for the compiler being invoked |
| pub host: String, |
| |
| /// Path to / name of the GDB executable |
| pub gdb: Option<String>, |
| |
| /// Version of GDB, encoded as ((major * 1000) + minor) * 1000 + patch |
| pub gdb_version: Option<u32>, |
| |
| /// Whether GDB has native rust support |
| pub gdb_native_rust: bool, |
| |
| /// Version of LLDB |
| pub lldb_version: Option<String>, |
| |
| /// Version of LLVM |
| pub llvm_version: Option<String>, |
| |
| /// Is LLVM a system LLVM |
| pub system_llvm: bool, |
| |
| /// Path to the android tools |
| pub android_cross_path: PathBuf, |
| |
| /// Extra parameter to run adb on arm-linux-androideabi |
| pub adb_path: String, |
| |
| /// Extra parameter to run test suite on arm-linux-androideabi |
| pub adb_test_dir: String, |
| |
| /// status whether android device available or not |
| pub adb_device_status: bool, |
| |
| /// the path containing LLDB's Python module |
| pub lldb_python_dir: Option<String>, |
| |
| /// Explain what's going on |
| pub verbose: bool, |
| |
| /// Print one character per test instead of one line |
| pub quiet: bool, |
| |
| /// Whether to use colors in test. |
| pub color: ColorConfig, |
| |
| /// where to find the remote test client process, if we're using it |
| pub remote_test_client: Option<PathBuf>, |
| |
| /// If true, this will generate a coverage file with UI test files that run `MachineApplicable` |
| /// diagnostics but are missing `run-rustfix` annotations. The generated coverage file is |
| /// created in `/<build_base>/rustfix_missing_coverage.txt` |
| pub rustfix_coverage: bool, |
| |
| // Configuration for various run-make tests frobbing things like C compilers |
| // or querying about various LLVM component information. |
| pub cc: String, |
| pub cxx: String, |
| pub cflags: String, |
| pub ar: String, |
| pub linker: Option<String>, |
| pub llvm_components: String, |
| pub llvm_cxxflags: String, |
| pub nodejs: Option<String>, |
| } |
| |
| #[derive(Clone)] |
| pub struct TestPaths { |
| pub file: PathBuf, // e.g., compile-test/foo/bar/baz.rs |
| pub base: PathBuf, // e.g., compile-test, auxiliary |
| pub relative_dir: PathBuf, // e.g., foo/bar |
| } |
| |
| pub const UI_STDERR: &str = "stderr"; |
| pub const UI_STDOUT: &str = "stdout"; |
| pub const UI_FIXED: &str = "fixed"; |
| |
| impl Config { |
| /// Add rustc flags to link with the crate's dependencies in addition to the crate itself |
| pub fn link_deps(&mut self) { |
| let varname = dylib_env_var(); |
| |
| // Dependencies can be found in the environment variable. Throw everything there into the |
| // link flags |
| let lib_paths = env::var(varname).unwrap_or_else(|e| { |
| panic!("Cannot link to dependencies. Problem with env var '{}': {:?}", varname, e) |
| }); |
| |
| // Append to current flags if any are set, otherwise make new String |
| let mut flags = self.target_rustcflags.take().unwrap_or_else(String::new); |
| for p in env::split_paths(&lib_paths) { |
| flags += " -L "; |
| flags += p.to_str().unwrap(); // Can't fail. We already know this is unicode |
| } |
| |
| self.target_rustcflags = Some(flags); |
| } |
| |
| /// Remove rmeta files from target `deps` directory |
| /// |
| /// These files are created by `cargo check`, and conflict with |
| /// `cargo build` rlib files, causing E0464 for tests which use |
| /// the parent crate. |
| pub fn clean_rmeta(&self) { |
| if self.target_rustcflags.is_some() { |
| for directory in self.target_rustcflags |
| .as_ref() |
| .unwrap() |
| .split_whitespace() |
| .filter(|s| s.ends_with("/deps")) |
| { |
| if let Ok(mut entries) = read_dir(directory) { |
| while let Some(Ok(entry)) = entries.next() { |
| if entry.file_name().to_string_lossy().ends_with(".rmeta") { |
| let _ = remove_file(entry.path()); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| #[cfg(feature = "tmp")] |
| pub fn tempdir(mut self) -> ConfigWithTemp { |
| let tmp = tempfile::Builder::new().prefix("compiletest").tempdir() |
| .expect("failed to create temporary directory"); |
| self.build_base = tmp.path().to_owned(); |
| config_tempdir::ConfigWithTemp { |
| config: self, |
| tempdir: tmp, |
| } |
| } |
| } |
| |
| #[cfg(feature = "tmp")] |
| mod config_tempdir { |
| use tempfile; |
| use std::ops; |
| |
| pub struct ConfigWithTemp { |
| pub config: super::Config, |
| pub tempdir: tempfile::TempDir, |
| } |
| |
| impl ops::Deref for ConfigWithTemp { |
| type Target = super::Config; |
| |
| fn deref(&self) -> &Self::Target { |
| &self.config |
| } |
| } |
| |
| impl ops::DerefMut for ConfigWithTemp { |
| fn deref_mut(&mut self) -> &mut Self::Target { |
| &mut self.config |
| } |
| } |
| } |
| |
| #[cfg(feature = "tmp")] |
| pub use self::config_tempdir::ConfigWithTemp; |
| |
| |
| impl Default for Config { |
| fn default() -> Config { |
| #[cfg(feature = "rustc")] |
| let platform = rustc_session::config::host_triple().to_string(); |
| |
| Config { |
| compile_lib_path: PathBuf::from(""), |
| run_lib_path: PathBuf::from(""), |
| rustc_path: PathBuf::from("rustc"), |
| rustdoc_path: None, |
| lldb_python: "python".to_owned(), |
| docck_python: "docck-python".to_owned(), |
| valgrind_path: None, |
| force_valgrind: false, |
| llvm_filecheck: None, |
| src_base: PathBuf::from("tests/run-pass"), |
| build_base: env::temp_dir(), |
| stage_id: "stage-id".to_owned(), |
| mode: Mode::RunPass, |
| run_ignored: false, |
| filter: None, |
| filter_exact: false, |
| logfile: None, |
| runtool: None, |
| host_rustcflags: None, |
| target_rustcflags: None, |
| #[cfg(feature = "rustc")] |
| target: platform.clone(), |
| #[cfg(not(feature = "rustc"))] |
| target: env!("TARGET").to_string(), |
| #[cfg(feature = "rustc")] |
| host: platform.clone(), |
| #[cfg(not(feature = "rustc"))] |
| host: env!("HOST").to_string(), |
| rustfix_coverage: false, |
| gdb: None, |
| gdb_version: None, |
| gdb_native_rust: false, |
| lldb_version: None, |
| llvm_version: None, |
| system_llvm: false, |
| android_cross_path: PathBuf::from("android-cross-path"), |
| adb_path: "adb-path".to_owned(), |
| adb_test_dir: "adb-test-dir/target".to_owned(), |
| adb_device_status: false, |
| lldb_python_dir: None, |
| verbose: false, |
| quiet: false, |
| color: ColorConfig::AutoColor, |
| remote_test_client: None, |
| cc: "cc".to_string(), |
| cxx: "cxx".to_string(), |
| cflags: "cflags".to_string(), |
| ar: "ar".to_string(), |
| linker: None, |
| llvm_components: "llvm-components".to_string(), |
| llvm_cxxflags: "llvm-cxxflags".to_string(), |
| nodejs: None, |
| } |
| } |
| } |