Skip to content

Commit 079c5f2

Browse files
committed
test(rustfix): Using snapbox for snapshot testing
`.json` files will have pretty printed json when updated
1 parent 85c3aea commit 079c5f2

File tree

1 file changed

+43
-101
lines changed

1 file changed

+43
-101
lines changed

crates/rustfix/tests/parse_and_replace.rs

+43-101
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,15 @@
66
//! rustfix and applies the recommended suggestions to the `.rs` file. It then
77
//! compares the result with the corresponding `.fixed.rs` file. If they don't
88
//! match, then the test fails.
9-
//!
10-
//! There are several debugging environment variables for this test that you can set:
11-
//!
12-
//! - `RUST_LOG=parse_and_replace=debug`: Print debug information.
13-
//! - `RUSTFIX_TEST_BLESS=test-name.rs`: When given the name of a test, this
14-
//! will overwrite the `.json` and `.fixed.rs` files with the expected
15-
//! values. This can be used when adding a new test.
16-
//! - `RUSTFIX_TEST_RECORD_JSON=1`: Records the JSON output to
17-
//! `*.recorded.json` files. You can then move that to `.json` or whatever
18-
//! you need.
19-
//! - `RUSTFIX_TEST_RECORD_FIXED_RUST=1`: Records the fixed result to
20-
//! `*.recorded.rs` files. You can then move that to `.rs` or whatever you
21-
//! need.
229
2310
#![allow(clippy::disallowed_methods, clippy::print_stdout, clippy::print_stderr)]
2411

2512
use anyhow::{anyhow, Context, Error};
2613
use cargo_test_macro::cargo_test;
2714
use rustfix::apply_suggestions;
15+
use serde_json::Value;
16+
use snapbox::data::DataFormat;
17+
use snapbox::{Assert, Data};
2818
use std::collections::HashSet;
2919
use std::env;
3020
use std::ffi::OsString;
@@ -38,14 +28,6 @@ mod fixmode {
3828
pub const EVERYTHING: &str = "yolo";
3929
}
4030

41-
mod settings {
42-
// can be set as env var to debug
43-
pub const CHECK_JSON: &str = "RUSTFIX_TEST_CHECK_JSON";
44-
pub const RECORD_JSON: &str = "RUSTFIX_TEST_RECORD_JSON";
45-
pub const RECORD_FIXED_RUST: &str = "RUSTFIX_TEST_RECORD_FIXED_RUST";
46-
pub const BLESS: &str = "RUSTFIX_TEST_BLESS";
47-
}
48-
4931
fn compile(file: &Path) -> Result<Output, Error> {
5032
let tmp = tempdir()?;
5133

@@ -95,47 +77,15 @@ fn compiles_without_errors(file: &Path) -> Result<(), Error> {
9577
file,
9678
String::from_utf8(res.stderr)?
9779
);
98-
Err(anyhow!(
99-
"failed with status {:?} (`env RUST_LOG=parse_and_replace=info` for more info)",
100-
res.status.code(),
101-
))
80+
Err(anyhow!("failed with status {:?}", res.status.code()))
10281
}
10382
}
10483
}
10584

