返回 DeepSeek-Reasonix
shell_launch_test.go
根目录 / internal / sandbox / shell_launch_test.go
1 package sandbox
2
3 import (
4 "context"
5 "os"
6 "path/filepath"
7 "slices"
8 "testing"
9
10 "reasonix/internal/secrets"
11 )
12
13 func TestWindowsPowerShellCandidatesIncludeStoreAlias(t *testing.T) {
14 t.Setenv("ProgramFiles", `C:\PF`)
15 t.Setenv("ProgramW6432", "")
16 t.Setenv("ProgramFiles(x86)", "")
17 t.Setenv("LOCALAPPDATA", `C:\LAD`)
18 t.Setenv("SystemRoot", `C:\WIN`)
19 got := windowsPowerShellCandidates()
20 want := []string{
21 filepath.Join(`C:\PF`, "PowerShell", "7", "pwsh.exe"),
22 filepath.Join(`C:\LAD`, "Microsoft", "WindowsApps", "pwsh.exe"),
23 filepath.Join(`C:\WIN`, "System32", "WindowsPowerShell", "v1.0", "powershell.exe"),
24 }
25 if !slices.Equal(got, want) {
26 t.Fatalf("candidates = %q, want %q", got, want)
27 }
28 }
29
30 // A Store pwsh that is found but cannot start must not win auto-detection: the
31 // next interpreter that does start is selected instead.
32 func TestAutoSkipsPowerShellThatDoesNotLaunch(t *testing.T) {
33 alias := `C:\fake\WindowsApps\pwsh.exe`
34 winPS := []string{alias, `C:\fake\System32\powershell.exe`}
35 launches := func(p string) bool { return p != alias && p != `C:\fake\pwsh.exe` }
36 yes := func(string) bool { return true }
37 no := func(string) bool { return false }
38
39 lookPath := launchablePowerShellLookPath(fakeLookPath(map[string]string{"pwsh": `C:\fake\pwsh.exe`, "powershell": `C:\fake\powershell.exe`}), launches)
40 got := resolveShell("", "", nil, "windows", lookPath, yes, nil, launchablePowerShells(winPS, launches), no, no)
41 if got.Kind != ShellPowerShell || got.Path != `C:\fake\System32\powershell.exe` {
42 t.Fatalf("auto = %+v, want Windows PowerShell 5.1", got)
43 }
44
45 launches = func(string) bool { return true }
46 lookPath = launchablePowerShellLookPath(fakeLookPath(map[string]string{"pwsh": `C:\fake\pwsh.exe`, "powershell": `C:\fake\powershell.exe`}), launches)
47 got = resolveShell("", "", nil, "windows", lookPath, yes, nil, launchablePowerShells(winPS, launches), no, no)
48 if got.Path != alias {
49 t.Fatalf("auto = %+v, want the Store pwsh when it launches", got)
50 }
51 }
52
53 func TestLaunchablePowerShellLookPathLeavesOtherNamesAlone(t *testing.T) {
54 lookPath := launchablePowerShellLookPath(fakeLookPath(map[string]string{"bash": `C:\fake\bash.exe`, "pwsh": `C:\fake\pwsh.exe`}), func(string) bool { return false })
55 if p, err := lookPath("bash"); err != nil || p != `C:\fake\bash.exe` {
56 t.Fatalf("bash = %q, %v", p, err)
57 }
58 if _, err := lookPath("pwsh"); err == nil {
59 t.Fatal("pwsh that cannot launch was still found")
60 }
61 }
62
63 // Only an execution alias pays a launch; a regular executable is taken as found.
64 func TestPowerShellLaunchesProbesOnlyAliases(t *testing.T) {
65 probed := 0
66 saved := aliasLaunches
67 aliasLaunches = &launchProbes{seen: map[string]launchProbe{}, run: func(string) bool { probed++; return false }}
68 t.Cleanup(func() { aliasLaunches = saved })
69
70 regular := filepath.Join(t.TempDir(), "pwsh.exe")
71 if err := os.WriteFile(regular, []byte("MZ"), 0o755); err != nil {
72 t.Fatal(err)
73 }
74 if !powerShellLaunches(regular) || probed != 0 {
75 t.Fatalf("regular file: launches=%v probes=%d, want true without a probe", powerShellLaunches(regular), probed)
76 }
77 }
78
79 func TestLaunchProbesAnswerRepeatedDiscoveryOnce(t *testing.T) {
80 runs := 0
81 l := &launchProbes{seen: map[string]launchProbe{}, run: func(string) bool { runs++; return true }}
82 for range 3 {
83 if !l.check(`C:\Users\u\AppData\Local\Microsoft\WindowsApps\pwsh.exe`) {
84 t.Fatal("probe answer lost")
85 }
86 }
87 if runs != 1 {
88 t.Fatalf("probe ran %d times, want 1", runs)
89 }
90 }
91
92 func TestPowerShellProbeRunsNothingOfTheUsers(t *testing.T) {
93 cmd := powerShellProbeCommand(context.Background(), `C:\x\pwsh.exe`)
94 if want := []string{`C:\x\pwsh.exe`, "-NoLogo", "-NoProfile", "-NonInteractive", "-Command", "exit 0"}; !slices.Equal(cmd.Args, want) {
95 t.Fatalf("args = %q", cmd.Args)
96 }
97 if !slices.Equal(cmd.Env, secrets.ProcessEnv()) || cmd.Dir != os.TempDir() {
98 t.Fatalf("env/dir not scrubbed: dir=%q", cmd.Dir)
99 }
100 }
101
101 lines GO