3 use std::path::{Path, PathBuf};
4 use std::{env, ffi::OsString};
5 use ui_test::{color_eyre::Result, Config, DependencyBuilder, Mode, OutputConflictHandling};
7 fn miri_path() -> PathBuf {
8 PathBuf::from(option_env!("MIRI").unwrap_or(env!("CARGO_BIN_EXE_miri")))
11 fn run_tests(mode: Mode, path: &str, target: Option<String>) -> Result<()> {
12 let in_rustc_test_suite = option_env!("RUSTC_STAGE").is_some();
14 // Add some flags we always want.
15 let mut flags: Vec<OsString> = Vec::new();
16 flags.push("--edition".into());
17 flags.push("2018".into());
18 if in_rustc_test_suite {
19 // Less aggressive warnings to make the rustc toolstate management less painful.
20 // (We often get warnings when e.g. a feature gets stabilized or some lint gets added/improved.)
21 flags.push("-Astable-features".into());
22 flags.push("-Aunused".into());
24 flags.push("-Dwarnings".into());
25 flags.push("-Dunused".into());
27 if let Some(sysroot) = env::var_os("MIRI_SYSROOT") {
28 flags.push("--sysroot".into());
31 if let Ok(extra_flags) = env::var("MIRIFLAGS") {
32 for flag in extra_flags.split_whitespace() {
33 flags.push(flag.into());
36 flags.push("-Zui-testing".into());
37 if let Some(target) = &target {
38 flags.push("--target".into());
39 flags.push(target.into());
42 let skip_ui_checks = env::var_os("MIRI_SKIP_UI_CHECKS").is_some();
44 let output_conflict_handling = match (env::var_os("MIRI_BLESS").is_some(), skip_ui_checks) {
45 (false, false) => OutputConflictHandling::Error,
46 (true, false) => OutputConflictHandling::Bless,
47 (false, true) => OutputConflictHandling::Ignore,
48 (true, true) => panic!("cannot use MIRI_BLESS and MIRI_SKIP_UI_CHECKS at the same time"),
51 // Pass on all unknown arguments as filters.
52 let mut quiet = false;
53 let path_filter = std::env::args().skip(1).filter(|arg| {
63 let use_std = env::var_os("MIRI_NO_STD").is_none();
68 stderr_filters: STDERR.clone(),
69 stdout_filters: STDOUT.clone(),
70 root_dir: PathBuf::from(path),
72 path_filter: path_filter.collect(),
74 output_conflict_handling,
75 dependencies_crate_manifest_path: use_std
76 .then(|| Path::new("test_dependencies").join("Cargo.toml")),
77 dependency_builder: Some(DependencyBuilder {
78 program: std::env::var_os("CARGO").unwrap().into(),
81 "--manifest-path".into(),
82 "cargo-miri/Cargo.toml".into(),
90 ui_test::run_tests(config)
93 macro_rules! regexes {
94 ($name:ident: $($regex:expr => $replacement:expr,)*) => {lazy_static::lazy_static! {
95 static ref $name: Vec<(Regex, &'static str)> = vec![
96 $((Regex::new($regex).unwrap(), $replacement),)*
103 // Windows file paths
109 // erase line and column info
110 r"\.rs:[0-9]+:[0-9]+(: [0-9]+:[0-9]+)?" => ".rs:LL:CC",
112 "alloc[0-9]+" => "ALLOC",
113 // erase Stacked Borrows tags
114 "<[0-9]+>" => "<TAG>",
115 // erase whitespace that differs between platforms
116 r" +at (.*\.rs)" => " at $1",
117 // erase generics in backtraces
118 "([0-9]+: .*)::<.*>" => "$1",
119 // erase addresses in backtraces
120 "([0-9]+: ) +0x[0-9a-f]+ - (.*)" => "$1$2",
121 // erase long hexadecimals
122 r"0x[0-9a-fA-F]+[0-9a-fA-F]{2,2}" => "$$HEX",
123 // erase specific alignments
124 "alignment [0-9]+" => "alignment ALIGN",
125 // erase thread caller ids
126 r"call [0-9]+" => "call ID",
127 // erase platform module paths
128 "sys::[a-z]+::" => "sys::PLATFORM::",
129 // Windows file paths
131 // erase Rust stdlib path
132 "[^ `]*/(rust[^/]*|checkout)/library/" => "RUSTLIB/",
133 // erase platform file paths
134 "sys/[a-z]+/" => "sys/PLATFORM/",
135 // erase paths into the crate registry
136 r"[^ ]*/\.cargo/registry/.*/(.*\.rs)" => "CARGO_REGISTRY/$1",
139 fn ui(mode: Mode, path: &str) -> Result<()> {
140 let target = get_target();
143 "## Running ui tests in {path} against miri for {}",
144 target.as_deref().unwrap_or("host")
146 eprintln!("{}", msg.green().bold());
148 run_tests(mode, path, target)
151 fn get_target() -> Option<String> {
152 env::var("MIRI_TEST_TARGET").ok()
155 fn main() -> Result<()> {
156 ui_test::color_eyre::install()?;
158 // Add a test env var to do environment communication tests.
159 env::set_var("MIRI_ENV_VAR_TEST", "0");
160 // Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
161 env::set_var("MIRI_TEMP", env::temp_dir());
163 ui(Mode::Pass, "tests/pass")?;
164 ui(Mode::Panic, "tests/panic")?;
165 ui(Mode::Fail, "tests/fail")?;