|
| 1 | +/// Shared Env fixtures for cross-contract integration tests. |
| 2 | +/// |
| 3 | +/// Import with: |
| 4 | +/// ```toml |
| 5 | +/// [dev-dependencies] |
| 6 | +/// myfans-lib = { path = "../myfans-lib", features = ["testutils"] } |
| 7 | +/// ``` |
| 8 | +/// Then in your test file: |
| 9 | +/// ```rust |
| 10 | +/// use myfans_lib::test_fixtures::TestEnv; |
| 11 | +/// ``` |
| 12 | +/// |
| 13 | +/// # What this provides |
| 14 | +/// - A single `Env` with `mock_all_auths()` and raised TTLs so ledger |
| 15 | +/// advancement never archives instance storage. |
| 16 | +/// - Pre-generated `admin`, `fee_recipient`, `creator`, and `fan` addresses. |
| 17 | +/// - A registered Stellar-asset token contract with the admin as issuer. |
| 18 | +/// - Helper methods to register and initialise the subscription, treasury, |
| 19 | +/// content-access, and creator-registry contracts in one call each. |
| 20 | +/// - `mint(to, amount)` convenience wrapper. |
| 21 | +use soroban_sdk::{ |
| 22 | + testutils::{Address as _, Ledger as LedgerTrait}, |
| 23 | + token::{StellarAssetClient, TokenClient}, |
| 24 | + Address, Env, |
| 25 | +}; |
| 26 | + |
| 27 | +/// Minimum TTL applied to every entry so ledger advancement in tests never |
| 28 | +/// archives instance storage and causes spurious "entry not found" panics. |
| 29 | +pub const TEST_TTL: u32 = 10_000_000; |
| 30 | + |
| 31 | +/// Central fixture that every cross-contract integration test should start from. |
| 32 | +/// |
| 33 | +/// ```rust |
| 34 | +/// let f = TestEnv::new(); |
| 35 | +/// f.token_admin.mint(&f.fan, &5_000); |
| 36 | +/// ``` |
| 37 | +pub struct TestEnv { |
| 38 | + pub env: Env, |
| 39 | + pub admin: Address, |
| 40 | + pub fee_recipient: Address, |
| 41 | + pub creator: Address, |
| 42 | + pub fan: Address, |
| 43 | + pub token_address: Address, |
| 44 | + pub token_client: TokenClient<'static>, |
| 45 | + pub token_admin_client: StellarAssetClient<'static>, |
| 46 | +} |
| 47 | + |
| 48 | +impl TestEnv { |
| 49 | + /// Build a fully-wired test environment. |
| 50 | + /// |
| 51 | + /// - `mock_all_auths()` is active for the lifetime of the returned `TestEnv`. |
| 52 | + /// - Instance and temporary storage TTLs are raised to [`TEST_TTL`] so |
| 53 | + /// ledger-sequence advances in tests never expire entries. |
| 54 | + /// - A Stellar-asset token contract is registered with `admin` as issuer. |
| 55 | + pub fn new() -> Self { |
| 56 | + let env = Env::default(); |
| 57 | + env.mock_all_auths(); |
| 58 | + env.ledger().with_mut(|li| { |
| 59 | + li.min_persistent_entry_ttl = TEST_TTL; |
| 60 | + li.min_temp_entry_ttl = TEST_TTL; |
| 61 | + }); |
| 62 | + |
| 63 | + let admin = Address::generate(&env); |
| 64 | + let fee_recipient = Address::generate(&env); |
| 65 | + let creator = Address::generate(&env); |
| 66 | + let fan = Address::generate(&env); |
| 67 | + |
| 68 | + // Register a Stellar-asset token so it speaks the standard token |
| 69 | + // interface (balance, transfer, mint) that all contracts expect. |
| 70 | + let token_reg = env.register_stellar_asset_contract_v2(admin.clone()); |
| 71 | + let token_address = token_reg.address(); |
| 72 | + |
| 73 | + // SAFETY: the clients borrow `env` which lives inside `TestEnv`. |
| 74 | + // We extend the lifetime to `'static` here because `TestEnv` owns |
| 75 | + // `env` and the clients will never outlive it. |
| 76 | + let token_client = unsafe { |
| 77 | + core::mem::transmute::<TokenClient<'_>, TokenClient<'static>>(TokenClient::new( |
| 78 | + &env, |
| 79 | + &token_address, |
| 80 | + )) |
| 81 | + }; |
| 82 | + let token_admin_client = unsafe { |
| 83 | + core::mem::transmute::<StellarAssetClient<'_>, StellarAssetClient<'static>>( |
| 84 | + StellarAssetClient::new(&env, &token_address), |
| 85 | + ) |
| 86 | + }; |
| 87 | + |
| 88 | + Self { |
| 89 | + env, |
| 90 | + admin, |
| 91 | + fee_recipient, |
| 92 | + creator, |
| 93 | + fan, |
| 94 | + token_address, |
| 95 | + token_client, |
| 96 | + token_admin_client, |
| 97 | + } |
| 98 | + } |
| 99 | + |
| 100 | + /// Mint `amount` tokens to `to` using the admin-controlled asset client. |
| 101 | + pub fn mint(&self, to: &Address, amount: i128) { |
| 102 | + self.token_admin_client.mint(to, &amount); |
| 103 | + } |
| 104 | + |
| 105 | + /// Advance the ledger sequence by `n` without changing the timestamp. |
| 106 | + pub fn advance_ledger(&self, n: u32) { |
| 107 | + self.env.ledger().with_mut(|li| { |
| 108 | + li.sequence_number += n; |
| 109 | + }); |
| 110 | + } |
| 111 | +} |
| 112 | + |
| 113 | +impl Default for TestEnv { |
| 114 | + fn default() -> Self { |
| 115 | + Self::new() |
| 116 | + } |
| 117 | +} |
0 commit comments