diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2023-06-10 11:09:45 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-10 11:09:45 -0400 |
commit | 7f15126f23d97f20a4fb33e43136cd4d13825863 (patch) | |
tree | 85d77389969b31999680059e65954a9fa863758e /test_util/src | |
parent | f3326eebd6af2aaca1543e8cb543a7b16762bc96 (diff) |
chore(tests): test_util - Add `PathRef` (#19450)
This adds a new `PathRef` struct to test_util for making it easier to
work with paths in test code. I'm going to expand on this more in the
future.
Diffstat (limited to 'test_util/src')
-rw-r--r-- | test_util/src/builders.rs | 71 | ||||
-rw-r--r-- | test_util/src/fs.rs | 394 | ||||
-rw-r--r-- | test_util/src/lib.rs | 81 | ||||
-rw-r--r-- | test_util/src/lsp.rs | 6 | ||||
-rw-r--r-- | test_util/src/npm.rs | 10 | ||||
-rw-r--r-- | test_util/src/temp_dir.rs | 175 |
6 files changed, 464 insertions, 273 deletions
diff --git a/test_util/src/builders.rs b/test_util/src/builders.rs index 049ccbd67..582380bac 100644 --- a/test_util/src/builders.rs +++ b/test_util/src/builders.rs @@ -2,6 +2,7 @@ use std::cell::RefCell; use std::collections::HashMap; +use std::ffi::OsStr; use std::io::Read; use std::io::Write; use std::path::Path; @@ -13,9 +14,9 @@ use std::rc::Rc; use os_pipe::pipe; use pretty_assertions::assert_eq; -use crate::copy_dir_recursive; use crate::deno_exe_path; use crate::env_vars_for_npm_tests_no_sync_download; +use crate::fs::PathRef; use crate::http_server; use crate::lsp::LspClientBuilder; use crate::new_deno_dir; @@ -38,7 +39,7 @@ pub struct TestContextBuilder { copy_temp_dir: Option<String>, cwd: Option<String>, envs: HashMap<String, String>, - deno_exe: Option<PathBuf>, + deno_exe: Option<PathRef>, } impl TestContextBuilder { @@ -129,17 +130,17 @@ impl TestContextBuilder { temp_dir }; let testdata_dir = if let Some(temp_copy_dir) = &self.copy_temp_dir { - let test_data_path = testdata_path().join(temp_copy_dir); + let test_data_path = PathRef::new(testdata_path()).join(temp_copy_dir); let temp_copy_dir = temp_dir.path().join(temp_copy_dir); - std::fs::create_dir_all(&temp_copy_dir).unwrap(); - copy_dir_recursive(&test_data_path, &temp_copy_dir).unwrap(); - temp_dir.path().to_owned() + temp_copy_dir.create_dir_all(); + test_data_path.copy_to_recursive(&temp_copy_dir); + temp_dir.path().clone() } else { - testdata_path() + PathRef::new(testdata_path()) }; let deno_exe = self.deno_exe.clone().unwrap_or_else(deno_exe_path); - println!("deno_exe path {}", deno_exe.display()); + println!("deno_exe path {}", deno_exe); let http_server_guard = if self.use_http_server { Some(Rc::new(http_server())) @@ -162,14 +163,14 @@ impl TestContextBuilder { #[derive(Clone)] pub struct TestContext { - deno_exe: PathBuf, + deno_exe: PathRef, envs: HashMap<String, String>, use_temp_cwd: bool, cwd: Option<String>, _http_server_guard: Option<Rc<HttpServerGuard>>, deno_dir: TempDir, temp_dir: TempDir, - testdata_dir: PathBuf, + testdata_dir: PathRef, } impl Default for TestContext { @@ -183,7 +184,7 @@ impl TestContext { TestContextBuilder::default().use_http_server().build() } - pub fn testdata_path(&self) -> &PathBuf { + pub fn testdata_path(&self) -> &PathRef { &self.testdata_dir } @@ -197,7 +198,7 @@ impl TestContext { pub fn new_command(&self) -> TestCommandBuilder { TestCommandBuilder { - command_name: self.deno_exe.to_string_lossy().to_string(), + command_name: self.deno_exe.to_string(), args: Default::default(), args_vec: Default::default(), stdin: Default::default(), @@ -229,8 +230,8 @@ pub struct TestCommandBuilder { } impl TestCommandBuilder { - pub fn command_name(mut self, name: impl AsRef<str>) -> Self { - self.command_name = name.as_ref().to_string(); + pub fn command_name(mut self, name: impl AsRef<OsStr>) -> Self { + self.command_name = name.as_ref().to_string_lossy().to_string(); self } @@ -261,10 +262,15 @@ impl TestCommandBuilder { self } - pub fn env(mut self, key: impl AsRef<str>, value: impl AsRef<str>) -> Self { - self - .envs - .insert(key.as_ref().to_string(), value.as_ref().to_string()); + pub fn env( + mut self, + key: impl AsRef<OsStr>, + value: impl AsRef<OsStr>, + ) -> Self { + self.envs.insert( + key.as_ref().to_string_lossy().to_string(), + value.as_ref().to_string_lossy().to_string(), + ); self } @@ -273,12 +279,12 @@ impl TestCommandBuilder { self } - pub fn cwd(mut self, cwd: impl AsRef<str>) -> Self { - self.cwd = Some(cwd.as_ref().to_string()); + pub fn cwd(mut self, cwd: impl AsRef<OsStr>) -> Self { + self.cwd = Some(cwd.as_ref().to_string_lossy().to_string()); self } - fn build_cwd(&self) -> PathBuf { + fn build_cwd(&self) -> PathRef { let cwd = self.cwd.as_ref().or(self.context.cwd.as_ref()); if self.context.use_temp_cwd { assert!(cwd.is_none()); @@ -290,12 +296,12 @@ impl TestCommandBuilder { } } - fn build_command_path(&self) -> PathBuf { + fn build_command_path(&self) -> PathRef { let command_name = &self.command_name; if command_name == "deno" { deno_exe_path() } else { - PathBuf::from(command_name) + PathRef::new(PathBuf::from(command_name)) } } @@ -317,7 +323,10 @@ impl TestCommandBuilder { } .iter() .map(|arg| { - arg.replace("$TESTDATA", &self.context.testdata_dir.to_string_lossy()) + arg.replace( + "$TESTDATA", + &self.context.testdata_dir.as_path().to_string_lossy(), + ) }) .collect::<Vec<_>>() } @@ -352,9 +361,9 @@ impl TestCommandBuilder { } action(Pty::new( - &self.build_command_path(), + self.build_command_path().as_path(), &args, - &self.build_cwd(), + self.build_cwd().as_path(), Some(envs), )) } @@ -383,7 +392,7 @@ impl TestCommandBuilder { let mut command = Command::new(self.build_command_path()); println!("command {} {}", self.command_name, args.join(" ")); - println!("command cwd {:?}", &cwd); + println!("command cwd {}", cwd); command.args(args.iter()); if self.env_clear { command.env_clear(); @@ -464,7 +473,7 @@ pub struct TestCommandOutput { std_out_err: Option<(String, String)>, exit_code: Option<i32>, signal: Option<i32>, - testdata_dir: PathBuf, + testdata_dir: PathRef, asserted_stdout: RefCell<bool>, asserted_stderr: RefCell<bool>, asserted_combined: RefCell<bool>, @@ -514,7 +523,7 @@ impl Drop for TestCommandOutput { } impl TestCommandOutput { - pub fn testdata_dir(&self) -> &PathBuf { + pub fn testdata_dir(&self) -> &PathRef { &self.testdata_dir } @@ -669,10 +678,10 @@ impl TestCommandOutput { file_path: impl AsRef<Path>, ) -> &Self { let output_path = self.testdata_dir().join(file_path); - println!("output path {}", output_path.display()); + println!("output path {}", output_path); let expected_text = std::fs::read_to_string(&output_path).unwrap_or_else(|err| { - panic!("failed loading {}\n\n{err:#}", output_path.display()) + panic!("failed loading {}\n\n{err:#}", output_path) }); self.inner_assert_matches_text(actual, expected_text) } diff --git a/test_util/src/fs.rs b/test_util/src/fs.rs new file mode 100644 index 000000000..12750ffa4 --- /dev/null +++ b/test_util/src/fs.rs @@ -0,0 +1,394 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. + +use std::borrow::Cow; +use std::ffi::OsStr; +use std::fs; +use std::path::Path; +use std::path::PathBuf; +use std::process::Command; +use std::sync::Arc; + +use anyhow::Context; +use lsp_types::Url; + +/// Represents a path on the file system, which can be used +/// to perform specific actions. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct PathRef(PathBuf); + +impl AsRef<Path> for PathRef { + fn as_ref(&self) -> &Path { + self.as_path() + } +} + +impl AsRef<OsStr> for PathRef { + fn as_ref(&self) -> &OsStr { + self.as_path().as_ref() + } +} + +impl std::fmt::Display for PathRef { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.as_path().display()) + } +} + +impl PathRef { + pub fn new(path: impl AsRef<Path>) -> Self { + Self(path.as_ref().to_path_buf()) + } + + pub fn parent(&self) -> PathRef { + PathRef(self.as_path().parent().unwrap().to_path_buf()) + } + + pub fn uri(&self) -> Url { + Url::from_directory_path(self.as_path()).unwrap() + } + + pub fn as_path(&self) -> &Path { + self.0.as_path() + } + + pub fn to_path_buf(&self) -> PathBuf { + self.0.to_path_buf() + } + + pub fn to_string_lossy(&self) -> Cow<str> { + self.0.to_string_lossy() + } + + pub fn exists(&self) -> bool { + self.0.exists() + } + + pub fn try_exists(&self) -> std::io::Result<bool> { + self.0.try_exists() + } + + pub fn is_dir(&self) -> bool { + self.0.is_dir() + } + + pub fn is_file(&self) -> bool { + self.0.is_file() + } + + pub fn join(&self, path: impl AsRef<Path>) -> PathRef { + PathRef(self.as_path().join(path)) + } + + pub fn with_extension(&self, ext: impl AsRef<OsStr>) -> PathRef { + PathRef(self.as_path().with_extension(ext)) + } + + pub fn canonicalize(&self) -> PathRef { + PathRef(strip_unc_prefix(self.as_path().canonicalize().unwrap())) + } + + pub fn create_dir_all(&self) { + fs::create_dir_all(self).unwrap(); + } + + pub fn remove_file(&self) { + fs::remove_file(self).unwrap(); + } + + pub fn remove_dir_all(&self) { + fs::remove_dir_all(self).unwrap(); + } + + pub fn read_to_string(&self) -> String { + self.read_to_string_if_exists().unwrap() + } + + pub fn read_to_string_if_exists(&self) -> Result<String, anyhow::Error> { + fs::read_to_string(self) + .with_context(|| format!("Could not find file: {}", self)) + } + + pub fn rename(&self, to: impl AsRef<Path>) { + fs::rename(self, self.join(to)).unwrap(); + } + + pub fn write(&self, text: impl AsRef<str>) { + fs::write(self, text.as_ref()).unwrap(); + } + + pub fn symlink_dir( + &self, + oldpath: impl AsRef<Path>, + newpath: impl AsRef<Path>, + ) { + #[cfg(unix)] + { + use std::os::unix::fs::symlink; + symlink(self.as_path().join(oldpath), self.as_path().join(newpath)) + .unwrap(); + } + #[cfg(not(unix))] + { + use std::os::windows::fs::symlink_dir; + symlink_dir(self.as_path().join(oldpath), self.as_path().join(newpath)) + .unwrap(); + } + } + + pub fn symlink_file( + &self, + oldpath: impl AsRef<Path>, + newpath: impl AsRef<Path>, + ) { + #[cfg(unix)] + { + use std::os::unix::fs::symlink; + symlink(self.as_path().join(oldpath), self.as_path().join(newpath)) + .unwrap(); + } + #[cfg(not(unix))] + { + use std::os::windows::fs::symlink_file; + symlink_file(self.as_path().join(oldpath), self.as_path().join(newpath)) + .unwrap(); + } + } + + pub fn read_dir(&self) -> fs::ReadDir { + fs::read_dir(self.as_path()) + .with_context(|| format!("Reading {}", self.as_path().display())) + .unwrap() + } + + pub fn copy(&self, to: &impl AsRef<Path>) { + std::fs::copy(self.as_path(), to) + .with_context(|| format!("Copying {} to {}", self, to.as_ref().display())) + .unwrap(); + } + + /// Copies this directory to another directory. + /// + /// Note: Does not handle symlinks. + pub fn copy_to_recursive(&self, to: &PathRef) { + to.create_dir_all(); + let read_dir = self.read_dir(); + + for entry in read_dir { + let entry = entry.unwrap(); + let file_type = entry.file_type().unwrap(); + let new_from = self.join(entry.file_name()); + let new_to = to.join(entry.file_name()); + + if file_type.is_dir() { + new_from.copy_to_recursive(&new_to); + } else if file_type.is_file() { + new_from.copy(&new_to); + } + } + } + + pub fn make_dir_readonly(&self) { + self.create_dir_all(); + if cfg!(windows) { + Command::new("attrib").arg("+r").arg(self).output().unwrap(); + } else if cfg!(unix) { + Command::new("chmod").arg("555").arg(self).output().unwrap(); + } + } +} + +#[cfg(not(windows))] +#[inline] +fn strip_unc_prefix(path: PathBuf) -> PathBuf { + path +} + +/// Strips the unc prefix (ex. \\?\) from Windows paths. +/// +/// Lifted from deno_core for use in the tests. +#[cfg(windows)] +fn strip_unc_prefix(path: PathBuf) -> PathBuf { + use std::path::Component; + use std::path::Prefix; + + let mut components = path.components(); + match components.next() { + Some(Component::Prefix(prefix)) => { + match prefix.kind() { + // \\?\device + Prefix::Verbatim(device) => { + let mut path = PathBuf::new(); + path.push(format!(r"\\{}\", device.to_string_lossy())); + path.extend(components.filter(|c| !matches!(c, Component::RootDir))); + path + } + // \\?\c:\path + Prefix::VerbatimDisk(_) => { + let mut path = PathBuf::new(); + path.push(prefix.as_os_str().to_string_lossy().replace(r"\\?\", "")); + path.extend(components); + path + } + // \\?\UNC\hostname\share_name\path + Prefix::VerbatimUNC(hostname, share_name) => { + let mut path = PathBuf::new(); + path.push(format!( + r"\\{}\{}\", + hostname.to_string_lossy(), + share_name.to_string_lossy() + )); + path.extend(components.filter(|c| !matches!(c, Component::RootDir))); + path + } + _ => path, + } + } + _ => path, + } +} + +enum TempDirInner { + TempDir { + path_ref: PathRef, + // kept alive for the duration of the temp dir + _dir: tempfile::TempDir, + }, + Path(PathRef), + Symlinked { + symlink: Arc<TempDirInner>, + target: Arc<TempDirInner>, + }, +} + +impl TempDirInner { + pub fn path(&self) -> &PathRef { + match self { + Self::Path(path_ref) => path_ref, + Self::TempDir { path_ref, .. } => path_ref, + Self::Symlinked { symlink, .. } => symlink.path(), + } + } + + pub fn target_path(&self) -> &PathRef { + match self { + TempDirInner::Symlinked { target, .. } => target.target_path(), + _ => self.path(), + } + } +} + +impl Drop for TempDirInner { + fn drop(&mut self) { + if let Self::Path(path) = self { + _ = fs::remove_dir_all(path); + } + } +} + +/// For creating temporary directories in tests. +/// +/// This was done because `tempfiles::TempDir` was very slow on Windows. +/// +/// Note: Do not use this in actual code as this does not protect against +/// "insecure temporary file" security vulnerabilities. +#[derive(Clone)] +pub struct TempDir(Arc<TempDirInner>); + +impl Default for TempDir { + fn default() -> Self { + Self::new() + } +} + +impl TempDir { + pub fn new() -> Self { + Self::new_inner(&std::env::temp_dir(), None) + } + + pub fn new_with_prefix(prefix: &str) -> Self { + Self::new_inner(&std::env::temp_dir(), Some(prefix)) + } + + pub fn new_with_path(path: &Path) -> Self { + Self(Arc::new(TempDirInner::Path(PathRef(path.to_path_buf())))) + } + + pub fn new_symlinked(target: TempDir) -> Self { + let target_path = target.path(); + let path = target_path.parent().join(format!( + "{}_symlinked", + target_path.as_path().file_name().unwrap().to_str().unwrap() + )); + target.symlink_dir(target.path(), &path); + TempDir(Arc::new(TempDirInner::Symlinked { + target: target.0, + symlink: Self::new_with_path(path.as_path()).0, + })) + } + + /// Create a new temporary directory with the given prefix as part of its name, if specified. + fn new_inner(parent_dir: &Path, prefix: Option<&str>) -> Self { + let mut builder = tempfile::Builder::new(); + builder.prefix(prefix.unwrap_or("deno-cli-test")); + let dir = builder + .tempdir_in(parent_dir) + .expect("Failed to create a temporary directory"); + Self(Arc::new(TempDirInner::TempDir { + path_ref: PathRef(dir.path().to_path_buf()), + _dir: dir, + })) + } + + pub fn uri(&self) -> Url { + Url::from_directory_path(self.path()).unwrap() + } + + pub fn path(&self) -> &PathRef { + self.0.path() + } + + /// The resolved final target path if this is a symlink. + pub fn target_path(&self) -> &PathRef { + self.0.target_path() + } + + pub fn create_dir_all(&self, path: impl AsRef<Path>) { + self.target_path().join(path).create_dir_all() + } + + pub fn remove_file(&self, path: impl AsRef<Path>) { + self.target_path().join(path).remove_file() + } + + pub fn remove_dir_all(&self, path: impl AsRef<Path>) { + self.target_path().join(path).remove_dir_all() + } + + pub fn read_to_string(&self, path: impl AsRef<Path>) -> String { + self.target_path().join(path).read_to_string() + } + + pub fn rename(&self, from: impl AsRef<Path>, to: impl AsRef<Path>) { + self.target_path().join(from).rename(to) + } + + pub fn write(&self, path: impl AsRef<Path>, text: impl AsRef<str>) { + self.target_path().join(path).write(text) + } + + pub fn symlink_dir( + &self, + oldpath: impl AsRef<Path>, + newpath: impl AsRef<Path>, + ) { + self.target_path().symlink_dir(oldpath, newpath) + } + + pub fn symlink_file( + &self, + oldpath: impl AsRef<Path>, + newpath: impl AsRef<Path>, + ) { + self.target_path().symlink_file(oldpath, newpath) + } +} diff --git a/test_util/src/lib.rs b/test_util/src/lib.rs index f88092ad9..a457f25ae 100644 --- a/test_util/src/lib.rs +++ b/test_util/src/lib.rs @@ -56,16 +56,17 @@ use url::Url; pub mod assertions; mod builders; pub mod factory; +mod fs; pub mod lsp; mod npm; pub mod pty; -mod temp_dir; pub use builders::TestCommandBuilder; pub use builders::TestCommandOutput; pub use builders::TestContext; pub use builders::TestContextBuilder; -pub use temp_dir::TempDir; +pub use fs::PathRef; +pub use fs::TempDir; const PORT: u16 = 4545; const TEST_AUTH_TOKEN: &str = "abcdef123456789"; @@ -115,30 +116,31 @@ pub fn env_vars_for_npm_tests() -> Vec<(String, String)> { env_vars } -pub fn root_path() -> PathBuf { - PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"))) - .parent() - .unwrap() - .to_path_buf() +pub fn root_path() -> PathRef { + PathRef::new( + PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"))) + .parent() + .unwrap(), + ) } -pub fn prebuilt_path() -> PathBuf { +pub fn prebuilt_path() -> PathRef { third_party_path().join("prebuilt") } -pub fn tests_path() -> PathBuf { +pub fn tests_path() -> PathRef { root_path().join("cli").join("tests") } -pub fn testdata_path() -> PathBuf { +pub fn testdata_path() -> PathRef { tests_path().join("testdata") } -pub fn third_party_path() -> PathBuf { +pub fn third_party_path() -> PathRef { root_path().join("third_party") } -pub fn napi_tests_path() -> PathBuf { +pub fn napi_tests_path() -> PathRef { root_path().join("test_napi") } @@ -147,7 +149,7 @@ pub fn npm_registry_url() -> String { "http://localhost:4545/npm/registry/".to_string() } -pub fn std_path() -> PathBuf { +pub fn std_path() -> PathRef { root_path().join("test_util").join("std") } @@ -155,22 +157,22 @@ pub fn std_file_url() -> String { Url::from_directory_path(std_path()).unwrap().to_string() } -pub fn target_dir() -> PathBuf { +pub fn target_dir() -> PathRef { let current_exe = std::env::current_exe().unwrap(); let target_dir = current_exe.parent().unwrap().parent().unwrap(); - target_dir.into() + PathRef::new(target_dir) } -pub fn deno_exe_path() -> PathBuf { +pub fn deno_exe_path() -> PathRef { // Something like /Users/rld/src/deno/target/debug/deps/deno - let mut p = target_dir().join("deno"); + let mut p = target_dir().join("deno").to_path_buf(); if cfg!(windows) { p.set_extension("exe"); } - p + PathRef::new(p) } -pub fn prebuilt_tool_path(tool: &str) -> PathBuf { +pub fn prebuilt_tool_path(tool: &str) -> PathRef { let mut exe = tool.to_string(); exe.push_str(if cfg!(windows) { ".exe" } else { "" }); prebuilt_path().join(platform_dir_name()).join(exe) @@ -189,7 +191,7 @@ pub fn platform_dir_name() -> &'static str { } pub fn test_server_path() -> PathBuf { - let mut p = target_dir().join("test_server"); + let mut p = target_dir().join("test_server").to_path_buf(); if cfg!(windows) { p.set_extension("exe"); } @@ -710,8 +712,7 @@ async fn absolute_redirect( } } - let mut file_path = testdata_path(); - file_path.push(&req.uri().path()[1..]); + let file_path = testdata_path().join(&req.uri().path()[1..]); if file_path.is_dir() || !file_path.exists() { let mut not_found_resp = Response::new(Body::empty()); *not_found_resp.status_mut() = StatusCode::NOT_FOUND; @@ -1091,7 +1092,7 @@ async fn main_server( Ok(res) } _ => { - let mut file_path = testdata_path(); + let mut file_path = testdata_path().to_path_buf(); file_path.push(&req.uri().path()[1..]); if let Ok(file) = tokio::fs::read(&file_path).await { let file_resp = custom_headers(req.uri().path(), file); @@ -1138,8 +1139,7 @@ async fn main_server( } } } else if let Some(suffix) = req.uri().path().strip_prefix("/deno_std/") { - let mut file_path = std_path(); - file_path.push(suffix); + let file_path = std_path().join(suffix); if let Ok(file) = tokio::fs::read(&file_path).await { let file_resp = custom_headers(req.uri().path(), file); return Ok(file_resp); @@ -2385,37 +2385,6 @@ pub fn parse_max_mem(output: &str) -> Option<u64> { None } -/// Copies a directory to another directory. -/// -/// Note: Does not handle symlinks. -pub fn copy_dir_recursive(from: &Path, to: &Path) -> Result<(), anyhow::Error> { - use anyhow::Context; - - std::fs::create_dir_all(to) - .with_context(|| format!("Creating {}", to.display()))?; - let read_dir = std::fs::read_dir(from) - .with_context(|| format!("Reading {}", from.display()))?; - - for entry in read_dir { - let entry = entry?; - let file_type = entry.file_type()?; - let new_from = from.join(entry.file_name()); - let new_to = to.join(entry.file_name()); - - if file_type.is_dir() { - copy_dir_recursive(&new_from, &new_to).with_context(|| { - format!("Dir {} to {}", new_from.display(), new_to.display()) - })?; - } else if file_type.is_file() { - std::fs::copy(&new_from, &new_to).with_context(|| { - format!("Copying {} to {}", new_from.display(), new_to.display()) - })?; - } - } - - Ok(()) -} - #[cfg(test)] mod tests { use super::*; diff --git a/test_util/src/lsp.rs b/test_util/src/lsp.rs index 87dfaf6f9..462779b3a 100644 --- a/test_util/src/lsp.rs +++ b/test_util/src/lsp.rs @@ -2,6 +2,7 @@ use crate::deno_exe_path; use crate::npm_registry_url; +use crate::PathRef; use crate::TestContext; use crate::TestContextBuilder; @@ -38,7 +39,6 @@ use std::collections::HashSet; use std::io; use std::io::Write; use std::path::Path; -use std::path::PathBuf; use std::process::Child; use std::process::ChildStdin; use std::process::ChildStdout; @@ -468,7 +468,7 @@ impl InitializeParamsBuilder { pub struct LspClientBuilder { print_stderr: bool, - deno_exe: PathBuf, + deno_exe: PathRef, context: Option<TestContext>, use_diagnostic_sync: bool, } @@ -485,7 +485,7 @@ impl LspClientBuilder { } pub fn deno_exe(&mut self, exe_path: impl AsRef<Path>) -> &mut Self { - self.deno_exe = exe_path.as_ref().to_path_buf(); + self.deno_exe = PathRef::new(exe_path); self } diff --git a/test_util/src/npm.rs b/test_util/src/npm.rs index 18949ad44..98308ae21 100644 --- a/test_util/src/npm.rs +++ b/test_util/src/npm.rs @@ -93,10 +93,7 @@ fn get_npm_package(package_name: &str) -> Result<Option<CustomNpmPackage>> { builder .append_dir_all("package", &version_folder) .with_context(|| { - format!( - "Error adding tarball for directory: {}", - version_folder.display() - ) + format!("Error adding tarball for directory: {}", version_folder) })?; builder.finish()?; } @@ -128,10 +125,7 @@ fn get_npm_package(package_name: &str) -> Result<Option<CustomNpmPackage>> { let package_json_path = version_folder.join("package.json"); let package_json_text = fs::read_to_string(&package_json_path) .with_context(|| { - format!( - "Error reading package.json at {}", - package_json_path.display() - ) + format!("Error reading package.json at {}", package_json_path) })?; let mut version_info: serde_json::Map<String, serde_json::Value> = serde_json::from_str(&package_json_text)?; diff --git a/test_util/src/temp_dir.rs b/test_util/src/temp_dir.rs deleted file mode 100644 index 4ec6eb9f8..000000000 --- a/test_util/src/temp_dir.rs +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. - -use std::fs; -use std::path::Path; -use std::path::PathBuf; -use std::sync::Arc; - -use anyhow::Context; -use lsp_types::Url; - -enum TempDirInner { - TempDir(tempfile::TempDir), - Path(PathBuf), - Symlinked { - symlink: Arc<TempDirInner>, - target: Arc<TempDirInner>, - }, -} - -impl TempDirInner { - pub fn path(&self) -> &Path { - match self { - Self::Path(path) => path.as_path(), - Self::TempDir(dir) => dir.path(), - Self::Symlinked { symlink, .. } => symlink.path(), - } - } - - pub fn target_path(&self) -> &Path { - match self { - TempDirInner::Symlinked { target, .. } => target.target_path(), - _ => self.path(), - } - } -} - -impl Drop for TempDirInner { - fn drop(&mut self) { - if let Self::Path(path) = self { - _ = fs::remove_dir_all(path); - } - } -} - -/// For creating temporary directories in tests. -/// -/// This was done because `tempfiles::TempDir` was very slow on Windows. -/// -/// Note: Do not use this in actual code as this does not protect against -/// "insecure temporary file" security vulnerabilities. -#[derive(Clone)] -pub struct TempDir(Arc<TempDirInner>); - -impl Default for TempDir { - fn default() -> Self { - Self::new() - } -} - -impl TempDir { - pub fn new() -> Self { - Self::new_inner(&std::env::temp_dir(), None) - } - - pub fn new_in(path: &Path) -> Self { - Self::new_inner(path, None) - } - - pub fn new_with_prefix(prefix: &str) -> Self { - Self::new_inner(&std::env::temp_dir(), Some(prefix)) - } - - pub fn new_with_path(path: &Path) -> Self { - Self(Arc::new(TempDirInner::Path(path.to_path_buf()))) - } - - pub fn new_symlinked(target: TempDir) -> Self { - let target_path = target.path(); - let path = target_path.parent().unwrap().join(format!( - "{}_symlinked", - target_path.file_name().unwrap().to_str().unwrap() - )); - target.symlink_dir(target.path(), &path); - TempDir(Arc::new(TempDirInner::Symlinked { - target: target.0, - symlink: Self::new_with_path(&path).0, - })) - } - - /// Create a new temporary directory with the given prefix as part of its name, if specified. - fn new_inner(parent_dir: &Path, prefix: Option<&str>) -> Self { - let mut builder = tempfile::Builder::new(); - builder.prefix(prefix.unwrap_or("deno-cli-test")); - let dir = builder - .tempdir_in(parent_dir) - .expect("Failed to create a temporary directory"); - Self(Arc::new(TempDirInner::TempDir(dir))) - } - - pub fn uri(&self) -> Url { - Url::from_directory_path(self.path()).unwrap() - } - - pub fn path(&self) -> &Path { - self.0.path() - } - - /// The resolved final target path if this is a symlink. - pub fn target_path(&self) -> &Path { - self.0.target_path() - } - - pub fn create_dir_all(&self, path: impl AsRef<Path>) { - fs::create_dir_all(self.target_path().join(path)).unwrap(); - } - - pub fn remove_file(&self, path: impl AsRef<Path>) { - fs::remove_file(self.target_path().join(path)).unwrap(); - } - - pub fn remove_dir_all(&self, path: impl AsRef<Path>) { - fs::remove_dir_all(self.target_path().join(path)).unwrap(); - } - - pub fn read_to_string(&self, path: impl AsRef<Path>) -> String { - let file_path = self.target_path().join(path); - fs::read_to_string(&file_path) - .with_context(|| format!("Could not find file: {}", file_path.display())) - .unwrap() - } - - pub fn rename(&self, from: impl AsRef<Path>, to: impl AsRef<Path>) { - fs::rename(self.target_path().join(from), self.path().join(to)).unwrap(); - } - - pub fn write(&self, path: impl AsRef<Path>, text: impl AsRef<str>) { - fs::write(self.target_path().join(path), text.as_ref()).unwrap(); - } - - pub fn symlink_dir( - &self, - oldpath: impl AsRef<Path>, - newpath: impl AsRef<Path>, - ) { - #[cfg(unix)] - { - use std::os::unix::fs::symlink; - symlink(self.path().join(oldpath), self.path().join(newpath)).unwrap(); - } - #[cfg(not(unix))] - { - use std::os::windows::fs::symlink_dir; - symlink_dir(self.path().join(oldpath), self.path().join(newpath)) - .unwrap(); - } - } - - pub fn symlink_file( - &self, - oldpath: impl AsRef<Path>, - newpath: impl AsRef<Path>, - ) { - #[cfg(unix)] - { - use std::os::unix::fs::symlink; - symlink(self.path().join(oldpath), self.path().join(newpath)).unwrap(); - } - #[cfg(not(unix))] - { - use std::os::windows::fs::symlink_file; - symlink_file(self.path().join(oldpath), self.path().join(newpath)) - .unwrap(); - } - } -} |