]> git.proxmox.com Git - rustc.git/blame - src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/testdir.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / src / tools / rust-analyzer / crates / rust-analyzer / tests / slow-tests / testdir.rs
CommitLineData
064997fb
FG
1use std::{
2 fs, io,
3 path::{Path, PathBuf},
4 sync::atomic::{AtomicUsize, Ordering},
5};
6
7pub(crate) struct TestDir {
8 path: PathBuf,
9 keep: bool,
10}
11
12impl TestDir {
13 pub(crate) fn new() -> TestDir {
14 let temp_dir = std::env::temp_dir();
15 // On MacOS builders on GitHub actions, the temp dir is a symlink, and
16 // that causes problems down the line. Specifically:
17 // * Cargo may emit different PackageId depending on the working directory
18 // * rust-analyzer may fail to map LSP URIs to correct paths.
19 //
20 // Work-around this by canonicalizing. Note that we don't want to do this
21 // on *every* OS, as on windows `canonicalize` itself creates problems.
22 #[cfg(target_os = "macos")]
23 let temp_dir = temp_dir.canonicalize().unwrap();
24
25 let base = temp_dir.join("testdir");
26 let pid = std::process::id();
27
28 static CNT: AtomicUsize = AtomicUsize::new(0);
29 for _ in 0..100 {
30 let cnt = CNT.fetch_add(1, Ordering::Relaxed);
f25598a0 31 let path = base.join(format!("{pid}_{cnt}"));
064997fb
FG
32 if path.is_dir() {
33 continue;
34 }
35 fs::create_dir_all(&path).unwrap();
36 return TestDir { path, keep: false };
37 }
38 panic!("Failed to create a temporary directory")
39 }
40 #[allow(unused)]
41 pub(crate) fn keep(mut self) -> TestDir {
42 self.keep = true;
43 self
44 }
45 pub(crate) fn path(&self) -> &Path {
46 &self.path
47 }
48}
49
50impl Drop for TestDir {
51 fn drop(&mut self) {
52 if self.keep {
53 return;
54 }
55 remove_dir_all(&self.path).unwrap_or_else(|err| {
f25598a0 56 panic!("failed to remove temporary directory {}: {err}", self.path.display())
064997fb
FG
57 })
58 }
59}
60
61#[cfg(not(windows))]
62fn remove_dir_all(path: &Path) -> io::Result<()> {
63 fs::remove_dir_all(path)
64}
65
66#[cfg(windows)]
67fn remove_dir_all(path: &Path) -> io::Result<()> {
68 for _ in 0..99 {
69 if fs::remove_dir_all(path).is_ok() {
70 return Ok(());
71 }
72 std::thread::sleep(std::time::Duration::from_millis(10))
73 }
74 fs::remove_dir_all(path)
75}