package cli import ( "bytes" "io" "net" "testing" "time" ) type fragmentConn struct { chunks [][]byte written bytes.Buffer } func (c *fragmentConn) Read(p []byte) (int, error) { if len(c.chunks) == 0 { return 0, io.EOF } b := c.chunks[0] n := copy(p, b) if n == len(b) { c.chunks = c.chunks[1:] } else { c.chunks[0] = b[n:] } return n, nil } func (c *fragmentConn) Write(p []byte) (int, error) { return c.written.Write(p) } func (c *fragmentConn) Close() error { return nil } func (c *fragmentConn) LocalAddr() net.Addr { return nil } func (c *fragmentConn) RemoteAddr() net.Addr { return nil } func (c *fragmentConn) SetDeadline(time.Time) error { return nil } func (c *fragmentConn) SetReadDeadline(time.Time) error { return nil } func (c *fragmentConn) SetWriteDeadline(time.Time) error { return nil } func TestTelnetFragmentedNegotiationAndNewline(t *testing.T) { c := &fragmentConn{chunks: [][]byte{{'a', iac}, {do}, {optEcho, '\r'}, {'\n', 'b'}}} tc := NewTelnetConn(c) got, err := io.ReadAll(tc) if err != nil || string(got) != "a\nb" { t.Fatalf("got %q, %v", got, err) } if !bytes.Contains(c.written.Bytes(), []byte{iac, will, optEcho}) { t.Fatal("missing option response") } n, err := tc.Write([]byte("a\nb")) if err != nil || n != 3 { t.Fatalf("write %d %v", n, err) } }