]> git.lizzy.rs Git - rust.git/blob - tests/compiletest.rs
008fc7806457fd45d36bfc38b1d0b08bd27572a9
[rust.git] / tests / compiletest.rs
1 use colored::*;
2 use regex::Regex;
3 use std::env;
4 use std::path::PathBuf;
5 use ui_test::{color_eyre::Result, Config, Mode, OutputConflictHandling};
6
7 fn miri_path() -> PathBuf {
8     PathBuf::from(option_env!("MIRI").unwrap_or(env!("CARGO_BIN_EXE_miri")))
9 }
10
11 fn run_tests(mode: Mode, path: &str, target: Option<String>) -> Result<()> {
12     let in_rustc_test_suite = option_env!("RUSTC_STAGE").is_some();
13
14     // Add some flags we always want.
15     let mut flags = Vec::new();
16     flags.push("--edition".to_owned());
17     flags.push("2018".to_owned());
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".to_owned());
22     } else {
23         flags.push("-Dwarnings".to_owned());
24         flags.push("-Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs
25     }
26     if let Ok(sysroot) = env::var("MIRI_SYSROOT") {
27         flags.push("--sysroot".to_string());
28         flags.push(sysroot);
29     }
30     if let Ok(extra_flags) = env::var("MIRIFLAGS") {
31         for flag in extra_flags.split_whitespace() {
32             flags.push(flag.to_string());
33         }
34     }
35     flags.push("-Zui-testing".to_string());
36     if let Some(target) = &target {
37         flags.push("--target".to_string());
38         flags.push(target.clone());
39     }
40
41     let skip_ui_checks = env::var_os("MIRI_SKIP_UI_CHECKS").is_some();
42
43     let output_conflict_handling = match (env::var_os("MIRI_BLESS").is_some(), skip_ui_checks) {
44         (false, false) => OutputConflictHandling::Error,
45         (true, false) => OutputConflictHandling::Bless,
46         (false, true) => OutputConflictHandling::Ignore,
47         (true, true) => panic!("cannot use MIRI_BLESS and MIRI_SKIP_UI_CHECKS at the same time"),
48     };
49
50     // Pass on all arguments as filters.
51     let path_filter = std::env::args().skip(1);
52
53     let config = Config {
54         args: flags,
55         target,
56         stderr_filters: STDERR.clone(),
57         stdout_filters: STDOUT.clone(),
58         root_dir: PathBuf::from(path),
59         mode,
60         path_filter: path_filter.collect(),
61         program: miri_path(),
62         output_conflict_handling,
63     };
64     ui_test::run_tests(config)
65 }
66
67 macro_rules! regexes {
68     ($name:ident: $($regex:expr => $replacement:expr,)*) => {lazy_static::lazy_static! {
69         static ref $name: Vec<(Regex, &'static str)> = vec![
70             $((Regex::new($regex).unwrap(), $replacement),)*
71         ];
72     }};
73 }
74
75 regexes! {
76     STDOUT:
77     // Windows file paths
78     r"\\"                           => "/",
79 }
80
81 regexes! {
82     STDERR:
83     // erase line and column info
84     r"\.rs:[0-9]+:[0-9]+(: [0-9]+:[0-9]+)?" => ".rs:LL:CC",
85     // erase alloc ids
86     "alloc[0-9]+"                    => "ALLOC",
87     // erase Stacked Borrows tags
88     "<[0-9]+>"                       => "<TAG>",
89     // erase whitespace that differs between platforms
90     r" +at (.*\.rs)"                 => " at $1",
91     // erase generics in backtraces
92     "([0-9]+: .*)::<.*>"             => "$1",
93     // erase addresses in backtraces
94     "([0-9]+: ) +0x[0-9a-f]+ - (.*)" => "$1$2",
95     // erase long hexadecimals
96     r"0x[0-9a-fA-F]+[0-9a-fA-F]{2,2}" => "$$HEX",
97     // erase specific alignments
98     "alignment [0-9]+"               => "alignment ALIGN",
99     // erase thread caller ids
100     r"\(call [0-9]+\)"              => "(call ID)",
101     // erase platform module paths
102     "sys::[a-z]+::"                  => "sys::PLATFORM::",
103     // Windows file paths
104     r"\\"                           => "/",
105     // erase Rust stdlib path
106     "[^ `]*/(rust[^/]*|checkout)/library/" => "RUSTLIB/",
107     // erase platform file paths
108     "sys/[a-z]+/"                    => "sys/PLATFORM/",
109 }
110
111 fn ui(mode: Mode, path: &str) -> Result<()> {
112     let target = get_target();
113
114     let msg = format!(
115         "## Running ui tests in {path} against miri for {}",
116         target.as_deref().unwrap_or("host")
117     );
118     eprintln!("{}", msg.green().bold());
119
120     run_tests(mode, path, target)
121 }
122
123 fn get_target() -> Option<String> {
124     env::var("MIRI_TEST_TARGET").ok()
125 }
126
127 fn main() -> Result<()> {
128     ui_test::color_eyre::install()?;
129
130     // Add a test env var to do environment communication tests.
131     env::set_var("MIRI_ENV_VAR_TEST", "0");
132     // Let the tests know where to store temp files (they might run for a different target, which can make this hard to find).
133     env::set_var("MIRI_TEMP", env::temp_dir());
134
135     ui(Mode::Pass, "tests/pass")?;
136     ui(Mode::Panic, "tests/panic")?;
137     ui(Mode::Fail, "tests/fail")?;
138
139     Ok(())
140 }