netmock

package module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 27, 2021 License: MIT Imports: 8 Imported by: 0

README

netmock: Simulate Go network connections

netmock is a Go package for simulating net connections, including delays and disconnects.

This is work in progress. The README will be updated with future commits.

Acknowledgements

Parts of netmock have been adapted from the bufconn package from grpc-go.

Documentation

Overview

Package netmock is a mock implementation of a subset of the net package.

netmock simulates TCP-like (i.e., reliable, ordered, error-checked) communication between hosts on a network. Additionally, netmock allows for simulating characteristics of real-world networks such as link latency and network partitions. Payload data is transferred via in-memory buffers in a thread-safe manner.

Hosts are added to a network using the AddHost method. A host belongs to exactly one network (the network that it was created on). Within that network, the host is uniquely identified by one or more addresses assigned at creation. Addresses are not constrained to IP addresses, but can be arbitrary names consisting from letters (a-z, A-Z), digits (0-9), hyphens (-), colons (:), and periods (.). The first address from the slice of assigned addresses is selected as the host's "canonical" address. This address is used to identify the host when opening new connections to other hosts. Note that, as of now, netmock has no concept of ports.

nw :=  netmock.NewNetwork()

host, err:= nw.AddHost("localhost:8080")
if err != nil {
    // handle error (address already assigned, invalid address, etc.)
}

// Hosts can have multiple addresses. The first address is picked as the canonical address.
dwarves, err := nw.AddHost("Doc", "Grumpy", "Happy", "Sleepy", "Bashful". "Sneezy", "Dopey")
dwarves.Addr() // "Doc"

Connections between hosts are established using functions analogous to those found in the net package: Listen(), Dial(), and DialContext().

// server goroutine
ln, err := h1.Listen("localhost:8080")
if err != nil {
    // handle error
}

for {
    conn, err := ln.Accept()
    if err != nil {
        // handle error
    }
    go handleConnection(conn)
}

// client goroutine
conn, err := h2.Dial("localhost:8080")
if err != nil {
    // handle error
}

Delays between hosts can be configured on an address-to-address basis using the network's SetDelay method. The delay is applied to all existing and future connections between the specified addresses until a new delay is specified. As of now, delays are always symmetric.

n.SetDelay("localhost:8080", "localhost:8081", 100 * time.Millisecond)

Hosts can be disconnected from the network using the Disconnect method. Existing connections will remain intact (i.e., are not closed), but will be unable to send or receive data. Similarly, dialing the disconnected host will result in an error. A disconnected host can be re-connected to the network using the Connect method.

Delays are always incurred on the reader side. Writing to a conn is guaranteed to succeed immediately, provided that the underlying buffer has sufficient capacity and the conn has not been closed. This mimics the behavior of TCP connections, where outgoing data is buffered by the OS before being sent over the network. From this perspective, a disconnected host experiences an infinite delay (until being reconnected to the network).

Index

Constants

View Source
const DefaultBufSize int = 16384

DefaultBufSize is the default size (in bytes) of the internal buffer created for new connections between hosts.

Variables

View Source
var ErrAddrInUse = errors.New("addr in use")
View Source
var ErrClosed = errors.New("closed")
View Source
var ErrConnRefused = errors.New("connection refused")
View Source
var ErrInvalidAddr = errors.New("invalid address")
View Source
var ErrNoAddrs = errors.New("no addresses")
View Source
var ErrNoRoute = errors.New("no route")
View Source
var ErrTimeout net.Error = netErrorTimeout{fmt.Errorf("timeout")}
View Source
var ErrUnknownAddr = errors.New("unknown address")

Functions

This section is empty.

Types

type Host

type Host struct {
	// contains filtered or unexported fields
}

A Host represents a member of a network.

Multiple goroutines may invoke methods on a Host simultaneously.

func (*Host) Addr

func (h *Host) Addr() net.Addr

Addr returns the canonical address of this host.

func (*Host) Connect

func (h *Host) Connect()

Connect connects this host to the network.

Reconnecting a disconnected host will reverse the effects invoked by Disconnect. In particular, connections involving this host will resume operation, listeners will be able to accept new connections, and new connections can be dialed.

This method is idempotent; it has no effect if the host is already connected.

func (*Host) Dial

func (h *Host) Dial(address string) (net.Conn, error)

Dial connects to the given address.

Calling dial on a disconnected host will return an error. Similarly, specifying an invalid or unassigned address, or an adress that refers to a disconnected target host will also return an error.

To specify a timeout or cancel dialling preemptively, use DialContext.

func (*Host) DialContext

func (h *Host) DialContext(ctx context.Context, address string) (net.Conn, error)

func (*Host) Disconnect

func (h *Host) Disconnect()

Disconnect disconnects this host from the network.

When called on a connected host, all existing connections involving the host will stop operation: write operations will continue to succeed until the underlying buffer is full, whereas read operations will block until both peers are reconnected. This affects either peer (i.e., this host and the remote host). Attempts to establish new connections involving this host will fail until the host is reconnected. Similarly, calling Accept on a listener created by this host will block as long as the host remains disconnected.

This method is idempotent; it has no effect if the host is already disconnected.

func (*Host) IsConnected added in v0.2.0

func (h *Host) IsConnected() bool

IsConnected returns whether the host is connected to the network.

func (*Host) Listen

func (h *Host) Listen(address string) (net.Listener, error)

Listen announces on the given address.

If the address is not assigned to the host, or is already bound to another listener, an erorr is returend. Note that, in contrast to net.Listen, Listen will not bind to all available addresses when an empty address is specified.

func (*Host) SetBufferSize

func (h *Host) SetBufferSize(size int)

SetBufferSize sets the size (in bytes) of the internal buffers created for new connections.

If the specified size is less than or equal to 0, the default buffer size is used.

type Network

type Network struct {
	// contains filtered or unexported fields
}

A Network is a collection of hosts.

Multiple goroutines may invoke methods on a Network simultaneously.

func NewNetwork

func NewNetwork() *Network

NewNetwork creates a new network with no hosts.

func (*Network) AddHost

func (n *Network) AddHost(addrs ...string) (*Host, error)

AddHost adds a new host to the network.

The host is identified by the addresses specified in addrs. If addrs is empty or nil, or any of the addresses is invalid or already assigned, AddHost returns an error.

Hosts created by AddHost are connected by default.

func (*Network) Lookup

func (n *Network) Lookup(address string) *Host

Lookup returns the host that the given address is assigned to, or nil if the address is not assigned to any host.

func (*Network) SetDelay

func (n *Network) SetDelay(fromAddr string, toAddr string, delay time.Duration) error

SetDelay configures symmetric delays between addresses.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL