mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-25 21:39:25 +01:00
add a fuzz test for IRCStreamConn changes
This commit is contained in:
parent
c78253fd93
commit
a34918e729
135
irc/ircconn_test.go
Normal file
135
irc/ircconn_test.go
Normal file
@ -0,0 +1,135 @@
|
||||
// Copyright (c) 2020 Shivaram Lingamneni <slingamn@cs.stanford.edu>
|
||||
// released under the MIT license
|
||||
|
||||
package irc
|
||||
|
||||
import (
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/oragono/oragono/irc/utils"
|
||||
)
|
||||
|
||||
// mockConn is a fake net.Conn / io.Reader that yields len(counts) lines,
|
||||
// each consisting of counts[i] 'a' characters and a terminating '\n'
|
||||
type mockConn struct {
|
||||
counts []int
|
||||
}
|
||||
|
||||
func min(i, j int) (m int) {
|
||||
if i < j {
|
||||
return i
|
||||
} else {
|
||||
return j
|
||||
}
|
||||
}
|
||||
|
||||
func (c *mockConn) Read(b []byte) (n int, err error) {
|
||||
for len(b) > 0 {
|
||||
if len(c.counts) == 0 {
|
||||
return n, io.EOF
|
||||
}
|
||||
if c.counts[0] == 0 {
|
||||
b[0] = '\n'
|
||||
c.counts = c.counts[1:]
|
||||
b = b[1:]
|
||||
n += 1
|
||||
continue
|
||||
}
|
||||
size := min(c.counts[0], len(b))
|
||||
for i := 0; i < size; i++ {
|
||||
b[i] = 'a'
|
||||
}
|
||||
c.counts[0] -= size
|
||||
b = b[size:]
|
||||
n += size
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (c *mockConn) Write(b []byte) (n int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (c *mockConn) Close() error {
|
||||
c.counts = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *mockConn) LocalAddr() net.Addr {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *mockConn) RemoteAddr() net.Addr {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *mockConn) SetDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *mockConn) SetReadDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *mockConn) SetWriteDeadline(t time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func newMockConn(counts []int) *utils.WrappedConn {
|
||||
cpCounts := make([]int, len(counts))
|
||||
copy(cpCounts, counts)
|
||||
c := &mockConn{
|
||||
counts: cpCounts,
|
||||
}
|
||||
return &utils.WrappedConn{
|
||||
Conn: c,
|
||||
}
|
||||
}
|
||||
|
||||
// construct a mock reader with some number of \n-terminated lines,
|
||||
// verify that IRCStreamConn can read and split them as expected
|
||||
func doLineReaderTest(counts []int, t *testing.T) {
|
||||
c := newMockConn(counts)
|
||||
r := NewIRCStreamConn(c)
|
||||
var readCounts []int
|
||||
for {
|
||||
line, err := r.ReadLine()
|
||||
if err == nil {
|
||||
readCounts = append(readCounts, len(line))
|
||||
} else if err == io.EOF {
|
||||
break
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(counts, readCounts) {
|
||||
t.Errorf("expected %#v, got %#v", counts, readCounts)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
maxMockReaderLen = 100
|
||||
maxMockReaderLineLen = 4096 + 511
|
||||
)
|
||||
|
||||
func TestLineReader(t *testing.T) {
|
||||
counts := []int{44, 428, 3, 0, 200, 2000, 0, 4044, 33, 3, 2, 1, 0, 1, 2, 3, 48, 555}
|
||||
doLineReaderTest(counts, t)
|
||||
|
||||
// fuzz
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
for i := 0; i < 1000; i++ {
|
||||
countsLen := r.Intn(maxMockReaderLen) + 1
|
||||
counts := make([]int, countsLen)
|
||||
for i := 0; i < countsLen; i++ {
|
||||
counts[i] = r.Intn(maxMockReaderLineLen)
|
||||
}
|
||||
doLineReaderTest(counts, t)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user