]> git.lizzy.rs Git - rust.git/blob - tests/compiletest.rs
Print one character per test instead of one line
[rust.git] / tests / compiletest.rs
1 use colored::*;
2 use regex::Regex;
3 use std::path::{Path, PathBuf};
4 use std::{env, ffi::OsString};
5 use ui_test::{color_eyre::Result, Config, DependencyBuilder, 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<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());
23     } else {
24         flags.push("-Dwarnings".into());
25         flags.push("-Dunused".into());
26     }
27     if let Some(sysroot) = env::var_os("MIRI_SYSROOT") {
28         flags.push("--sysroot".into());
29         flags.push(sysroot);
30     }
31     if let Ok(extra_flags) = env::var("MIRIFLAGS") {
32         for flag in extra_flags.split_whitespace() {
33             flags.push(flag.into());
34         }
35     }
36     flags.push("-Zui-testing".into());
37     if let Some(target) = &target {
38         flags.push("--target".into());
39         flags.push(target.into());
40     }
41
42     let skip_ui_checks = env::var_os("MIRI_SKIP_UI_CHECKS").is_some();
43
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"),
49     };
50
51     // Pass on all unknown arguments as filters.
52     let mut quiet = false;
53     let path_filter = std::env::args().skip(1).filter(|arg| {
54         match &**arg {
55             "--quiet" => {
56                 quiet = true;
57                 false
58             }
59             _ => true,
60         }
61     });
62
63     let use_std = env::var_os("MIRI_NO_STD").is_none();
64
65     let config = Config {
66         args: flags,
67         target,
68         stderr_filters: STDERR.clone(),
69         stdout_filters: STDOUT.clone(),
70         root_dir: PathBuf::from(path),
71         mode,
72         path_filter: path_filter.collect(),
73         program: miri_path(),
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(),
79             args: vec![
80                 "run".into(),
81                 "--manifest-path".into(),
82                 "cargo-miri/Cargo.toml".into(),
83                 "--".into(),
84                 "miri".into(),
85             ],
86             envs: vec![],
87         }),
88         quiet,
89     };
90     ui_test::run_tests(config)
91 }
92
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),)*
97         ];
98     }};
99 }
100
101 regexes! {
102     STDOUT:
103     // Windows file paths
104     r"\\"                           => "/",
105 }
106
107 regexes! {
108     STDERR:
109     // erase line and column info
110     r"\.rs:[0-9]+:[0-9]+(: [0-9]+:[0-9]+)?" => ".rs:LL:CC",
111     // erase alloc ids
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
130     r"\\"                           => "/",
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",
137 }
138
139 fn ui(mode: Mode, path: &str) -> Result<()> {
140     let target = get_target();
141
142     let msg = format!(
143         "## Running ui tests in {path} against miri for {}",
144         target.as_deref().unwrap_or("host")
145     );
146     eprintln!("{}", msg.green().bold());
147
148     run_tests(mode, path, target)
149 }
150
151 fn get_target() -> Option<String> {
152     env::var("MIRI_TEST_TARGET").ok()
153 }
154
155 fn main() -> Result<()> {
156     ui_test::color_eyre::install()?;
157
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());
162
163     ui(Mode::Pass, "tests/pass")?;
164     ui(Mode::Panic, "tests/panic")?;
165     ui(Mode::Fail, "tests/fail")?;
166
167     Ok(())
168 }