diff --git a/hack/make/test-unit b/hack/make/test-unit index 1c2ba3ff3b..d3f182c094 100644 --- a/hack/make/test-unit +++ b/hack/make/test-unit @@ -50,6 +50,7 @@ bundle_test_unit() { fi go test -cover -ldflags "$LDFLAGS" "${BUILDFLAGS[@]}" $TESTFLAGS $pkg_list + go test -cover -ldflags "$LDFLAGS" "${BUILDFLAGS[@]}" $TESTFLAGS github.com/docker/docker/pkg/term -test.root } bundle_test_unit 2>&1 | tee -a "$DEST/test.log" diff --git a/pkg/term/proxy_test.go b/pkg/term/proxy_test.go new file mode 100644 index 0000000000..baba193d16 --- /dev/null +++ b/pkg/term/proxy_test.go @@ -0,0 +1,92 @@ +package term + +import ( + "bytes" + "fmt" + "reflect" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestEscapeProxyRead(t *testing.T) { + escapeKeys, _ := ToBytes("DEL") + keys, _ := ToBytes("a,b,c,+") + reader := NewEscapeProxy(bytes.NewReader(keys), escapeKeys) + buf := make([]byte, len(keys)) + nr, err := reader.Read(buf) + require.NoError(t, err) + require.EqualValues(t, nr, len(keys), fmt.Sprintf("nr %d should be equal to the number of %d", nr, len(keys))) + require.Equal(t, keys, buf, "keys & the read buffer should be equal") + + keys, _ = ToBytes("") + reader = NewEscapeProxy(bytes.NewReader(keys), escapeKeys) + buf = make([]byte, len(keys)) + nr, err = reader.Read(buf) + require.Error(t, err, "Should throw error when no keys are to read") + require.EqualValues(t, nr, 0, "nr should be zero") + require.Condition(t, func() (success bool) { return len(keys) == 0 && len(buf) == 0 }, "keys & the read buffer size should be zero") + + escapeKeys, _ = ToBytes("ctrl-x,ctrl-@") + keys, _ = ToBytes("DEL") + reader = NewEscapeProxy(bytes.NewReader(keys), escapeKeys) + buf = make([]byte, len(keys)) + nr, err = reader.Read(buf) + require.NoError(t, err) + require.EqualValues(t, nr, 1, fmt.Sprintf("nr %d should be equal to the number of 1", nr)) + require.Equal(t, keys, buf, "keys & the read buffer should be equal") + + escapeKeys, _ = ToBytes("ctrl-c") + keys, _ = ToBytes("ctrl-c") + reader = NewEscapeProxy(bytes.NewReader(keys), escapeKeys) + buf = make([]byte, len(keys)) + nr, err = reader.Read(buf) + require.Condition(t, func() (success bool) { + return reflect.TypeOf(err).Name() == "EscapeError" + }, err) + require.EqualValues(t, nr, 0, "nr should be equal to 0") + require.Equal(t, keys, buf, "keys & the read buffer should be equal") + + escapeKeys, _ = ToBytes("ctrl-c,ctrl-z") + keys, _ = ToBytes("ctrl-c,ctrl-z") + reader = NewEscapeProxy(bytes.NewReader(keys), escapeKeys) + buf = make([]byte, 1) + nr, err = reader.Read(buf) + require.NoError(t, err) + require.EqualValues(t, nr, 0, "nr should be equal to 0") + require.Equal(t, keys[0:1], buf, "keys & the read buffer should be equal") + nr, err = reader.Read(buf) + require.Condition(t, func() (success bool) { + return reflect.TypeOf(err).Name() == "EscapeError" + }, err) + require.EqualValues(t, nr, 0, "nr should be equal to 0") + require.Equal(t, keys[1:], buf, "keys & the read buffer should be equal") + + escapeKeys, _ = ToBytes("ctrl-c,ctrl-z") + keys, _ = ToBytes("ctrl-c,DEL,+") + reader = NewEscapeProxy(bytes.NewReader(keys), escapeKeys) + buf = make([]byte, 1) + nr, err = reader.Read(buf) + require.NoError(t, err) + require.EqualValues(t, nr, 0, "nr should be equal to 0") + require.Equal(t, keys[0:1], buf, "keys & the read buffer should be equal") + buf = make([]byte, len(keys)) + nr, err = reader.Read(buf) + require.NoError(t, err) + require.EqualValues(t, nr, len(keys), fmt.Sprintf("nr should be equal to %d", len(keys))) + require.Equal(t, keys, buf, "keys & the read buffer should be equal") + + escapeKeys, _ = ToBytes("ctrl-c,ctrl-z") + keys, _ = ToBytes("ctrl-c,DEL") + reader = NewEscapeProxy(bytes.NewReader(keys), escapeKeys) + buf = make([]byte, 1) + nr, err = reader.Read(buf) + require.NoError(t, err) + require.EqualValues(t, nr, 0, "nr should be equal to 0") + require.Equal(t, keys[0:1], buf, "keys & the read buffer should be equal") + buf = make([]byte, len(keys)) + nr, err = reader.Read(buf) + require.NoError(t, err) + require.EqualValues(t, nr, len(keys), fmt.Sprintf("nr should be equal to %d", len(keys))) + require.Equal(t, keys, buf, "keys & the read buffer should be equal") +} diff --git a/pkg/term/term_linux_test.go b/pkg/term/term_linux_test.go new file mode 100644 index 0000000000..a1628c4c6d --- /dev/null +++ b/pkg/term/term_linux_test.go @@ -0,0 +1,120 @@ +//+build linux + +package term + +import ( + "flag" + "io/ioutil" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +var rootEnabled bool + +func init() { + flag.BoolVar(&rootEnabled, "test.root", false, "enable tests that require root") +} + +// RequiresRoot skips tests that require root, unless the test.root flag has +// been set +func RequiresRoot(t *testing.T) { + if !rootEnabled { + t.Skip("skipping test that requires root") + return + } + assert.Equal(t, 0, os.Getuid(), "This test must be run as root.") +} + +func newTtyForTest(t *testing.T) (*os.File, error) { + RequiresRoot(t) + return os.OpenFile("/dev/tty", os.O_RDWR, os.ModeDevice) +} + +func newTempFile() (*os.File, error) { + return ioutil.TempFile(os.TempDir(), "temp") +} + +func TestGetWinsize(t *testing.T) { + tty, err := newTtyForTest(t) + defer tty.Close() + require.NoError(t, err) + winSize, err := GetWinsize(tty.Fd()) + require.NoError(t, err) + require.NotNil(t, winSize) + require.NotNil(t, winSize.Height) + require.NotNil(t, winSize.Width) + newSize := Winsize{Width: 200, Height: 200, x: winSize.x, y: winSize.y} + err = SetWinsize(tty.Fd(), &newSize) + require.NoError(t, err) + winSize, err = GetWinsize(tty.Fd()) + require.NoError(t, err) + require.Equal(t, *winSize, newSize) +} + +func TestSetWinsize(t *testing.T) { + tty, err := newTtyForTest(t) + defer tty.Close() + require.NoError(t, err) + winSize, err := GetWinsize(tty.Fd()) + require.NoError(t, err) + require.NotNil(t, winSize) + newSize := Winsize{Width: 200, Height: 200, x: winSize.x, y: winSize.y} + err = SetWinsize(tty.Fd(), &newSize) + require.NoError(t, err) + winSize, err = GetWinsize(tty.Fd()) + require.NoError(t, err) + require.Equal(t, *winSize, newSize) +} + +func TestGetFdInfo(t *testing.T) { + tty, err := newTtyForTest(t) + defer tty.Close() + require.NoError(t, err) + inFd, isTerminal := GetFdInfo(tty) + require.Equal(t, inFd, tty.Fd()) + require.Equal(t, isTerminal, true) + tmpFile, err := newTempFile() + defer tmpFile.Close() + inFd, isTerminal = GetFdInfo(tmpFile) + require.Equal(t, inFd, tmpFile.Fd()) + require.Equal(t, isTerminal, false) +} + +func TestIsTerminal(t *testing.T) { + tty, err := newTtyForTest(t) + defer tty.Close() + require.NoError(t, err) + isTerminal := IsTerminal(tty.Fd()) + require.Equal(t, isTerminal, true) + tmpFile, err := newTempFile() + defer tmpFile.Close() + isTerminal = IsTerminal(tmpFile.Fd()) + require.Equal(t, isTerminal, false) +} + +func TestSaveState(t *testing.T) { + tty, err := newTtyForTest(t) + defer tty.Close() + require.NoError(t, err) + state, err := SaveState(tty.Fd()) + require.NoError(t, err) + require.NotNil(t, state) + tty, err = newTtyForTest(t) + defer tty.Close() + err = RestoreTerminal(tty.Fd(), state) + require.NoError(t, err) +} + +func TestDisableEcho(t *testing.T) { + tty, err := newTtyForTest(t) + defer tty.Close() + require.NoError(t, err) + state, err := SetRawTerminal(tty.Fd()) + require.NoError(t, err) + require.NotNil(t, state) + err = DisableEcho(tty.Fd(), state) + require.NoError(t, err) +}