Canonicalize paths when running tests (#23655)

张小白 created

In the Windows test environment, the paths generated by `temp_tree()`
are symlink paths, which causes certain tests to fail.

I later noticed that when opening a project, we seem to always use
`canonicalize` to normalize the paths, as shown here:
https://github.com/zed-industries/zed/pull/21039.

This PR adopts a similar approach for the test environment to address
the issue.

Release Notes:

- N/A

Change summary

crates/extension_host/src/extension_store_test.rs |  6 +-
crates/project/src/project_tests.rs               |  8 ++--
crates/util/src/test.rs                           | 24 ++++++++++--
crates/worktree/src/worktree_tests.rs             | 32 ++++++++--------
4 files changed, 43 insertions(+), 27 deletions(-)

Detailed changes

crates/extension_host/src/extension_store_test.rs 🔗

@@ -25,7 +25,7 @@ use std::{
     sync::Arc,
 };
 use theme::ThemeRegistry;
-use util::test::temp_tree;
+use util::test::TempTree;
 
 #[cfg(test)]
 #[ctor::ctor]
@@ -470,11 +470,11 @@ async fn test_extension_store_with_test_extension(cx: &mut TestAppContext) {
     let test_extension_dir = root_dir.join("extensions").join(test_extension_id);
 
     let fs = Arc::new(RealFs::default());
-    let extensions_dir = temp_tree(json!({
+    let extensions_dir = TempTree::new(json!({
         "installed": {},
         "work": {}
     }));
-    let project_dir = temp_tree(json!({
+    let project_dir = TempTree::new(json!({
         "test.gleam": ""
     }));
 

crates/project/src/project_tests.rs 🔗

@@ -27,7 +27,7 @@ use unindent::Unindent as _;
 use util::{
     assert_set_eq,
     paths::{replace_path_separator, PathMatcher},
-    test::temp_tree,
+    test::TempTree,
     TryFutureExt as _,
 };
 
@@ -67,7 +67,7 @@ async fn test_symlinks(cx: &mut gpui::TestAppContext) {
     init_test(cx);
     cx.executor().allow_parking();
 
-    let dir = temp_tree(json!({
+    let dir = TempTree::new(json!({
         "root": {
             "apple": "",
             "banana": {
@@ -106,7 +106,7 @@ async fn test_symlinks(cx: &mut gpui::TestAppContext) {
 async fn test_editorconfig_support(cx: &mut gpui::TestAppContext) {
     init_test(cx);
 
-    let dir = temp_tree(json!({
+    let dir = TempTree::new(json!({
         ".editorconfig": r#"
         root = true
         [*.rs]
@@ -3187,7 +3187,7 @@ async fn test_rescan_and_remote_updates(cx: &mut gpui::TestAppContext) {
     init_test(cx);
     cx.executor().allow_parking();
 
-    let dir = temp_tree(json!({
+    let dir = TempTree::new(json!({
         "a": {
             "file1": "",
             "file2": "",

crates/util/src/test.rs 🔗

@@ -11,10 +11,26 @@ use tempfile::TempDir;
 pub use assertions::*;
 pub use marked_text::*;
 
-pub fn temp_tree(tree: serde_json::Value) -> TempDir {
-    let dir = TempDir::new().unwrap();
-    write_tree(dir.path(), tree);
-    dir
+pub struct TempTree {
+    _temp_dir: TempDir,
+    path: PathBuf,
+}
+
+impl TempTree {
+    pub fn new(tree: serde_json::Value) -> Self {
+        let dir = TempDir::new().unwrap();
+        let path = std::fs::canonicalize(dir.path()).unwrap();
+        write_tree(path.as_path(), tree);
+
+        Self {
+            _temp_dir: dir,
+            path,
+        }
+    }
+
+    pub fn path(&self) -> &Path {
+        self.path.as_path()
+    }
 }
 
 fn write_tree(path: &Path, tree: serde_json::Value) {

crates/worktree/src/worktree_tests.rs 🔗

@@ -25,7 +25,7 @@ use std::{
     path::{Path, PathBuf},
     sync::Arc,
 };
-use util::{test::temp_tree, ResultExt};
+use util::{test::TempTree, ResultExt};
 
 #[gpui::test]
 async fn test_traversal(cx: &mut TestAppContext) {
@@ -352,7 +352,7 @@ async fn test_renaming_case_only(cx: &mut TestAppContext) {
     const NEW_NAME: &str = "AAA.rs";
 
     let fs = Arc::new(RealFs::default());
-    let temp_root = temp_tree(json!({
+    let temp_root = TempTree::new(json!({
         OLD_NAME: "",
     }));
 
@@ -846,7 +846,7 @@ async fn test_update_gitignore(cx: &mut TestAppContext) {
 async fn test_write_file(cx: &mut TestAppContext) {
     init_test(cx);
     cx.executor().allow_parking();
-    let dir = temp_tree(json!({
+    let dir = TempTree::new(json!({
         ".git": {},
         ".gitignore": "ignored-dir\n",
         "tracked-dir": {},
@@ -903,7 +903,7 @@ async fn test_write_file(cx: &mut TestAppContext) {
 async fn test_file_scan_inclusions(cx: &mut TestAppContext) {
     init_test(cx);
     cx.executor().allow_parking();
-    let dir = temp_tree(json!({
+    let dir = TempTree::new(json!({
         ".gitignore": "**/target\n/node_modules\ntop_level.txt\n",
         "target": {
             "index": "blah2"
@@ -973,7 +973,7 @@ async fn test_file_scan_inclusions(cx: &mut TestAppContext) {
 async fn test_file_scan_exclusions_overrules_inclusions(cx: &mut TestAppContext) {
     init_test(cx);
     cx.executor().allow_parking();
-    let dir = temp_tree(json!({
+    let dir = TempTree::new(json!({
         ".gitignore": "**/target\n/node_modules\n",
         "target": {
             "index": "blah2"
@@ -1031,7 +1031,7 @@ async fn test_file_scan_exclusions_overrules_inclusions(cx: &mut TestAppContext)
 async fn test_file_scan_inclusions_reindexes_on_setting_change(cx: &mut TestAppContext) {
     init_test(cx);
     cx.executor().allow_parking();
-    let dir = temp_tree(json!({
+    let dir = TempTree::new(json!({
         ".gitignore": "**/target\n/node_modules/\n",
         "target": {
             "index": "blah2"
@@ -1108,7 +1108,7 @@ async fn test_file_scan_inclusions_reindexes_on_setting_change(cx: &mut TestAppC
 async fn test_file_scan_exclusions(cx: &mut TestAppContext) {
     init_test(cx);
     cx.executor().allow_parking();
-    let dir = temp_tree(json!({
+    let dir = TempTree::new(json!({
         ".gitignore": "**/target\n/node_modules\n",
         "target": {
             "index": "blah2"
@@ -1206,7 +1206,7 @@ async fn test_file_scan_exclusions(cx: &mut TestAppContext) {
 async fn test_fs_events_in_exclusions(cx: &mut TestAppContext) {
     init_test(cx);
     cx.executor().allow_parking();
-    let dir = temp_tree(json!({
+    let dir = TempTree::new(json!({
         ".git": {
             "HEAD": "ref: refs/heads/main\n",
             "foo": "bar",
@@ -1349,7 +1349,7 @@ async fn test_fs_events_in_exclusions(cx: &mut TestAppContext) {
 async fn test_fs_events_in_dot_git_worktree(cx: &mut TestAppContext) {
     init_test(cx);
     cx.executor().allow_parking();
-    let dir = temp_tree(json!({
+    let dir = TempTree::new(json!({
         ".git": {
             "HEAD": "ref: refs/heads/main\n",
             "foo": "foo contents",
@@ -1562,7 +1562,7 @@ async fn test_create_dir_all_on_create_entry(cx: &mut TestAppContext) {
     });
 
     let fs_real = Arc::new(RealFs::default());
-    let temp_root = temp_tree(json!({
+    let temp_root = TempTree::new(json!({
         "a": {}
     }));
 
@@ -2160,7 +2160,7 @@ const CONFLICT: FileStatus = FileStatus::Unmerged(UnmergedStatus {
 async fn test_rename_work_directory(cx: &mut TestAppContext) {
     init_test(cx);
     cx.executor().allow_parking();
-    let root = temp_tree(json!({
+    let root = TempTree::new(json!({
         "projects": {
             "project1": {
                 "a": "",
@@ -2231,7 +2231,7 @@ async fn test_rename_work_directory(cx: &mut TestAppContext) {
 async fn test_git_repository_for_path(cx: &mut TestAppContext) {
     init_test(cx);
     cx.executor().allow_parking();
-    let root = temp_tree(json!({
+    let root = TempTree::new(json!({
         "c.txt": "",
         "dir1": {
             ".git": {},
@@ -2341,7 +2341,7 @@ async fn test_file_status(cx: &mut TestAppContext) {
     cx.executor().allow_parking();
     const IGNORE_RULE: &str = "**/target";
 
-    let root = temp_tree(json!({
+    let root = TempTree::new(json!({
         "project": {
             "a.txt": "a",
             "b.txt": "bb",
@@ -2530,7 +2530,7 @@ async fn test_git_repository_status(cx: &mut TestAppContext) {
     init_test(cx);
     cx.executor().allow_parking();
 
-    let root = temp_tree(json!({
+    let root = TempTree::new(json!({
         "project": {
             "a.txt": "a",    // Modified
             "b.txt": "bb",   // Added
@@ -2644,7 +2644,7 @@ async fn test_git_status_postprocessing(cx: &mut TestAppContext) {
     init_test(cx);
     cx.executor().allow_parking();
 
-    let root = temp_tree(json!({
+    let root = TempTree::new(json!({
         "project": {
             "sub": {},
             "a.txt": "",
@@ -2700,7 +2700,7 @@ async fn test_repository_subfolder_git_status(cx: &mut TestAppContext) {
     init_test(cx);
     cx.executor().allow_parking();
 
-    let root = temp_tree(json!({
+    let root = TempTree::new(json!({
         "my-repo": {
             // .git folder will go here
             "a.txt": "a",