diff --git a/tests/testsuite/build_script.rs b/tests/testsuite/build_script.rs index 8bda5aa4dca..fb22b7e245f 100644 --- a/tests/testsuite/build_script.rs +++ b/tests/testsuite/build_script.rs @@ -3171,9 +3171,12 @@ fn switch_features_rerun() { ) .build(); - p.cargo("run -v --features=foo").with_stdout("foo\n").run(); - p.cargo("run -v").with_stdout("bar\n").run(); - p.cargo("run -v --features=foo").with_stdout("foo\n").run(); + p.cargo("build -v --features=foo").run(); + p.rename_run("foo", "with_foo").with_stdout("foo\n").run(); + p.cargo("build -v").run(); + p.rename_run("foo", "without_foo").with_stdout("bar\n").run(); + p.cargo("build -v --features=foo").run(); + p.rename_run("foo", "with_foo2").with_stdout("foo\n").run(); } #[test] diff --git a/tests/testsuite/freshness.rs b/tests/testsuite/freshness.rs index e21ded04345..dfa9e223824 100644 --- a/tests/testsuite/freshness.rs +++ b/tests/testsuite/freshness.rs @@ -447,17 +447,6 @@ fn changing_bin_features_caches_targets() { ) .build(); - // Windows has a problem with replacing a binary that was just executed. - // Unlinking it will succeed, but then attempting to immediately replace - // it will sometimes fail with "Already Exists". - // See https://github.com/rust-lang/cargo/issues/5481 - let foo_proc = |name: &str| { - let src = p.bin("foo"); - let dst = p.bin(name); - fs::rename(&src, &dst).expect("Failed to rename foo"); - p.process(dst) - }; - p.cargo("build") .with_stderr( "\ @@ -466,7 +455,7 @@ fn changing_bin_features_caches_targets() { ", ) .run(); - foo_proc("off1").with_stdout("feature off").run(); + p.rename_run("foo", "off1").with_stdout("feature off").run(); p.cargo("build --features foo") .with_stderr( @@ -476,7 +465,7 @@ fn changing_bin_features_caches_targets() { ", ) .run(); - foo_proc("on1").with_stdout("feature on").run(); + p.rename_run("foo", "on1").with_stdout("feature on").run(); /* Targets should be cached from the first build */ @@ -487,7 +476,7 @@ fn changing_bin_features_caches_targets() { ", ) .run(); - foo_proc("off2").with_stdout("feature off").run(); + p.rename_run("foo", "off2").with_stdout("feature off").run(); p.cargo("build --features foo") .with_stderr( @@ -496,7 +485,7 @@ fn changing_bin_features_caches_targets() { ", ) .run(); - foo_proc("on2").with_stdout("feature on").run(); + p.rename_run("foo", "on2").with_stdout("feature on").run(); } #[test] diff --git a/tests/testsuite/support/mod.rs b/tests/testsuite/support/mod.rs index ea5b8751f59..6498a000142 100644 --- a/tests/testsuite/support/mod.rs +++ b/tests/testsuite/support/mod.rs @@ -399,6 +399,27 @@ impl Project { execs } + /// Safely run a process after `cargo build`. + /// + /// Windows has a problem where a process cannot be reliably + /// be replaced, removed, or renamed immediately after executing it. + /// The action may fail (with errors like Access is denied), or + /// it may succeed, but future attempts to use the same filename + /// will fail with "Already Exists". + /// + /// If you have a test that needs to do `cargo run` multiple + /// times, you should instead use `cargo build` and use this + /// method to run the executable. Each time you call this, + /// use a new name for `dst`. + /// See https://github.com/rust-lang/cargo/issues/5481 + pub fn rename_run(&self, src: &str, dst: &str) -> Execs { + let src = self.bin(src); + let dst = self.bin(dst); + fs::rename(&src, &dst) + .unwrap_or_else(|e| panic!("Failed to rename `{:?}` to `{:?}`: {}", src, dst, e)); + self.process(dst) + } + /// Returns the contents of `Cargo.lock`. pub fn read_lockfile(&self) -> String { self.read_file("Cargo.lock")