Skip to content

Running Server Binaries

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

Running Server Binaries

Package proc (doc.go) runs an external NNTP server for a test and stops it afterwards. It needs a Unix system (it sends SIGTERM and SIGKILL).

Options

Field Effect
Path the binary (required). A relative path with a / is resolved against the test's directory, a bare name through PATH
Args its arguments
Env added to the test's environment
Dir working directory; "" = a fresh t.TempDir()
StopTimeout SIGTERM, then SIGKILL after this long; 0 = 5s
Deadline the wait for readiness and pipe deadlines; 0 = the hang guard
Logs files (relative to Dir) to print when the test fails
Ulimit resource limits, each as the shell's ulimit takes it: "-n 16", "-f 64", ... (since v0.5.0)

TCP

p := proc.StartTCP(t, proc.Options{
	Path: "../../src/myserver",
	Args: []string{"-upstream", up.Addr(), "-listen", "127.0.0.1:11119"},
	Logs: []string{"myserver.log"},
}, "127.0.0.1:11119")
c := client.Dial(t, p.Addr())

StartTCP waits until a connection to the address gets a greeting line, and sends QUIT on that probe connection. So the server sees one connection before the test's own. Its stdout is captured together with stderr.

Stdin and stdout (inetd style)

p := proc.StartStdio(t, proc.Options{Path: "../../src/myserver", Args: []string{"-i"}})
c := client.New(t, p.Conn())
if _, err := c.ReadGreeting(); err != nil {
	t.Fatal(err)
}

p.Conn() is a net.Conn over the pipes; deadlines work on it.

Resource limits

Ulimit starts the binary through /bin/sh, which sets the limits and then execs it, so the PID and the signals stay the binary's. Each entry is -<letter> <number> or -<letter> unlimited; anything else fails the test.

p := proc.StartStdio(t, proc.Options{
	Path:   "../../src/myserver",
	Args:   []string{"-i"},
	Ulimit: []string{"-n 16", "-f 64"}, // 16 open files, files up to 64 blocks of 512 bytes
})
  • -n (open files) makes the server run out of file descriptors.
  • -f (file size, in 512-byte blocks for sh) makes writes beyond it fail with EFBIG, as writes fail on a full disk. The process also gets SIGXFSZ, which ends it unless it ignores that signal.

NewsCache's spoolfull_test.go uses both, and a small tmpfs in a user namespace for a real full disk where the system allows one.

Process

Method Effect
Conn() stdio mode: the client side; nil in TCP mode
Addr() TCP mode: the address; "" in stdio mode
Pid(), Signal(sig) e.g. SIGHUP to make the server reload
Stop() SIGTERM, SIGKILL after StopTimeout, then wait; safe to call twice
Wait() the exit error, once; bounded by the Deadline
Done() a channel closed once the process exited: a bounded wait (select with a timer) that, unlike Wait, never stops it
Stderr() output captured so far

When the test ends, the process is stopped. When the test failed, its stderr (and stdout in TCP mode) and every file in Logs are printed with t.Log.

NewsCache's harness_test.go uses both modes: newscache -i under StartStdio for one session, and newscache -n under StartTCP for the daemon.

Clone this wiki locally