Skip to content

🧪 RevFramework Currency — Testing Philosophy

This document explains how the Currency system is tested, what the tests are designed to protect, and what they intentionally do not claim.

This is not marketing material.

It is an engineering-facing overview of the testing philosophy behind the Currency system.


🎯 The Goal of the Tests

The Currency tests exist to protect:

  • behavioural guarantees
  • regression safety
  • deterministic wallet behaviour
  • explicit transaction semantics
  • audit and idempotency correctness
  • edge-case handling across composed service stacks

The tests are designed to answer questions like:

  • “Does this behaviour still work after refactors?”
  • “Did a supported public API contract accidentally change?”
  • “Do failed mutations leave balances untouched?”
  • “Do transaction rollback paths still behave consistently?”
  • “Do composed wrappers still expose the right capabilities?”
  • “Do audit, batch, escrow, authority, caps, and idempotency still interact correctly?”

The goal is predictability, not “perfect software.”


🔒 Hostile Consumer Tests

Most Currency tests are written as Hostile Consumer tests.

This means the tests interact with the system exactly the way a real Unity project would:

  • through public APIs
  • through supported interfaces
  • through supported factories
  • through supported service wrappers
  • through supported adapters and seams
  • without reflection
  • without private-field access
  • without editor-only shortcuts unless testing editor-authored assets

These tests intentionally avoid depending on implementation details.

If a Hostile test passes, the supported public Currency contract is behaving correctly.


✅ HappyPath Tests

Currency also has dedicated HappyPath tests.

These are not edge-case torture tests.

They prove that the system’s main intended workflows operate cleanly from a user-facing perspective.

HappyPath coverage focuses on flows such as:

  • creating wallets
  • crediting balances
  • debiting balances
  • transferring currency between owners
  • spending cost bundles
  • granting rewards
  • restoring wallet snapshots
  • composing common stacks
  • resolving scene services
  • using normal transaction flows successfully

These tests are deliberately readable.

Their purpose is to prove that the “normal developer path” works without needing to understand every internal decorator, policy, or failure branch.


⚙️ InternalTruth Tests

The Currency system also contains a smaller set of InternalTruth tests.

These tests validate internal framework assumptions that are important for long-term stability but are not part of the supported public API.

Examples include:

  • decorator composition order
  • internal RID parsing semantics
  • policy preview assumptions
  • transaction rollback boundaries
  • escrow-first rollback behaviour
  • hidden audit propagation through wrapper chains
  • internal cache / pruning expectations
  • capability exposure through composed services

InternalTruth tests are intentionally separated from Hostile tests.

They exist to protect framework integrity during future refactors.

They are not an invitation for users to rely on internals.


🧩 What the Currency Tests Validate

The current Currency test suite validates behaviour including:

Core Wallet Behaviour

  • Wallet creation
  • Balance reads
  • Credit behaviour
  • Debit behaviour
  • SetBalance behaviour
  • Transfer behaviour
  • Invalid owner / currency / amount handling
  • Event emission for successful mutations
  • No event emission for failed mutations

Caps & Policies

  • Minimum and maximum cap enforcement
  • Clamp mode behaviour
  • Fail mode behaviour
  • SetBalance cap behaviour
  • Transfer cap behaviour
  • Policy sanitization
  • Duplicate rule handling
  • Transfer policy provider behaviour

Transactions

  • Ordered staged operations
  • Successful commit behaviour
  • Failed commit behaviour
  • Friendly-stack rollback
  • Best-effort rollback boundaries
  • Transfer transaction semantics
  • Long-loop transaction stability
  • Batch emission during transactions

Escrow & Hold Transactions

  • Direct escrow hold / commit / release / expire behaviour
  • TTL expiry behaviour
  • No-TTL hold behaviour
  • Destroyed-owner handling
  • Read-only escrow inspection
  • Owner token indexing
  • HoldTxn success paths
  • HoldTxn failure and release paths
  • Repeated hold / release / expire cycles
  • Require-escrow enforcement

Audit

  • Audit metadata propagation
  • Reason and sourceId preservation
  • Newest-first ordering
  • Per-owner audit isolation
  • Capacity-bounded audit history
  • Live audit subscriptions
  • Unsubscribe behaviour
  • No audit entries for failed mutations
  • Hidden audit propagation in internal wrapper chains

Idempotency

  • RID-based replay detection
  • Replay scope by owner
  • Replay scope by currency
  • Replay scope by operation kind
  • Replay behaviour for Credit / Debit / SetBalance / Transfer
  • No mutation on replay
  • No duplicate events on replay
  • Capacity-bounded replay history
  • Eviction behaviour
  • Non-audit path passthrough

Authority

  • Unauthorized mutation blocking
  • Missing-authority behaviour
  • Allow-all authority behaviour
  • Denied Credit / Debit / SetBalance / Transfer
  • No wallet mutation on denied operations
  • No events or audit entries on denied operations
  • Authority behaviour inside transactions and composed stacks

Batch Events

  • Batch wrapper capability exposure
  • One batch event per explicit emit
  • Per-op events still firing during batches
  • Cancel behaviour
  • Empty batch behaviour
  • Transaction batch behaviour
  • HoldTxn batch behaviour

Persistence

  • Wallet snapshot capture
  • Restore success paths
  • Restore invalid input handling
  • Restore rollback on mid-failure
  • Audit-aware restore metadata
  • Large-scale capture / mutate / restore round trips
  • Repeated restore cycles
  • Surviving-owner restore behaviour after destroyed owners

Scene Resolution & Bootstrap

  • Scene-local service resolution
  • Active-scene fallback
  • Inactive child service discovery
  • Resolver cache invalidation
  • Destroyed-service recovery
  • Published override precedence
  • Dispose-scope fallback behaviour
  • Resolver churn stability

Definitions & Formatting

  • CurrencyDefinition authored values
  • CurrencySet lookup behaviour
  • Currency ID normalization
  • Missing / null definition handling
  • Display formatting
  • Grouped / plain / compact formatting
  • Signed delta formatting
  • Template replacement

Scale & Correctness

  • Many-owner wallet isolation
  • Bulk credit / debit correctness
  • Many transfer correctness
  • Global total preservation during transfers
  • Failed operations at scale
  • Repeated transaction loops
  • Repeated escrow loops
  • Repeated persistence round trips

🧠 Deterministic Test Infrastructure

The Currency tests use deterministic test infrastructure where needed, including:

  • scene-created currency services
  • manual time providers
  • explicit authority fakes
  • authored ScriptableObject policies
  • controlled composed service stacks
  • repeatable owner and wallet setup
  • bounded-capacity audit and idempotency configurations

This allows difficult service-composition, lifecycle, and rollback paths to be tested reliably.

The goal is not to fake the framework into passing.

The goal is to put the real framework surfaces under controlled, repeatable pressure.


❌ What These Tests Do NOT Claim

The tests do not claim:

  • the framework is bug-free
  • every possible gameplay economy is covered
  • multiplayer correctness is guaranteed
  • third-party integrations are validated
  • every project-specific adapter is safe
  • all rollback paths are perfectly atomic in hostile external conditions
  • all performance/stress limits are proven

The tests validate framework behaviour and guarantees — not every possible project implementation.


🧩 The Philosophy

RevFramework systems are designed around:

  • explicit guarantees
  • predictable behaviour
  • transparent failure handling
  • modular integration seams
  • service-driven composition
  • honest public API boundaries

The Currency tests exist to lock those guarantees down over time as the framework evolves.

The goal is not to hide complexity.

The goal is to make Currency behaviour understandable, stable, and intentional.


TL;DR

The Currency tests are designed to protect guarantees, not pretend software can never fail.

Hostile tests validate supported public behaviour.

HappyPath tests prove the normal developer workflow works.

InternalTruth tests protect hidden framework assumptions.

Together, they help keep Currency predictable as RevFramework evolves.