Skip to content

Add saturating-arithmetic and balance-cap edge-case tests for the accrual formula #140

Description

@greatest0fallt1me

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:314334, 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

  • Balance-cap, saturating-multiply, large-elapsed, zero-elapsed, and sequential-drain tests added.
  • At least one test uses rate_per_second = i128::MAX and asserts the settled amount never exceeds balance and is never negative.
  • No test relies on real sleeps; all use ledger-time mutation.
  • New snapshot JSON files committed and reviewed.
  • cargo test and cargo clippy ... -D warnings pass.

Suggested execution

1. Fork the repo and create a branchgit 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions