Skip to content

Commit

Permalink
Show the unnormalized output on output mismatch failure
Browse files Browse the repository at this point in the history
  • Loading branch information
oli-obk committed Feb 25, 2025
1 parent a9a8ea0 commit 4989e9b
Show file tree
Hide file tree
Showing 16 changed files with 115 additions and 74 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Removed

## [0.29.0] - 2025-02-25

### Added

### Fixed

### Changed

* output conflict handling now only takes the unnormalized output and is expected to normalize itself if desired.

### Removed

## [0.28.0] - 2025-01-27

### Added
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ui_test"
version = "0.28.0"
version = "0.29.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "A test framework for testing rustc diagnostics output"
Expand Down
27 changes: 15 additions & 12 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
use crate::{
diagnostics::{self, Diagnostics},
parser::CommandParserFunc,
per_test_config::{Comments, Condition},
per_test_config::{Comments, Condition, TestConfig},
CommandBuilder, Error, Errored, Errors,
};
use color_eyre::eyre::Result;
Expand Down Expand Up @@ -85,7 +85,7 @@ impl AbortCheck {
}

/// Function that performs the actual output conflict handling.
pub type OutputConflictHandling = fn(&Path, Vec<u8>, &mut Errors, &Config);
pub type OutputConflictHandling = fn(&Path, &[u8], &mut Errors, &TestConfig);

