1# Chapter 14: tests/support, the harness 2 3Every test in chapter 13 begins the same way: start a Postgres, install the 4extension, point it at a mock Jev, make a table with a row in it. This 5library is that beginning, written once. 6 7```rust 8let mock = MockJev::start(|_| Reply::json(200, noul(0.95))).await; 9let (_pg, client) = jev_instance(&mock).await; 10let row = client.query_one("SELECT jev_prob(t, $1) FROM tickets t", &[&QUESTION]).await?; 11``` 12 13Three lines, and behind them: `initdb` into a temporary directory, a 14`postgres` child process listening on a Unix socket in that directory, the 15extension served in place from the buck build, `jev.endpoint`, `jev.model` 16and `jev.ca_file` set to the mock, `TYPESAFE_API_KEY=test-key` in the 17server's environment, `statement_timeout` at 20 seconds, `CREATE EXTENSION 18postjevsql`, and a `tickets` table with one row ("Help! My payouts have been 19failing for 3 days."). When `_pg` goes out of scope, the server goes too. 20 21> **Aside: a server that cannot outlive its test.** Tests crash, and buck 22> kills test binaries that run too long. A Postgres left running after either 23> would hold its port and its memory until someone noticed. So the 24> postmaster is started with `PR_SET_PDEATHSIG`: the kernel itself sends it 25> SIGQUIT the moment the thread that started it dies, SIGKILL included. 26> Nothing in the test has to remember to clean up, because nothing can 27> forget. 28 29> **Aside: at most one server per core.** buck runs several test binaries at 30> once, each running a test per core, each with its own Postgres. On 3 cores 31> that once reached a load average of 28. So each instance holds an `flock` 32> on one of a fixed set of slot files for its life, machine-wide, and a test 33> that needs two at once (a target and a sidecar) takes them together with 34> `TestPostgres::start_all`, all or none. 35 36Postgres 17 needed one more trick. Postgres 18 can be told where to find an 37extension (`extension_control_path`); 17 reads extensions only from its own 38install directory. So on 17 the harness builds a prefix of symlinks in the 39temporary directory, with the built extension linked into its 40`share/postgresql/extension`, and runs the server from there. 41 42> **Try it.** Read [mod.rs](mod.rs): `jev_instance`, `jev_instance_with` 43> (extra settings) and `jev_instance_env` (the server's environment in full) 44> are the whole public face of it. 45 46## For the people who maintain it 47 48| File | What | 49| --- | --- | 50| [mod.rs](mod.rs) | `jev_instance` and its variants, `TICKET`, `noul` (a canned answer), `assert_json_eq`, and `mock_jev`, re-exporting jevcrates' `jev-mock`. | 51| [postgres.rs](postgres.rs) | `TestPostgres` and `Instance`: the throwaway server, its slots, its teardown, and the PG17 symlink prefix. | 52| [dns.rs](dns.rs) | A DNS server on loopback answering from a fixed table and recording every question, for `tests/dns.rs`. | 53| [gates.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. | 54| [BUCK](BUCK) | The `support` library, visible to `//tests/...` and `//tools/record-gates`. | 55| [Cargo.toml](Cargo.toml) | Generated by `tools/cargo-gen` (chapter 20). | 56 57← Previous: [Chapter 13, tests/](../) · Up: [tests](../) · Next: [Chapter 15, fixtures/](../fixtures/) →