Skip to content

Commit 8ffd9cd

Browse files
committed
Add tests validating the sequence for cargo fix.
This adds a set of tests which validates various edge cases around how `cargo fix` works in terms of calling `rustc` multiple times. This uses a replacement of `rustc` so it doesn't depend on the behavior of rustc itself which is not always stable.
1 parent 42d2c02 commit 8ffd9cd

File tree

4 files changed

+516
-175
lines changed

4 files changed

+516
-175
lines changed

src/cargo/util/diagnostic_server.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ https://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-proje
234234
fn gen_please_report_this_bug_text(url: &str) -> String {
235235
format!(
236236
"This likely indicates a bug in either rustc or cargo itself,\n\
237-
and we would appreciate a bug report! You're likely to see \n\
237+
and we would appreciate a bug report! You're likely to see\n\
238238
a number of compiler warnings after this message which cargo\n\
239239
attempted to fix but failed. If you could open an issue at\n\
240240
{}\n\

tests/testsuite/fix.rs

Lines changed: 1 addition & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use cargo_test_support::git::{self, init};
66
use cargo_test_support::paths::{self, CargoPathExt};
77
use cargo_test_support::registry::{Dependency, Package};
88
use cargo_test_support::tools;
9-
use cargo_test_support::{basic_manifest, is_nightly, project, Project};
9+
use cargo_test_support::{basic_manifest, is_nightly, project};
1010

1111
#[cargo_test]
1212
fn do_not_fix_broken_builds() {
@@ -53,179 +53,6 @@ fn fix_broken_if_requested() {
5353
.run();
5454
}
5555

56-
fn rustc_shim_for_cargo_fix() -> Project {
57-
// This works as follows:
58-
// - Create a `rustc` shim (the "foo" project) which will pretend that the
59-
// verification step fails.
60-
// - There is an empty build script so `foo` has `OUT_DIR` to track the steps.
61-
// - The first "check", `foo` creates a file in OUT_DIR, and it completes
62-
// successfully with a warning diagnostic to remove unused `mut`.
63-
// - rustfix removes the `mut`.
64-
// - The second "check" to verify the changes, `foo` swaps out the content
65-
// with something that fails to compile. It creates a second file so it
66-
// won't do anything in the third check.
67-
// - cargo fix discovers that the fix failed, and it backs out the changes.
68-
// - The third "check" is done to display the original diagnostics of the
69-
// original code.
70-
let p = project()
71-
.file(
72-
"foo/Cargo.toml",
73-
r#"
74-
[package]
75-
name = 'foo'
76-
version = '0.1.0'
77-
[workspace]
78-
"#,
79-
)
80-
.file(
81-
"foo/src/main.rs",
82-
r#"
83-
use std::env;
84-
use std::fs;
85-
use std::io::Write;
86-
use std::path::{Path, PathBuf};
87-
use std::process::{self, Command};
88-
89-
fn main() {
90-
// Ignore calls to things like --print=file-names and compiling build.rs.
91-
// Also compatible for rustc invocations with `@path` argfile.
92-
let is_lib_rs = env::args_os()
93-
.map(PathBuf::from)
94-
.flat_map(|p| if let Some(p) = p.to_str().unwrap_or_default().strip_prefix("@") {
95-
fs::read_to_string(p).unwrap().lines().map(PathBuf::from).collect()
96-
} else {
97-
vec![p]
98-
})
99-
.any(|l| l == Path::new("src/lib.rs"));
100-
if is_lib_rs {
101-
let path = PathBuf::from(env::var_os("OUT_DIR").unwrap());
102-
let first = path.join("first");
103-
let second = path.join("second");
104-
if first.exists() && !second.exists() {
105-
fs::write("src/lib.rs", b"not rust code").unwrap();
106-
fs::File::create(&second).unwrap();
107-
} else {
108-
fs::File::create(&first).unwrap();
109-
}
110-
}
111-
let status = Command::new("rustc")
112-
.args(env::args().skip(1))
113-
.env_remove("CARGO_MAKEFLAGS")
114-
.status()
115-
.expect("failed to run rustc");
116-
process::exit(status.code().unwrap_or(2));
117-
}
118-
"#,
119-
)
120-
.file(
121-
"bar/Cargo.toml",
122-
r#"
123-
[package]
124-
name = 'bar'
125-
version = '0.1.0'
126-
[workspace]
127-
"#,
128-
)
129-
.file("bar/build.rs", "fn main() {}")
130-
.file(
131-
"bar/src/lib.rs",
132-
r#"
133-
pub fn foo() {
134-
let mut x = 3;
135-
drop(x);
136-
}
137-
"#,
138-
)
139-
.build();
140-
141-
// Build our rustc shim
142-
p.cargo("build").cwd("foo").run();
143-
144-
p
145-
}
146-
147-
#[cargo_test]
148-
fn broken_fixes_backed_out() {
149-
let p = rustc_shim_for_cargo_fix();
150-
// Attempt to fix code, but our shim will always fail the second compile.
151-
p.cargo("fix --allow-no-vcs --lib")
152-
.cwd("bar")
153-
.env("__CARGO_FIX_YOLO", "1")
154-
.env("RUSTC", p.root().join("foo/target/debug/foo"))
155-
.with_stderr_contains(
156-
"warning: failed to automatically apply fixes suggested by rustc \
157-
to crate `bar`\n\
158-
\n\
159-
after fixes were automatically applied the compiler reported \
160-
errors within these files:\n\
161-
\n \
162-
* src/lib.rs\n\
163-
\n\
164-
This likely indicates a bug in either rustc or cargo itself,\n\
165-
and we would appreciate a bug report! You're likely to see \n\
166-
a number of compiler warnings after this message which cargo\n\
167-
attempted to fix but failed. If you could open an issue at\n\
168-
https://github.com/rust-lang/rust/issues\n\
169-
quoting the full output of this command we'd be very appreciative!\n\
170-
Note that you may be able to make some more progress in the near-term\n\
171-
fixing code with the `--broken-code` flag\n\
172-
\n\
173-
The following errors were reported:\n\
174-
error: expected one of `!` or `::`, found `rust`\n\
175-
",
176-
)
177-
.with_stderr_contains("Original diagnostics will follow.")
178-
.with_stderr_contains("[WARNING] variable does not need to be mutable")
179-
.with_stderr_does_not_contain("[..][FIXED][..]")
180-
.run();
181-
182-
// Make sure the fix which should have been applied was backed out
183-
assert!(p.read_file("bar/src/lib.rs").contains("let mut x = 3;"));
184-
}
185-
186-
#[cargo_test]
187-
fn broken_clippy_fixes_backed_out() {
188-
let p = rustc_shim_for_cargo_fix();
189-
// Attempt to fix code, but our shim will always fail the second compile.
190-
// Also, we use `clippy` as a workspace wrapper to make sure that we properly
191-
// generate the report bug text.
192-
p.cargo("fix --allow-no-vcs --lib")
193-
.cwd("bar")
194-
.env("__CARGO_FIX_YOLO", "1")
195-
.env("RUSTC", p.root().join("foo/target/debug/foo"))
196-
// We can't use `clippy` so we use a `rustc` workspace wrapper instead
197-
.env("RUSTC_WORKSPACE_WRAPPER", tools::wrapped_clippy_driver())
198-
.with_stderr_contains(
199-
"warning: failed to automatically apply fixes suggested by rustc \
200-
to crate `bar`\n\
201-
\n\
202-
after fixes were automatically applied the compiler reported \
203-
errors within these files:\n\
204-
\n \
205-
* src/lib.rs\n\
206-
\n\
207-
This likely indicates a bug in either rustc or cargo itself,\n\
208-
and we would appreciate a bug report! You're likely to see \n\
209-
a number of compiler warnings after this message which cargo\n\
210-
attempted to fix but failed. If you could open an issue at\n\
211-
https://github.com/rust-lang/rust-clippy/issues\n\
212-
quoting the full output of this command we'd be very appreciative!\n\
213-
Note that you may be able to make some more progress in the near-term\n\
214-
fixing code with the `--broken-code` flag\n\
215-
\n\
216-
The following errors were reported:\n\
217-
error: expected one of `!` or `::`, found `rust`\n\
218-
",
219-
)
220-
.with_stderr_contains("Original diagnostics will follow.")
221-
.with_stderr_contains("[WARNING] variable does not need to be mutable")
222-
.with_stderr_does_not_contain("[..][FIXED][..]")
223-
.run();
224-
225-
// Make sure the fix which should have been applied was backed out
226-
assert!(p.read_file("bar/src/lib.rs").contains("let mut x = 3;"));
227-
}
228-
22956
#[cargo_test]
23057
fn fix_path_deps() {
23158
let p = project()

0 commit comments

Comments
 (0)