test(governance): run the ban-chain e2e simulation tests in CI#4450
Conversation
## Problem Issue #4301 asks for an end-to-end simulation-network test of the governance ban chain (rate-limit reject -> MAD flag -> Normal -> ... -> Evicted -> Banned -> wire-traffic drop), as the required behavioral gate before flipping governance into Enforce mode on gateways. The tests themselves already exist: `sim_e2e_tests` in crates/core/src/contract/governance.rs (added in PR #4309) contains `governance_ban_chain_end_to_end` and `popular_contract_with_subscribers_not_evicted`. They drive the full production wiring inside a `run_controlled_simulation` network (1 gateway + 5 nodes), assert the abuser lands on the per-node ContractBanList (the wire-boundary enforcement signal) and reaches the terminal Banned state, and assert honest / popular-with-subscribers contracts are NOT banned (no collateral damage). The gap: those tests never actually ran in CI, so the gate was not enforced and the tests could silently rot. The module is gated behind `#[cfg(all(test, feature = "simulation_tests"))]` and lives in the lib (it must -- it uses `pub(crate)` accessors like `Ring::governance`, `Ring::contract_ban_list`, and the test-only `hosting_manager_*` counters that an external tests/ integration binary cannot reach). But: - the workspace test job runs the lib tests WITHOUT `simulation_tests`, so the module is compiled out there; and - the Simulation job enables `simulation_tests` but only runs specific `--test <integration_binary>` targets, which excludes lib tests. So the module fell through the crack between the two jobs. ## Solution Add `--lib` to the Simulation job's build (`--no-run`) and run steps so the lib test binary is compiled and executed alongside the integration binaries. To avoid re-running the ~3000 ordinary freenet lib unit tests (already covered by the workspace test job), the run step restricts execution with a nextest filterset: kind(test) | (kind(lib) & test(sim_e2e_tests)) i.e. all integration tests plus only the governance sim e2e lib tests. No production code changes; this is a CI/test wiring fix only. ## Testing Ran the two tests locally under the CI feature set and they pass deterministically: cargo nextest run -p freenet --no-default-features \ --features "trace,websocket,redb,wasmtime-backend,testing,simulation_tests" \ --lib -E 'test(sim_e2e_tests)' # 2 tests run: 2 passed (governance_ban_chain_end_to_end 115.5s, # popular_contract_with_subscribers_not_evicted 88.3s) Verified the filterset selects exactly the integration tests plus the two sim e2e lib tests via `cargo nextest list`. Closes #4301 [AI-assisted - Claude] Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rule Review: No issues foundRules checked: No rule violations detected. Assessment details:
Rule review against |
Multi-model review — cleanRisk tier: this touches CI configuration (a high-risk surface per the project review rules), so I ran the full review even though the diff is small and test-only. As a subagent I ran the lenses serially. External model (Codex, gpt-5.5) — clean, no introduced correctness issues. Codex independently reproduced the nextest filterset behavior in a scratch crate and confirmed Claude lenses (serial):
No blocking findings. Proceeding once CI is green. [AI-assisted - Claude] |
Problem
Issue #4301 asks for an end-to-end simulation-network test of the governance ban chain (rate-limit reject → MAD flag →
Normal → … → Evicted → Banned→ wire-traffic drop), as the required behavioral gate before flipping governance into Enforce mode on gateways.The tests themselves already exist: the
sim_e2e_testsmodule incrates/core/src/contract/governance.rs(added in PR #4309) containsgovernance_ban_chain_end_to_endandpopular_contract_with_subscribers_not_evicted. They drive the full production wiring inside arun_controlled_simulationnetwork (1 gateway + 5 nodes):governance_ban_chain_end_to_end— floods an abuser contract with heavy UPDATEs (cost flows through the realExecutor → Ring::commit_state_write → report_contract_resource_usage → GovernanceManager::ingest_costpath, driven by the per-nodegovernance_reaper_loopon virtual time), asserts the abuser lands on the per-nodeContractBanList(the wire-boundary enforcement signal thatnode.rsconsults to drop banned traffic) and reaches the terminalBannedstate, and asserts every honest contract is NOT banned (no collateral damage).popular_contract_with_subscribers_not_evicted— the tracking: contract + peer resource-usage governance #4296 false-positive control: a same-cost contract with many live downstream subscribers is NOT banned on its host, while the zero-beneficiary abuser IS.The gap this PR closes: those tests never actually ran in CI, so the gate was not enforced and the tests could silently rot. The module is gated behind
#[cfg(all(test, feature = "simulation_tests"))]and lives in the lib — it must, because it usespub(crate)accessors (Ring::governance,Ring::contract_ban_list, the test-onlyhosting_manager_*counters) that an externaltests/integration binary cannot reach. But:simulation_tests, so the module is compiled out there; andsimulation_testsbut only runs specific--test <integration_binary>targets, which excludes lib tests.So the module fell through the crack between the two jobs and was dead in CI.
Solution
Add
--libto the Simulation job's build (--no-run) and run steps so the lib test binary is compiled and executed alongside the integration binaries. To avoid re-running the ~3000 ordinary freenet lib unit tests (already covered by the workspace test job), the run step restricts execution with a nextest filterset:i.e. all integration tests plus only the governance sim e2e lib tests.
No production code changes — this is a CI/test wiring fix only.
Testing
Ran the two tests locally under the CI feature set; both pass deterministically:
Verified via
cargo nextest listthat the filterset selects exactly the integration tests plus the two sim e2e lib tests (not the other lib unit tests).Closes #4301
[AI-assisted - Claude]