tailscale/net/nettest/conn.go
David Crawshaw 41ac4a79d6 net/nettest: new package with net-like testing primitives
This is a lot like wiring up a local UDP socket, read and write
deadlines work. The big difference is the Block feature, which
lets you stop the packet flow without breaking the connection.
This lets you emulate broken sockets and test timeouts actually
work.

Signed-off-by: David Crawshaw <crawshaw@tailscale.com>
2020-03-12 14:42:48 -04:00

87 lines
2.0 KiB
Go

// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package nettest
import (
"io"
"time"
)
// Conn is a bi-directional in-memory stream that looks like a TCP net.Conn.
type Conn interface {
io.Reader
io.Writer
io.Closer
// The *Deadline methods follow the semantics of net.Conn.
SetDeadline(t time.Time) error
SetReadDeadline(t time.Time) error
SetWriteDeadline(t time.Time) error
// SetReadBlock blocks or unblocks the Read method of this Conn.
// It reports an error if the existing value matches the new value,
// or if the Conn has been Closed.
SetReadBlock(bool) error
// SetWriteBlock blocks or unblocks the Write method of this Conn.
// It reports an error if the existing value matches the new value,
// or if the Conn has been Closed.
SetWriteBlock(bool) error
}
// NewConn creates a pair of Conns that are wired together by pipes.
func NewConn(name string, maxBuf int) (Conn, Conn) {
r := NewPipe(name+"|0", maxBuf)
w := NewPipe(name+"|1", maxBuf)
return &connHalf{r: r, w: w}, &connHalf{r: w, w: r}
}
type connHalf struct {
r, w *Pipe
}
func (c *connHalf) Read(b []byte) (n int, err error) {
return c.r.Read(b)
}
func (c *connHalf) Write(b []byte) (n int, err error) {
return c.w.Write(b)
}
func (c *connHalf) Close() error {
err1 := c.r.Close()
err2 := c.w.Close()
if err1 != nil {
return err1
}
return err2
}
func (c *connHalf) SetDeadline(t time.Time) error {
err1 := c.SetReadDeadline(t)
err2 := c.SetWriteDeadline(t)
if err1 != nil {
return err1
}
return err2
}
func (c *connHalf) SetReadDeadline(t time.Time) error {
return c.r.SetReadDeadline(t)
}
func (c *connHalf) SetWriteDeadline(t time.Time) error {
return c.w.SetWriteDeadline(t)
}
func (c *connHalf) SetReadBlock(b bool) error {
if b {
return c.r.Block()
}
return c.r.Unblock()
}
func (c *connHalf) SetWriteBlock(b bool) error {
if b {
return c.w.Block()
}
return c.w.Unblock()
}