Skip to content

Commit 5ece6ea

Browse files
committed
Populate Config with Args instead of passing it to run_tests_generic
1 parent 73dcb41 commit 5ece6ea

File tree

17 files changed

+199
-119
lines changed

17 files changed

+199
-119
lines changed

src/cmd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl CommandBuilder {
4848
}
4949
}
5050

51-
/// Same as [`rustc`], but with arguments for obtaining the cfgs.
51+
/// Same as [`CommandBuilder::rustc`], but with arguments for obtaining the cfgs.
5252
pub fn cfgs() -> Self {
5353
Self {
5454
args: vec!["--print".into(), "cfg".into()],

src/config.rs

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub use color_eyre;
55
use color_eyre::eyre::Result;
66
use std::{
77
ffi::OsString,
8+
num::NonZeroUsize,
89
path::{Path, PathBuf},
910
};
1011

@@ -34,16 +35,24 @@ pub struct Config {
3435
pub program: CommandBuilder,
3536
/// The command to run to obtain the cfgs that the output is supposed to
3637
pub cfgs: CommandBuilder,
38+
/// What to do in case the stdout/stderr output differs from the expected one.
39+
pub output_conflict_handling: OutputConflictHandling,
3740
/// Path to a `Cargo.toml` that describes which dependencies the tests can access.
3841
pub dependencies_crate_manifest_path: Option<PathBuf>,
3942
/// The command to run can be changed from `cargo` to any custom command to build the
40-
/// dependencies in `dependencies_crate_manifest_path`
43+
/// dependencies in `dependencies_crate_manifest_path`.
4144
pub dependency_builder: CommandBuilder,
4245
/// Where to dump files like the binaries compiled from tests.
4346
/// Defaults to `target/ui` in the current directory.
4447
pub out_dir: PathBuf,
45-
/// The default edition to use on all tests
48+
/// The default edition to use on all tests.
4649
pub edition: Option<String>,
50+
/// Skip test files whose names contain any of these entries.
51+
pub skip_files: Vec<String>,
52+
/// Only test files whose names contain any of these entries.
53+
pub filter_files: Vec<String>,
54+
/// Override the number of threads to use.
55+
pub threads: Option<NonZeroUsize>,
4756
}
4857

4958
impl Config {
@@ -74,13 +83,17 @@ impl Config {
7483
},
7584
program: CommandBuilder::rustc(),
7685
cfgs: CommandBuilder::cfgs(),
86+
output_conflict_handling: OutputConflictHandling::Bless,
7787
dependencies_crate_manifest_path: None,
7888
dependency_builder: CommandBuilder::cargo(),
7989
out_dir: std::env::var_os("CARGO_TARGET_DIR")
8090
.map(PathBuf::from)
8191
.unwrap_or_else(|| std::env::current_dir().unwrap().join("target"))
8292
.join("ui"),
8393
edition: Some("2021".into()),
94+
skip_files: Vec::new(),
95+
filter_files: Vec::new(),
96+
threads: None,
8497
}
8598
}
8699

@@ -98,6 +111,42 @@ impl Config {
98111
}
99112
}
100113

