Skip to content

Commit d674aa1

Browse files
committed
Fix existing tests
Fixes #13
1 parent bffd821 commit d674aa1

File tree

1 file changed

+116
-48
lines changed

1 file changed

+116
-48
lines changed

webtty/webtty_test.go

Lines changed: 116 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -9,52 +9,65 @@ import (
99
"testing"
1010
)
1111

12-
type pipePair struct {
13-
*io.PipeReader
14-
*io.PipeWriter
12+
type mockMaster struct {
13+
gottyToMasterReader io.Reader
14+
gottyToMasterWriter io.Writer
15+
masterToGottyReader io.Reader
16+
masterToGottyWriter io.Writer
17+
}
18+
19+
type mockSlave struct {
20+
gottyToSlaveReader io.Reader
21+
gottyToSlaveWriter io.Writer
22+
slaveToGottyReader io.Reader
23+
slaveToGottyWriter io.Writer
24+
columns, rows int
1525
}
1626

1727
func TestWriteFromPTY(t *testing.T) {
18-
connInPipeReader, connInPipeWriter := io.Pipe() // in to conn
19-
connOutPipeReader, _ := io.Pipe() // out from conn
28+
mMaster := newMockMaster()
29+
mSlave := newMockSlave()
2030

21-
conn := pipePair{
22-
connOutPipeReader,
23-
connInPipeWriter,
24-
}
25-
dt, err := New(conn)
31+
dt, err := New(mMaster, mSlave)
2632
if err != nil {
2733
t.Fatalf("Unexpected error from New(): %s", err)
2834
}
2935

36+
// Launch GoTTY
3037
ctx, cancel := context.WithCancel(context.Background())
3138
var wg sync.WaitGroup
3239
wg.Add(1)
3340
go func() {
3441
wg.Done()
35-
err := dt.Run(ctx)
36-
if err != nil {
37-
t.Fatalf("Unexpected error from Run(): %s", err)
38-
}
42+
dt.Run(ctx)
3943
}()
4044

41-
message := []byte("foobar")
42-
n, err := dt.TTY().Write(message)
43-
if err != nil {
44-
t.Fatalf("Unexpected error from Write(): %s", err)
45-
}
46-
if n != len(message) {
47-
t.Fatalf("Write() accepted `%d` for message `%s`", n, message)
48-
}
45+
// Check that the initialization happens as expected
46+
checkNextMsgType(t, mMaster.gottyToMasterReader, SetWindowTitle)
47+
checkNextMsgType(t, mMaster.gottyToMasterReader, SetBufferSize)
4948

49+
// Simulate the slave (the process being run by GoTTY)
50+
// echoing "foobar"
5051
buf := make([]byte, 1024)
51-
n, err = connInPipeReader.Read(buf)
52+
message := []byte("foobar")
53+
54+
wg.Add(1)
55+
go func() {
56+
dt.handleSlaveReadEvent(message)
57+
wg.Done()
58+
}()
59+
60+
// And then make sure it makes it way to the client
61+
// through the websocket as an output message
62+
n, err := mMaster.gottyToMasterReader.Read(buf)
5263
if err != nil {
5364
t.Fatalf("Unexpected error from Read(): %s", err)
5465
}
5566
if buf[0] != Output {
5667
t.Fatalf("Unexpected message type `%c`", buf[0])
5768
}
69+
70+
// Decode it and make sure it's intact
5871
decoded := make([]byte, 1024)
5972
n, err = base64.StdEncoding.Decode(decoded, buf[1:n])
6073
if err != nil {
@@ -68,29 +81,38 @@ func TestWriteFromPTY(t *testing.T) {
6881
wg.Wait()
6982
}
7083

71-
func TestWriteFromConn(t *testing.T) {
72-
connInPipeReader, connInPipeWriter := io.Pipe() // in to conn
73-
connOutPipeReader, connOutPipeWriter := io.Pipe() // out from conn
84+
func checkNextMsgType(t *testing.T, connInPipeReader io.Reader, expected byte) {
85+
msgType, _ := nextMsg(t, connInPipeReader)
86+
if msgType != expected {
87+
t.Fatalf("Unexpected message type `%c`", msgType)
88+
}
89+
}
7490

75-
conn := pipePair{
76-
connOutPipeReader,
77-
connInPipeWriter,
91+
func nextMsg(t *testing.T, reader io.Reader) (byte, []byte) {
92+
buf := make([]byte, 1024)
93+
_, err := reader.Read(buf)
94+
if err != nil {
95+
t.Fatalf("unexpected error %v", err)
7896
}
97+
return buf[0], buf[1:]
98+
}
7999

80-
dt, err := New(conn)
100+
func TestWriteFromConn(t *testing.T) {
101+
mMaster := newMockMaster()
102+
mSlave := newMockSlave()
103+
104+
dt, err := New(mMaster, mSlave, WithPermitWrite())
81105
if err != nil {
82106
t.Fatalf("Unexpected error from New(): %s", err)
83107
}
84108

109+
// Launch GoTTY
85110
ctx, cancel := context.WithCancel(context.Background())
86111
var wg sync.WaitGroup
87112
wg.Add(1)
88113
go func() {
89114
wg.Done()
90-
err := dt.Run(ctx)
91-
if err != nil {
92-
t.Fatalf("Unexpected error from Run(): %s", err)
93-
}
115+
dt.Run(ctx)
94116
}()
95117

96118
var (
@@ -99,17 +121,20 @@ func TestWriteFromConn(t *testing.T) {
99121
)
100122
readBuf := make([]byte, 1024)
101123

102-
// input
103-
message = []byte("0hello\n") // line buffered canonical mode
104-
n, err = connOutPipeWriter.Write(message)
105-
if err != nil {
106-
t.Fatalf("Unexpected error from Write(): %s", err)
107-
}
108-
if n != len(message) {
109-
t.Fatalf("Write() accepted `%d` for message `%s`", n, message)
110-
}
124+
// Absorb initialization messages
125+
mMaster.gottyToMasterReader.Read(readBuf)
126+
mMaster.gottyToMasterReader.Read(readBuf)
127+
128+
// simulate input from frontend...
129+
message = []byte("1hello\n") // line buffered canonical mode
130+
wg.Add(1)
131+
go func() {
132+
dt.handleMasterReadEvent(message)
133+
wg.Done()
134+
}()
111135

112-
n, err = dt.TTY().Read(readBuf)
136+
// ...and make sure it makes it through to the slave intact
137+
n, err = mSlave.gottyToSlaveReader.Read(readBuf)
113138
if err != nil {
114139
t.Fatalf("Unexpected error from Write(): %s", err)
115140
}
@@ -118,17 +143,20 @@ func TestWriteFromConn(t *testing.T) {
118143
}
119144

120145
// ping
121-
message = []byte("1\n") // line buffered canonical mode
122-
n, err = connOutPipeWriter.Write(message)
146+
message = []byte("2\n") // line buffered canonical mode
147+
n, err = mMaster.masterToGottyWriter.Write(message)
148+
if err != nil {
149+
t.Fatalf("Unexpected error from Write(): %s", err)
150+
}
123151
if n != len(message) {
124152
t.Fatalf("Write() accepted `%d` for message `%s`", n, message)
125153
}
126154

127-
n, err = connInPipeReader.Read(readBuf)
155+
n, err = mMaster.gottyToMasterReader.Read(readBuf)
128156
if err != nil {
129157
t.Fatalf("Unexpected error from Read(): %s", err)
130158
}
131-
if !bytes.Equal(readBuf[:n], []byte{'1'}) {
159+
if !bytes.Equal(readBuf[:n], []byte{'2'}) {
132160
t.Fatalf("Unexpected message received: `%s`", readBuf[:n])
133161
}
134162

@@ -137,3 +165,43 @@ func TestWriteFromConn(t *testing.T) {
137165
cancel()
138166
wg.Wait()
139167
}
168+
169+
func newMockMaster() *mockMaster {
170+
rv := &mockMaster{}
171+
rv.gottyToMasterReader, rv.gottyToMasterWriter = io.Pipe()
172+
rv.masterToGottyReader, rv.masterToGottyWriter = io.Pipe()
173+
return rv
174+
}
175+
176+
func (mm *mockMaster) Read(buf []byte) (int, error) {
177+
return mm.masterToGottyReader.Read(buf)
178+
}
179+
180+
func (mm *mockMaster) Write(buf []byte) (int, error) {
181+
return mm.gottyToMasterWriter.Write(buf)
182+
}
183+
184+
func newMockSlave() *mockSlave {
185+
rv := &mockSlave{}
186+
rv.gottyToSlaveReader, rv.gottyToSlaveWriter = io.Pipe()
187+
rv.slaveToGottyReader, rv.slaveToGottyWriter = io.Pipe()
188+
return rv
189+
}
190+
191+
func (ms *mockSlave) Read(buf []byte) (int, error) {
192+
return ms.slaveToGottyReader.Read(buf)
193+
}
194+
195+
func (ms *mockSlave) Write(buf []byte) (int, error) {
196+
return ms.gottyToSlaveWriter.Write(buf)
197+
}
198+
199+
func (ms *mockSlave) WindowTitleVariables() map[string]interface{} {
200+
return nil
201+
}
202+
203+
func (ms *mockSlave) ResizeTerminal(columns int, rows int) error {
204+
ms.columns = columns
205+
ms.rows = rows
206+
return nil
207+
}

0 commit comments

Comments
 (0)