impl Config {
/// Create a blank configuration that doesn't do anything interesting
Expand Down Expand Up @@ -484,36 +484,39 @@ impl Config {
/// test.
pub fn error_on_output_conflict(
path: &Path,
actual: Vec<u8>,
output: &[u8],
errors: &mut Errors,
config: &Config,
config: &TestConfig,
) {
let normalized = config.normalize(output, &path.extension().unwrap().to_string_lossy());
let expected = std::fs::read(path).unwrap_or_default();
if actual != expected {
if normalized != expected {
errors.push(Error::OutputDiffers {
path: path.to_path_buf(),
actual,
actual: normalized,
output: output.to_vec(),
expected,
bless_command: config.bless_command.clone(),
bless_command: config.config.bless_command.clone(),
});
}
}

/// Ignore mismatches in the stderr/stdout files.
pub fn ignore_output_conflict(
_path: &Path,
_actual: Vec<u8>,
_output: &[u8],
_errors: &mut Errors,
_config: &Config,
_config: &TestConfig,
) {
}

/// Instead of erroring if the stderr/stdout differs from the expected
/// automatically replace it with the found output (after applying filters).
pub fn bless_output_files(path: &Path, actual: Vec<u8>, _errors: &mut Errors, _config: &Config) {
if actual.is_empty() {
pub fn bless_output_files(path: &Path, output: &[u8], _errors: &mut Errors, config: &TestConfig) {
if output.is_empty() {
let _ = std::fs::remove_file(path);
} else {
std::fs::write(path, &actual).unwrap();
let actual = config.normalize(output, &path.extension().unwrap().to_string_lossy());
std::fs::write(path, actual).unwrap();
}
}
4 changes: 3 additions & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ pub enum Error {
OutputDiffers {
/// The file containing the expected output that differs from the actual output.
path: PathBuf,
/// The output from the command.
/// The normalized output from the command.
actual: Vec<u8>,
/// The unnormalized output from the command.
output: Vec<u8>,
/// The contents of the file.
expected: Vec<u8>,
/// A command, that when run, causes the output to get blessed instead of erroring.
Expand Down
3 changes: 1 addition & 2 deletions src/per_test_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,8 @@ impl TestConfig {
}

pub(crate) fn check_output(&self, output: &[u8], errors: &mut Errors, kind: &str) -> PathBuf {
let output = self.normalize(output, kind);
let path = self.output_path(kind);
(self.config.output_conflict_handling)(&path, output, errors, &self.config);
(self.config.output_conflict_handling)(&path, output, errors, self);
path
}

Expand Down
1 change: 1 addition & 0 deletions src/status_emitter/gha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ fn gha_error(error: &Error, test_path: &str, revision: &str) {
Error::OutputDiffers {
path: output_path,
actual,
output: _,
expected,
bless_command,
} => {
Expand Down
57 changes: 42 additions & 15 deletions src/status_emitter/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -706,27 +706,54 @@ fn print_error(error: &Error, path: &Path) {
Error::OutputDiffers {
path: output_path,
actual,
output,
expected,
bless_command,
} => {
print_error_header("actual output differed from expected");
if let Some(bless_command) = bless_command {
let bless = || {
if let Some(bless_command) = bless_command {
println!(
"Execute `{}` to update `{}` to the actual output",
bless_command,
display(output_path)
);
}
};
if expected.is_empty() {
print_error_header("no output was expected");
bless();
println!(
"Execute `{}` to update `{}` to the actual output",
bless_command,
display(output_path)
"{}",
format!(
"+++ <{} output>",
output_path.extension().unwrap().to_str().unwrap()
)
.green()
);
println!("{}", String::from_utf8_lossy(output));
} else if output.is_empty() {
print_error_header("no output was emitted");
if let Some(bless_command) = bless_command {
println!(
"Execute `{}` to remove `{}`",
bless_command,
display(output_path)
);
}
} else {
print_error_header("actual output differed from expected");
bless();
println!("{}", format!("--- {}", display(output_path)).red());
println!(
"{}",
format!(
"+++ <{} output>",
output_path.extension().unwrap().to_str().unwrap()
)
.green()
);
crate::diff::print_diff(expected, actual);
}
println!("{}", format!("--- {}", display(output_path)).red());
println!(
"{}",
format!(
"+++ <{} output>",
output_path.extension().unwrap().to_str().unwrap()
)
.green()
);
crate::diff::print_diff(expected, actual);
}
Error::ErrorsWithoutPattern { path, msgs } => {
if let Some((path, _)) = path.as_ref() {
Expand Down
2 changes: 1 addition & 1 deletion tests/integrations/basic-bin/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/integrations/basic-fail-mode/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/integrations/basic-fail/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 32 additions & 35 deletions tests/integrations/basic-fail/Cargo.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -104,20 +104,19 @@ error: test got exit status: 1, but expected 0
| ^^^ compilation failed, but was expected to succeed
|

error: actual output differed from expected
error: no output was expected
Execute `DO NOT BLESS. These are meant to fail` to update `tests/actual_tests/executable_compile_err.stderr` to the actual output
--- tests/actual_tests/executable_compile_err.stderr
+++ <stderr output>
+error: this file contains an unclosed delimiter
+ --> tests/actual_tests/executable_compile_err.rs:4:2
+ |
+3 | fn main() {
+ | - unclosed delimiter
+4 |
+ | ^
+
+error: aborting due to 1 previous error
+
error: this file contains an unclosed delimiter
--> tests/actual_tests/executable_compile_err.rs:4:2
|
3 | fn main() {
| - unclosed delimiter
4 |
| ^

error: aborting due to 1 previous error



full stderr:
Expand Down Expand Up @@ -1206,19 +1205,18 @@ error: test got exit status: 1, but expected 0
| ^^^ compilation failed, but was expected to succeed
|

error: actual output differed from expected
error: no output was expected
Execute `DO NOT BLESS. These are meant to fail` to update `tests/actual_tests/executable.stderr` to the actual output
--- tests/actual_tests/executable.stderr
+++ <stderr output>
+error[E0432]: unresolved import `basic_fail`
+ --> tests/actual_tests/executable.rs:1:5
+ |
+1 | use basic_fail::add;
+ | ^^^^^^^^^^ use of undeclared crate or module `basic_fail`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0432`.
error[E0432]: unresolved import `basic_fail`
--> tests/actual_tests/executable.rs:1:5
|
1 | use basic_fail::add;
| ^^^^^^^^^^ use of undeclared crate or module `basic_fail`

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0432`.



Expand All @@ -1232,20 +1230,19 @@ error: test got exit status: 1, but expected 0
| ^^^ compilation failed, but was expected to succeed
|

error: actual output differed from expected
error: no output was expected
Execute `DO NOT BLESS. These are meant to fail` to update `tests/actual_tests/executable_compile_err.stderr` to the actual output
--- tests/actual_tests/executable_compile_err.stderr
+++ <stderr output>
+error: this file contains an unclosed delimiter
+ --> tests/actual_tests/executable_compile_err.rs:4:2
+ |
+3 | fn main() {
+ | - unclosed delimiter
+4 |
+ | ^
+
+error: aborting due to 1 previous error
+
error: this file contains an unclosed delimiter
--> tests/actual_tests/executable_compile_err.rs:4:2
|
3 | fn main() {
| - unclosed delimiter
4 |
| ^

error: aborting due to 1 previous error




Expand Down
2 changes: 1 addition & 1 deletion tests/integrations/basic/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/integrations/cargo-run/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/integrations/dep-fail/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/integrations/ui_test_dep_bug/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 4989e9b

Please sign in to comment.