返回 DeepSeek-Reasonix
clipboard_wsl_process_test.go
根目录 / internal / cli / clipboard_wsl_process_test.go
1 package cli
2
3 import (
4 "context"
5 "errors"
6 "os"
7 "path/filepath"
8 "runtime"
9 "strings"
10 "testing"
11 "time"
12 )
13
14 func TestWSLClipboardPreservesLinuxBackends(t *testing.T) {
15 for _, tc := range []struct {
16 name string
17 wayland string
18 programs []string
19 want string
20 args string
21 }{
22 {"wayland", "wayland-0", []string{"wl-copy", "xclip", "xsel"}, "wl-copy", ""},
23 {"xclip", "", []string{"xclip", "xsel"}, "xclip", "-in -selection clipboard"},
24 {"prefer Linux to Windows", "", []string{"xclip", "powershell.exe"}, "xclip", "-in -selection clipboard"},
25 {"xsel", "", []string{"xsel"}, "xsel", "--input --clipboard"},
26 {"missing wayland utility", "wayland-0", []string{"xclip"}, "xclip", "-in -selection clipboard"},
27 {"no wayland session", "", []string{"wl-copy", "xclip"}, "xclip", "-in -selection clipboard"},
28 } {
29 t.Run(tc.name, func(t *testing.T) {
30 dir := setupWSLClipboardProcessTest(t)
31 t.Setenv("WAYLAND_DISPLAY", tc.wayland)
32 for _, name := range tc.programs {
33 installWSLClipboardFixture(t, dir, name, "printf '%s' '"+name+"' > \"$CLIPBOARD_TEST_BACKEND\"\nprintf '%s' \"$*\" > \"$CLIPBOARD_TEST_ARGS\"\n/bin/cat > \"$CLIPBOARD_TEST_TEXT\"\n")
34 }
35 text := "中文\n你好 🚀\r\n'\"; $(not-a-command)\n"
36 if err := writeWSLClipboardText(text); err != nil {
37 t.Fatalf("copy with a working Linux backend but no PowerShell: %v", err)
38 }
39 assertWSLClipboardFile(t, "CLIPBOARD_TEST_TEXT", text)
40 assertWSLClipboardFile(t, "CLIPBOARD_TEST_BACKEND", tc.want)
41 assertWSLClipboardFile(t, "CLIPBOARD_TEST_ARGS", tc.args)
42 })
43 }
44 }
45
46 func TestWSLClipboardBridgeProcess(t *testing.T) {
47 for _, fail := range []bool{false, true} {
48 t.Run(map[bool]string{false: "success", true: "failure"}[fail], func(t *testing.T) {
49 dir := setupWSLClipboardProcessTest(t)
50 script := "/bin/cat > \"$CLIPBOARD_TEST_TEXT\"\n"
51 installWSLClipboardFixture(t, dir, "clip.exe", "exit 99\n")
52 if fail {
53 script += "echo clipboard-unavailable >&2\nexit 7\n"
54 }
55 installWSLClipboardFixture(t, dir, "powershell.exe", script)
56 text := "中文\n你好 🚀\r\n'\"; $(not-a-command)\n"
57 err := writeWSLClipboardText(text)
58 if fail {
59 if err == nil || !strings.Contains(err.Error(), "clipboard-unavailable") {
60 t.Fatalf("expected command failure with stderr, got %v", err)
61 }
62 } else if err != nil {
63 t.Fatal(err)
64 }
65 assertWSLClipboardFile(t, "CLIPBOARD_TEST_TEXT", text)
66 })
67 }
68 }
69
70 func TestWSLClipboardCommandCancellation(t *testing.T) {
71 dir := setupWSLClipboardProcessTest(t)
72 installWSLClipboardFixture(t, dir, "powershell.exe", "echo ready >&2\nexec /bin/sleep 60\n")
73 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
74 defer cancel()
75 cmd := newWSLClipboardCommand(ctx, "中文")
76 // Cancel only after the child is running, without relying on startup timing.
77 cmd.Stderr = clipboardCancelWriter{cancel: cancel}
78 if err := cmd.Run(); err == nil {
79 t.Fatal("a canceled clipboard command succeeded")
80 }
81 if !errors.Is(ctx.Err(), context.Canceled) {
82 t.Fatalf("command did not respond to cancellation: %v", ctx.Err())
83 }
84 if cmd.ProcessState == nil {
85 t.Fatal("canceled clipboard child was not reaped")
86 }
87 }
88
89 type clipboardCancelWriter struct{ cancel context.CancelFunc }
90
91 func (w clipboardCancelWriter) Write(p []byte) (int, error) {
92 w.cancel()
93 return len(p), nil
94 }
95
96 func setupWSLClipboardProcessTest(t *testing.T) string {
97 t.Helper()
98 if runtime.GOOS == "windows" {
99 t.Skip("WSL command execution uses POSIX executable fixtures")
100 }
101 dir := t.TempDir()
102 t.Setenv("PATH", dir)
103 t.Setenv("WAYLAND_DISPLAY", "")
104 for _, key := range []string{"CLIPBOARD_TEST_TEXT", "CLIPBOARD_TEST_BACKEND", "CLIPBOARD_TEST_ARGS"} {
105 t.Setenv(key, filepath.Join(dir, key))
106 }
107 return dir
108 }
109
110 func installWSLClipboardFixture(t *testing.T, dir, name, script string) {
111 t.Helper()
112 if err := os.WriteFile(filepath.Join(dir, name), []byte("#!/bin/sh\n"+script), 0700); err != nil {
113 t.Fatal(err)
114 }
115 }
116
117 func assertWSLClipboardFile(t *testing.T, key, want string) {
118 t.Helper()
119 got, err := os.ReadFile(os.Getenv(key))
120 if err != nil || string(got) != want {
121 t.Fatalf("%s = %q, %v; want %q", key, got, err, want)
122 }
123 }
124
124 lines GO