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
|
return line, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if cc.start == 0 && len(cc.buf) == cc.maxSize {
|
// are we out of space? we can read more if any of these are true:
|
||||||
return nil, ErrReadQ // out of space, can't expand or slide
|
// 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 {
|
if cc.eof {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
package ircreader
|
package ircreader
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -107,3 +108,67 @@ func TestLineReader(t *testing.T) {
|
|||||||
doLineReaderTest(counts, 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