Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 77e71f3

Browse files
authored
test: Improve TestSSH/ForwardGPG stability on macOS via pty.ReadRune (#5739)
Writing to stdin for `coder ssh` too early could result in the input being discarded. To work around this we add a new `ptytest` method called `ReadRune` that lets us read one character of output. This will indicate the command is ready to accept input. It could be one character of the prompt, or of the loading message waiting for connection to be established.
1 parent db78770 commit 77e71f3

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

cli/ssh_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,10 @@ Expire-Date: 0
475475
// real error from being printed.
476476
t.Cleanup(cancel)
477477

478+
// Wait for the prompt or any output really to indicate the command has
479+
// started and accepting input on stdin.
480+
_ = pty.ReadRune(ctx)
481+
478482
pty.WriteLine("echo hello 'world'")
479483
pty.ExpectMatch("hello world")
480484

pty/ptytest/ptytest.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,47 @@ func (p *PTY) ExpectMatch(str string) string {
182182
}
183183
}
184184

185+
func (p *PTY) ReadRune(ctx context.Context) rune {
186+
p.t.Helper()
187+
188+
// A timeout is mandatory, caller can decide by passing a context
189+
// that times out.
190+
if _, ok := ctx.Deadline(); !ok {
191+
timeout := testutil.WaitMedium
192+
p.logf("ReadRune ctx has no deadline, using %s", timeout)
193+
var cancel context.CancelFunc
194+
//nolint:gocritic // Rule guard doesn't detect that we're using testutil.Wait*.
195+
ctx, cancel = context.WithTimeout(ctx, timeout)
196+
defer cancel()
197+
}
198+
199+
var r rune
200+
match := make(chan error, 1)
201+
go func() {
202+
defer close(match)
203+
var err error
204+
r, _, err = p.runeReader.ReadRune()
205+
match <- err
206+
}()
207+
208+
select {
209+
case err := <-match:
210+
if err != nil {
211+
p.fatalf("read error", "%v (wanted newline; got %q)", err, r)
212+
return 0
213+
}
214+
p.logf("matched rune = %q", r)
215+
return r
216+
case <-ctx.Done():
217+
// Ensure goroutine is cleaned up before test exit.
218+
_ = p.close("read rune context done: " + ctx.Err().Error())
219+
<-match
220+
221+
p.fatalf("read rune context done", "wanted rune; got nothing")
222+
return 0
223+
}
224+
}
225+
185226
func (p *PTY) ReadLine() string {
186227
p.t.Helper()
187228

0 commit comments

Comments
 (0)