# 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` | European wheel, split-bet payouts, zero handling, 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. Windows: repeat 2-9 and confirm keys are not duplicated or printed twice. ## Manual roulette checklist 1. `play roulette` shows the balance, chip size, empty bets, and controls. 2. `R`/`B`/`E`/`O` add one chip; digits + Enter add a number; `C` clears; `+`/`=`/`-` change the chip size. 3. Space scrolls the wheel under a fixed ball marker and ends on the winning number. 4. Check a split result: - `17 black odd`: black+odd pay, red+even lose, straight 17 pays 36x. - `0`: all outside bets lose; a straight 0 pays 36x. 5. Numbers are color-coded: red numbers red, 0 green, black default. Check the bets line, the rolling strip, and the winning number. 6. The result board shows the winning number/color/parity, the payout, and the new balance. The next spin reuses the placed bets. ## 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 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`.