返回 DeepSeek-Reasonix
write_roots_plan_test.go
根目录 / internal / sandbox / write_roots_plan_test.go
1 //go:build !windows
2
3 package sandbox
4
5 import (
6 "os"
7 "path/filepath"
8 "slices"
9 "testing"
10 )
11
12 // outsideHostDirs plans as if the test's temp tree were no host write
13 // directory, which it is on macOS.
14 func outsideHostDirs(t *testing.T) {
15 t.Helper()
16 prev := hostWritePins
17 hostWritePins = func() hostPins { return nil }
18 t.Cleanup(func() { hostWritePins = prev })
19 }
20
21 func planDir(t *testing.T, path string) string {
22 t.Helper()
23 if err := os.MkdirAll(path, 0o755); err != nil {
24 t.Fatal(err)
25 }
26 real, err := filepath.EvalSymlinks(path)
27 if err != nil {
28 t.Fatal(err)
29 }
30 return real
31 }
32
33 func planLink(t *testing.T, target, link string) {
34 t.Helper()
35 if err := os.Symlink(target, link); err != nil {
36 t.Fatal(err)
37 }
38 }
39
40 func TestPlanRefusesARootReachedThroughALinkInAWritableDir(t *testing.T) {
41 base := t.TempDir()
42 ws := planDir(t, filepath.Join(base, "ws"))
43 outside := planDir(t, filepath.Join(base, "outside"))
44 planDir(t, filepath.Join(outside, "b"))
45 later, nested := filepath.Join(ws, "later"), filepath.Join(ws, "a", "b")
46 planLink(t, outside, later)
47 planLink(t, outside, filepath.Join(ws, "a"))
48 plan := planWriteRoots([]string{ws, later, nested}, nil, "")
49 if !slices.Equal(plan.dirs, []string{ws}) || len(plan.refused) != 2 {
50 t.Fatalf("plan = %+v, want only the workspace", plan)
51 }
52 }
53
54 func TestPlanFollowsALinkNoConfinedCommandCanRewrite(t *testing.T) {
55 outsideHostDirs(t)
56 base := t.TempDir()
57 target := planDir(t, filepath.Join(base, "real"))
58 link := filepath.Join(base, "link")
59 planLink(t, target, link)
60 plan := planWriteRoots([]string{link}, nil, "")
61 if len(plan.refused) != 0 || !slices.Equal(plan.dirs, []string{target}) {
62 t.Fatalf("plan = %+v, want the link's target", plan)
63 }
64 }
65
66 func TestPlanARootRepointedAtTheRootDirectoryRefusesNoOther(t *testing.T) {
67 outsideHostDirs(t)
68 base := t.TempDir()
69 ws := planDir(t, filepath.Join(base, "ws"))
70 target := planDir(t, filepath.Join(base, "real"))
71 link := filepath.Join(base, "link")
72 planLink(t, target, link)
73 later := filepath.Join(ws, "later")
74 planLink(t, "/", later)
75 plan := planWriteRoots([]string{ws, later, link}, nil, "")
76 if !slices.Equal(plan.dirs, []string{ws, target}) || len(plan.refused) != 1 {
77 t.Fatalf("plan = %+v, want only the re-pointed root refused", plan)
78 }
79 }
80
81 // A host cache's own entry is inside the grant it names, so a confined command
82 // can move it aside and leave a link there; the pinned identity refuses it.
83 func TestPlanRefusesAHostDirectoryWhoseOwnEntryBecameALink(t *testing.T) {
84 base := t.TempDir()
85 ws := planDir(t, filepath.Join(base, "ws"))
86 cache := planDir(t, filepath.Join(base, "home", ".cache"))
87 gopath := planDir(t, filepath.Join(base, "home", "go"))
88 agents := planDir(t, filepath.Join(base, "home", "Library", "LaunchAgents"))
89 prev := hostWritePins
90 pins := hostPins{}
91 for _, d := range []string{cache, gopath} {
92 info, _ := os.Stat(d)
93 pins[d] = hostIdentity{path: d, info: info}
94 }
95 hostWritePins = func() hostPins { return pins }
96 t.Cleanup(func() { hostWritePins = prev })
97 if err := os.Rename(gopath, filepath.Join(cache, "stash")); err != nil {
98 t.Fatal(err)
99 }
100 planLink(t, agents, gopath)
101 plan := planWriteRoots([]string{ws}, []string{cache, gopath}, "")
102 if slices.Contains(plan.dirs, agents) || len(plan.refused) != 1 {
103 t.Fatalf("plan = %+v, want the re-pointed cache refused", plan)
104 }
105 }
106
107 func TestHostWriteDirectoriesPinOnlyTheirPath(t *testing.T) {
108 for key, id := range pinHostWriteDirs() {
109 if id.info != nil {
110 t.Fatalf("%s pins a file identity; a cache rebuilt in place would be refused", key)
111 }
112 }
113 }
114
114 lines GO