turbo-editors/turbo-corepublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-core.git
git clone ssh://git@rickub.com/turbo-editors/turbo-core.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

root_test.go · 115 lines · 3.2 KBGo Blame HistoryRaw
🛟 Updated. 28d5985 k33g 4h ago1package app
2
3import (
4 "os"
5 "path/filepath"
6 "testing"
7
8 "codeberg.org/turbo-editors/turbo-core/profile"
9)
10
11// touch creates an empty file, making its directory first.
12func touch(t *testing.T, path string) {
13 t.Helper()
14 if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
15 t.Fatalf("creating %s: %v", filepath.Dir(path), err)
16 }
17 if err := os.WriteFile(path, nil, 0o644); err != nil {
18 t.Fatalf("writing %s: %v", path, err)
19 }
20}
21
22func TestProjectRootWalksUpToTheMarker(t *testing.T) {
23 root := t.TempDir()
24 touch(t, filepath.Join(root, "go.mod"))
25 deep := filepath.Join(root, "internal", "app", "app.go")
26 touch(t, deep)
27
28 got := ProjectRoot(profile.Profile{RootMarkers: []string{"go.mod"}}, []string{deep})
29
30 if got != root {
31 t.Errorf("ProjectRoot() = %q, want %q", got, root)
32 }
33}
34
35func TestProjectRootTakesTheFirstMarkerItMeetsGoingUp(t *testing.T) {
36 // A nested module is its own project; walking past it to the outer one
37 // would hand the language server a workspace the file is not in.
38 outer := t.TempDir()
39 touch(t, filepath.Join(outer, "Cargo.toml"))
40 inner := filepath.Join(outer, "crates", "parser")
41 touch(t, filepath.Join(inner, "Cargo.toml"))
42 file := filepath.Join(inner, "src", "lib.rs")
43 touch(t, file)
44
45 got := ProjectRoot(profile.Profile{RootMarkers: []string{"Cargo.toml"}}, []string{file})
46
47 if got != inner {
48 t.Errorf("ProjectRoot() = %q, want the nearest root %q", got, inner)
49 }
50}
51
52func TestProjectRootAcceptsAnyOfTheMarkers(t *testing.T) {
53 root := t.TempDir()
54 touch(t, filepath.Join(root, "Cargo.toml"))
55 file := filepath.Join(root, "src", "main.rs")
56 touch(t, file)
57
58 got := ProjectRoot(profile.Profile{RootMarkers: []string{"rust-toolchain.toml", "Cargo.toml"}}, []string{file})
59
60 if got != root {
61 t.Errorf("ProjectRoot() = %q, want %q", got, root)
62 }
63}
64
65func TestProjectRootFallsBackToTheFilesOwnDirectory(t *testing.T) {
66 // A file outside any project still has to give the server somewhere; the
67 // filesystem root would be absurd.
68 dir := t.TempDir()
69 file := filepath.Join(dir, "scratch.go")
70 touch(t, file)
71
72 got := ProjectRoot(profile.Profile{RootMarkers: []string{"no-such-marker-file"}}, []string{file})
73
74 if got != dir {
75 t.Errorf("ProjectRoot() = %q, want %q", got, dir)
76 }
77}
78
79func TestProjectRootWithNoFilesUsesTheWorkingDirectory(t *testing.T) {
80 dir := t.TempDir()
81 touch(t, filepath.Join(dir, "go.mod"))
82 t.Chdir(dir)
83
84 got := ProjectRoot(profile.Profile{RootMarkers: []string{"go.mod"}}, nil)
85
86 // The temporary directory may be reached through a symlink, so the
87 // comparison is on what the two resolve to.
88 if resolve(t, got) != resolve(t, dir) {
89 t.Errorf("ProjectRoot() = %q, want %q", got, dir)
90 }
91}
92
93func TestAProfileWithNoMarkersDoesNotWalk(t *testing.T) {
94 // An editor for a language with no project file at all: the directory the
95 // file is in is the best answer available.
96 dir := t.TempDir()
97 file := filepath.Join(dir, "notes.txt")
98 touch(t, file)
99
100 got := ProjectRoot(profile.Profile{}, []string{file})
101
102 if got != dir {
103 t.Errorf("ProjectRoot() = %q, want %q", got, dir)
104 }
105}
106
107// resolve follows symlinks, which is what /tmp is on some systems.
108func resolve(t *testing.T, path string) string {
109 t.Helper()
110 resolved, err := filepath.EvalSymlinks(path)
111 if err != nil {
112 return path
113 }
114 return resolved
115}