Replace legacy metadata and relay expectations with current protocol-8 JSONL assertions. Scenarios now bind every source to authenticated PeerId and exact ContentId, prove typed attempt lifecycle order, and fence cancellation, quarantine, rollback, republishing, and peer-departure outcomes against vacuous success. Isolated topologies distinguish direct author pulls from relay and ambient mDNS substitution. The run log records focused diagnostics and the final fresh-image S1-S49 acceptance result without presenting Docker-host throughput as a representative external-LAN measurement. Test Plan: - `LANSPREAD_S37_MIN_MIB_PER_S=100 just peer-cli-tests` -- passed S1-S49 - S37 -- passed 2,147,483,656 bytes in 17 chunks at 551.10 MiB/s - `python3 -m py_compile crates/lanspread-peer-cli/scripts/run_extended_scenarios.py` -- passed - `ruff check --select F,E9 crates/lanspread-peer-cli/scripts/run_extended_scenarios.py` -- passed - `git diff --cached --check` -- passed
3.1 KiB
lanspread-peer-cli
Scriptable peer harness for automated LAN-spread tests. The binary starts the core peer runtime without the Tauri GUI, reads one JSON command per stdin line, and writes JSONL events, results, and errors to stdout.
Running
just peer-cli-build
just peer-cli-image
just peer-cli-tests
just peer-cli-run alpha
Useful flags:
--games-dir PATHstores local archives and installs.--state-dir PATHstores the generated peer identity.--identity-file PATHloads one existing peer identity strictly. Missing or invalid files fail startup without repair, quarantine, or fallback.--catalog-db PATHand--manifests-dir PATHselect one coherent catalog authority profile.--fixture GAME_IDseeds a tiny archive that the fixture unpacker can install. The selected profile must already authorize that exact fixture.
Fixture Game Directories
fixtures/fixture-alpha, fixtures/fixture-bravo, and
fixtures/fixture-charlie are ready-to-use game directories for local CLI smoke
tests. Point --games-dir at one of them to start a peer with several
catalog-backed fake games. Each game includes version.ini and a real RAR
archive renamed to .eti; fixture-alpha and fixture-bravo share ggoo,
while fixture-bravo and fixture-charlie share cnc4.
The checked-in catalogs/default profile authorizes the normal alpha, bravo,
charlie, and persona packages. catalogs/solid and catalogs/multi are
separate authorities because their cnctw packages intentionally contain
different bytes and extracted layouts. catalogs/unknown is a source-only
cod2 profile used to prove that another peer's honest catalog cannot extend
the client's local catalog.
Regenerate and verify the profiles with:
just fixture-catalogs
just fixture-catalogs-check
Both commands use the Rust catalog publisher. Dynamic sparse and many-file
acceptance packages use the same test-only generator through
just fixture-download-only-catalog or just fixture-catalog; the Python
scenario runner never derives hashes or catalog rows itself. Production
artifacts are a separate corpus and are checked by
just catalog-check-production.
Commands
Every command is a JSON object with cmd or command; id is optional and is
echoed back on the result or error line.
{"id":"s1","cmd":"status"}
{"id":"p1","cmd":"wait-peers","count":1,"timeout_ms":5000}
{"id":"c1","cmd":"connect","peer_id":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","addr":"127.0.0.1:34567"}
{"id":"g1","cmd":"list-games"}
{"id":"d1","cmd":"download","game_id":"fixture-one","install":true}
{"id":"i1","cmd":"install","game_id":"fixture-one"}
{"id":"u1","cmd":"uninstall","game_id":"fixture-one"}
{"id":"q1","cmd":"shutdown"}
connect requires the target's peer_id and addr from the same
local-peer-ready event. Address-only connects are rejected because the peer ID
is the TLS identity pin, not descriptive metadata.
The status result includes receiver-side active_operations and sender-side
active_outbound_transfers counts by game ID, which the scenario runner uses to
verify transfer lifecycle cleanup.