Merge pull request #13305 from pdostal/fix/poll-tty-echo-mode-in-password-tests

Poll TTY echo mode instead of sleeping in password tests
This commit is contained in:
William Martin 2026-05-07 20:32:56 +02:00 committed by GitHub
commit b698aa7462
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 41 additions and 9 deletions

View file

@ -1,10 +1,11 @@
//go:build !windows
//go:build linux || darwin
package prompter_test
import (
"fmt"
"io"
"os"
"slices"
"strings"
"testing"
@ -17,6 +18,7 @@ import (
"github.com/hinshun/vt10x"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"golang.org/x/sys/unix"
)
// The following tests are broadly testing the accessible prompter, and NOT asserting
@ -34,8 +36,6 @@ import (
// but doesn't mandate that prompts always look exactly the same.
func TestAccessiblePrompter(t *testing.T) {
beforePasswordSendTimeout := 100 * time.Millisecond
t.Run("Select", func(t *testing.T) {
console := newTestVirtualTerminal(t)
p := newTestAccessiblePrompter(t, console)
@ -505,8 +505,8 @@ func TestAccessiblePrompter(t *testing.T) {
_, err := console.ExpectString("Enter password")
require.NoError(t, err)
// Wait to ensure huh has time to set the echo mode
time.Sleep(beforePasswordSendTimeout)
// Wait until huh has disabled echo mode on the TTY
require.NoError(t, waitForEchoDisabled(console.Tty(), 5*time.Second))
// Enter a number
_, err = console.SendLine(dummyPassword)
@ -596,8 +596,8 @@ func TestAccessiblePrompter(t *testing.T) {
_, err := console.ExpectString("Paste your authentication token:")
require.NoError(t, err)
// Wait to ensure huh has time to set the echo mode
time.Sleep(beforePasswordSendTimeout)
// Wait until huh has disabled echo mode on the TTY
require.NoError(t, waitForEchoDisabled(console.Tty(), 5*time.Second))
// Enter some dummy auth token
_, err = console.SendLine(dummyAuthToken)
@ -641,8 +641,8 @@ func TestAccessiblePrompter(t *testing.T) {
_, err = console.ExpectString("Paste your authentication token:")
require.NoError(t, err)
// Wait to ensure huh has time to set the echo mode
time.Sleep(beforePasswordSendTimeout)
// Wait until huh has disabled echo mode on the TTY
require.NoError(t, waitForEchoDisabled(console.Tty(), 5*time.Second))
// Now enter some dummy auth token to return control back to the test
_, err = console.SendLine(dummyAuthTokenForAfterFailure)
@ -956,3 +956,21 @@ func testCloser(t *testing.T, closer io.Closer) {
t.Errorf("Close failed: %s", err)
}
}
// waitForEchoDisabled polls the TTY until echo mode is disabled or the
// timeout is reached. This is used in password and auth token tests to
// ensure that huh has configured the terminal before we send input.
func waitForEchoDisabled(tty *os.File, timeout time.Duration) error {
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
termios, err := unix.IoctlGetTermios(int(tty.Fd()), ioctlGetTermios)
if err != nil {
return fmt.Errorf("getting terminal attributes: %w", err)
}
if termios.Lflag&unix.ECHO == 0 {
return nil
}
time.Sleep(time.Millisecond)
}
return fmt.Errorf("timed out waiting for echo mode to be disabled")
}

View file

@ -0,0 +1,7 @@
//go:build darwin
package prompter_test
import "golang.org/x/sys/unix"
const ioctlGetTermios = unix.TIOCGETA

View file

@ -0,0 +1,7 @@
//go:build linux
package prompter_test
import "golang.org/x/sys/unix"
const ioctlGetTermios = unix.TCGETS