Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_steel/tests/rig/README.md

4.1 KiB, 4 runs

created by r1870400018:14547, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1# The rig
2
3Starts a real Steel -- its own wallet, its own Ozone, its own certificates -- and
4drives it over HTTPS with a real dashboard session. Then throws it all away.
5
6`cargo test` does not run this. It is a shell script, it wants a free port and
7half a minute, and it is here to be run by hand:
8
9```
10fe2o3_steel/tests/rig/run.sh
11```
12
13Nothing else is needed. It builds the binary, makes a wallet, starts a server in
14a temporary directory, runs the checks, and stops.
15
16## Why it exists
17
18An in-crate test asks the code whether it works. The code says yes. That is worth
19something, and it is not worth what it looks like: a DKIM signer in this workspace
20sat broken for three months behind tests that agreed with it.
21
22Some things cannot be asked from inside at all. Whether the dashboard's cookie
23reaches a handler is a fact about `Path=/admin` and a browser, not about a
24function. The composer's whole design rests on it, and the route it replaced was
25gated on a session that could never arrive -- a gate that refused its own author
26exactly as it refused a stranger, and therefore looked correct from every angle
27except this one.
28
29So the checks here are the ones only an outside caller can make: that an
30anonymous write is refused, that a draft is served to nobody while its author can
31still read it, that a renamed post takes its old key with it, that a deleted post
32stays deleted through an import, and that a slug with a path in it writes nothing.
33
34## What it is not
35
36It is not a substitute for the unit tests, and it does not run in CI. It is slow,
37it binds a port, and it will fail on a machine where port 9443 is busy
38(`RIG_PORT=nnnn` moves it).
39
40It knows some things that cost an afternoon to learn, and they are in `run.sh`
41where they bite:
42
43- **Wallet creation needs a terminal.** It reads the passphrase through
44 crossterm's raw mode, so a pipe will not do -- hence the pty in
45 `make_wallet.py`. In raw mode Enter is a carriage return, not a newline.
46- **`server -d` or nothing.** Without `-d` a first run refuses to start in
47 production mode and exits 0, silently, having said nothing about why.
48- **stdin must stay open.** The server keeps a shell beside the listener, and an
49 EOF on stdin ends the process. Hence the fifo.
50- **`dev_cfg` is a required config block.** Every `FromDatMap` field is, unless it
51 says otherwise.
52- **Run one rig at a time.** A second run while another is held (`RIG_HOLD=1`)
53 produces false failures in `console_rig`, which authenticates over a WebSocket
54 and will find the wrong server. It looks exactly like a gate regression — a
55 non-admin getting 200 instead of 403 — and is not one. Kill the held rig first.
56
57## The passphrase
58
59`rig-test-passphrase-not-a-secret`, in the clear, on purpose. It protects a
60wallet that exists for thirty seconds and holds nothing.
61
62## The byte range rig
63
64`range.sh` is the second script here, and it answers a different question: does a
65window of a file, asked for over the wire, arrive as the bytes that are actually
66in the file at that offset?
67
68```
69fe2o3_steel/tests/rig/range.sh
70RIG_TRANSCRIPT=1 fe2o3_steel/tests/rig/range.sh # print the exchanges too
71```
72
73It serves a ten megabyte file of a counting pattern and drives it with curl:
74`-r 0-99`, `-r 100-`, `-r -50`, a window from the middle, a start past the end, a
75suffix longer than the file, a unit that is not `bytes`, several ranges at once,
76an empty file, a one byte file, and a `HEAD`. Every body is compared with `cmp`
77against the same window cut out of the file with `dd` -- because a response of the
78right length carrying the wrong bytes is exactly the failure a length check
79misses, and exactly what a viewer sees as a video that will not play.
80
81The whole sweep runs twice, once as curl chooses and once under `--http2`. Steel
82offers only `http/1.1` over ALPN today, so `--http2` negotiates 1.1 and falls
83back; the second pass is there so that the day ALPN offers `h2`, the sweep already
84covers it.
85
86The last check asks for two windows down one connection. A body that is shorter or
87longer than the `Content-Length` promised desynchronises every message after it,
88and that can only be seen when a second request follows the first on the same
89connection.