114+
/// Populate the config with the values from parsed command line arguments.
115+
/// If neither `--bless` or `--check` are provided `default_bless` is used.
116+
///
117+
/// The default output conflict handling command suggests adding `--bless`
118+
/// to the end of the current command.
119+
pub fn with_args(&mut self, args: &Args, default_bless: bool) {
120+
let Args {
121+
ref filters,
122+
quiet: _,
123+
check,
124+
bless,
125+
threads: _,
126+
ref skip,
127+
} = *args;
128+
129+
self.filter_files.extend_from_slice(filters);
130+
self.skip_files.extend_from_slice(skip);
131+
132+
let bless = match (bless, check) {
133+
(_, true) => false,
134+
(true, _) => true,
135+
_ => default_bless,
136+
};
137+
self.output_conflict_handling = if bless {
138+
OutputConflictHandling::Bless
139+
} else {
140+
OutputConflictHandling::Error(format!(
141+
"{} --bless",
142+
std::env::args()
143+
.map(|s| format!("{s:?}"))
144+
.collect::<Vec<_>>()
145+
.join(" ")
146+
))
147+
};
148+
}
149+
101150
/// Replace all occurrences of a path in stderr/stdout with a byte string.
102151
pub fn path_filter(&mut self, path: &Path, replacement: &'static (impl AsRef<[u8]> + ?Sized)) {
103152
self.path_stderr_filter(path, replacement);
@@ -154,8 +203,8 @@ impl Config {
154203

155204
/// Compile dependencies and return the right flags
156205
/// to find the dependencies.
157-
pub fn build_dependencies(&self, args: &Args) -> Result<Vec<OsString>> {
158-
let dependencies = build_dependencies(args, self)?;
206+
pub fn build_dependencies(&self) -> Result<Vec<OsString>> {
207+
let dependencies = build_dependencies(self)?;
159208
let mut args = vec![];
160209
for (name, artifacts) in dependencies.dependencies {
161210
for dependency in artifacts {
@@ -207,3 +256,15 @@ impl Config {
207256
.any(|arch| self.target.as_ref().unwrap().contains(arch))
208257
}
209258
}
259+
260+
#[derive(Debug, Clone)]
261+
/// The different options for what to do when stdout/stderr files differ from the actual output.
262+
pub enum OutputConflictHandling {
263+
/// The string should be a command that can be executed to bless all tests.
264+
Error(String),
265+
/// Ignore mismatches in the stderr/stdout files.
266+
Ignore,
267+
/// Instead of erroring if the stderr/stdout differs from the expected
268+
/// automatically replace it with the found output (after applying filters).
269+
Bless,
270+
}

src/config/args.rs

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
44
use std::{borrow::Cow, num::NonZeroUsize};
55

6-
use color_eyre::eyre::{bail, ensure, eyre, Result};
6+
use color_eyre::eyre::{bail, ensure, Result};
77

88
/// Plain arguments if `ui_test` is used as a binary.
9-
#[derive(Debug)]
9+
#[derive(Debug, Default)]
1010
pub struct Args {
1111
/// Filters that will be used to match on individual tests
1212
pub filters: Vec<String>,
@@ -23,37 +23,17 @@ pub struct Args {
2323
pub bless: bool,
2424

2525
/// The number of threads to use
26-
pub threads: NonZeroUsize,
26+
pub threads: Option<NonZeroUsize>,
2727

2828
/// Skip tests whose names contain any of these entries.
2929
pub skip: Vec<String>,
3030
}
3131

3232
impl Args {
33-
/// Dummy arguments, but with the number of threads loaded from the environment.
34-
/// The boolearn argument decides whether to bless (`true`) or whether to error (`false`)
35-
pub fn default(bless: bool) -> Result<Self> {
36-
Ok(Args {
37-
filters: vec![],
38-
quiet: false,
39-
bless,
40-
check: !bless,
41-
skip: vec![],
42-
threads: match std::env::var_os("RUST_TEST_THREADS") {
43-
None => std::thread::available_parallelism()?,
44-
Some(n) => n
45-
.to_str()
46-
.ok_or_else(|| eyre!("could not parse RUST_TEST_THREADS env var"))?
47-
.parse()?,
48-
},
49-
})
50-
}
51-
5233
/// Parse the program arguments.
5334
/// This is meant to be used if `ui_test` is used as a `harness=false` test, called from `cargo test`.
54-
/// The boolearn argument decides whether to bless (`true`) or whether to error (`false`)
55-
pub fn test(bless: bool) -> Result<Self> {
56-
Self::default(bless)?.parse_args(std::env::args().skip(1))
35+
pub fn test() -> Result<Self> {
36+
Self::default().parse_args(std::env::args().skip(1))
5737
}
5838

5939
/// Parse arguments into an existing `Args` struct.
@@ -73,7 +53,7 @@ impl Args {
7353
} else if arg == "--help" {
7454
bail!("available flags: --quiet, --check, --bless, --test-threads=n, --skip")
7555
} else if let Some(n) = parse_value("--test-threads", &arg, &mut iter)? {
76-
self.threads = n.parse()?;
56+
self.threads = Some(n.parse()?);
7757
} else if arg.starts_with("--") {
7858
bail!(
7959
"unknown command line flag `{arg}`: {:?}",

src/dependencies.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ use std::{
1010
sync::{Arc, OnceLock, RwLock},
1111
};
1212

13-
use crate::{build_aux, status_emitter::StatusEmitter, Args, Config, Errored, Mode};
13+
use crate::{
14+
build_aux, status_emitter::StatusEmitter, Config, Errored, Mode, OutputConflictHandling,
15+
};
1416

1517
#[derive(Default, Debug)]
1618
pub struct Dependencies {
@@ -43,7 +45,7 @@ fn cfgs(config: &Config) -> Result<Vec<Cfg>> {
4345
}
4446

4547
/// Compiles dependencies and returns the crate names and corresponding rmeta files.
46-
pub(crate) fn build_dependencies(args: &Args, config: &Config) -> Result<Dependencies> {
48+
pub(crate) fn build_dependencies(config: &Config) -> Result<Dependencies> {
4749
let manifest_path = match &config.dependencies_crate_manifest_path {
4850
Some(path) => path.to_owned(),
4951
None => return Ok(Default::default()),
@@ -57,10 +59,12 @@ pub(crate) fn build_dependencies(args: &Args, config: &Config) -> Result<Depende
5759
}
5860

5961
// Reusable closure for setting up the environment both for artifact generation and `cargo_metadata`
60-
let set_locking = |cmd: &mut Command| {
61-
if !matches!(config.mode, Mode::Yolo { .. }) && args.check {
62+
let set_locking = |cmd: &mut Command| match (&config.output_conflict_handling, &config.mode) {
63+
(_, Mode::Yolo { .. }) => {}
64+
(OutputConflictHandling::Error(_), _) => {
6265
cmd.arg("--locked");
6366
}
67+
_ => {}
6468
};
6569

6670
set_locking(&mut build);
@@ -233,12 +237,7 @@ impl<'a> BuildManager<'a> {
233237
/// that need to be passed in order to build the dependencies.
234238
/// The error is only reported once, all follow up invocations of the same build will
235239
/// have a generic error about a previous build failing.
236-
pub fn build(
237-
&self,
238-
what: Build,
239-
config: &Config,
240-
args: &Args,
241-
) -> Result<Vec<OsString>, Errored> {
240+
pub fn build(&self, what: Build, config: &Config) -> Result<Vec<OsString>, Errored> {
242241
// Fast path without much contention.
243242
if let Some(res) = self.cache.read().unwrap().get(&what).and_then(|o| o.get()) {
244243
return res.clone().map_err(|()| Errored {
@@ -276,7 +275,7 @@ impl<'a> BuildManager<'a> {
276275
.register_test(what.description().into())
277276
.for_revision("");
278277
let res = match &what {
279-
Build::Dependencies => match config.build_dependencies(args) {
278+
Build::Dependencies => match config.build_dependencies() {
280279
Ok(args) => Ok(args),
281280
Err(e) => {
282281
err = Some(Errored {
@@ -288,7 +287,7 @@ impl<'a> BuildManager<'a> {
288287
Err(())
289288
}
290289
},
291-
Build::Aux { aux_file } => match build_aux(aux_file, config, args, self) {
290+
Build::Aux { aux_file } => match build_aux(aux_file, config, self) {
292291
Ok(args) => Ok(args.iter().map(Into::into).collect()),
293292
Err(e) => {
294293
err = Some(e);

src/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ pub enum Error {
3232
actual: Vec<u8>,
3333
/// The contents of the file.
3434
expected: Vec<u8>,
35+
/// A command, that when run, causes the output to get blessed instead of erroring.
36+
bless_command: String,
3537
},
3638
/// There were errors that don't have a pattern.
3739
ErrorsWithoutPattern {

0 commit comments

Comments
 (0)