[fuzz] only one way to set config variables

This commit is contained in:
Anton Kaliaev 2017-04-13 11:55:14 +04:00
parent 7dcc3dbcd1
commit 5965578c56
No known key found for this signature in database
GPG Key ID: 7B6881D965918214
2 changed files with 94 additions and 111 deletions

203
fuzz.go
View File

@ -1,7 +1,6 @@
package p2p package p2p
import ( import (
"fmt"
"math/rand" "math/rand"
"net" "net"
"sync" "sync"
@ -15,58 +14,6 @@ const (
FuzzModeDelay FuzzModeDelay
) )
type FuzzConnConfig struct {
Mode int
MaxDelay time.Duration
ProbDropRW float64
ProbDropConn float64
ProbSleep float64
}
func defaultFuzzConnConfig() *FuzzConnConfig {
return &FuzzConnConfig{
Mode: FuzzModeDrop,
MaxDelay: 3 * time.Second,
ProbDropRW: 0.2,
ProbDropConn: 0.00,
ProbSleep: 0.00,
}
}
func FuzzConn(conn net.Conn) net.Conn {
return FuzzConnFromConfig(conn, defaultFuzzConnConfig())
}
func FuzzConnFromConfig(conn net.Conn, config *FuzzConnConfig) net.Conn {
return &FuzzedConnection{
conn: conn,
start: make(<-chan time.Time),
active: true,
mode: config.Mode,
maxDelay: config.MaxDelay,
probDropRW: config.ProbDropRW,
probDropConn: config.ProbDropConn,
probSleep: config.ProbSleep,
}
}
func FuzzConnAfter(conn net.Conn, d time.Duration) net.Conn {
return FuzzConnAfterFromConfig(conn, d, defaultFuzzConnConfig())
}
func FuzzConnAfterFromConfig(conn net.Conn, d time.Duration, config *FuzzConnConfig) net.Conn {
return &FuzzedConnection{
conn: conn,
start: time.After(d),
active: false,
mode: config.Mode,
maxDelay: config.MaxDelay,
probDropRW: config.ProbDropRW,
probDropConn: config.ProbDropConn,
probSleep: config.ProbSleep,
}
}
// FuzzedConnection wraps any net.Conn and depending on the mode either delays // FuzzedConnection wraps any net.Conn and depending on the mode either delays
// reads/writes or randomly drops reads/writes/connections. // reads/writes or randomly drops reads/writes/connections.
type FuzzedConnection struct { type FuzzedConnection struct {
@ -76,43 +23,108 @@ type FuzzedConnection struct {
start <-chan time.Time start <-chan time.Time
active bool active bool
mode int config *FuzzConnConfig
maxDelay time.Duration
probDropRW float64
probDropConn float64
probSleep float64
} }
func (fc *FuzzedConnection) randomDuration() time.Duration { // FuzzConnConfig is a FuzzedConnection configuration.
maxDelayMillis := int(fc.maxDelay.Nanoseconds() / 1000) type FuzzConnConfig struct {
return time.Millisecond * time.Duration(rand.Int()%maxDelayMillis) Mode int
MaxDelay time.Duration
ProbDropRW float64
ProbDropConn float64
ProbSleep float64
} }
func (fc *FuzzedConnection) SetMode(mode int) { // DefaultFuzzConnConfig returns the default config.
switch mode { func DefaultFuzzConnConfig() *FuzzConnConfig {
case FuzzModeDrop: return &FuzzConnConfig{
fc.mode = FuzzModeDrop Mode: FuzzModeDrop,
case FuzzModeDelay: MaxDelay: 3 * time.Second,
fc.mode = FuzzModeDelay ProbDropRW: 0.2,
default: ProbDropConn: 0.00,
panic(fmt.Sprintf("Unknown mode %d", mode)) ProbSleep: 0.00,
} }
} }
func (fc *FuzzedConnection) SetProbDropRW(prob float64) { // FuzzConn creates a new FuzzedConnection. Fuzzing starts immediately.
fc.probDropRW = prob func FuzzConn(conn net.Conn) net.Conn {
return FuzzConnFromConfig(conn, DefaultFuzzConnConfig())
} }
func (fc *FuzzedConnection) SetProbDropConn(prob float64) { // FuzzConnFromConfig creates a new FuzzedConnection from a config. Fuzzing
fc.probDropConn = prob // starts immediately.
func FuzzConnFromConfig(conn net.Conn, config *FuzzConnConfig) net.Conn {
return &FuzzedConnection{
conn: conn,
start: make(<-chan time.Time),
active: true,
config: config,
}
} }
func (fc *FuzzedConnection) SetProbSleep(prob float64) { // FuzzConnAfter creates a new FuzzedConnection. Fuzzing starts when the
fc.probSleep = prob // duration elapses.
func FuzzConnAfter(conn net.Conn, d time.Duration) net.Conn {
return FuzzConnAfterFromConfig(conn, d, DefaultFuzzConnConfig())
} }
func (fc *FuzzedConnection) SetMaxDelay(d time.Duration) { // FuzzConnAfterFromConfig creates a new FuzzedConnection from a config.
fc.maxDelay = d // Fuzzing starts when the duration elapses.
func FuzzConnAfterFromConfig(conn net.Conn, d time.Duration, config *FuzzConnConfig) net.Conn {
return &FuzzedConnection{
conn: conn,
start: time.After(d),
active: false,
config: config,
}
}
// Config returns the connection's config.
func (fc *FuzzedConnection) Config() *FuzzConnConfig {
return fc.config
}
// Read implements net.Conn.
func (fc *FuzzedConnection) Read(data []byte) (n int, err error) {
if fc.fuzz() {
return 0, nil
}
return fc.conn.Read(data)
}
// Write implements net.Conn.
func (fc *FuzzedConnection) Write(data []byte) (n int, err error) {
if fc.fuzz() {
return 0, nil
}
return fc.conn.Write(data)
}
// Close implements net.Conn.
func (fc *FuzzedConnection) Close() error { return fc.conn.Close() }
// LocalAddr implements net.Conn.
func (fc *FuzzedConnection) LocalAddr() net.Addr { return fc.conn.LocalAddr() }
// RemoteAddr implements net.Conn.
func (fc *FuzzedConnection) RemoteAddr() net.Addr { return fc.conn.RemoteAddr() }
// SetDeadline implements net.Conn.
func (fc *FuzzedConnection) SetDeadline(t time.Time) error { return fc.conn.SetDeadline(t) }
// SetReadDeadline implements net.Conn.
func (fc *FuzzedConnection) SetReadDeadline(t time.Time) error {
return fc.conn.SetReadDeadline(t)
}
// SetWriteDeadline implements net.Conn.
func (fc *FuzzedConnection) SetWriteDeadline(t time.Time) error {
return fc.conn.SetWriteDeadline(t)
}
func (fc *FuzzedConnection) randomDuration() time.Duration {
maxDelayMillis := int(fc.config.MaxDelay.Nanoseconds() / 1000)
return time.Millisecond * time.Duration(rand.Int()%maxDelayMillis)
} }
// implements the fuzz (delay, kill conn) // implements the fuzz (delay, kill conn)
@ -122,18 +134,18 @@ func (fc *FuzzedConnection) fuzz() bool {
return false return false
} }
switch fc.mode { switch fc.config.Mode {
case FuzzModeDrop: case FuzzModeDrop:
// randomly drop the r/w, drop the conn, or sleep // randomly drop the r/w, drop the conn, or sleep
r := rand.Float64() r := rand.Float64()
if r <= fc.probDropRW { if r <= fc.config.ProbDropRW {
return true return true
} else if r < fc.probDropRW+fc.probDropConn { } else if r < fc.config.ProbDropRW+fc.config.ProbDropConn {
// XXX: can't this fail because machine precision? // XXX: can't this fail because machine precision?
// XXX: do we need an error? // XXX: do we need an error?
fc.Close() fc.Close()
return true return true
} else if r < fc.probDropRW+fc.probDropConn+fc.probSleep { } else if r < fc.config.ProbDropRW+fc.config.ProbDropConn+fc.config.ProbSleep {
time.Sleep(fc.randomDuration()) time.Sleep(fc.randomDuration())
} }
case FuzzModeDelay: case FuzzModeDelay:
@ -143,7 +155,6 @@ func (fc *FuzzedConnection) fuzz() bool {
return false return false
} }
// we don't fuzz until start chan fires
func (fc *FuzzedConnection) shouldFuzz() bool { func (fc *FuzzedConnection) shouldFuzz() bool {
if fc.active { if fc.active {
return true return true
@ -160,31 +171,3 @@ func (fc *FuzzedConnection) shouldFuzz() bool {
return false return false
} }
} }
// Read implements net.Conn
func (fc *FuzzedConnection) Read(data []byte) (n int, err error) {
if fc.fuzz() {
return 0, nil
}
return fc.conn.Read(data)
}
// Write implements net.Conn
func (fc *FuzzedConnection) Write(data []byte) (n int, err error) {
if fc.fuzz() {
return 0, nil
}
return fc.conn.Write(data)
}
// Implements net.Conn
func (fc *FuzzedConnection) Close() error { return fc.conn.Close() }
func (fc *FuzzedConnection) LocalAddr() net.Addr { return fc.conn.LocalAddr() }
func (fc *FuzzedConnection) RemoteAddr() net.Addr { return fc.conn.RemoteAddr() }
func (fc *FuzzedConnection) SetDeadline(t time.Time) error { return fc.conn.SetDeadline(t) }
func (fc *FuzzedConnection) SetReadDeadline(t time.Time) error {
return fc.conn.SetReadDeadline(t)
}
func (fc *FuzzedConnection) SetWriteDeadline(t time.Time) error {
return fc.conn.SetWriteDeadline(t)
}

View File

@ -52,7 +52,7 @@ func defaultPeerConfig() *PeerConfig {
HandshakeTimeout: 20 * time.Second, HandshakeTimeout: 20 * time.Second,
DialTimeout: 3 * time.Second, DialTimeout: 3 * time.Second,
MConfig: defaultMConnectionConfig(), MConfig: defaultMConnectionConfig(),
FuzzConfig: defaultFuzzConnConfig(), FuzzConfig: DefaultFuzzConnConfig(),
} }
} }