diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/TESTING.md | 52 | ||||
| -rw-r--r-- | docs/adr/0001-testable-client-server-cores.md | 48 |
2 files changed, 100 insertions, 0 deletions
diff --git a/docs/TESTING.md b/docs/TESTING.md new file mode 100644 index 0000000..6cac6fa --- /dev/null +++ b/docs/TESTING.md | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | # Testing | ||
| 2 | |||
| 3 | ## Automated suite | ||
| 4 | |||
| 5 | ```sh | ||
| 6 | cargo test | ||
| 7 | ``` | ||
| 8 | |||
| 9 | The suite is deterministic and headless: no network, no PTY, no sleeps, no | ||
| 10 | shared global database. Each test owns its state. | ||
| 11 | |||
| 12 | | File | Covers | | ||
| 13 | | --- | --- | | ||
| 14 | | `tests/client_core.rs` | Client command/game flows via a headless screen applying logical effects. | | ||
| 15 | | `tests/client_ui.rs` | Help, history, completion, bet parsing, display width, cursor math. | | ||
| 16 | | `tests/protocol.rs` | Newline buffering and timeout/error classification. | | ||
| 17 | | `tests/server_core.rs` | Handler, bcrypt migration, SQL injection, transaction rollback, `plays` audit, sessions. | | ||
| 18 | | `tests/slots.rs` | Server slots payout rules and overflow handling. | | ||
| 19 | | `tests/storage.rs` | Client/server SQLite storage helpers. | | ||
| 20 | | `tests/tofu.rs` | SPKI fingerprint and TOFU decisions. | | ||
| 21 | |||
| 22 | `tests/tofu.rs` shells out to `openssl`, so run it on a machine where the | ||
| 23 | `openssl` CLI is available. | ||
| 24 | |||
| 25 | ## Manual TUI checklist | ||
| 26 | |||
| 27 | There is no CI. Run this on Linux and on a Windows VM before a release. | ||
| 28 | Use an 80-column terminal because several output lines are width-sensitive. | ||
| 29 | |||
| 30 | 1. Start the server with a valid `identity.p12`, then start the client. | ||
| 31 | 2. First contact prints three lines and the 64-character fingerprint does not | ||
| 32 | wrap at 80 columns. `Connected to ...` shows a one-decimal ping. | ||
| 33 | 3. `register` / `login`: backspace removes one `*` per key, Esc cancels the | ||
| 34 | prompt, Ctrl+C exits and restores the terminal. | ||
| 35 | 4. `help` fits 80 columns. Tab completion wraps within 76 columns and the | ||
| 36 | cursor stays visible. | ||
| 37 | 5. `play slots 50` shows `Bet: 50 PLN` and the fetched balance. | ||
| 38 | 6. Space shows `Spinning...`, then the reels, win text, and new balance inside | ||
| 39 | the same 7-line board. The controls line is never overwritten. | ||
| 40 | 7. `+` / `-` after a spin changes only the bet; no stale result lines appear. | ||
| 41 | 8. `q` clears the board. Ctrl+C in a game clears the board and exits. | ||
| 42 | 9. `info`, `ping`, `send hello`, and `hosts` print readable output; the host | ||
| 43 | fingerprint fits 80 columns. | ||
| 44 | 10. Windows: repeat 2-9 and confirm keys are not duplicated or printed twice. | ||
| 45 | |||
| 46 | ## Manual server checks | ||
| 47 | |||
| 48 | - Register, log out, log in again (bcrypt path). | ||
| 49 | - Log in with a pre-0.3 user row (legacy SHA-256) and confirm it still works; | ||
| 50 | the row is upgraded to bcrypt. | ||
| 51 | - Spin several times and confirm `plays` grows by one row per spin while | ||
| 52 | `users.balance` changes by `winnings - bet`. | ||
diff --git a/docs/adr/0001-testable-client-server-cores.md b/docs/adr/0001-testable-client-server-cores.md new file mode 100644 index 0000000..2e3cd1e --- /dev/null +++ b/docs/adr/0001-testable-client-server-cores.md | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | # 0001: Testable client and server cores | ||
| 2 | |||
| 3 | Status: Accepted (2026-10-28) | ||
| 4 | |||
| 5 | ## Context | ||
| 6 | |||
| 7 | The client and server started as binaries with their game logic and I/O mixed | ||
| 8 | together. That made the TUI hard to reason about: a spin appended results below | ||
| 9 | the board, a later bet change redrew at the wrong line, and none of it could be | ||
| 10 | tested without a terminal. The server handler had the same problem: it owned | ||
| 11 | static database and session state, so its security-sensitive paths could not be | ||
| 12 | exercised from `tests/`. | ||
| 13 | |||
| 14 | ## Decision | ||
| 15 | |||
| 16 | - The library (`src/lib.rs`) owns shared logic. `src/bin/client` and | ||
| 17 | `src/bin/server` are thin adapters for crossterm, TLS, environment variables, | ||
| 18 | and interactive prompts. | ||
| 19 | - `client::core::ClientCore` owns input, history, commands, game state, and | ||
| 20 | pending replies. It returns `Effect`s (`Print`, `ReplaceRegion`, `ClearRegion`, | ||
| 21 | `SetPrompt`, `SendLine`, `Interactive`, ...). The binary applies them; the | ||
| 22 | tests apply them to a headless screen. | ||
| 23 | - `server::core::ServerCore` owns message handling and receives an injected | ||
| 24 | `Connection`, `GameRegistry`, and bcrypt cost. The binary only owns the TLS | ||
| 25 | listener and per-connection thread. | ||
| 26 | - Tests live in `tests/` and exercise the library. Pure UI math is tested | ||
| 27 | directly; terminal ANSI output is checked manually with `docs/TESTING.md`. | ||
| 28 | There are no PTY tests because they cannot cover Windows and `RULES.md` | ||
| 29 | requires identical behaviour on all platforms. | ||
| 30 | - The client keeps sending its SHA-256 credential. The server stores | ||
| 31 | `bcrypt(credential)` and upgrades legacy SHA-256 rows on the first successful | ||
| 32 | login. This protects a stolen server database without changing the wire | ||
| 33 | protocol, but the client-side credential remains replayable if `client.db` | ||
| 34 | leaks. | ||
| 35 | - Each settled spin writes a durable `plays` row in the same transaction as the | ||
| 36 | balance updates. The in-memory session is a transient guard and is removed | ||
| 37 | as soon as the spin settles or fails. | ||
| 38 | |||
| 39 | ## Consequences | ||
| 40 | |||
| 41 | - Client flows and server security rules are testable without a terminal or a | ||
| 42 | network. A visual bug becomes an assertion about the headless screen. | ||
| 43 | - The binaries have an extra translation layer (`Effect` application), and the | ||
| 44 | server opens a SQLite connection per client. | ||
| 45 | - Terminal rendering still needs a manual Linux/Windows pass; the checklist is | ||
| 46 | in `docs/TESTING.md`. | ||
| 47 | - Password storage is stronger, but not a full PAKE. A future MAJOR protocol | ||
| 48 | change can replace the replayable credential. | ||
