| name | testing-strategy |
| description | Test taxonomy, coverage strategy, and test patterns for STWO. Covers unit test locations, coverage gaps, property testing opportunities, CI matrix, and patterns for field, prove-verify, and constraint tests. Use when adding tests, reviewing coverage, debugging failures, or assessing test adequacy.
|
Testing Strategy
Test Taxonomy
Unit Tests (Inline)
All tests are inline #[cfg(test)] modules — no separate tests/ directories.
Well-tested domains (run cargo test --features prover -- --list to get current counts):
| Domain | File(s) | Coverage |
|---|
| FRI verifier | core/fri.rs | Excellent — includes rejection tests |
| Field arithmetic | core/fields/m31.rs, cm31.rs, qm31.rs | Basic ops + inverse |
| Batch inverse | core/fields/mod.rs | Including edge cases |
| Circle group | core/circle.rs | Generator, coset, random point |
| Vanishing polys | core/constraints.rs | Coset/point vanishing + degree |
| Blake2s channel | core/channel/blake2s.rs | Draw/mix operations |
| Merkle trees | core/vcs/blake2_merkle.rs | Including decommit failures |
| SIMD M31 | prover/backend/simd/m31.rs | Arithmetic + SIMD load/store |
| SIMD FFT | prover/backend/simd/fft/ | Butterfly through full FFT |
| SIMD circle | prover/backend/simd/circle.rs | Eval, interpolate, extend |
| GKR/lookups | prover/lookups/ | Sumcheck, GKR, grand product |
| PCS | core/pcs/mod.rs | Security bits only — sparse |
E2E Tests (via Examples)
The crates/examples/ crate contains prove-then-verify tests:
- Wide Fibonacci with preprocessed columns
- Poseidon2 hash proof
- Blake2s proof (round, scheduler, XOR table)
- State machine
- Plonk-style
- XOR with GKR lookups
These test the full proving pipeline but only on the happy path.
Benchmarks as Tests
Criterion benchmarks in crates/stwo/benches/ exercise hot paths.
They serve as regression detectors in CI.
Coverage Gaps (CRITICAL)
Soundness-Critical Files With Zero Unit Tests
| File | Risk | What's Missing |
|---|
core/verifier.rs | CRITICAL | No rejection tests for malformed proofs |
core/pcs/verifier.rs | CRITICAL | No unit tests for PCS verification |
core/pcs/quotients.rs | CRITICAL | No tests for DEEP quotient construction |
prover/lookups/gkr_prover.rs | HIGH | Tested only transitively |
prover/lookups/mle.rs | HIGH | Empty #[cfg(test)] block |
core/proof_of_work.rs | MEDIUM | PoW verifier side untested |
Missing Test Categories
-
No property-based tests: No proptest, quickcheck, or Arbitrary anywhere.
This is a significant gap for field arithmetic and polynomial operations.
-
No adversarial verifier tests: The verifier is only tested on valid proofs.
There are no tests for:
- Proofs with corrupted Merkle commitments
- Proofs with wrong OODS evaluations
- Proofs with invalid composition polynomial
- Proofs with wrong PoW nonce
-
No fuzzing targets: No cargo-fuzz or honggfuzz configurations.
How to Run Tests
cargo test --features prover
cargo test --features "prover,parallel,tracing"
cargo test --release --features "slow-tests,prover"
cargo test --package stwo --features prover
cargo test --package stwo-constraint-framework --features prover
cargo test --features prover -- test_name
cd ensure-verifier-no_std && cargo build -r
Test Patterns for STWO
Field Arithmetic Tests
#[test]
fn test_field_op() {
let a = M31::from(42);
let b = M31::from(17);
assert_eq!(a + b - b, a);
assert_eq!(a * b * b.inverse(), a);
assert_eq!(a * M31::one(), a);
assert_eq!(a + M31::zero(), a);
}
Prove-Verify Round Trip
#[test]
fn test_prove_verify() {
let trace = generate_trace(&input);
let config = PcsConfig { ... };
let proof = prove::<SimdBackend, Blake2sMerkleChannel>(&components, &mut channel, scheme);
verify::<Blake2sMerkleChannel>(&components, &mut channel, &mut verifier, proof).unwrap();
}
Constraint Assertion
#[test]
fn test_constraints_hold() {
let trace = generate_trace(&input);
assert_constraints_on_trace(&component, &trace);
}
FRI Rejection Tests (Reference Pattern)
From core/fri.rs — the best-tested module. Pattern to follow:
#[test]
fn test_fri_proof_invalid_X() {
let (proof, config) = generate_valid_proof();
let mut corrupted = proof;
corrupted.X = invalid_value;
let result = verify(corrupted);
assert!(matches!(result, Err(FriVerificationError::XInvalid)));
}
Adding Tests: Priority Order
When adding tests, prioritize by risk:
- Verifier rejection tests — Ensure malformed proofs are rejected
- Property tests for field arithmetic — All algebraic identities hold
- DEEP quotient correctness — Quotients are actually low-degree
- PCS verifier unit tests — Commitment verification logic
- GKR prover correctness — Prove-verify round trips
- Adversarial proof tests — Proofs with targeted corruptions
Test Configuration
Feature Flags
| Flag | Effect |
|---|
prover | Enables prover code (required for most tests) |
parallel | Enables rayon parallelism |
slow-tests | Enables long-running tests (release mode only) |
tracing | Enables tracing instrumentation |
CI Matrix
Tests run on multiple configurations:
- nightly + prover (primary)
- stable + prover (compatibility)
- stable + no-default-features (verifier-only)
- nightly + parallel (threading)
- nightly + slow-tests + release
- AVX2, AVX512, NEON, WASM targets
Forbidden Actions
In this domain, agents must NEVER:
- Remove or weaken any existing test
- Mark a test as
#[ignore] without documented justification
- Reduce test coverage in soundness-critical code
- Use
#[should_panic] to mask a real failure
- Skip running tests before submitting changes to proof-system code