1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
use std::path::Path;
use colored::Colorize;
use ui_test::color_eyre::Result;
use ui_test::*;
fn main() -> Result<()> {
run("integrations", Mode::Pass)?;
run("integrations", Mode::Panic)?;
eprintln!("integration tests done");
Ok(())
}
fn run(name: &str, mode: Mode) -> Result<()> {
eprintln!("\n{} `{name}` tests in mode {mode}", "Running".green());
let path = Path::new(file!()).parent().unwrap();
let root_dir = path.join(name);
let bless = std::env::args().all(|arg| arg != "--check");
let mut config = Config {
trailing_args: vec!["--".into(), "--test-threads".into(), "1".into()],
mode,
..Config::cargo(root_dir.clone())
};
if bless {
config.output_conflict_handling = OutputConflictHandling::Bless;
}
config.program.args = vec![
"test".into(),
"--color".into(),
"never".into(),
"--quiet".into(),
"--jobs".into(),
"1".into(),
"--no-fail-fast".into(),
];
config
.program
.envs
.push(("BLESS".into(), bless.then(|| String::new().into())));
config.stdout_filter("in ([0-9]m )?[0-9\\.]+s", "");
config.stderr_filter(r#""--out-dir"(,)? "[^"]+""#, r#""--out-dir"$1 "$$TMP"#);
config.stderr_filter(
"( *process didn't exit successfully: `[^-]+)-[0-9a-f]+",
"$1-HASH",
);
// Windows io::Error uses "exit code".
config.stderr_filter("exit code", "exit status");
// The order of the `/deps` directory flag is flaky
config.stderr_filter("/deps", "");
config.path_stderr_filter(&std::path::Path::new(path), "$DIR");
config.stderr_filter("[0-9a-f]+\\.rmeta", "$$HASH.rmeta");
// Windows backslashes are sometimes escaped.
// Insert the replacement filter at the start to make sure the filter for single backslashes
// runs afterwards.
config
.stderr_filters
.insert(0, (Match::Exact(b"\\\\".iter().copied().collect()), b"\\"));
config.stderr_filter("\\.exe", b"");
config.stderr_filter(r#"(panic.*)\.rs:[0-9]+:[0-9]+"#, "$1.rs");
config.stderr_filter(" [0-9]: .*", "");
config.stderr_filter("/target/[^/]+/[^/]+/debug", "/target/$$TMP/$$TRIPLE/debug");
config.stderr_filter("/target/[^/]+/tests", "/target/$$TMP/tests");
// Normalize proc macro filenames on windows to their linux repr
config.stderr_filter("/([^/\\.]+)\\.dll", "/lib$1.so");
// Normalize proc macro filenames on mac to their linux repr
config.stderr_filter("/([^/\\.]+)\\.dylib", "/$1.so");
config.stderr_filter("(command: )\"[^<rp][^\"]+", "$1\"$$CMD");
config.stderr_filter("(src/.*?\\.rs):[0-9]+:[0-9]+", "$1:LL:CC");
config.stderr_filter("program not found", "No such file or directory");
config.stderr_filter(" \\(os error [0-9]+\\)", "");
run_tests_generic(
config,
|path| {
let fail = path
.parent()
.unwrap()
.file_name()
.unwrap()
.to_str()
.unwrap()
.ends_with("-fail");
if cfg!(windows) && path.components().any(|c| c.as_os_str() == "basic-bin") {
// on windows there's also a .pdb file, so we get additional errors that aren't there on other platforms
return false;
}
path.ends_with("Cargo.toml")
&& path.parent().unwrap().parent().unwrap() == root_dir
&& match mode {
Mode::Pass => !fail,
// This is weird, but `cargo test` returns 101 instead of 1 when
// multiple [[test]]s exist. If there's only one test, it returns
// 1 on failure.
Mode::Panic => fail,
Mode::Fix | Mode::Run { .. } | Mode::Yolo | Mode::Fail { .. } => unreachable!(),
}
},
|_, _| None,
(
ui_test::status_emitter::Text,
ui_test::status_emitter::Gha::<true> {
name: format!("{mode:?}"),
},
),
)
}
|