1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
14 type MockTerminal struct {
20 func (c *MockTerminal) Read(data []byte) (n int, err error) {
25 if n > len(c.toSend) {
31 if c.bytesPerRead > 0 && n > c.bytesPerRead {
34 copy(data, c.toSend[:n])
35 c.toSend = c.toSend[n:]
39 func (c *MockTerminal) Write(data []byte) (n int, err error) {
40 c.received = append(c.received, data...)
44 func TestClose(t *testing.T) {
46 ss := NewTerminal(c, "> ")
47 line, err := ss.ReadLine()
49 t.Errorf("Expected empty line but got: %s", line)
52 t.Errorf("Error should have been EOF but got: %s", err)
56 var keyPressTests = []struct {
74 in: "a\x1b[Cb\r", // right
78 in: "a\x1b[Db\r", // left
82 in: "a\177b\r", // backspace
89 in: "\x1b[B\r", // down
92 in: "line\x1b[A\x1b[B\r", // up then down
96 in: "line1\rline2\x1b[A\r", // recall previous line.
101 // recall two previous lines and append.
102 in: "line1\rline2\rline3\x1b[A\x1b[Axxx\r",
107 // Ctrl-A to move to beginning of line followed by ^K to kill
109 in: "a b \001\013\r",
113 // Ctrl-A to move to beginning of line, Ctrl-E to move to end,
114 // finally ^K to kill nothing.
115 in: "a b \001\005\013\r",
139 in: "one two thr\x1b[D\027\r",
151 in: "ab\x1b[D\013\r",
159 in: "£\r\x1b[A\177\r", // non-ASCII char, enter, up, backspace.
164 in: "£\r££\x1b[A\x1b[B\177\r", // non-ASCII char, enter, 2x non-ASCII, up, down, backspace, enter.
169 // Ctrl-D at the end of the line should be ignored.
174 // a, b, left, Ctrl-D should erase the b.
175 in: "ab\x1b[D\004\r",
179 // a, b, c, d, left, left, ^U should erase to the beginning of
181 in: "abcd\x1b[D\x1b[D\025\r",
185 // Bracketed paste mode: control sequences should be returned
186 // verbatim in paste mode.
187 in: "abc\x1b[200~de\177f\x1b[201~\177\r",
191 // Enter in bracketed paste mode should still work.
192 in: "abc\x1b[200~d\refg\x1b[201~h\r",
197 // Lines consisting entirely of pasted data should be indicated as such.
200 err: ErrPasteIndicator,
204 func TestKeyPresses(t *testing.T) {
205 for i, test := range keyPressTests {
206 for j := 1; j < len(test.in); j++ {
208 toSend: []byte(test.in),
211 ss := NewTerminal(c, "> ")
212 for k := 0; k < test.throwAwayLines; k++ {
213 _, err := ss.ReadLine()
215 t.Errorf("Throwaway line %d from test %d resulted in error: %s", k, i, err)
218 line, err := ss.ReadLine()
219 if line != test.line {
220 t.Errorf("Line resulting from test %d (%d bytes per read) was '%s', expected '%s'", i, j, line, test.line)
224 t.Errorf("Error resulting from test %d (%d bytes per read) was '%v', expected '%v'", i, j, err, test.err)
231 func TestPasswordNotSaved(t *testing.T) {
233 toSend: []byte("password\r\x1b[A\r"),
236 ss := NewTerminal(c, "> ")
237 pw, _ := ss.ReadPassword("> ")
238 if pw != "password" {
239 t.Fatalf("failed to read password, got %s", pw)
241 line, _ := ss.ReadLine()
243 t.Fatalf("password was saved in history")
247 var setSizeTests = []struct {
255 func TestTerminalSetSize(t *testing.T) {
256 for _, setSize := range setSizeTests {
258 toSend: []byte("password\r\x1b[A\r"),
261 ss := NewTerminal(c, "> ")
262 ss.SetSize(setSize.width, setSize.height)
263 pw, _ := ss.ReadPassword("Password: ")
264 if pw != "password" {
265 t.Fatalf("failed to read password, got %s", pw)
267 if string(c.received) != "Password: \r\n" {
268 t.Errorf("failed to set the temporary prompt expected %q, got %q", "Password: ", c.received)
273 func TestReadPasswordLineEnd(t *testing.T) {
274 var tests = []struct {
280 {"test\r\n", "test"},
281 {"testtesttesttes\n", "testtesttesttes"},
282 {"testtesttesttes\r\n", "testtesttesttes"},
283 {"testtesttesttesttest\n", "testtesttesttesttest"},
284 {"testtesttesttesttest\r\n", "testtesttesttesttest"},
286 for _, test := range tests {
287 buf := new(bytes.Buffer)
288 if _, err := buf.WriteString(test.input); err != nil {
292 have, err := readPasswordLine(buf)
294 t.Errorf("readPasswordLine(%q) failed: %v", test.input, err)
297 if string(have) != test.want {
298 t.Errorf("readPasswordLine(%q) returns %q, but %q is expected", test.input, string(have), test.want)
302 if _, err = buf.WriteString(test.input); err != nil {
305 have, err = readPasswordLine(buf)
307 t.Errorf("readPasswordLine(%q) failed: %v", test.input, err)
310 if string(have) != test.want {
311 t.Errorf("readPasswordLine(%q) returns %q, but %q is expected", test.input, string(have), test.want)
317 func TestMakeRawState(t *testing.T) {
318 fd := int(os.Stdout.Fd())
320 t.Skip("stdout is not a terminal; skipping test")
323 st, err := GetState(fd)
325 t.Fatalf("failed to get terminal state from GetState: %s", err)
327 defer Restore(fd, st)
328 raw, err := MakeRaw(fd)
330 t.Fatalf("failed to get terminal state from MakeRaw: %s", err)
334 t.Errorf("states do not match; was %v, expected %v", raw, st)
338 func TestOutputNewlines(t *testing.T) {
339 // \n should be changed to \r\n in terminal output.
340 buf := new(bytes.Buffer)
341 term := NewTerminal(buf, ">")
343 term.Write([]byte("1\n2\n"))
344 output := string(buf.Bytes())
345 const expected = "1\r\n2\r\n"
347 if output != expected {
348 t.Errorf("incorrect output: was %q, expected %q", output, expected)