Skip to content

Commit

Permalink
Add more test helpers, cleanup existing tests. Add editorconfig and g…
Browse files Browse the repository at this point in the history
…olangci config, comply with golangci rules.
  • Loading branch information
creack committed Oct 31, 2023
1 parent ccf8e7e commit e7ab9d1
Show file tree
Hide file tree
Showing 10 changed files with 537 additions and 206 deletions.
54 changes: 54 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
root = true

# Sane defaults.
[*]
# Always use unix end of line.
end_of_line = lf
# Always insert a new line at the end of files.
insert_final_newline = true
# Don't leave trailing whitespaces.
trim_trailing_whitespace = true
# Default to utf8 encoding.
charset = utf-8
# Space > tab for consistent aligns.
indent_style = space
# Default to 2 spaces for indent/tabs.
indent_size = 2
# Flag long lines.
max_line_length = 140

# Explicitly define settings for commonly used files.

[*.go]
indent_style = tab
indent_size = 8

[*.feature]
indent_style = space
indent_size = 2

[*.json]
indent_style = space
indent_size = 2

[*.{yml,yaml}]
indent_style = space
indent_size = 2

[*.tf]
indent_style = space
indent_size = 2

[*.md]
# Don't check line lenghts in files.
max_line_length = 0

[{Makefile,*.mk}]
indent_style = tab
indent_size = 8

[{Dockerfile,Dockerfile.*}]
indent_size = 4

[*.sql]
indent_size = 2
324 changes: 324 additions & 0 deletions .golangci.yml

Large diffs are not rendered by default.

262 changes: 72 additions & 190 deletions doc_test.go
Original file line number Diff line number Diff line change
@@ -1,39 +1,10 @@
package pty

import (
"bytes"
"io"
"os"
"testing"
)

// Will fill p from reader r.
func readBytes(r io.Reader, p []byte) error {
_, err := io.ReadFull(r, p)
return err
}

// openCloses opens a pty/tty pair and stages the closing as part of the cleanup.
func openClose(t *testing.T) (pty, tty *os.File) {
t.Helper()

pty, tty, err := Open()
if err != nil {
t.Fatalf("Unexpected error from Open: %s.", err)
}
t.Cleanup(func() {
if err := tty.Close(); err != nil {
t.Errorf("Unexpected error from tty Close: %s.", err)
}

if err := pty.Close(); err != nil {
t.Errorf("Unexpected error from pty Close: %s.", err)
}
})

return pty, tty
}

func TestOpen(t *testing.T) {
t.Parallel()

Expand All @@ -60,31 +31,22 @@ func TestName(t *testing.T) {
func TestOpenByName(t *testing.T) {
t.Parallel()

pty, tty := openClose(t)
pty, tty := openClose(t) // Get the pty/tty pair.

// Manually open the tty from the exiting name.
ttyFile, err := os.OpenFile(tty.Name(), os.O_RDWR, 0o600)
if err != nil {
t.Fatalf("Failed to open tty file: %s.", err)
}
noError(t, err, "Failed to open tty file")
defer func() { _ = 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.Fatalf("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.Fatalf("Unexpected error from readBytes: %s.", err)
}
if !bytes.Equal(text, buffer) {
t.Errorf("Unexpected result returned from Read, got %v expected %v", buffer, text)
}
n, err := ttyFile.Write(text) // Write the text to the manually open tty.
noError(t, err, "Unexpected error from Write") // Make sure it didn't fail.
assert(t, len(text), n, "Unexpected count returned from Write") // Assert the number of bytes written.

buffer := readN(t, pty, len(text), "Unexpected error from pty Read")
assertBytes(t, text, buffer, "Unexpected result result returned from pty Read")
}

func TestGetsize(t *testing.T) {
Expand All @@ -93,50 +55,30 @@ func TestGetsize(t *testing.T) {
pty, tty := openClose(t)

prows, pcols, err := Getsize(pty)
if err != nil {
t.Errorf("Unexpected error from Getsize: %s.", err)
}
noError(t, err, "Unexpected error from pty Getsize")

trows, tcols, err := Getsize(tty)
if err != nil {
t.Errorf("Unexpected error from Getsize: %s.", err)
}
noError(t, err, "Unexpected error from tty Getsize")

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)
}
assert(t, prows, trows, "rows from Getsize on pty and tty should match")
assert(t, pcols, tcols, "cols from Getsize on pty and tty should match")
}

func TestGetsizefull(t *testing.T) {
func TestGetsizeFull(t *testing.T) {
t.Parallel()

pty, tty := openClose(t)

psize, err := GetsizeFull(pty)
if err != nil {
t.Fatalf("Unexpected error from GetsizeFull: %s.", err)
}
noError(t, err, "Unexpected error from pty GetsizeFull")

tsize, err := GetsizeFull(tty)
if err != nil {
t.Fatalf("Unexpected error from GetsizeFull: %s.", err)
}
noError(t, err, "Unexpected error from tty GetsizeFull")

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)
}
assert(t, psize.X, tsize.X, "X from GetsizeFull on pty and tty should match")
assert(t, psize.Y, tsize.Y, "Y from GetsizeFull on pty and tty should match")
assert(t, psize.Rows, tsize.Rows, "rows from GetsizeFull on pty and tty should match")
assert(t, psize.Cols, tsize.Cols, "cols from GetsizeFull on pty and tty should match")
}

func TestSetsize(t *testing.T) {
Expand All @@ -145,91 +87,58 @@ func TestSetsize(t *testing.T) {
pty, tty := openClose(t)

psize, err := GetsizeFull(pty)
if err != nil {
t.Fatalf("Unexpected error from GetsizeFull: %s.", err)
}
noError(t, err, "Unexpected error from pty GetsizeFull")

psize.X = psize.X + 1
psize.Y = psize.Y + 1
psize.Rows = psize.Rows + 1
psize.Cols = psize.Cols + 1
psize.X++
psize.Y++
psize.Rows++
psize.Cols++

if err := Setsize(tty, psize); err != nil {
t.Fatalf("Unexpected error from Setsize: %s", err)
}
noError(t, Setsize(tty, psize), "Unexpected error from Setsize")

tsize, err := GetsizeFull(tty)
if err != nil {
t.Fatalf("Unexpected error from GetsizeFull: %s.", err)
}
noError(t, err, "Unexpected error from tty GetsizeFull")

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)
}
assert(t, psize.X, tsize.X, "Unexpected Getsize X result after Setsize")
assert(t, psize.Y, tsize.Y, "Unexpected Getsize Y result after Setsize")
assert(t, psize.Rows, tsize.Rows, "Unexpected Getsize Rows result after Setsize")
assert(t, psize.Cols, tsize.Cols, "Unexpected Getsize Cols result after Setsize")
}

