Merge pull request #43 from goshuirc/ircreader_bug
fix an edge case in IRCReader
This commit is contained in:
commit
2c4b83d648
@ -66,8 +66,12 @@ func (cc *IRCReader) ReadLine() ([]byte, error) {
|
||||
return line, nil
|
||||
}
|
||||
|
||||
if cc.start == 0 && len(cc.buf) == cc.maxSize {
|
||||
return nil, ErrReadQ // out of space, can't expand or slide
|
||||
// are we out of space? we can read more if any of these are true:
|
||||
// 1. cc.start != 0, so we can slide the existing data back
|
||||
// 2. cc.end < len(cc.buf), so we can read data into the end of the buffer
|
||||
// 3. len(cc.buf) < cc.maxSize, so we can grow the buffer
|
||||
if cc.start == 0 && cc.end == len(cc.buf) && len(cc.buf) == cc.maxSize {
|
||||
return nil, ErrReadQ
|
||||
}
|
||||
|
||||
if cc.eof {
|
||||
|
@ -4,6 +4,7 @@
|
||||
package ircreader
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
@ -107,3 +108,67 @@ func TestLineReader(t *testing.T) {
|
||||
doLineReaderTest(counts, t)
|
||||
}
|
||||
}
|
||||
|
||||
type mockConnLimits struct {
|
||||
// simulates the arrival of data via TCP;
|
||||
// each Read() call will read from at most one of the slices
|
||||
reads [][]byte
|
||||
}
|
||||
|
||||
func (c *mockConnLimits) Read(b []byte) (n int, err error) {
|
||||
if len(c.reads) == 0 {
|
||||
return n, io.EOF
|
||||
}
|
||||
readLen := min(len(c.reads[0]), len(b))
|
||||
copy(b[:readLen], c.reads[0][:readLen])
|
||||
c.reads[0] = c.reads[0][readLen:]
|
||||
if len(c.reads[0]) == 0 {
|
||||
c.reads = c.reads[1:]
|
||||
}
|
||||
return readLen, nil
|
||||
}
|
||||
|
||||
func makeLine(length int, ending bool) (result []byte) {
|
||||
totalLen := length
|
||||
if ending {
|
||||
totalLen++
|
||||
}
|
||||
result = make([]byte, totalLen)
|
||||
for i := 0; i < length; i++ {
|
||||
result[i] = 'a'
|
||||
}
|
||||
if ending {
|
||||
result[len(result)-1] = '\n'
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func assertEqual(found, expected interface{}) {
|
||||
if !reflect.DeepEqual(found, expected) {
|
||||
panic(fmt.Sprintf("expected %#v, found %#v", expected, found))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegression(t *testing.T) {
|
||||
var c mockConnLimits
|
||||
// this read fills up the buffer with a terminated line:
|
||||
c.reads = append(c.reads, makeLine(4605, true))
|
||||
// this is a large, unterminated read:
|
||||
c.reads = append(c.reads, makeLine(4095, false))
|
||||
// this terminates the previous read, within the acceptable limit:
|
||||
c.reads = append(c.reads, makeLine(500, true))
|
||||
|
||||
var cc IRCReader
|
||||
cc.Initialize(&c, 512, 4096+512)
|
||||
|
||||
line, err := cc.ReadLine()
|
||||
assertEqual(len(line), 4605)
|
||||
assertEqual(err, nil)
|
||||
|
||||
line, err = cc.ReadLine()
|
||||
assertEqual(len(line), 4595)
|
||||
assertEqual(err, nil)
|
||||
|
||||
line, err = cc.ReadLine()
|
||||
assertEqual(err, io.EOF)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user