Skip to content
go-while edited this page Oct 23, 2026 · 3 revisions

Faults

Options.Faults makes the fake server misbehave on purpose. Faults apply in Store mode, and in Script mode to the reply of a matched step. They don't apply to your own Handler. The maps are copied when the server starts.

Keys are upper-cased command names ("ARTICLE"). OverrideLine takes a whole client line instead ("ARTICLE 2": the command upper-cased, the arguments joined by single spaces).

Field Effect
Delay wait this long before the reply to that command (at most the Deadline)
CloseAfter close the connection after the reply to the N-th client line (unmatched lines count too)
Override write these lines instead of the normal reply
OverrideLine Override for one exact client line; wins over Override
OverrideFrom Override/OverrideLine of that command apply only from its N-th use on a connection
OverrideTimes Override/OverrideLine of that command apply at most N times per connection
DropInMultiline close the connection after N lines of that command's reply (the status line counts; 0 closes before anything is written)
LongLine add one line of N x bytes after the status line
Drip write the reply one byte at a time, with this pause between bytes: a slow server that a per-read timeout never sees as stalled
LineDelay write the reply one line at a time, with this pause between lines: a slow server on a large OVER
Endless write the reply without its . terminator, then <n> endless lines until the client closes, the server closes or the Deadline passes

The faults apply in this order: Delay; OverrideLine, else Override; LongLine; DropInMultiline; then the write, through Drip when set and with LineDelay between lines; then Endless. Drip, LineDelay and Endless stop at the Deadline and close the connection.

On a compressed connection (COMPRESS DEFLATE) every fault works on the inflated stream: each write is deflated and flushed on its own, so a Drip byte or a LineDelay line reaches the client by itself, and a reply cut by DropInMultiline or CloseAfter ends at a flush.

For POST the faults apply to the first reply (the 340). An Override for POST that doesn't start with 340 is final: no article is read.

PeerHandler is a Handler, so faults don't apply to it; its own options (Defer431Once, Defer436Once, Reject, NoStream, StallModeStream) make it misbehave (see Fake Server).

Examples

Several faults at once:

s := fakeserver.New(t, fakeserver.Options{Store: st, Faults: fakeserver.Faults{
	Delay:           map[string]time.Duration{"GROUP": 100 * time.Millisecond},
	OverrideLine:    map[string][]string{"ARTICLE 2": {"430 No such article"}},
	DropInMultiline: map[string]int{"XOVER": 2}, // status line and one record, then close
	LineDelay:       map[string]time.Duration{"OVER": 10 * time.Millisecond},
}})

The strict client sees the cut XOVER reply as a NoTerminator error (see Strict Client).

A login that expires

Servers ask for the login again when it times out. With User and Pass set, a 480 written to a logged-in connection ends its login, so the client must send AUTHINFO again before the command works:

s := fakeserver.New(t, fakeserver.Options{
	Store:     st,
	StoreOpts: fakeserver.StoreOptions{User: "u", Pass: "p"},
	Faults: fakeserver.Faults{
		Override:      map[string][]string{"OVER": {"480 Authentication required"}},
		OverrideFrom:  map[string]int{"OVER": 2}, // the 2nd OVER on a connection ...
		OverrideTimes: map[string]int{"OVER": 1}, // ... and only that one
	},
})

The first OVER is answered, the second gets 480, and after a new AUTHINFO the next OVER is answered again. Without User and Pass a 480 changes nothing.

A server with NEWNEWS turned off

INN answers NEWNEWS with 502 when its access configuration doesn't allow it; StoreOptions.NoNewnews gives the 500 of a server that doesn't know the command:

Faults: fakeserver.Faults{
	Override: map[string][]string{"NEWNEWS": {"502 NEWNEWS command disabled by administrator"}},
},

Stalls

These are Options fields, not faults:

  • RawStall: the server accepts TCP and never writes (a TLS handshake that never finishes).
  • NoGreeting: no greeting; without a Handler the server only records what it reads.
  • A Script step with Hang: true: no reply from that step on.

Clone this wiki locally