Skip to content

Faults ​

The fault package has pipes that make an HTTP mock answer wrong, to test how a client handles a server that fails, or a bad network. A pipe of either level acts on the body with Pipe, and on every byte of the answer, its head included, with WirePipe:

Fault pipes ​

PipeLevelWhat the client gets
fault.EmptyResponse()WirePipeNo byte at all: the connection ends where it waits for a status line.
fault.MalformedResponseChunk()WirePipeThe status line and headers, with the mock's status, then garbage in place of the first chunk of the body, then the end of the connection.
fault.RandomDataThenClose()WirePipefault.RandomDataSize random bytes in place of the answer, then the end of the connection.
fault.ConnectionResetByPeer()WirePipeA TCP reset, such as ECONNRESET, before a status line.
fault.ChunkedDribbleDelay(chunks, total)PipeThe whole body, in chunks flushed parts spread over total: part k comes at k·total/chunks, and the body ends at total. The body is held until the reply wrote all of it.
fault.Latency(latency, jitter)EitherEvery write and flush latency later, give or take jitter at random, in order. The answer keeps its pace: the writer doesn't wait.
fault.Bandwidth(bytesPerSecond)EitherEach write at that rate, in flushed pieces of a tenth of a second. fault.Bandwidth3G and the other fault.Bandwidth* constants are common links, in bytes per second.
fault.Slicer(averageSize, sizeVariation, delay)EitherEach write in flushed slices of averageSize bytes, give or take sizeVariation at random, delay apart.
fault.SlowClose(delay)EitherThe whole answer, then its end delay later: the body's last chunk with Pipe, the close of the connection with WirePipe.
fault.Timeout(timeout)EitherNothing, then the end of the connection timeout after the answer began; with Pipe, the head comes with that end. A timeout of 0 never ends.
fault.LimitData(n)EitherThe first n bytes, then the end of the connection: bytes of the body with Pipe, of the whole answer with WirePipe.
fault.ConnectionResetByPeerAfter(d)EitherThe answer as it comes, then a TCP reset d after it began. With Pipe over HTTP/2, the stream is cut instead.
go
m.MustMock(mockhttp.Getf("/users").WirePipe(fault.ConnectionResetByPeer()).Reply(mockhttp.OK()))
m.MustMock(mockhttp.Getf("/report").Pipe(fault.ChunkedDribbleDelay(5, 2*time.Second)).Reply(mockhttp.OK().BodyFile("report.csv")))
m.MustMock(mockhttp.Getf("/search").WirePipe(fault.Latency(300*time.Millisecond, 60*time.Millisecond)).Reply(mockhttp.OK()))
m.MustMock(mockhttp.Getf("/video").Pipe(fault.Bandwidth(fault.Bandwidth3G)).Reply(mockhttp.OK().BodyFile("video.mp4")))

A wire fault needs HTTP/1.x, as wire pipes do. Faults combine with other pipes: a fault on the wire comes after the pipes of Pipe. A mock that answers with a fault still counts the call, and runs its callbacks and events, before the connection ends.

In mock files ​

pipes, wire_pipes and upstream_pipes list faults for Pipe, WirePipe and UpstreamPipe. A fault is an object: type names it, after its function in snake case, and its other keys are its parameters, by name. Durations are whole milliseconds or a Go duration, such as 1.5s. A parameter with a default can be left out.

typeParameters
empty_response, malformed_response_chunk, random_data_then_close, connection_reset_by_peerNone.
chunked_dribble_delaychunks, total
latencylatency; jitter, 0 by default
bandwidthrate: bytes per second, or a fault.Bandwidth* constant in snake case: gprs, dial_up, 2g, good_2g, 3g, good_3g, dsl, 4g, wifi or fiber
sliceraverage_size; size_variation and delay, 0 by default
slow_closedelay
timeoutafter, 0 by default: never
limit_databytes
connection_reset_by_peer_afterafter
yaml
request:
  method: GET
  path: /report
response:
  status: 200
  body_file: report.csv
pipes:
  - type: bandwidth
    rate: 3g
  - type: connection_reset_by_peer_after
    after: 5s
wire_pipes:
  - type: latency
    latency: 300ms
    jitter: 60ms

A fault with a missing parameter, a key it doesn't take, or a value its function refuses fails the file, with each problem at its key, such as pipes[1].after. faultbuild.Build, of package fault/faultbuild, builds a fault from its object in Go.

A mock describes its faults the same way, so the admin API shows them and its store keeps them. A pipe of your own, such as a vlatte.PipeFunc, isn't in the description.