github.com/mem/u-root@v2.0.1-0.20181004165302-9b18b4636a33+incompatible/cmds/elvish/edit/tty/reader_unix_test.go (about) 1 // +build !windows,!plan9 2 3 package tty 4 5 import ( 6 "os" 7 "testing" 8 "time" 9 10 "github.com/u-root/u-root/cmds/elvish/edit/ui" 11 ) 12 13 // timeout is the longest time the tests wait between writing something on 14 // the writer and reading it from the reader before declaring that the 15 // reader has a bug. 16 const timeoutInterval = 100 * time.Millisecond 17 18 func timeout() <-chan time.Time { 19 return time.After(timeoutInterval) 20 } 21 22 var ( 23 theWriter *os.File 24 innerReader *os.File 25 theReader *reader 26 ) 27 28 func TestMain(m *testing.M) { 29 r, w, err := os.Pipe() 30 if err != nil { 31 panic("os.Pipe returned error, something is seriously wrong") 32 } 33 defer r.Close() 34 defer w.Close() 35 theWriter = w 36 innerReader = r 37 theReader = newReader(r) 38 theReader.Start() 39 defer theReader.Stop() 40 41 os.Exit(m.Run()) 42 } 43 44 var keyTests = []struct { 45 input string 46 want Event 47 }{ 48 // Simple graphical key. 49 {"x", KeyEvent{'x', 0}}, 50 {"X", KeyEvent{'X', 0}}, 51 {" ", KeyEvent{' ', 0}}, 52 53 // Ctrl key. 54 {"\001", KeyEvent{'A', ui.Ctrl}}, 55 {"\033", KeyEvent{'[', ui.Ctrl}}, 56 57 // Ctrl-ish keys, but not thought as Ctrl keys by our reader. 58 {"\n", KeyEvent{'\n', 0}}, 59 {"\t", KeyEvent{'\t', 0}}, 60 {"\x7f", KeyEvent{'\x7f', 0}}, // backspace 61 62 // Alt plus simple graphical key. 63 {"\033a", KeyEvent{'a', ui.Alt}}, 64 {"\033[", KeyEvent{'[', ui.Alt}}, 65 66 // G3-style key. 67 {"\033OA", KeyEvent{ui.Up, 0}}, 68 {"\033OH", KeyEvent{ui.Home, 0}}, 69 70 // CSI-sequence key identified by the ending rune. 71 {"\033[A", KeyEvent{ui.Up, 0}}, 72 {"\033[H", KeyEvent{ui.Home, 0}}, 73 // Test for all possible modifier 74 {"\033[1;2A", KeyEvent{ui.Up, ui.Shift}}, 75 76 // CSI-sequence key with one argument, always ending in '~'. 77 {"\033[1~", KeyEvent{ui.Home, 0}}, 78 {"\033[11~", KeyEvent{ui.F1, 0}}, 79 80 // CSI-sequence key with three arguments and ending in '~'. The first 81 // argument is always 27, the second identifies the modifier and the last 82 // identifies the key. 83 {"\033[27;4;63~", KeyEvent{';', ui.Shift | ui.Alt}}, 84 } 85 86 // FIXME: Fix test flakiness. 87 func DISABLED_TestKey(t *testing.T) { 88 for _, test := range keyTests { 89 theWriter.WriteString(test.input) 90 select { 91 case event := <-theReader.EventChan(): 92 if event != test.want { 93 t.Errorf("Reader reads event %v, want %v", event, test.want) 94 } 95 case <-timeout(): 96 t.Errorf("Reader timed out") 97 } 98 } 99 } 100 101 // TestStopMakesUnderlyingFileAvailable tests that after calling Stop, the 102 // Reader no longer attempts to read from the underlying file, so it is 103 // available for use by others. 104 func TestStopMakesUnderlyingFileAvailable(t *testing.T) { 105 theReader.Stop() 106 defer theReader.Start() 107 108 s := "lorem ipsum" 109 theWriter.WriteString(s) 110 gotChan := make(chan string) 111 go func() { 112 var buf [32]byte 113 nr, err := innerReader.Read(buf[:]) 114 if err != nil { 115 t.Errorf("inner.Read returns error: %v", err) 116 } 117 gotChan <- string(buf[:nr]) 118 }() 119 select { 120 case got := <-gotChan: 121 if got != s { 122 t.Errorf("got %q, want %q", got, s) 123 } 124 case <-time.After(time.Second): 125 t.Error("inner.Read times out") 126 } 127 } 128 129 // TestStartAfterStopIndeedStarts tests that calling Start very shortly after 130 // Stop puts the Reader the correct started state. 131 // FIXME: Fix test flakiness. 132 func DISABLED_TestStartAfterStopIndeedStarts(t *testing.T) { 133 for i := 0; i < 100; i++ { 134 theReader.Stop() 135 theReader.Start() 136 137 theWriter.WriteString("a") 138 select { 139 case event := <-theReader.EventChan(): 140 wantEvent := KeyEvent(ui.Key{'a', 0}) 141 if event != wantEvent { 142 t.Errorf("After Stop and Start, Reader reads %v, want %v", event, wantEvent) 143 } 144 case <-timeout(): 145 t.Errorf("After Stop and Start, Reader timed out") 146 } 147 } 148 }