-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Expand file tree
/
Copy pathserve_pipe_test.go
More file actions
85 lines (65 loc) · 2.2 KB
/
Copy pathserve_pipe_test.go
File metadata and controls
85 lines (65 loc) · 2.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//go:build !windows
package cli
import (
"encoding/json"
"os"
"path/filepath"
"syscall"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// TestServeLoop_RequestPipe validates the fifo transport used by fish: the
// daemon opens the fifo O_RDWR (so it never sees EOF between writers) and
// clients do open-write-close per request.
func TestServeLoop_RequestPipe(t *testing.T) {
t.Setenv("OMP_CACHE_DIR", t.TempDir())
pwd := t.TempDir()
chdirBackToWD(t)
fifoPath := filepath.Join(t.TempDir(), "omp-serve-test.req")
require.NoError(t, syscall.Mkfifo(fifoPath, 0o600))
in, err := openServeInput(fifoPath)
require.NoError(t, err, "O_RDWR open of a fifo must not fail or block without a writer")
stdoutR, stdoutW, err := os.Pipe()
require.NoError(t, err)
reader := newRecordReader(stdoutR)
done := make(chan struct{})
go func() {
defer close(done)
runServeLoop(in, stdoutW)
}()
t.Cleanup(func() {
_ = in.Close()
_ = stdoutW.Close()
_ = stdoutR.Close()
})
writeRequest := func(v any) {
// open-write-close per request, exactly like fish's `echo $json > fifo`
f, err := os.OpenFile(fifoPath, os.O_WRONLY, 0)
require.NoError(t, err)
data, err := json.Marshal(v)
require.NoError(t, err)
data = append(data, '\n', 0) // trailing 0: empty env blob, just the terminator
_, err = f.Write(data)
require.NoError(t, err)
require.NoError(t, f.Close())
}
writeRequest(map[string]any{"command": "render", "id": 1, "shell": "fish", "pwd": pwd})
records := reader.collect(500 * time.Millisecond)
require.NotEmpty(t, records, "render request over the fifo must produce records")
for _, rec := range records {
assert.Equal(t, "1", rec.id)
}
// A second open-write-close must reach the daemon too: its own O_RDWR
// handle prevents EOF between writers.
writeRequest(map[string]any{"command": "render", "id": 2, "shell": "fish", "pwd": pwd})
records = reader.collect(500 * time.Millisecond)
require.NotEmpty(t, records, "second fifo writer must still reach the daemon")
writeRequest(map[string]any{"command": "quit"})
select {
case <-done:
case <-time.After(2 * time.Second):
t.Fatal("serve loop did not exit after quit over the fifo")
}
}