11 // FuzzModeDrop is a mode in which we randomly drop reads/writes, connections or sleep
13 // FuzzModeDelay is a mode in which we randomly sleep
17 // FuzzedConnection wraps any net.Conn and depending on the mode either delays
18 // reads/writes or randomly drops reads/writes/connections.
19 type FuzzedConnection struct {
23 start <-chan time.Time
26 config *FuzzConnConfig
29 // FuzzConnConfig is a FuzzedConnection configuration.
30 type FuzzConnConfig struct {
32 MaxDelay time.Duration
38 // DefaultFuzzConnConfig returns the default config.
39 func DefaultFuzzConnConfig() *FuzzConnConfig {
40 return &FuzzConnConfig{
42 MaxDelay: 3 * time.Second,
49 // FuzzConn creates a new FuzzedConnection. Fuzzing starts immediately.
50 func FuzzConn(conn net.Conn) net.Conn {
51 return FuzzConnFromConfig(conn, DefaultFuzzConnConfig())
54 // FuzzConnFromConfig creates a new FuzzedConnection from a config. Fuzzing
55 // starts immediately.
56 func FuzzConnFromConfig(conn net.Conn, config *FuzzConnConfig) net.Conn {
57 return &FuzzedConnection{
59 start: make(<-chan time.Time),
65 // FuzzConnAfter creates a new FuzzedConnection. Fuzzing starts when the
67 func FuzzConnAfter(conn net.Conn, d time.Duration) net.Conn {
68 return FuzzConnAfterFromConfig(conn, d, DefaultFuzzConnConfig())
71 // FuzzConnAfterFromConfig creates a new FuzzedConnection from a config.
72 // Fuzzing starts when the duration elapses.
73 func FuzzConnAfterFromConfig(conn net.Conn, d time.Duration, config *FuzzConnConfig) net.Conn {
74 return &FuzzedConnection{
82 // Config returns the connection's config.
83 func (fc *FuzzedConnection) Config() *FuzzConnConfig {
87 // Read implements net.Conn.
88 func (fc *FuzzedConnection) Read(data []byte) (n int, err error) {
92 return fc.conn.Read(data)
95 // Write implements net.Conn.
96 func (fc *FuzzedConnection) Write(data []byte) (n int, err error) {
100 return fc.conn.Write(data)
103 // Close implements net.Conn.
104 func (fc *FuzzedConnection) Close() error { return fc.conn.Close() }
106 // LocalAddr implements net.Conn.
107 func (fc *FuzzedConnection) LocalAddr() net.Addr { return fc.conn.LocalAddr() }
109 // RemoteAddr implements net.Conn.
110 func (fc *FuzzedConnection) RemoteAddr() net.Addr { return fc.conn.RemoteAddr() }
112 // SetDeadline implements net.Conn.
113 func (fc *FuzzedConnection) SetDeadline(t time.Time) error { return fc.conn.SetDeadline(t) }
115 // SetReadDeadline implements net.Conn.
116 func (fc *FuzzedConnection) SetReadDeadline(t time.Time) error {
117 return fc.conn.SetReadDeadline(t)
120 // SetWriteDeadline implements net.Conn.
121 func (fc *FuzzedConnection) SetWriteDeadline(t time.Time) error {
122 return fc.conn.SetWriteDeadline(t)
125 func (fc *FuzzedConnection) randomDuration() time.Duration {
126 maxDelayMillis := int(fc.config.MaxDelay.Nanoseconds() / 1000)
127 return time.Millisecond * time.Duration(rand.Int()%maxDelayMillis)
130 // implements the fuzz (delay, kill conn)
131 // and returns whether or not the read/write should be ignored
132 func (fc *FuzzedConnection) fuzz() bool {
133 if !fc.shouldFuzz() {
137 switch fc.config.Mode {
139 // randomly drop the r/w, drop the conn, or sleep
141 if r <= fc.config.ProbDropRW {
143 } else if r < fc.config.ProbDropRW+fc.config.ProbDropConn {
144 // XXX: can't this fail because machine precision?
145 // XXX: do we need an error?
148 } else if r < fc.config.ProbDropRW+fc.config.ProbDropConn+fc.config.ProbSleep {
149 time.Sleep(fc.randomDuration())
153 time.Sleep(fc.randomDuration())
158 func (fc *FuzzedConnection) shouldFuzz() bool {
164 defer fc.mtx.Unlock()