@@ -2,12 +2,16 @@ package cliui_test
2
2
3
3
import (
4
4
"context"
5
+ "os"
6
+ "os/exec"
5
7
"testing"
8
+ "time"
6
9
7
10
"github.com/spf13/cobra"
8
11
"github.com/stretchr/testify/require"
9
12
10
13
"github.com/coder/coder/cli/cliui"
14
+ "github.com/coder/coder/pty"
11
15
"github.com/coder/coder/pty/ptytest"
12
16
)
13
17
@@ -110,3 +114,56 @@ func newPrompt(ptty *ptytest.PTY, opts cliui.PromptOptions) (string, error) {
110
114
cmd .SetIn (ptty .Input ())
111
115
return value ,cmd .ExecuteContext (context .Background ())
112
116
}
117
+
118
+ func TestPasswordTerminalState (t * testing.T ) {
119
+ if os .Getenv ("TEST_SUBPROCESS" )== "1" {
120
+ passwordHelper ()
121
+ return
122
+ }
123
+ t .Parallel ()
124
+
125
+ ptty := ptytest .New (t )
126
+ ptyWithFlags ,ok := ptty .PTY .(pty.WithFlags )
127
+ if ! ok {
128
+ t .Skip ("unable to check PTY local echo on this platform" )
129
+ }
130
+
131
+ cmd := exec .Command (os .Args [0 ],"-test.run=TestPasswordTerminalState" )//nolint:gosec
132
+ cmd .Env = append (os .Environ (),"TEST_SUBPROCESS=1" )
133
+ // connect the child process's stdio to the PTY directly, not via a pipe
134
+ cmd .Stdin = ptty .Input ().Reader
135
+ cmd .Stdout = ptty .Output ().Writer
136
+ cmd .Stderr = os .Stderr
137
+ err := cmd .Start ()
138
+ require .NoError (t ,err )
139
+ process := cmd .Process
140
+ defer process .Kill ()
141
+
142
+ ptty .ExpectMatch ("Password: " )
143
+ time .Sleep (100 * time .Millisecond )// wait for child process to turn off echo and start reading input
144
+
145
+ echo ,err := ptyWithFlags .EchoEnabled ()
146
+ require .NoError (t ,err )
147
+ require .False (t ,echo ,"echo is on while reading password" )
148
+
149
+ err = process .Signal (os .Interrupt )
150
+ require .NoError (t ,err )
151
+ _ ,err = process .Wait ()
152
+ require .NoError (t ,err )
153
+
154
+ echo ,err = ptyWithFlags .EchoEnabled ()
155
+ require .NoError (t ,err )
156
+ require .True (t ,echo ,"echo is off after reading password" )
157
+ }
158
+
159
+ func passwordHelper () {
160
+ cmd := & cobra.Command {
161
+ Run :func (cmd * cobra.Command ,args []string ) {
162
+ cliui .Prompt (cmd , cliui.PromptOptions {
163
+ Text :"Password:" ,
164
+ Secret :true ,
165
+ })
166
+ },
167
+ }
168
+ cmd .ExecuteContext (context .Background ())
169
+ }