123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- package pty
- import (
- "bytes"
- "io"
- "os"
- "testing"
- )
- // Will fill p from reader r
- func readBytes(r io.Reader, p []byte) error {
- bytesRead := 0
- for bytesRead < len(p) {
- n, err := r.Read(p[bytesRead:])
- if err != nil {
- return err
- }
- bytesRead = bytesRead + n
- }
- return nil
- }
- func TestOpen(t *testing.T) {
- t.Parallel()
- pty, tty, err := Open()
- if err != nil {
- t.Errorf("Unexpected error from Open: %s", err)
- }
- err = tty.Close()
- if err != nil {
- t.Errorf("Unexpected error from tty Close: %s", err)
- }
- err = pty.Close()
- if err != nil {
- t.Errorf("Unexpected error from pty Close: %s", err)
- }
- }
- func TestName(t *testing.T) {
- t.Parallel()
- pty, tty, err := Open()
- if err != nil {
- t.Errorf("Unexpected error from Open: %s", err)
- }
- // Check name isn't empty. There's variation on what exactly the OS calls these files.
- if pty.Name() == "" {
- t.Error("pty name was empty")
- }
- if tty.Name() == "" {
- t.Error("tty name was empty")
- }
- err = tty.Close()
- if err != nil {
- t.Errorf("Unexpected error from tty Close: %s", err)
- }
- err = pty.Close()
- if err != nil {
- t.Errorf("Unexpected error from pty Close: %s", err)
- }
- }
- // TestOpenByName ensures that the name associated with the tty is valid
- // and can be opened and used if passed by file name (rather than passing
- // the existing open file descriptor).
- func TestOpenByName(t *testing.T) {
- t.Parallel()
- pty, tty, err := Open()
- if err != nil {
- t.Fatal(err)
- }
- defer pty.Close()
- defer tty.Close()
- ttyFile, err := os.OpenFile(tty.Name(), os.O_RDWR, 0600)
- if err != nil {
- t.Fatalf("Failed to open tty file: %v", err)
- }
- defer ttyFile.Close()
- // Ensure we can write to the newly opened tty file and read on the pty.
- text := []byte("ping")
- n, err := ttyFile.Write(text)
- if err != nil {
- t.Errorf("Unexpected error from Write: %s", err)
- }
- if n != len(text) {
- t.Errorf("Unexpected count returned from Write, got %d expected %d", n, len(text))
- }
- buffer := make([]byte, len(text))
- if err := readBytes(pty, buffer); err != nil {
- t.Errorf("Unexpected error from readBytes: %s", err)
- }
- if !bytes.Equal(text, buffer) {
- t.Errorf("Unexpected result returned from Read, got %v expected %v", buffer, text)
- }
- }
- func TestGetsize(t *testing.T) {
- t.Parallel()
- pty, tty, err := Open()
- if err != nil {
- t.Errorf("Unexpected error from Open: %s", err)
- }
- prows, pcols, err := Getsize(pty)
- if err != nil {
- t.Errorf("Unexpected error from Getsize: %s", err)
- }
- trows, tcols, err := Getsize(tty)
- if err != nil {
- t.Errorf("Unexpected error from Getsize: %s", err)
- }
- if prows != trows {
- t.Errorf("pty rows != tty rows: %d != %d", prows, trows)
- }
- if prows != trows {
- t.Errorf("pty cols != tty cols: %d != %d", pcols, tcols)
- }
- err = tty.Close()
- if err != nil {
- t.Errorf("Unexpected error from tty Close: %s", err)
- }
- err = pty.Close()
- if err != nil {
- t.Errorf("Unexpected error from pty Close: %s", err)
- }
- }
- func TestGetsizefull(t *testing.T) {
- t.Parallel()
- pty, tty, err := Open()
- if err != nil {
- t.Errorf("Unexpected error from Open: %s", err)
- }
- psize, err := GetsizeFull(pty)
- if err != nil {
- t.Errorf("Unexpected error from GetsizeFull: %s", err)
- }
- tsize, err := GetsizeFull(tty)
- if err != nil {
- t.Errorf("Unexpected error from GetsizeFull: %s", err)
- }
- if psize.X != tsize.X {
- t.Errorf("pty x != tty x: %d != %d", psize.X, tsize.X)
- }
- if psize.Y != tsize.Y {
- t.Errorf("pty y != tty y: %d != %d", psize.Y, tsize.Y)
- }
- if psize.Rows != tsize.Rows {
- t.Errorf("pty rows != tty rows: %d != %d", psize.Rows, tsize.Rows)
- }
- if psize.Cols != tsize.Cols {
- t.Errorf("pty cols != tty cols: %d != %d", psize.Cols, tsize.Cols)
- }
- err = tty.Close()
- if err != nil {
- t.Errorf("Unexpected error from tty Close: %s", err)
- }
- err = pty.Close()
- if err != nil {
- t.Errorf("Unexpected error from pty Close: %s", err)
- }
- }
- func TestSetsize(t *testing.T) {
- t.Parallel()
- pty, tty, err := Open()
- if err != nil {
- t.Errorf("Unexpected error from Open: %s", err)
- }
- psize, err := GetsizeFull(pty)
- if err != nil {
- t.Errorf("Unexpected error from GetsizeFull: %s", err)
- }
- psize.X = psize.X + 1
- psize.Y = psize.Y + 1
- psize.Rows = psize.Rows + 1
- psize.Cols = psize.Cols + 1
- err = Setsize(tty, psize)
- if err != nil {
- t.Errorf("Unexpected error from Setsize: %s", err)
- }
- tsize, err := GetsizeFull(tty)
- if err != nil {
- t.Errorf("Unexpected error from GetsizeFull: %s", err)
- }
- if psize.X != tsize.X {
- t.Errorf("pty x != tty x: %d != %d", psize.X, tsize.X)
- }
- if psize.Y != tsize.Y {
- t.Errorf("pty y != tty y: %d != %d", psize.Y, tsize.Y)
- }
- if psize.Rows != tsize.Rows {
- t.Errorf("pty rows != tty rows: %d != %d", psize.Rows, tsize.Rows)
- }
- if psize.Cols != tsize.Cols {
- t.Errorf("pty cols != tty cols: %d != %d", psize.Cols, tsize.Cols)
- }
- err = tty.Close()
- if err != nil {
- t.Errorf("Unexpected error from tty Close: %s", err)
- }
- err = pty.Close()
- if err != nil {
- t.Errorf("Unexpected error from pty Close: %s", err)
- }
- }
- func TestReadWriteText(t *testing.T) {
- t.Parallel()
- pty, tty, err := Open()
- if err != nil {
- t.Errorf("Unexpected error from Open: %s", err)
- }
- // Write to tty, read from pty
- text := []byte("ping")
- n, err := tty.Write(text)
- if err != nil {
- t.Errorf("Unexpected error from Write: %s", err)
- }
- if n != len(text) {
- t.Errorf("Unexpected count returned from Write, got %d expected %d", n, len(text))
- }
- buffer := make([]byte, 4)
- err = readBytes(pty, buffer)
- if err != nil {
- t.Errorf("Unexpected error from readBytes: %s", err)
- }
- if !bytes.Equal(text, buffer) {
- t.Errorf("Unexpected result returned from Read, got %v expected %v", buffer, text)
- }
- // Write to pty, read from tty.
- // We need to send a \n otherwise this will block in the terminal driver.
- text = []byte("pong\n")
- n, err = pty.Write(text)
- if err != nil {
- t.Errorf("Unexpected error from Write: %s", err)
- }
- if n != len(text) {
- t.Errorf("Unexpected count returned from Write, got %d expected %d", n, len(text))
- }
- buffer = make([]byte, 5)
- err = readBytes(tty, buffer)
- if err != nil {
- t.Errorf("Unexpected error from readBytes: %s", err)
- }
- expect := []byte("pong\n")
- if !bytes.Equal(expect, buffer) {
- t.Errorf("Unexpected result returned from Read, got %v expected %v", buffer, expect)
- }
- // Read the echo back from pty
- buffer = make([]byte, 5)
- err = readBytes(pty, buffer)
- if err != nil {
- t.Errorf("Unexpected error from readBytes: %s", err)
- }
- expect = []byte("pong\r")
- if !bytes.Equal(expect, buffer) {
- t.Errorf("Unexpected result returned from Read, got %v expected %v", buffer, expect)
- }
- err = tty.Close()
- if err != nil {
- t.Errorf("Unexpected error from tty Close: %s", err)
- }
- err = pty.Close()
- if err != nil {
- t.Errorf("Unexpected error from pty Close: %s", err)
- }
- }
- func TestReadWriteControls(t *testing.T) {
- t.Parallel()
- pty, tty, err := Open()
- if err != nil {
- t.Errorf("Unexpected error from Open: %s", err)
- }
- // Write the start of a line to pty
- text := []byte("pind")
- n, err := pty.Write(text)
- if err != nil {
- t.Errorf("Unexpected error from Write: %s", err)
- }
- if n != len(text) {
- t.Errorf("Unexpected count returned from Write, got %d expected %d", n, len(text))
- }
- // Backspace that last char
- n, err = pty.Write([]byte("\b"))
- if err != nil {
- t.Errorf("Unexpected error from Write: %s", err)
- }
- if n != 1 {
- t.Errorf("Unexpected count returned from Write, got %d expected %d", n, 1)
- }
- // Write the correct char and a CR
- n, err = pty.Write([]byte("g\n"))
- if err != nil {
- t.Errorf("Unexpected error from Write: %s", err)
- }
- if n != 2 {
- t.Errorf("Unexpected count returned from Write, got %d expected %d", n, 2)
- }
- // Read the line
- buffer := make([]byte, 7)
- err = readBytes(tty, buffer)
- if err != nil {
- t.Errorf("Unexpected error from readBytes: %s", err)
- }
- expect := []byte("pind\bg\n")
- if !bytes.Equal(expect, buffer) {
- t.Errorf("Unexpected result returned from Read, got %v expected %v", buffer, expect)
- }
- // Read the echo back from pty
- buffer = make([]byte, 7)
- err = readBytes(pty, buffer)
- if err != nil {
- t.Errorf("Unexpected error from readBytes: %s", err)
- }
- expect = []byte("pind^Hg")
- if !bytes.Equal(expect, buffer) {
- t.Errorf("Unexpected result returned from Read, got %v expected %v", buffer, expect)
- }
- err = tty.Close()
- if err != nil {
- t.Errorf("Unexpected error from tty Close: %s", err)
- }
- err = pty.Close()
- if err != nil {
- t.Errorf("Unexpected error from pty Close: %s", err)
- }
- }
|