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  }