Description
The accrual formula min((now - start_time) * rate_per_second, balance) is documented as saturating and balance-capped in docs/accrual-spec.md §3 and in the long module note at src/lib.rs:314–334, but the test suite only covers ordinary values (e.g. test_settle_returns_amount settles 100, src/lib.rs:843). There are no tests proving the saturation and cap guards actually hold at the i128/u64 boundaries. This issue adds dedicated edge-case coverage so the “no silent wrap” guarantee is enforced by CI rather than only asserted in prose.
Requirements and context
Functional (test scenarios)
- Balance cap fires:
rate_per_second = 100, balance = 1_000, advance 20s → settled 1_000, balance == 0 (mirrors docs/accrual-spec.md §6 Example 2).
- Saturating multiply: create a stream with
rate_per_second = i128::MAX and a small balance, advance several seconds, assert the settled amount equals balance (not a wrapped/negative value) and balance ends at 0.
- Astronomical elapsed: advance the ledger by a very large number of seconds via
env.ledger().with_mut(|li| li.timestamp += ...) and assert the result is still min(saturated_product, balance) with no panic.
- Zero elapsed: settle in the same ledger second (
elapsed == 0) and assert 0 settled and balance unchanged (docs/accrual-spec.md §6 Example 3).
- Sequential settlements drain exactly to
0 over multiple windows (Example 4), and a post-exhaustion settle returns 0.
Non-functional / repo conventions
- Follow
docs/testing-strategy.md: name tests by behaviour, fresh Env::default() per test, advance time via ledger mutation (no sleeps).
- Tests live inline in
#[cfg(test)] mod test in src/lib.rs; new committed snapshots land under test_snapshots/test/.
Acceptance criteria
Suggested execution
1. Fork the repo and create a branch — git checkout -b testing/accrual-saturation-edge-cases.
2. Implement changes — no production change expected; if a test reveals a real wrap/cap bug, fix it in src/lib.rs and note it in the PR.
3. Write/extend tests — add the scenarios above to the inline #[cfg(test)] mod test; reuse the advance_ledger_time helper at src/lib.rs:646.
4. Test and commit
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --features testutils
UPDATE_SNAPSHOTS=1 cargo test --features testutils # only if snapshots changed intentionally
Example commit message
test(accrual): cover saturating multiply and balance-cap edge cases
Guidelines
- Target 95% line coverage for the accrual paths (
docs/coverage.sh).
- If behaviour is clarified, update
docs/accrual-spec.md §3/§7 to keep the “matches src/lib.rs” claim honest.
- Timeframe: 96 hours.
Description
The accrual formula
min((now - start_time) * rate_per_second, balance)is documented as saturating and balance-capped indocs/accrual-spec.md§3 and in the long module note atsrc/lib.rs:314–334, but the test suite only covers ordinary values (e.g.test_settle_returns_amountsettles100,src/lib.rs:843). There are no tests proving the saturation and cap guards actually hold at thei128/u64boundaries. This issue adds dedicated edge-case coverage so the “no silent wrap” guarantee is enforced by CI rather than only asserted in prose.Requirements and context
Functional (test scenarios)
rate_per_second = 100,balance = 1_000, advance20s→ settled1_000,balance == 0(mirrorsdocs/accrual-spec.md§6 Example 2).rate_per_second = i128::MAXand a smallbalance, advance several seconds, assert the settled amount equalsbalance(not a wrapped/negative value) andbalanceends at0.env.ledger().with_mut(|li| li.timestamp += ...)and assert the result is stillmin(saturated_product, balance)with no panic.elapsed == 0) and assert0settled andbalanceunchanged (docs/accrual-spec.md§6 Example 3).0over multiple windows (Example 4), and a post-exhaustion settle returns0.Non-functional / repo conventions
docs/testing-strategy.md: name tests by behaviour, freshEnv::default()per test, advance time via ledger mutation (no sleeps).#[cfg(test)] mod testinsrc/lib.rs; new committed snapshots land undertest_snapshots/test/.Acceptance criteria
rate_per_second = i128::MAXand asserts the settled amount never exceedsbalanceand is never negative.cargo testandcargo clippy ... -D warningspass.Suggested execution
1. Fork the repo and create a branch —
git checkout -b testing/accrual-saturation-edge-cases.2. Implement changes — no production change expected; if a test reveals a real wrap/cap bug, fix it in
src/lib.rsand note it in the PR.3. Write/extend tests — add the scenarios above to the inline
#[cfg(test)] mod test; reuse theadvance_ledger_timehelper atsrc/lib.rs:646.4. Test and commit
Example commit message
Guidelines
docs/coverage.sh).docs/accrual-spec.md§3/§7 to keep the “matches src/lib.rs” claim honest.