Skip to content

test: property tests for expiry arithmetic (grant, extend, renew, subscribe) + fix main build - #146

Merged
Busiii-adetiba merged 1 commit into
SynapsVault:mainfrom
adenueltech:test/issue-108-expiry-property-tests
Oct 17, 2026
Merged

Busiii-adetiba merged 1 commit into
SynapsVault:mainfrom
adenueltech:test/issue-108-expiry-property-tests

Conversation

@adenueltech

Copy link
Copy Markdown
Contributor

Closes #108

Property tests

New expiry_props test modules (proptest, 64 cases each) check every expiry rule against a plain-integer model instead of hand-picked examples.

access-lease (contracts/access-lease/src/expiry_props.rs)

  • grant_lease sets expires_at = now + duration exactly, or returns InvalidDuration on u32 overflow and stores nothing.
  • A lease is valid on every ledger before expires_at and invalid from expires_at on.
  • extend_lease adds to max(expires_at, now), so an active lease keeps its remaining time and an expired one restarts. The result is always later than both. Overflow is rejected and the stored lease is left unchanged.
  • Consecutive extensions accumulate exactly.
  • Re-granting returns AlreadyActive while the lease is active; after expiry it restarts from now.
  • Zero-length grants and extensions are always rejected.

subscription (contracts/subscription/src/expiry_props.rs)

  • subscribe ends exactly one CYCLE after now.
  • A subscription is active strictly before current_period_end.
  • renew extends from max(current_period_end, now), increments total_renewals and keeps started_at.
  • k early renewals add exactly k cycles.
  • After cancel, access lasts until the period end and renew returns Cancelled. Re-subscribing carries over the remaining paid time, or restarts from now after it lapses.
  • A duplicate subscribe while active returns AlreadySubbed and leaves the subscription unchanged.

The tests set a long minimum entry TTL on the test ledger, so time can move across several full cycles without storage being archived. The subscription Overflow branch isn't exercised: it needs a ledger within one cycle of u32::MAX, where the host's own TTL arithmetic fails first. That's noted in the test.

Fixes needed to get main building

CI on main has failed on every run since Oct 16, and the workspace didn't compile, so no tests could run. The minimal fixes, each from conflicting merges:

Area Problem Fix
access-lease grant_lease Two merged bodies (Ok(lease) followed by another expression), the parse error CI reports Delegate to the existing grant_lease_internal
all contracts use common::{BUMP, BUMP_THRESH, DAY} clashed with each crate's own constants. common::DAY is in seconds, and its BUMP_THRESH > BUMP Keep the original per-crate ledger-based constants
version fns common::get_version/is_compatible are u32-based and matched none of the three call sites Restore per-contract get_version/is_compatible (last-green behaviour)
subscription require_admin Called common::require_admin with a DataKey Load the admin and call it correctly
common crate Pinned soroban-sdk = "20.0.0" (workspace is 29), not a workspace member, missing from Cargo.lock (breaks --locked) Use the workspace SDK, add to members and lockfile
vault-registry String::from_bytes given &Bytes Pass the byte slice
vault-registry is_compatible The #83 test expects "0.1." and "0.1.2.3" to be rejected, but they were accepted Also require a non-empty, numeric patch component
subscription events subscribe/renew emitted a map, but docs and tests specify the tuple (current_period_end, price, payment_reference) data_format = "vec"
tests Old ContractEvents API (len/get_unchecked), removed transfer_ownership, old 2-arg list, upgrade to a never-uploaded hash, a 32-vs-33 length typo, an empty-metadata proptest generator, a stale upgrade fixture Ported to soroban-sdk 29 and the two-step transfer, passed &false, &None to list (old behaviour), uploaded real WASM, fixed the typo and generator, regenerated the fixture with make fixture steps (stellar-cli 27.0.0)
lint clippy len_zero, cargo fmt Fixed

How I tested (same steps as CI)

  • cargo fmt --all -- --check: OK
  • cargo clippy --workspace --all-targets --locked -- -D warnings: OK
  • RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps --locked: OK
  • cargo test --locked -p vault-registry: 62 passed
  • cargo test --locked -p access-lease: 34 passed (incl. 6 property tests)
  • cargo test --locked -p subscription: 14 passed (incl. 6 property tests)
  • Gas report test: OK
  • stellar contract build: all 3 contracts build

Note: the stricter vault-registry::is_compatible also rejects strings that aren't X.Y.Z. #144 (the docs PR for #115) lists the cases that return false, and I'll add this one there.

🤖 Generated with Claude Code

…renew and subscribe (SynapsVault#108)

Property tests (proptest, checked against an integer model):
- access-lease: grant sets expires_at = now + duration or rejects overflow;
  validity holds strictly before expiry; extend adds to max(expiry, now) or
  rejects overflow leaving the lease unchanged; extensions accumulate;
  re-grant only after expiry and restarts from now; zero rejected.
- subscription: subscribe ends one CYCLE after now; active strictly before
  period end; renew extends from max(period end, now); early renewals add
  whole cycles; re-subscribing after cancel carries over remaining time;
  duplicate subscribe rejected while active.

main has failed CI since Oct 16, so these could not run. Minimal fixes to
get the workspace compiling and CI green:
- access-lease: remove a duplicated grant_lease body left by a merge.
- Drop common BUMP/BUMP_THRESH/DAY imports that clashed with each crate's
  own ledger-based constants (common's DAY is in seconds).
- Restore per-contract get_version/is_compatible; the common helpers are
  u32-based and did not match any caller. Fix subscription require_admin.
- common: use the workspace soroban-sdk (was 20.0.0) and add it to the
  workspace members / Cargo.lock.
- vault-registry: fix String::from_bytes call; validate the patch component
  in is_compatible so "0.1." and "0.1.2.3" are rejected (SynapsVault#83 test).
- subscription: subscribe/renew events use data_format = "vec" to match the
  documented (current_period_end, price, payment_reference) tuple.
- Tests: port event assertions to the soroban-sdk 29 ContractEvents API,
  use propose/accept_transfer instead of removed transfer_ownership, pass
  the new list() filter args, upload real WASM for success-path upgrade
  tests, fix a 32-vs-33 length test and an empty-metadata generator.
- Regenerate the vault-registry upgrade fixture (make fixture).
- clippy (len_zero) and cargo fmt.

Closes SynapsVault#108

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@drips-wave

drips-wave Bot commented Oct 17, 2026

Copy link
Copy Markdown

@adenueltech Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Busiii-adetiba
Busiii-adetiba merged commit 8ee4d90 into SynapsVault:main Oct 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[cross-cutting] Add property tests for expiry arithmetic across grant, extend, renew and subscribe

2 participants