Wrap a net.Conn or net.PacketConn to simulate bandwidth limits, latency,
jitter, and packet loss in Go tests. No root, no tc, no external processes.
OS-level tools like tc-netem shape traffic for the whole machine. netem
works at the connection level, so tests stay hermetic and run anywhere.
lat := &policy.LatencyVar{}
lat.Set(100 * time.Millisecond)
conn := flakenet.NewPacketConn(udpConn, flakenet.PacketProfile{
Latency: lat,
Jitter: policy.RandomJitter(20 * time.Millisecond),
Loss: policy.RandomLoss(0.01),
})
// Conditions can change while the connection is live.
lat.Set(500 * time.Millisecond)Conditions are values, not constants. The Var types are safe for concurrent
use and can be reset on an active connection, so a test can degrade a link
mid-transfer without reconnecting.
Bandwidth: throughput ceiling in bits/sec (StaticBandwidth,BandwidthVar)Latency: base propagation delayJitter: delivery-time variance (RandomJitteris amplitude-based)Loss: packet drops (RandomLoss)Fault: trigger failures or closure on demand
Conn is stream-oriented. Delayed bytes queue in FIFO order, so jitter shows up
as head-of-line blocking rather than reordered or interleaved bytes.
PacketConn is datagram-oriented. Packets reorder naturally, and a later
datagram can overtake an earlier one under sufficient jitter.
Tooling comes from the Nix flake. direnv allow (or nix develop) gets you a
shell with the pinned Go toolchain, golangci-lint, and govulncheck.
make # list targets
make init # install the pre-commit hook
make ci # fmt-check, lint, test, vulnBuilds on cevatbarisyilmaz/lossy with two changes: queued delivery instead of a goroutine per packet, which bounds memory at high throughput, and FIFO ordering on streams, which fixes byte interleaving under high jitter.