Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow overriding the test output parser #215

Merged
merged 9 commits into from
Apr 7, 2024
2 changes: 2 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,5 @@ jobs:
run: cargo test --verbose --test integration -- --check
- name: Run unit tests
run: cargo test --verbose
- name: Test no-rustc mode
run: cargo check --no-default-features
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* aux builds and dependencies are now built *per* `Config` instead of being built just for the first `Config` and the result shared by the others
* the configs could be different enough that aux builds built with a different config are incompatible (e.g. different targets).
* replaced `Revisioned::aux_builds` with a rustc-specific custom flag
* replaced `dependency_builder` and `dependency_manifest_path` with `DependencyBuilder` `Flag` that you an add to the default comments.

### Removed

Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,7 @@ features = ["capture-spantrace"]
[[test]]
name = "integration"
harness = false

[features]
default = ["rustc"]
rustc = []
11 changes: 7 additions & 4 deletions src/aux_builds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use crate::{
custom_flags::Flag,
default_per_file_config,
per_test_config::{Comments, TestConfig},
rustc_stderr, CrateType, Error, Errored,
status_emitter::SilentStatus,
CrateType, Error, Errored,
};

impl Flag for AuxBuilder {
Expand Down Expand Up @@ -106,10 +107,12 @@ impl Build for AuxBuilder {

let mut config = TestConfig {
config,
revision: "",
comments: &comments,
path: &self.aux_file,
aux_dir: self.aux_file.parent().unwrap(),
status: &SilentStatus {
revision: String::new(),
path: self.aux_file.content.clone(),
},
};

config.patch_out_dir();
Expand All @@ -127,7 +130,7 @@ impl Build for AuxBuilder {
return Err(Errored {
command: aux_cmd,
errors: vec![error],
stderr: rustc_stderr::process(&self.aux_file, &output.stderr).rendered,
stderr: config.process(&output.stderr).rendered,
stdout: output.stdout,
});
}
Expand Down
52 changes: 16 additions & 36 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
use regex::bytes::Regex;
#[cfg(feature = "rustc")]
use spanned::Spanned;

#[cfg(feature = "rustc")]
use crate::{
aux_builds::AuxBuilder,
build_manager::BuildManager,
custom_flags::{run::Run, rustfix::RustfixMode, Flag},
dependencies::build_dependencies,
filter::Match,
aux_builds::AuxBuilder, build_manager::BuildManager, custom_flags::run::Run,
custom_flags::rustfix::RustfixMode, custom_flags::Flag, filter::Match,
per_test_config::TestConfig, rustc_stderr, Errored, Mode,
};
use crate::{
diagnostics::Diagnostics,
parser::CommandParserFunc,
per_test_config::{Comments, Condition, TestConfig},
CommandBuilder, Errored, Mode,
per_test_config::{Comments, Condition},
CommandBuilder,
};
pub use color_eyre;
use color_eyre::eyre::Result;
use std::{
collections::BTreeMap,
ffi::OsString,
num::NonZeroUsize,
path::{Path, PathBuf},
};
Expand All @@ -38,11 +40,6 @@ pub struct Config {
pub output_conflict_handling: OutputConflictHandling,
/// The recommended command to bless failing tests.
pub bless_command: Option<String>,
/// Path to a `Cargo.toml` that describes which dependencies the tests can access.
pub dependencies_crate_manifest_path: Option<PathBuf>,
/// The command to run can be changed from `cargo` to any custom command to build the
/// dependencies in `dependencies_crate_manifest_path`.
pub dependency_builder: CommandBuilder,
/// Where to dump files like the binaries compiled from tests.
/// Defaults to `target/ui` in the current directory.
pub out_dir: PathBuf,
Expand All @@ -62,11 +59,14 @@ pub struct Config {
pub comment_defaults: Comments,
/// Custom comment parsers
pub custom_comments: BTreeMap<&'static str, CommandParserFunc>,
/// Custom diagnostic extractor (invoked on the output of tests)
pub diagnostic_extractor: fn(&Path, &[u8]) -> Diagnostics,
}

impl Config {
/// Create a configuration for testing the output of running
/// `rustc` on the test files.
#[cfg(feature = "rustc")]
pub fn rustc(root_dir: impl Into<PathBuf>) -> Self {
let mut comment_defaults = Comments::default();

Expand Down Expand Up @@ -136,8 +136,6 @@ impl Config {
program: CommandBuilder::rustc(),
output_conflict_handling: OutputConflictHandling::Bless,
bless_command: None,
dependencies_crate_manifest_path: None,
dependency_builder: CommandBuilder::cargo(),
out_dir: std::env::var_os("CARGO_TARGET_DIR")
.map(PathBuf::from)
.unwrap_or_else(|| std::env::current_dir().unwrap().join("target"))
Expand All @@ -150,6 +148,7 @@ impl Config {
filter_exact: false,
comment_defaults,
custom_comments: Default::default(),
diagnostic_extractor: rustc_stderr::process,
};
config
.custom_comments
Expand Down Expand Up @@ -235,10 +234,12 @@ impl Config {

/// Create a configuration for testing the output of running
/// `cargo` on the test `Cargo.toml` files.
#[cfg(feature = "rustc")]
pub fn cargo(root_dir: impl Into<PathBuf>) -> Self {
let mut this = Self {
program: CommandBuilder::cargo(),
custom_comments: Default::default(),
diagnostic_extractor: rustc_stderr::process_cargo,
..Self::rustc(root_dir)
};
this.comment_defaults.base().custom.clear();
Expand Down Expand Up @@ -343,27 +344,6 @@ impl Config {
));
}

/// Compile dependencies and return the right flags
/// to find the dependencies.
pub fn build_dependencies(&self) -> Result<Vec<OsString>> {
let dependencies = build_dependencies(self)?;
let mut args = vec![];
for (name, artifacts) in dependencies.dependencies {
for dependency in artifacts {
args.push("--extern".into());
let mut dep = OsString::from(&name);
dep.push("=");
dep.push(dependency);
args.push(dep);
}
}
for import_path in dependencies.import_paths {
args.push("-L".into());
args.push(import_path.into());
}
Ok(args)
}

/// Make sure we have the host and target triples.
pub fn fill_host_and_target(&mut self) -> Result<()> {
if self.host.is_none() {
Expand Down
1 change: 1 addition & 0 deletions src/custom_flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::{

use crate::{build_manager::BuildManager, per_test_config::TestConfig, Config, Errored};

#[cfg(feature = "rustc")]
pub mod run;
pub mod rustfix;

Expand Down
8 changes: 5 additions & 3 deletions src/custom_flags/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@ impl Flag for Run {
let revision = config.extension("run");
let config = TestConfig {
config: config.config.clone(),
revision: &revision,
comments: config.comments,
path: config.path,
aux_dir: config.aux_dir,
status: &config.status.for_revision(&revision),
};
cmd.arg("--print").arg("file-names");
let output = cmd.output().unwrap();
Expand All @@ -44,7 +43,10 @@ impl Flag for Run {
let file = std::str::from_utf8(file).unwrap();
let exe_file = config.config.out_dir.join(file);
let mut exe = Command::new(&exe_file);
let stdin = config.path.with_extension(format!("{revision}.stdin"));
let stdin = config
.status
.path()
.with_extension(format!("{revision}.stdin"));
if stdin.exists() {
exe.stdin(std::fs::File::open(stdin).unwrap());
}
Expand Down
27 changes: 11 additions & 16 deletions src/custom_flags/rustfix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
build_manager::BuildManager,
parser::OptWithLine,
per_test_config::{Comments, Revisioned, TestConfig},
rustc_stderr, Error, Errored, Mode,
Error, Errored, Mode,
};

use super::Flag;
Expand Down Expand Up @@ -79,7 +79,7 @@ impl Flag for RustfixMode {
if suggestions.is_empty() {
None
} else {
let path_str = config.path.display().to_string();
let path_str = config.status.path().display().to_string();
for sugg in &suggestions {
for snip in &sugg.snippets {
if snip.file_name != path_str {
Expand All @@ -88,14 +88,14 @@ impl Flag for RustfixMode {
}
}
Some(rustfix::apply_suggestions(
&std::fs::read_to_string(config.path).unwrap(),
&std::fs::read_to_string(config.status.path()).unwrap(),
&suggestions,
))
}
})
.transpose()
.map_err(|err| Errored {
command: Command::new(format!("rustfix {}", config.path.display())),
command: Command::new(format!("rustfix {}", config.status.path().display())),
errors: vec![Error::Rustfix(err)],
stderr: output.stderr,
stdout: output.stdout,
Expand All @@ -119,21 +119,16 @@ impl Flag for RustfixMode {
require_annotations_for_level: Default::default(),
mode: OptWithLine::new(Mode::Pass, Span::default()),
diagnostic_code_prefix: OptWithLine::new(String::new(), Span::default()),
custom: config
.comments
.for_revision(config.revision)
.flat_map(|r| r.custom.clone())
.collect(),
custom: config.comments().flat_map(|r| r.custom.clone()).collect(),
},
))
.collect(),
};
let config = TestConfig {
config: config.config.clone(),
revision: config.revision,
comments: &rustfix_comments,
path: config.path,
aux_dir: config.aux_dir,
status: config.status,
};

let run = fixed_code.is_some();
Expand All @@ -148,22 +143,22 @@ impl Flag for RustfixMode {
// picking the crate name from the file name is problematic when `.revision_name` is inserted,
// so we compute it here before replacing the path.
let crate_name = config
.path
.status
.path()
.file_stem()
.unwrap()
.to_str()
.unwrap()
.replace('-', "_");
let config = TestConfig {
config: config.config,
revision: config.revision,
comments: &rustfix_comments,
path: &rustfix_path,
aux_dir: config.aux_dir,
status: &config.status.for_path(&rustfix_path),
};
if !errors.is_empty() {
return Err(Errored {
command: Command::new(format!("checking {}", config.path.display())),
command: Command::new(format!("checking {}", config.status.path().display())),
errors,
stderr: vec![],
stdout: vec![],
Expand All @@ -186,7 +181,7 @@ impl Flag for RustfixMode {
kind: "rustfix".into(),
status: output.status,
}],
stderr: rustc_stderr::process(&rustfix_path, &output.stderr).rendered,
stderr: config.process(&output.stderr).rendered,
stdout: output.stdout,
})
}
Expand Down
Loading
Loading