about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-08-23 06:26:51 +0200
committerGitHub <noreply@github.com>2024-08-23 06:26:51 +0200
commit370b3265ffb64e29ba3e960fa33f8fef80c11875 (patch)
treea834bf9e4078704e87ae6663aefcc2afb0be5b78 /tests
parentb5723af3457b9cd3795eeb97e9af2d34964854f2 (diff)
parent736f773844e7ebf05ccb827c17b7ad9eb28aa295 (diff)
downloadrust-370b3265ffb64e29ba3e960fa33f8fef80c11875.tar.gz
rust-370b3265ffb64e29ba3e960fa33f8fef80c11875.zip
Rollup merge of #127623 - lolbinarycat:fix_remove_dir_all, r=Amanieu
fix: fs::remove_dir_all: treat internal ENOENT as success

fixes #127576

try-job: test-various
Diffstat (limited to 'tests')
-rw-r--r--tests/run-make/remove-dir-all-race/rmake.rs62
1 files changed, 62 insertions, 0 deletions
diff --git a/tests/run-make/remove-dir-all-race/rmake.rs b/tests/run-make/remove-dir-all-race/rmake.rs
new file mode 100644
index 00000000000..03c94b76127
--- /dev/null
+++ b/tests/run-make/remove-dir-all-race/rmake.rs
@@ -0,0 +1,62 @@
+//@ ignore-windows
+
+// This test attempts to make sure that running `remove_dir_all`
+// doesn't result in a NotFound error one of the files it
+// is deleting is deleted concurrently.
+//
+// The windows implementation for `remove_dir_all` is significantly
+// more complicated, and has not yet been brought up to par with
+// the implementation on other platforms, so this test is marked as
+// `ignore-windows` until someone more expirenced with windows can
+// sort that out.
+
+use std::fs::remove_dir_all;
+use std::path::Path;
+use std::thread;
+use std::time::Duration;
+
+use run_make_support::rfs::{create_dir, write};
+use run_make_support::run_in_tmpdir;
+
+fn main() {
+    let mut race_happened = false;
+    run_in_tmpdir(|| {
+        for i in 0..150 {
+            create_dir("outer");
+            create_dir("outer/inner");
+            write("outer/inner.txt", b"sometext");
+
+            thread::scope(|scope| {
+                let t1 = scope.spawn(|| {
+                    thread::sleep(Duration::from_nanos(i));
+                    remove_dir_all("outer").unwrap();
+                });
+
+                let race_happened_ref = &race_happened;
+                let t2 = scope.spawn(|| {
+                    let r1 = remove_dir_all("outer/inner");
+                    let r2 = remove_dir_all("outer/inner.txt");
+                    if r1.is_ok() && r2.is_err() {
+                        race_happened = true;
+                    }
+                });
+            });
+
+            assert!(!Path::new("outer").exists());
+
+            // trying to remove a nonexistant top-level directory should
+            // still result in an error.
+            let Err(err) = remove_dir_all("outer") else {
+                panic!("removing nonexistant dir did not result in an error");
+            };
+            assert_eq!(err.kind(), std::io::ErrorKind::NotFound);
+        }
+    });
+    if !race_happened {
+        eprintln!(
+            "WARNING: multithreaded deletion never raced, \
+                   try increasing the number of attempts or \
+                   adjusting the sleep timing"
+        );
+    }
+}