Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Testing & Simulation

Four test layers, all verified pre-release. As of v1.24.0 (2026-07-24): 1201 Rust tests green + 4 ignored (regtest opt-in), 374 svelte-check files / 0 errors / 0 warnings.

1. Unit Tests

Per crate, pure logic. cargo test --workspace covers all 18 library crates + 6 binaries.

Key test counts (as of v1.24.0 — #[test] / #[tokio::test] attributes per crate; the authoritative total comes from cargo test --workspace):

CrateTestsWhat
warppool-api252axum handler tests against in-memory SQLite + mock GitHub/SMTP servers, incl. pool_metrics + notifier, API rate-limit middleware, GBT/IPC template-source admin switch, per-wallet odds panel (Poisson kernel + endpoint)
warppool-stratum-v2138NOISE handshake, codec roundtrips, session frames, PoW check, stale-share detection, VarDiff parity (idle decay + best-share, incl. direct Standard-channel seeding), job-history (template-refresh tolerance), address-allowlist (Standard + Extended channel-open)
warppool-storage117sqlx roundtrips, migrations, all tables, vardiff, audit_log, api_tokens, admin_2fa, pool_settings, goPool import, pool-size + peek_setting, single-transaction record_share + worker eviction, correlated solar/grid energy split, wallet_lifetime odds accumulator, share-outcome (personal-best + top-100 entry)
warppool-stratum-v1152 (+8 e2e)session state machine, rate limit (incl. live auth-rate switch, CIDR IP-gate, per-IP connection cap, reject-ratio + ban-when-disabled enforcement), address-allowlist on authorize, VarDiff (per-class incl. heavy-iron max_diff, suggest/d= honoring, idle decay, EMA rescale on retarget), ntime lower bound, worker-name cap, TLS roundtrip
warppool-telemetry75vendor probes (AxeOS / cgminer mock / Avalon estats), mDNS discovery, HTTP sweep, PoolMetrics + histogram
dvb-warppool-setup51wizard endpoints, install marker, Umbrel env defaults, goPool path resolver
warppool-config56TOML schema, coinbase_splits, VarDiffSettings/RetentionConfig/AutoProfileConfig::validate, retention/upnp blocks, comment-preserving save, profile-tier mapping
warppool-health35RPC call, bitcoin-conf parser, snippet generator, warnings aggregation
warppool-notifier51render_text, EmailSink/SlackSink construction, sink skip when env missing, MarkdownV2 escaping of miner/operator fields
warppool-autoupdate41version compare, asset matching, download_verified, atomic_swap, cosign subprocess
warppool-share-validator26sha256d vectors, dedup, network/pool target checks
warppool-bitcoin-rpc37 (+3 regtest, #[ignore])RPC envelope parsing, ZMQ frames, submit_block null result, transient-error retry, multi-node failover + broadcast
warppool-bitcoin-ipc12Cap’n Proto mining client for Bitcoin Core >= 31, TemplateSource trait, GBT/IPC selection + socket precheck
warppool-uninstall22per-OS path plans, marker gating, JSON roundtrip
warppool-job-builder26coinbase construction, BIP-34 height encoding, merkle branches, template mintime
warppool-translator13 (+5 e2e, +3 bin)extended-channel state machine, BIP-320 version rolling, prev-hash reverse
warppool-hwdetect11sysinfo detection, container env, recommendation reason keys
warppool-profiles7profile resolution, retention monotonicity, rpm→bucket rate derivation
warppool-simulator4sim-miner personas, scenarios

(The binaries carry their own glue-path tests: daemon 44 — supervisor loops, notifier hydration, wallet-moment cooldown, auto-backup loop, plus one #[ignore] per-worker regtest consensus E2E — CLI 7 for argument plumbing, and the macOS launcher 5.)

# Everything
cargo test --workspace

# A single crate
cargo test -p warppool-share-validator

# With output
cargo test -p warppool-stratum-v2 -- --nocapture

2. Integration Tests

Multiple crates in-process, axum mock servers for external services. Per crate under tests/.

Typical cases:

TestCrateWhat
e2e.rsstratum-v1TCP listener + ShareValidator + sim-miner roundtrip with a real subscribe/authorize/submit flow
regtest_e2e.rsbitcoin-rpc#[ignore] — against a running bitcoind regtest
update_apply_with_cosign_verify_but_no_env_returns_500apiaxum mock GitHub + mock asset server
metrics_renders_pool_counters_when_pool_metrics_setapi/metrics output against the Prometheus format

3. Simulation (dvb-warppool-sim)

Runs against the real daemon process (or spawned in-process). Scenarios are end-to-end stories.

Built-in scenarios

ScenarioDurationStatusWhat it verifies
solo-block-found30s✓ executablesim miner connects, block-found event fires
connection-storm-defense60s✓ executablerate limit kicks in under N parallel auth attempts
enterprise-load-smoke5min✓ executableN parallel miners of mixed personas run cleanly
small-24h-stability24hplan-onlySmall profile stays under 200 MB, no panics
rpc-outage-recovery10minplan-onlypool survives a 5-minute RPC outage

Invocation

solo-block-found runs self-contained — it spawns a Stratum V1 server in-process with network_target=[0xff;32] (every valid share becomes a BlockFound) and a JsonStratumMiner (persona BitaxeUltra). No Bitcoin Core required:

dvb-warppool-sim scenario solo-block-found --duration 10
# → Result: BLOCK FOUND after 55 ms (worker=bc1qsim-bitaxe, job_id=sim-job-1)

dvb-warppool-sim scenario connection-storm-defense --duration 15 --attackers 200
# → Success: 10, RateLimit: 190, OtherErr: 0
# → OK: rate limit fired 190x (burst allowance was 10)

dvb-warppool-sim scenario enterprise-load-smoke --duration 15 --miners 200
# → Accepted: 57400 (~3826 shares/s), Rejected: 0, Disconnects: 200

Personas

Sim miners mimic real hardware (hashrate, user agent, TLS support, reconnect pattern):

PersonaNominal hashrateTLSNote
nerdminer-v250 GH/snoplain only
bitaxe-ultra2 TH/syesclean reconnect
nerd-octaxe4.5 TH/syesNerdNOS quirks
avalon-q90 TH/snoCGMiner user agent
antminer-s23-pro580 TH/syesovert ASIC boost
adversarymalicious inputs

Failure modes

dvb-warppool-sim failures <mode> injects production problems:

  • rpc-down — Bitcoin Core unreachable
  • zmq-disconnect — block notify gone
  • tls-handshake-fail — expired cert
  • miner-hang — connection stalls after N shares
  • network-latency — artificial RTT
  • packet-loss — N% packet loss
  • invalid-template — broken coinbase tx
  • reorg — tip gets rolled back
  • memory-pressure — pool under RAM pressure
  • disk-full — SQLite write failure

Security suite

dvb-warppool-sim security drives adversarial inputs (line flood, connection storm, slowloris, auth flood, weak ciphers, …).

Correct outcome: every connection rejected cleanly, no panic, no OOM.

4. Regtest E2E (Phase 15b — opt-in)

For full E2E against a real bitcoind regtest:

eval "$(scripts/regtest-up.sh)"   # starts bitcoind regtest + sets env vars
cargo test -p warppool-bitcoin-rpc --test regtest_e2e -- --ignored --nocapture
scripts/regtest-down.sh --purge   # cleanup

Four #[ignore] tests in total — three in warppool-bitcoin-rpc:

TestWhat
regtest_blockchain_info_returns_regtest_chainchain == "regtest"
regtest_getblocktemplate_workstemplate carries version + bits + prev hash
regtest_submit_invalid_block_is_rejectedtrivially invalid hex → Rejected (not Accepted, not Error)

…plus a full consensus E2E in the daemon crate (per_worker_regtest_full_consensus_e2e, apps/dvb-warppool-daemon/src/regtest_e2e_tests.rs): it mines a real per-worker-coinbase block against regtest and asserts Bitcoin Core accepts it, the reward is attributed to the right worker, the witness commitment is correct and no cross-payment happens.

cargo test -p dvb-warppool-daemon --lib -- --ignored --nocapture per_worker

CI does not run them (no bitcoind in the runner image). Locally they are very useful before release tags. See Configuration Reference → WARPPOOL_E2E_REGTEST_*.

5. Performance Benchmarks (Phase 19 — opt-in)

Criterion suites for the hot paths:

CrateBenchHot path
warppool-share-validatorvalidateper accepted+rejected share
warppool-job-builderbuild_jobper new template
warppool-stratum-v1vardiffper accepted share
cargo bench --workspace
# or
cargo bench -p warppool-share-validator --bench validate

See Performance Benchmarks for baseline numbers and interpretation.

6. UI side (svelte-check)

cd ui
pnpm install
pnpm svelte-check
# → 374 files / 0 errors / 0 warnings

svelte-check is clean — 0 errors, 0 warnings.

7. Fuzzing (opt-in)

The inbound Stratum parser reads bytes straight off the wire, so it is the prime hardening target. Two layers:

  • Stable smoke fuzz (runs in the normal suite, no nightly): messages.rs::tests::fuzz_parse_never_panics drives StratumRequest::parse

    • sanitize_json_escapes through 20,000 deterministic mutated / pathological inputs (random bytes, byte-mutated valid messages, deep nesting, escape storms) and asserts none of them panic.
  • Coverage-guided fuzz (crates/stratum-v1/fuzz/, needs nightly + cargo install cargo-fuzz):

    cargo +nightly fuzz run parse_stratum     # from crates/stratum-v1/
    

    The fuzz/ crate has its own workspace root, so the main cargo build/test --workspace never pulls in the nightly-only dependency. Crashes go into fuzz/artifacts/; minimise and add the input as a regression case in fuzz_parse_never_panics.

CI

CI runs on a self-hosted Forgejo runner (git.warppool.org); the workflow files still live under .github/workflows/ but are executed by Forgejo Actions. There are no macOS and no Windows runners — everything below is Linux-only. See CI porting notes.

.github/workflows/ci.yml matrix:

  • cargo fmt --check (no diff)
  • cargo clippy --workspace --all-targets -- -D warnings (a few style lints allowed: field_reassign_with_default, get_first, too_many_arguments)
  • cargo test --workspace
  • cargo deny check (licenses + advisories — RustSec feed via deny)
  • UI job: pnpm install + pnpm svelte-check + pnpm build

Separate workflows (see Architecture):

  • release.yml — tag-triggered: multi-arch Docker + native Linux binaries + SBOM. No macOS/Windows jobs — the .dmg/tarball assets are built manually per release with packaging/macos/build-macos-release.sh, the .msi is paused
  • repro.yml — reproducible-builds verify (build twice + sha256 diff)
  • docs.yml — mdBook → docs.warppool.org
  • benches.yml — Criterion, manual dispatch only (not per-PR, not on tag push: the fat-LTO bench profile OOM-compiles on the CI box and benches must never gate a release)