From 0e715f76b68f69f1b9a741a8be2021d3ecec6369 Mon Sep 17 00:00:00 2001
From: Oneirical <manchot@videotron.ca>
Date: Tue, 11 Jun 2024 16:12:36 -0400
Subject: [PATCH] Add new test_while_readonly helper function to
 run-make-support

---
 src/tools/run-make-support/src/lib.rs         | 22 +++++++++++++
 tests/run-make/inaccessible-temp-dir/rmake.rs | 33 +++++++------------
 tests/run-make/output-with-hyphens/rmake.rs   |  2 +-
 3 files changed, 35 insertions(+), 22 deletions(-)

diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index b920f9a07db87..317c933797f26 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -169,6 +169,28 @@ pub fn cwd() -> PathBuf {
     env::current_dir().unwrap()
 }
 
+// FIXME(Oneirical): This will no longer be required after compiletest receives the ability
+// to manipulate read-only files. See https://github.com/rust-lang/rust/issues/126334
+/// Ensure that the path P is read-only while the test runs, and restore original permissions
+/// at the end so compiletest can clean up.
+#[track_caller]
+pub fn test_while_readonly<P: AsRef<Path>, F: FnOnce() + std::panic::UnwindSafe>(
+    path: P,
+    closure: F,
+) {
+    let path = path.as_ref();
+    let metadata = fs_wrapper::metadata(&path);
+    let original_perms = metadata.permissions();
+
+    let mut new_perms = original_perms.clone();
+    new_perms.set_readonly(true);
+    fs_wrapper::set_permissions(&path, new_perms);
+
+    assert!(std::panic::catch_unwind(closure).is_ok());
+
+    fs_wrapper::set_permissions(&path, original_perms);
+}
+
 /// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is
 /// available on the platform!
 #[track_caller]
diff --git a/tests/run-make/inaccessible-temp-dir/rmake.rs b/tests/run-make/inaccessible-temp-dir/rmake.rs
index 25c9d363820dc..1dce1ab0af21f 100644
--- a/tests/run-make/inaccessible-temp-dir/rmake.rs
+++ b/tests/run-make/inaccessible-temp-dir/rmake.rs
@@ -13,32 +13,23 @@
 // use a directory with non-existing parent like `/does-not-exist/output`.
 // See https://github.com/rust-lang/rust/issues/66530
 
-//@ only-linux
-// Reason: set_mode is only available on Unix
-
 //@ ignore-arm
 // Reason: linker error on `armhf-gnu`
 
-use run_make_support::{fs_wrapper, rustc};
+use run_make_support::{fs_wrapper, rustc, test_while_readonly};
 
 fn main() {
     // Create an inaccessible directory.
     fs_wrapper::create_dir("inaccessible");
-    let meta = fs_wrapper::metadata("inaccessible");
-    let mut perms = meta.permissions();
-    perms.set_mode(0o000); // Lock down the directory.
-    fs_wrapper::set_permissions("inaccessible", perms);
-
-    // Run rustc with `-Z temps-dir` set to a directory *inside* the inaccessible one,
-    // so that it can't create `tmp`.
-    rustc()
-        .input("program.rs")
-        .arg("-Ztemps-dir=inaccessible/tmp")
-        .run_fail()
-        .assert_stderr_contains(
-            "failed to find or create the directory specified by `--temps-dir`",
-        );
-
-    perms.set_mode(0o666); // Unlock the directory, so that compiletest can delete it.
-    fs_wrapper::set_permissions("inaccessible", perms);
+    test_while_readonly("inaccessible", || {
+        // Run rustc with `-Z temps-dir` set to a directory *inside* the inaccessible one,
+        // so that it can't create `tmp`.
+        rustc()
+            .input("program.rs")
+            .arg("-Ztemps-dir=inaccessible/tmp")
+            .run_fail()
+            .assert_stderr_contains(
+                "failed to find or create the directory specified by `--temps-dir`",
+            );
+    });
 }
diff --git a/tests/run-make/output-with-hyphens/rmake.rs b/tests/run-make/output-with-hyphens/rmake.rs
index 21c003c628b9e..83408c58f05db 100644
--- a/tests/run-make/output-with-hyphens/rmake.rs
+++ b/tests/run-make/output-with-hyphens/rmake.rs
@@ -7,7 +7,7 @@
 
 //@ ignore-cross-compile
 
-use run_make_support::{path, rustc};
+use run_make_support::{bin_name, path, rustc};
 
 fn main() {
     rustc().input("foo-bar.rs").crate_type("bin").run();