detached 3f44aac

test(pty): synchronize darwin resize assertion

commit
3f44aacc7e0dd80352e4d9a6a418cc2028f465c0
author
brice · · 2026-07-16 17:57 UTC
parent
68625c9
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
1 file · +36 -1
M internal/adapters/pty/pty_darwin_test.go +36 -1
@@ -74,19 +74,54 @@ func TestOpen_DarwinEchoAndOutputEOF(t *testing.T) {
7474 require.Contains(t, output, "roundtrip")
7575 }
7676
77+func readUntilDarwin(t *testing.T, p ports.PTY, marker string, deadline time.Duration) string {
78+ t.Helper()
79+ type result struct {
80+ output string
81+ err error
82+ }
83+ resultCh := make(chan result, 1)
84+ go func() {
85+ var output strings.Builder
86+ buf := make([]byte, 256)
87+ for !strings.Contains(output.String(), marker) {
88+ n, err := p.Read(buf)
89+ output.Write(buf[:n])
90+ if err != nil {
91+ resultCh <- result{output: output.String(), err: err}
92+ return
93+ }
94+ }
95+ resultCh <- result{output: output.String()}
96+ }()
97+
98+ select {
99+ case result := <-resultCh:
100+ require.NoError(t, result.err)
101+ return result.output
102+ case <-time.After(deadline):
103+ t.Fatal("timed out waiting for pty readiness")
104+ return ""
105+ }
106+}
107+
77108 func TestOpen_DarwinResizeAndForegroundPgid(t *testing.T) {
78109 if testing.Short() {
79110 t.Skip("skipping pty integration test in -short mode")
80111 }
81112
82- p, err := pty.NewFactory().Open(context.Background(), "sh", []string{"-c", "sleep 0.2; stty size"}, os.Environ(), "", domain.Size{Cols: 80, Rows: 24})
113+ const ready = "__vev_ready__"
114+ p, err := pty.NewFactory().Open(context.Background(), "sh", []string{"-c", "stty -echo; printf '__vev_ready__\\n'; IFS= read -r release; stty size"}, os.Environ(), "", domain.Size{Cols: 80, Rows: 24})
83115 require.NoError(t, err)
84116 t.Cleanup(func() { _ = p.Close() })
85117
118+ require.Contains(t, readUntilDarwin(t, p, ready, 5*time.Second), ready)
86119 pgid, err := p.ForegroundPgid()
87120 require.NoError(t, err)
88121 require.Greater(t, pgid, 0)
89122 require.NoError(t, p.Resize(domain.Size{Cols: 120, Rows: 40}))
123+ _, err = io.WriteString(p, "release\n")
124+ require.NoError(t, err)
90125 require.Equal(t, "40 120", strings.TrimSpace(string(readAllDarwin(t, p, 5*time.Second))))
91126 }
92127
@@ -74,19 +74,54 @@ func TestOpen_DarwinEchoAndOutputEOF(t *testing.T) {
74 require.Contains(t, output, "roundtrip")74 require.Contains(t, output, "roundtrip")
75 }75 }
76 76
77+func readUntilDarwin(t *testing.T, p ports.PTY, marker string, deadline time.Duration) string {
78+ t.Helper()
79+ type result struct {
80+ output string
81+ err error
82+ }
83+ resultCh := make(chan result, 1)
84+ go func() {
85+ var output strings.Builder
86+ buf := make([]byte, 256)
87+ for !strings.Contains(output.String(), marker) {
88+ n, err := p.Read(buf)
89+ output.Write(buf[:n])
90+ if err != nil {
91+ resultCh <- result{output: output.String(), err: err}
92+ return
93+ }
94+ }
95+ resultCh <- result{output: output.String()}
96+ }()
97+
98+ select {
99+ case result := <-resultCh:
100+ require.NoError(t, result.err)
101+ return result.output
102+ case <-time.After(deadline):
103+ t.Fatal("timed out waiting for pty readiness")
104+ return ""
105+ }
106+}
107+
77 func TestOpen_DarwinResizeAndForegroundPgid(t *testing.T) {108 func TestOpen_DarwinResizeAndForegroundPgid(t *testing.T) {
78 if testing.Short() {109 if testing.Short() {
79 t.Skip("skipping pty integration test in -short mode")110 t.Skip("skipping pty integration test in -short mode")
80 }111 }
81 112
82- p, err := pty.NewFactory().Open(context.Background(), "sh", []string{"-c", "sleep 0.2; stty size"}, os.Environ(), "", domain.Size{Cols: 80, Rows: 24})113+ const ready = "__vev_ready__"
114+ p, err := pty.NewFactory().Open(context.Background(), "sh", []string{"-c", "stty -echo; printf '__vev_ready__\\n'; IFS= read -r release; stty size"}, os.Environ(), "", domain.Size{Cols: 80, Rows: 24})
83 require.NoError(t, err)115 require.NoError(t, err)
84 t.Cleanup(func() { _ = p.Close() })116 t.Cleanup(func() { _ = p.Close() })
85 117
118+ require.Contains(t, readUntilDarwin(t, p, ready, 5*time.Second), ready)
86 pgid, err := p.ForegroundPgid()119 pgid, err := p.ForegroundPgid()
87 require.NoError(t, err)120 require.NoError(t, err)
88 require.Greater(t, pgid, 0)121 require.Greater(t, pgid, 0)
89 require.NoError(t, p.Resize(domain.Size{Cols: 120, Rows: 40}))122 require.NoError(t, p.Resize(domain.Size{Cols: 120, Rows: 40}))
123+ _, err = io.WriteString(p, "release\n")
124+ require.NoError(t, err)
90 require.Equal(t, "40 120", strings.TrimSpace(string(readAllDarwin(t, p, 5*time.Second))))125 require.Equal(t, "40 120", strings.TrimSpace(string(readAllDarwin(t, p, 5*time.Second))))
91 }126 }
92 127

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close