git-lfs/git/pkt_line_test.go
Taylor Blau f89c31bae4 git/pl: flush underlying *bufio.Writer only when necessary
Previously, we flushed intermediate data out of the underlying *bufio.Writer
used by the implementation of `pkt-line` in `*git.pktline` after _every_ write.
This means that we would flush after partial packets, whole packets, and after
pkt-line flush sequences. This is unnecessary.

Let us instead flush only after an entire packet has been written, after
writing the `0000` flush sequence.

/ref git-lfs/git-lfs#1640
2016-11-15 14:35:21 -07:00

237 lines
4.9 KiB
Go

package git
import (
"bytes"
"io"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type PacketReadTestCase struct {
In []byte
Payload []byte
Err string
}
func (c *PacketReadTestCase) Assert(t *testing.T) {
buf := bytes.NewReader(c.In)
rw := newPktline(buf, nil)
pkt, err := rw.readPacket()
if len(c.Payload) > 0 {
assert.Equal(t, c.Payload, pkt)
} else {
assert.Empty(t, pkt)
}
if len(c.Err) > 0 {
require.NotNil(t, err)
assert.Equal(t, c.Err, err.Error())
} else {
assert.Nil(t, err)
}
}
func TestPktLineReadsWholePackets(t *testing.T) {
tc := &PacketReadTestCase{
In: []byte{
0x30, 0x30, 0x30, 0x38, // 0008 (hex. length)
0x1, 0x2, 0x3, 0x4, // payload
},
Payload: []byte{0x1, 0x2, 0x3, 0x4},
}
tc.Assert(t)
}
func TestPktLineNoPacket(t *testing.T) {
tc := &PacketReadTestCase{
In: []byte{},
Err: io.EOF.Error(),
}
tc.Assert(t)
}
func TestPktLineEmptyPacket(t *testing.T) {
tc := &PacketReadTestCase{
In: []byte{
0x30, 0x30, 0x30, 0x34,
// No body (invalid)
},
Err: "Invalid packet length.",
}
tc.Assert(t)
}
func TestPktLineFlushPacket(t *testing.T) {
tc := &PacketReadTestCase{
In: []byte{0x30, 0x30, 0x30, 0x30}, // Flush packet
Payload: []byte{},
Err: "",
}
tc.Assert(t)
}
func TestPktLineDiscardsPacketsWithUnparseableLength(t *testing.T) {
tc := &PacketReadTestCase{
In: []byte{
0xff, 0xff, 0xff, 0xff, // ÿÿÿÿ (invalid hex. length)
// No body
},
Err: "strconv.ParseInt: parsing \"\\xff\\xff\\xff\\xff\": invalid syntax",
}
tc.Assert(t)
}
func TestPktLineReadsTextWithNewline(t *testing.T) {
rw := newPktline(bytes.NewReader([]byte{
0x30, 0x30, 0x30, 0x39, // 0009 (hex. length)
0x61, 0x62, 0x63, 0x64, 0xa,
// Empty body
}), nil)
str, err := rw.readPacketText()
assert.Nil(t, err)
assert.Equal(t, "abcd", str)
}
func TestPktLineReadsTextWithoutNewline(t *testing.T) {
rw := newPktline(bytes.NewReader([]byte{
0x30, 0x30, 0x30, 0x38, // 0009 (hex. length)
0x61, 0x62, 0x63, 0x64,
}), nil)
str, err := rw.readPacketText()
assert.Nil(t, err)
assert.Equal(t, "abcd", str)
}
func TestPktLineReadsTextWithErr(t *testing.T) {
rw := newPktline(bytes.NewReader([]byte{
0x30, 0x30, 0x30, 0x34, // 0004 (hex. length)
// No body
}), nil)
str, err := rw.readPacketText()
require.NotNil(t, err)
assert.Equal(t, "Invalid packet length.", err.Error())
assert.Equal(t, "", str)
}
func TestPktLineAppendsPacketLists(t *testing.T) {
rw := newPktline(bytes.NewReader([]byte{
0x30, 0x30, 0x30, 0x38, // 0009 (hex. length)
0x61, 0x62, 0x63, 0x64, // "abcd"
0x30, 0x30, 0x30, 0x38, // 0008 (hex. length)
0x65, 0x66, 0x67, 0x68, // "efgh"
0x30, 0x30, 0x30, 0x30, // 0000 (hex. length)
}), nil)
str, err := rw.readPacketList()
assert.Nil(t, err)
assert.Equal(t, []string{"abcd", "efgh"}, str)
}
func TestPktLineAppendsPacketListsAndReturnsErrs(t *testing.T) {
rw := newPktline(bytes.NewReader([]byte{
0x30, 0x30, 0x30, 0x38, // 0009 (hex. length)
0x61, 0x62, 0x63, 0x64, // "abcd"
0x30, 0x30, 0x30, 0x34, // 0004 (hex. length)
// No body
}), nil)
str, err := rw.readPacketList()
require.NotNil(t, err)
assert.Equal(t, "Invalid packet length.", err.Error())
assert.Empty(t, str)
}
func TestPktLineWritesPackets(t *testing.T) {
var buf bytes.Buffer
rw := newPktline(nil, &buf)
require.Nil(t, rw.writePacket([]byte{
0x1, 0x2, 0x3, 0x4,
}))
require.Nil(t, rw.writeFlush())
assert.Equal(t, []byte{
0x30, 0x30, 0x30, 0x38, // 0008 (hex. length)
0x1, 0x2, 0x3, 0x4, // payload
0x30, 0x30, 0x30, 0x30, // 0000 (flush packet)
}, buf.Bytes())
}
func TestPktLineWritesPacketsEqualToMaxLength(t *testing.T) {
var buf bytes.Buffer
rw := newPktline(nil, &buf)
err := rw.writePacket(make([]byte, MaxPacketLength))
assert.Nil(t, err)
assert.Equal(t, 4+MaxPacketLength, len(buf.Bytes()))
}
func TestPktLineDoesNotWritePacketsExceedingMaxLength(t *testing.T) {
var buf bytes.Buffer
rw := newPktline(nil, &buf)
err := rw.writePacket(make([]byte, MaxPacketLength+1))
require.NotNil(t, err)
assert.Equal(t, "Packet length exceeds maximal length", err.Error())
assert.Empty(t, buf.Bytes())
}
func TestPktLineWritesPacketText(t *testing.T) {
var buf bytes.Buffer
rw := newPktline(nil, &buf)
require.Nil(t, rw.writePacketText("abcd"))
require.Nil(t, rw.writeFlush())
assert.Equal(t, []byte{
0x30, 0x30, 0x30, 0x39, // 0009 (hex. length)
0x61, 0x62, 0x63, 0x64, 0xa, // "abcd\n" (payload)
0x30, 0x30, 0x30, 0x30, // 0000 (flush packet)
}, buf.Bytes())
}
func TestPktLineWritesPacketLists(t *testing.T) {
var buf bytes.Buffer
rw := newPktline(nil, &buf)
err := rw.writePacketList([]string{"foo", "bar"})
assert.Nil(t, err)
assert.Equal(t, []byte{
0x30, 0x30, 0x30, 0x38, // 0008 (hex. length)
0x66, 0x6f, 0x6f, 0xa, // "foo\n" (payload)
0x30, 0x30, 0x30, 0x38, // 0008 (hex. length)
0x62, 0x61, 0x72, 0xa, // "bar\n" (payload)
0x30, 0x30, 0x30, 0x30, // 0000 (hex. length)
}, buf.Bytes())
}