func TestReadWriteText(t *testing.T) {
t.Parallel()

pty, tty := openClose(t)

// Write to tty, read from pty
text := []byte("ping")
n, err := tty.Write(text)
if err != nil {
t.Fatalf("Unexpected error from Write: %s", err)
}
if n != len(text) {
t.Errorf("Unexpected count returned from Write, got %d expected %d.", n, len(text))
}
// Write to tty, read from pty.
{
text := []byte("ping")

buffer := make([]byte, 4)
if err := readBytes(pty, buffer); err != nil {
t.Fatalf("Unexpected error from readBytes: %s.", err)
}
if !bytes.Equal(text, buffer) {
t.Errorf("Unexpected result returned from Read, got %v expected %v.", buffer, text)
n, err := tty.Write(text)
noError(t, err, "Unexpected error from tty Write")
assert(t, n, len(text), "Unexpected count returned from tty Write")

buffer := readN(t, pty, len(text), "Unexpected error from pty Read")
assertBytes(t, text, buffer, "Unexpected result returned from pty Read")
}

// 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.Fatalf("Unexpected error from Write: %s.", err)
}
if n != len(text) {
t.Errorf("Unexpected count returned from Write, got %d expected %d.", n, len(text))
}
{
text := []byte("pong\n")

buffer = make([]byte, 5)
err = readBytes(tty, buffer)
if err != nil {
t.Fatalf("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)
}
n, err := pty.Write(text)
noError(t, err, "Unexpected error from pty Write")
assert(t, n, len(text), "Unexpected count returned from pty Write")

// Read the echo back from pty
buffer = make([]byte, 5)
err = readBytes(pty, buffer)
if err != nil {
t.Fatalf("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)
// Expect the raw text back when reading from tty.
buffer := readN(t, tty, len(text), "Unexpected error from tty Read")
assertBytes(t, text, buffer, "Unexpected result returned from tty Read")

// Read the echo back from pty. Expect LF to be CRLF.
expect := []byte("pong\r\n")
buffer = readN(t, pty, len(expect), "Unexpected error from pty Read")
assertBytes(t, expect, buffer, "Unexpected result returned from pty Read")
}
}

Expand All @@ -239,52 +148,25 @@ func TestReadWriteControls(t *testing.T) {
pty, tty := openClose(t)

// Write the start of a line to pty.
text := []byte("pind")
n, err := pty.Write(text)
if err != nil {
t.Fatalf("Unexpected error from Write: %s.", err)
}
if n != len(text) {
t.Errorf("Unexpected count returned from Write, got %d expected %d.", n, len(text))
}
n, err := pty.WriteString("pind") // Intentional typo.
noError(t, err, "Unexpected error from Write initial text") // Make sure it didn't fail.
assert(t, 4, n, "Unexpected count returned from Write initial text") // Assert the number of bytes written.

// Backspace that last char.
n, err = pty.Write([]byte("\b"))
if err != nil {
t.Fatalf("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.Fatalf("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)
}
n, err = pty.WriteString("\b") // "Remove" the typo.
noError(t, err, "Unexpected error from Write backspace") // Make sure it didn't fail.
assert(t, 1, n, "Unexpected count returned from Write backspace") // Assert the number of bytes written.

// Write the correct char and a LF.
n, err = pty.WriteString("g\n") // Fix the typo.
noError(t, err, "Unexpected error from Write fixed text") // Make sure it didn't fail.
assert(t, 2, n, "Unexpected count returned from Write fixed text") // Assert the number of bytes written.

// Read the line.
buffer := readN(t, tty, 7, "Unexpected error from tty Read")
assertBytes(t, []byte("pind\bg\n"), buffer, "Unexpected result returned from tty Read")

// Read the echo back from pty.
buffer = readN(t, pty, 9, "Unexpected error from pty Read")
assertBytes(t, []byte("pind^Hg\r\n"), buffer, "Unexpected result returned from pty Read")
}
Loading

0 comments on commit e7ab9d1

Please sign in to comment.