106-
fn diff(expected: &str, actual: &str) -> String {
107-
use similar::{ChangeTag, TextDiff};
108-
use std::fmt::Write;
109-
110-
let mut res = String::new();
111-
let diff = TextDiff::from_lines(expected.trim(), actual.trim());
112-
113-
let mut different = false;
114-
for op in diff.ops() {
115-
for change in diff.iter_changes(op) {
116-
let prefix = match change.tag() {
117-
ChangeTag::Equal => continue,
118-
ChangeTag::Insert => "+",
119-
ChangeTag::Delete => "-",
120-
};
121-
if !different {
122-
writeln!(&mut res, "differences found (+ == actual, - == expected):").unwrap();
123-
different = true;
124-
}
125-
write!(&mut res, "{} {}", prefix, change.value()).unwrap();
126-
}
127-
}
128-
if different {
129-
write!(&mut res, "").unwrap();
130-
}
131-
132-
res
133-
}
134-
13585
fn test_rustfix_with_file<P: AsRef<Path>>(file: P, mode: &str) {
13686
let file: &Path = file.as_ref();
13787
let json_file = file.with_extension("json");
138-
let fixed_file = file.with_extension("fixed.rs");
88+
let expected_fixed_file = file.with_extension("fixed.rs");
13989

14090
let filter_suggestions = if mode == fixmode::EVERYTHING {
14191
rustfix::Filter::Everything
@@ -144,60 +94,52 @@ fn test_rustfix_with_file<P: AsRef<Path>>(file: P, mode: &str) {
14494
};
14595

14696
let code = fs::read_to_string(file).unwrap();
147-
let errors = compile_and_get_json_errors(file)
148-
.with_context(|| format!("could not compile {}", file.display())).unwrap();
149-
let suggestions =
150-
rustfix::get_suggestions_from_json(&errors, &HashSet::new(), filter_suggestions)
151-
.context("could not load suggestions").unwrap();
15297

153-
if std::env::var(settings::RECORD_JSON).is_ok() {
154-
fs::write(file.with_extension("recorded.json"), &errors).unwrap();
155-
}
98+
let json = compile_and_get_json_errors(file)
99+
.with_context(|| format!("could not compile {}", file.display()))
100+
.unwrap();
156101

157-
if std::env::var(settings::CHECK_JSON).is_ok() {
158-
let expected_json = fs::read_to_string(&json_file)
159-
.with_context(|| format!("could not load json fixtures for {}", file.display())).unwrap();
160-
let expected_suggestions =
161-
rustfix::get_suggestions_from_json(&expected_json, &HashSet::new(), filter_suggestions)
162-
.context("could not load expected suggestions").unwrap();
163-
164-
assert!(
165-
expected_suggestions == suggestions,
166-
"got unexpected suggestions from clippy:\n{}",
167-
diff(
168-
&format!("{:?}", expected_suggestions),
169-
&format!("{:?}", suggestions)
170-
)
171-
);
172-
}
102+
let suggestions =
103+
rustfix::get_suggestions_from_json(&json, &HashSet::new(), filter_suggestions)
104+
.context("could not load suggestions")
105+
.unwrap();
173106

174107
let fixed = apply_suggestions(&code, &suggestions)
175-
.with_context(|| format!("could not apply suggestions to {}", file.display())).unwrap()
108+
.with_context(|| format!("could not apply suggestions to {}", file.display()))
109+
.unwrap()
176110
.replace('\r', "");
177111

178-
if std::env::var(settings::RECORD_FIXED_RUST).is_ok() {
179-
fs::write(file.with_extension("recorded.rs"), &fixed).unwrap();
180-
}
181-
182-
if let Some(bless_name) = std::env::var_os(settings::BLESS) {
183-
if bless_name == file.file_name().unwrap() {
184-
std::fs::write(&json_file, &errors).unwrap();
185-
std::fs::write(&fixed_file, &fixed).unwrap();
186-
}
112+
let actual_fix = Data::text(&fixed);
113+
let expected_fix = Data::read_from(expected_fixed_file.as_path(), Some(DataFormat::Text));
114+
115+
if actual_fix != expected_fix {
116+
let fixed_assert = Assert::new()
117+
.action_env(snapbox::assert::DEFAULT_ACTION_ENV)
118+
.try_eq(Some(&"Current Fix"), actual_fix, expected_fix);
119+
assert!(fixed_assert.is_ok(), "{}", fixed_assert.err().unwrap());
120+
121+
let expected_json = Data::read_from(json_file.as_path(), Some(DataFormat::Text));
122+
123+
let pretty_json = json
124+
.split("\n")
125+
.filter(|j| !j.is_empty())
126+
.map(|j| {
127+
serde_json::to_string_pretty(&serde_json::from_str::<Value>(j).unwrap()).unwrap()
128+
})
129+
.collect::<Vec<String>>()
130+
.join("\n");
131+
132+
let json_assert = Assert::new()
133+
.action_env(snapbox::assert::DEFAULT_ACTION_ENV)
134+
.try_eq(
135+
Some(&"Compiler Error"),
136+
Data::text(pretty_json),
137+
expected_json,
138+
);
139+
assert!(json_assert.is_ok(), "{}", json_assert.err().unwrap());
187140
}
188141

189-
let expected_fixed = fs::read_to_string(&fixed_file)
190-
.with_context(|| format!("could read fixed file for {}", file.display())).unwrap()
191-
.replace('\r', "");
192-
assert!(
193-
fixed.trim() == expected_fixed.trim(),
194-
"file {} doesn't look fixed:\n{}",
195-
file.display(),
196-
diff(fixed.trim(), expected_fixed.trim())
197-
);
198-
199-
compiles_without_errors(&fixed_file).unwrap();
200-
142+
compiles_without_errors(&expected_fixed_file).unwrap();
201143
}
202144

203145
macro_rules! run_test {

0 commit comments

Comments
 (0)