package main import ( "fmt" "io" "net" "strings" "testing" "time" "github.com/stretchr/testify/require" ) // TerminalTestClient is a terminal client of a test daemon, with a pipe as its // input. type TerminalTestClient struct { input *io.PipeWriter done chan error out *SyncBuffer } // Type writes one line to the input of the client. func (c *TerminalTestClient) Type(line string) { _, err := io.WriteString(c.input, line+"\n") if err != nil { panic(err) } } // Output returns what the client showed. func (c *TerminalTestClient) Output() string { return c.out.String() } // WaitFor waits until the client showed text. func (c *TerminalTestClient) WaitFor(t *testing.T, text string) { t.Helper() require.Eventually(t, func() bool { return strings.Contains(c.Output(), text) }, 10*time.Second, time.Millisecond, "output so far: %q", c.Output()) } // Close ends the input and waits for the client. func (c *TerminalTestClient) Close() error { err := c.input.Close() if err != nil { return fmt.Errorf("close terminal input: %w", err) } return <-c.done } // terminalStartTestClient connects a client to the daemon at socket. func terminalStartTestClient(t *testing.T, socket string) *TerminalTestClient { t.Helper() conn, err := net.Dial("unix", socket) require.NoError(t, err) reader, writer := io.Pipe() client := &TerminalTestClient{ input: writer, done: make(chan error, 1), out: &SyncBuffer{}, } go func() { client.done <- terminalSession(t.Context(), conn, reader, client.out) }() t.Cleanup(func() { _ = writer.Close() }) return client }