mirror of
https://github.com/coder/coder.git
synced 2025-07-12 00:14:10 +00:00
It looks like it is possible for screen to use control sequences instead of literal newlines which fails the tests. This reuses the existing readUntil function used in other pty tests.
71 lines
1.8 KiB
Go
71 lines
1.8 KiB
Go
package testutil
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/hinshun/vt10x"
|
|
)
|
|
|
|
// ReadUntilString emulates a terminal and reads one byte at a time until we
|
|
// either see the string we want, or the context expires. The PTY must be sized
|
|
// to 80x80 or there could be unexpected results.
|
|
func ReadUntilString(ctx context.Context, t *testing.T, want string, r io.Reader) error {
|
|
return ReadUntil(ctx, t, r, func(line string) bool {
|
|
return strings.TrimSpace(line) == want
|
|
})
|
|
}
|
|
|
|
// ReadUntil emulates a terminal and reads one byte at a time until the matcher
|
|
// returns true or the context expires. If the matcher is nil, read until EOF.
|
|
// The PTY must be sized to 80x80 or there could be unexpected results.
|
|
func ReadUntil(ctx context.Context, t *testing.T, r io.Reader, matcher func(line string) bool) error {
|
|
// output can contain virtual terminal sequences, so we need to parse these
|
|
// to correctly interpret getting what we want.
|
|
term := vt10x.New(vt10x.WithSize(80, 80))
|
|
readErrs := make(chan error, 1)
|
|
defer func() {
|
|
// Dump the terminal contents since they can be helpful for debugging, but
|
|
// skip empty lines since much of the terminal will usually be blank.
|
|
got := term.String()
|
|
lines := strings.Split(got, "\n")
|
|
for _, line := range lines {
|
|
if strings.TrimSpace(line) != "" {
|
|
t.Logf("got: %v", line)
|
|
}
|
|
}
|
|
}()
|
|
for {
|
|
b := make([]byte, 1)
|
|
go func() {
|
|
_, err := r.Read(b)
|
|
readErrs <- err
|
|
}()
|
|
select {
|
|
case err := <-readErrs:
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = term.Write(b)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
case <-ctx.Done():
|
|
return ctx.Err()
|
|
}
|
|
if matcher == nil {
|
|
// A nil matcher means to read until EOF.
|
|
continue
|
|
}
|
|
got := term.String()
|
|
lines := strings.Split(got, "\n")
|
|
for _, line := range lines {
|
|
if matcher(line) {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
}
|