Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/tools/compile_fail_utils/src/lib.rs
6596 views
1
use std::{
2
env,
3
path::{Path, PathBuf},
4
};
5
6
// Re-export ui_test so all the tests use the same version.
7
pub use ui_test;
8
9
use ui_test::{
10
bless_output_files,
11
color_eyre::eyre::eyre,
12
default_file_filter, default_per_file_config,
13
dependencies::DependencyBuilder,
14
ignore_output_conflict, run_tests_generic,
15
spanned::Spanned,
16
status_emitter::{Gha, StatusEmitter, Text},
17
Args, Config,
18
};
19
20
/// Use this instead of hand rolling configs.
21
///
22
/// `root_dir` is the directory your tests are contained in. Needs to be a path from crate root.
23
/// This config will build dependencies and will assume that the cargo manifest is placed at the
24
/// current working directory.
25
fn basic_config(root_dir: impl Into<PathBuf>, args: &Args) -> ui_test::Result<Config> {
26
let root_dir = root_dir.into();
27
28
match root_dir.try_exists() {
29
Ok(true) => { /* success */ }
30
Ok(false) => {
31
return Err(eyre!("path does not exist: {}", root_dir.display()));
32
}
33
Err(error) => {
34
return Err(eyre!(
35
"failed to read path: {} ({})",
36
root_dir.display(),
37
error
38
));
39
}
40
}
41
42
let mut config = Config {
43
bless_command: Some(
44
"`cargo test` with the BLESS environment variable set to any non empty value"
45
.to_string(),
46
),
47
output_conflict_handling: if env::var_os("BLESS").is_some() {
48
bless_output_files
49
} else {
50
// stderr output changes between rust versions so we just rely on annotations
51
ignore_output_conflict
52
},
53
..Config::rustc(root_dir)
54
};
55
56
config.with_args(args);
57
58
let bevy_root = "..";
59
60
// Don't leak contributor filesystem paths
61
config.path_stderr_filter(Path::new(bevy_root), b"$BEVY_ROOT");
62
if let Some(path) = option_env!("RUSTUP_HOME") {
63
config.path_stderr_filter(Path::new(path), b"$RUSTUP_HOME");
64
}
65
66
// ui_test doesn't compile regex with perl character classes.
67
// \pL = unicode class for letters, \pN = unicode class for numbers
68
config.stderr_filter(r"\/home\/[\pL\pN_@#\-\. ]+", "$HOME");
69
// Paths in .stderr seem to always be normalized to use /. Handle both anyway.
70
config.stderr_filter(
71
r"[a-zA-Z]:(?:\\|\/)users(?:\\|\/)[\pL\pN_@#\-\. ]+", // NOTE: [\pL\pN_@#\-\. ] is a poor attempt at handling usernames
72
"$HOME",
73
);
74
75
// Manually insert @aux-build:<dep> comments into test files. This needs to
76
// be done to build and link dependencies. Dependencies will be pulled from a
77
// Cargo.toml file.
78
config.comment_defaults.base().custom.insert(
79
"dependencies",
80
Spanned::dummy(vec![Box::new(DependencyBuilder::default())]),
81
);
82
83
Ok(config)
84
}
85
86
/// Runs ui tests for a single directory.
87
///
88
/// `root_dir` is the directory your tests are contained in. Needs to be a path from crate root.
89
pub fn test(test_name: impl Into<String>, test_root: impl Into<PathBuf>) -> ui_test::Result<()> {
90
test_multiple(test_name, [test_root])
91
}
92
93
/// Run ui tests with the given config
94
pub fn test_with_config(test_name: impl Into<String>, config: Config) -> ui_test::Result<()> {
95
test_with_multiple_configs(test_name, [Ok(config)])
96
}
97
98
/// Runs ui tests for a multiple directories.
99
///
100
/// `root_dirs` paths need to come from crate root.
101
pub fn test_multiple(
102
test_name: impl Into<String>,
103
test_roots: impl IntoIterator<Item = impl Into<PathBuf>>,
104
) -> ui_test::Result<()> {
105
let args = Args::test()?;
106
107
let configs = test_roots.into_iter().map(|root| basic_config(root, &args));
108
109
test_with_multiple_configs(test_name, configs)
110
}
111
112
/// Run ui test with the given configs.
113
///
114
/// Tests for configs are run in parallel.
115
pub fn test_with_multiple_configs(
116
test_name: impl Into<String>,
117
configs: impl IntoIterator<Item = ui_test::Result<Config>>,
118
) -> ui_test::Result<()> {
119
let configs = configs
120
.into_iter()
121
.collect::<ui_test::Result<Vec<Config>>>()?;
122
123
let emitter: Box<dyn StatusEmitter + Send> = if env::var_os("CI").is_some() {
124
Box::new((
125
Text::verbose(),
126
Gha {
127
group: true,
128
name: test_name.into(),
129
},
130
))
131
} else {
132
Box::new(Text::quiet())
133
};
134
135
run_tests_generic(
136
configs,
137
default_file_filter,
138
default_per_file_config,
139
emitter,
140
)
141
}
142
143