# Testing ## Automated suite ```sh cargo test ``` The suite is deterministic and headless: no network, no PTY, no sleeps, no shared global database. Each test owns its state. | File | Covers | | --- | --- | | `tests/client_core.rs` | Client command/game flows via a headless screen applying logical effects. | | `tests/client_ui.rs` | Help, history, completion, bet parsing, display width, cursor math. | | `tests/blackjack.rs` | Card totals, naturals, hit/stand/double, dealer bust, S17, state parsing. | | `tests/crash.rs` | Multiplier curve, payout floor, crash-point distribution, house edge, cap. | | `tests/protocol.rs` | Newline buffering and timeout/error classification. | | `tests/roulette.rs` | Wheel, every bet type and payout, zero handling, cursor lattice, result parser. | | `tests/server_core.rs` | Handler, bcrypt migration, SQL injection, transaction rollback, `plays` audit, sessions. | | `tests/server_setup.rs` | `--init` identity generation, PKCS#12 loadability, overwrite refusal. | | `tests/slots.rs` | Server slots payout rules and overflow handling. | | `tests/storage.rs` | Client/server SQLite storage helpers. | | `tests/tofu.rs` | SPKI fingerprint and TOFU decisions. | `tests/tofu.rs` and `tests/server_setup.rs` shell out to `openssl`, so run them on a machine where the `openssl` CLI is available. ## Development resets The server creates `server.db` in its working directory; the client creates `client.db` for host trust and stored credentials. While the software is in testing, delete both after a schema or trust change: ```sh rm -f server.db client.db ``` The audit schema is not auto-migrated from the pre-2.0 slots-only `plays` table. Starting against an old database will fail until it is removed. ## Manual TUI checklist There is no CI. Run this on Linux and on a Windows VM before a release. Use an 80-column terminal because several output lines are width-sensitive. 1. Run `cargo run --bin server -- --init` once, then start the server with a valid `identity.p12` and start the client. 2. First contact prints three lines and the 64-character fingerprint does not wrap at 80 columns. `Connected to ...` shows a one-decimal ping. 3. `register` / `login`: backspace removes one `*` per key, Esc cancels the prompt, Ctrl+C exits and restores the terminal. 4. `help` fits 80 columns. Tab completion wraps within 76 columns and the cursor stays visible. 5. `play slots 50` shows a 5x3 grid, the `Pays bet x symbol x shape` lines, and the fetched balance. 6. Space shows `Spinning...`, then the 3 rows, win text, winning-line list, and new balance inside the same 10-line board. Winning symbols appear as yellow/bold `{ X }` cells; the `Winning lines:` list names the payline (e.g. `4 (V)`). The controls line is never overwritten. Slots rules and RTP: `docs/SLOTS.md`. 7. `+` / `=` / `-` after a spin changes only the bet; no stale grid or result lines appear. 8. `q` clears the board. Ctrl+C in a game clears the board and exits. 9. `info`, `ping`, `send hello`, and `hosts` print readable output; the host fingerprint fits 80 columns. 10. Connect to the same server through two addresses (for example `127.0.0.1` and the machine's LAN IP). `hosts` must list both addresses on one line under a single fingerprint, because the certificate key is the same. 11. Windows: repeat 2-10 and confirm keys are not duplicated or printed twice. ## Manual roulette checklist 1. `play roulette` draws the full felt: 0, the 3x12 numbers, dozens, columns, and the six outside cells, with the cursor on number 1. 2. Arrows move the cursor. On the numbers the highlighted cells show the bet: one number (straight), two (split), four (corner). Down leaves the felt into the dozens, then columns, then outside; Up walks back. 3. ENTER places the chip where the cursor is; `C` clears; `+`/`=`/`-` change the chip size. The bets line lists every chip and the total. 4. Space scrolls the wheel under a fixed ball marker and ends on the winning number. 5. Check the payouts: - a straight pays 36x, a split 18x, a corner 9x; - a dozen or column pays 3x; - an outside bet pays 2x; - `0` loses every outside bet, both dozens and every column, and pays a straight 0. 6. The result line names the number, color and parity, the total returned and the profit. The next spin reuses the placed chips. ## Manual terminal size check 1. Start the client in a terminal smaller than 80x24: it must print `zagan.bet needs a terminal of at least 80x24 cells` and exit without switching to the alternate screen or raw mode. 2. At 80x24 every game board (slots 10 lines, roulette 12, blackjack 6, crash 6) must fit without wrapping. ## Manual blackjack checklist 1. `play blackjack` shows the ready board; Space deals. 2. The dealer's hole card is hidden while it is the player's turn. H/S/D work; D is only offered on the first two cards and reserves the extra bet. 3. Stand and check the dealer stands on all 17s. Check a dealer bust pays the player, and a natural blackjack pays 3:2. 4. Q during a hand forfeits the reserved bet (it is **not** refunded); Q after a hand just leaves. Disconnecting mid-hand also forfeits it. 5. Check the audit row: `game_type = blackjack`, the total bet (including a double), winnings, and the final cards/result in `details`. A forfeit has `result = forfeit`, `winnings = 0`. ## Manual crash checklist 1. `play crash` shows the ready board with a 1.00x multiplier; Space starts and reserves the bet. 2. The multiplier rises smoothly with no network traffic. Cash out with C and confirm the board shows the cashout multiplier, the payout and the new balance. 3. On another round, press nothing. The board must switch to `CRASHED at Xx` by itself when the crash point is reached, and the bet must be lost. 4. Press C just as a round crashes. Either it pays or the crashed result wins; a late cashout must never show an error over a finished round. 5. Q during a live round forfeits the bet; Q when idle just leaves. 6. Check the audit rows: one per round, `game_type = crash`, the reserved bet, the payout, and `crash_point`/`multiplier`/`result` in `details`. 7. Confirm the crash point is absent from the `CRASH_START` line (it must only appear once the round is over). ## Manual restart check 1. Start a blackjack hand (or a crash round) and confirm `pending_plays` has one row while the round is live. 2. `kill -9` the server, then start it again on the same database. The log must say `Settled 1 orphaned reservation(s) as abandoned after a restart`. 3. Confirm the balance did not change, `pending_plays` is empty, and `plays` has one row with `winnings = 0`, `details.result = "abandoned"` and `details.reason = "server_restart"`. ## Manual identity / credential checklist 1. Connect through one address, `register` and `login`. `hosts` shows the fingerprint. 2. `disconnect`, then `connect` through another address that reaches the same server (for example `10.0.0.100` when you first used `127.0.0.1`). The client must print `Authenticated as ` without asking for a password. 3. `hosts` must list both addresses on one line under one fingerprint. 4. `forget-host ` must say the credentials were kept and name the remaining address. Connecting through the remaining address still authenticates automatically. 5. `forget-host ` must say trust and credentials were cleared. The next connect is a first contact and does not authenticate. ## Manual server checks - Register, log out, log in again (bcrypt path). - Log in with a pre-0.3 user row (legacy SHA-256) and confirm it still works; the row is upgraded to bcrypt. - Spin several times and confirm `plays` grows by one row per spin while `users.balance` changes by `winnings - bet`.