Chapter 14: tests/support, the harness
Every test in chapter 13 begins the same way: start a Postgres, install the extension, point it at a mock Jev, make a table with a row in it. This library is that beginning, written once.
let mock = MockJev::start(|_| Reply::json(200, noul(0.95))).await;
let (_pg, client) = jev_instance(&mock).await;
let row = client.query_one("SELECT jev_prob(t, $1) FROM tickets t", &[&QUESTION]).await?;
Three lines, and behind them: initdb into a temporary directory, a
postgres child process listening on a Unix socket in that directory, the
extension served in place from the buck build, jev.endpoint, jev.model
and jev.ca_file set to the mock, TYPESAFE_API_KEY=test-key in the
server's environment, statement_timeout at 20 seconds, CREATE EXTENSION postjevsql, and a tickets table with one row ("Help! My payouts have been
failing for 3 days."). When _pg goes out of scope, the server goes too.
Aside: a server that cannot outlive its test. Tests crash, and buck kills test binaries that run too long. A Postgres left running after either would hold its port and its memory until someone noticed. So the postmaster is started with
PR_SET_PDEATHSIG: the kernel itself sends it SIGQUIT the moment the thread that started it dies, SIGKILL included. Nothing in the test has to remember to clean up, because nothing can forget.
Aside: at most one server per core. buck runs several test binaries at once, each running a test per core, each with its own Postgres. On 3 cores that once reached a load average of 28. So each instance holds an
flockon one of a fixed set of slot files for its life, machine-wide, and a test that needs two at once (a target and a sidecar) takes them together withTestPostgres::start_all, all or none.
Postgres 17 needed one more trick. Postgres 18 can be told where to find an
extension (extension_control_path); 17 reads extensions only from its own
install directory. So on 17 the harness builds a prefix of symlinks in the
temporary directory, with the built extension linked into its
share/postgresql/extension, and runs the server from there.
Try it. Read mod.rs:
jev_instance,jev_instance_with(extra settings) andjev_instance_env(the server's environment in full) are the whole public face of it.
For the people who maintain it
| File | What |
|---|---|
| mod.rs | jev_instance and its variants, TICKET, noul (a canned answer), assert_json_eq, and mock_jev, re-exporting jevcrates' jev-mock. |
| postgres.rs | TestPostgres and Instance: the throwaway server, its slots, its teardown, and the PG17 symlink prefix. |
| dns.rs | A DNS server on loopback answering from a fixed table and recording every question, for tests/dns.rs. |
| gates.rs | What the release gates' recordings ask (rows, question, SQL, fixture lookup), shared by tools/record-gates, which records them, and tests/gate_*.rs, which replay them. |
| BUCK | The support library, visible to //tests/... and //tools/record-gates. |
| Cargo.toml | Generated by tools/cargo-gen (chapter 20). |
← Previous: Chapter 13, tests/ · Up: tests · Next: Chapter 15, fixtures/ →