litesvm_utils/
assertions.rs

1//! Assertion helpers for testing account states
2//!
3//! This module provides convenient assertion methods for verifying
4//! account states in tests.
5
6use litesvm::LiteSVM;
7use solana_program::pubkey::Pubkey;
8use litesvm_token::spl_token;
9use solana_program_pack::Pack;
10
11/// Assertion helper methods for LiteSVM
12pub trait AssertionHelpers {
13    /// Assert that an account is closed (doesn't exist or has 0 lamports and 0 data)
14    ///
15    /// # Example
16    /// ```no_run
17    /// # use litesvm_utils::AssertionHelpers;
18    /// # use litesvm::LiteSVM;
19    /// # use solana_program::pubkey::Pubkey;
20    /// # let svm = LiteSVM::new();
21    /// # let account = Pubkey::new_unique();
22    /// svm.assert_account_closed(&account);
23    /// ```
24    fn assert_account_closed(&self, pubkey: &Pubkey);
25
26    /// Assert that an account exists
27    ///
28    /// # Example
29    /// ```no_run
30    /// # use litesvm_utils::AssertionHelpers;
31    /// # use litesvm::LiteSVM;
32    /// # use solana_program::pubkey::Pubkey;
33    /// # let svm = LiteSVM::new();
34    /// # let account = Pubkey::new_unique();
35    /// svm.assert_account_exists(&account);
36    /// ```
37    fn assert_account_exists(&self, pubkey: &Pubkey);
38
39    /// Assert token account balance
40    ///
41    /// # Example
42    /// ```no_run
43    /// # use litesvm_utils::AssertionHelpers;
44    /// # use litesvm::LiteSVM;
45    /// # use solana_program::pubkey::Pubkey;
46    /// # let svm = LiteSVM::new();
47    /// # let token_account = Pubkey::new_unique();
48    /// svm.assert_token_balance(&token_account, 1_000_000_000); // 1 token with 9 decimals
49    /// ```
50    fn assert_token_balance(&self, token_account: &Pubkey, expected: u64);
51
52    /// Assert SOL balance
53    ///
54    /// # Example
55    /// ```no_run
56    /// # use litesvm_utils::AssertionHelpers;
57    /// # use litesvm::LiteSVM;
58    /// # use solana_program::pubkey::Pubkey;
59    /// # let svm = LiteSVM::new();
60    /// # let account = Pubkey::new_unique();
61    /// svm.assert_sol_balance(&account, 1_000_000_000); // 1 SOL
62    /// ```
63    fn assert_sol_balance(&self, pubkey: &Pubkey, expected: u64);
64
65    /// Assert token mint supply
66    ///
67    /// # Example
68    /// ```no_run
69    /// # use litesvm_utils::AssertionHelpers;
70    /// # use litesvm::LiteSVM;
71    /// # use solana_program::pubkey::Pubkey;
72    /// # let svm = LiteSVM::new();
73    /// # let mint = Pubkey::new_unique();
74    /// svm.assert_mint_supply(&mint, 1_000_000_000);
75    /// ```
76    fn assert_mint_supply(&self, mint: &Pubkey, expected: u64);
77
78    /// Assert that an account is owned by a specific program
79    ///
80    /// # Example
81    /// ```no_run
82    /// # use litesvm_utils::AssertionHelpers;
83    /// # use litesvm::LiteSVM;
84    /// # use solana_program::pubkey::Pubkey;
85    /// # let svm = LiteSVM::new();
86    /// # let account = Pubkey::new_unique();
87    /// # let owner = Pubkey::new_unique();
88    /// svm.assert_account_owner(&account, &owner);
89    /// ```
90    fn assert_account_owner(&self, account: &Pubkey, expected_owner: &Pubkey);
91
92    /// Assert that an account has a specific data length
93    ///
94    /// # Example
95    /// ```no_run
96    /// # use litesvm_utils::AssertionHelpers;
97    /// # use litesvm::LiteSVM;
98    /// # use solana_program::pubkey::Pubkey;
99    /// # let svm = LiteSVM::new();
100    /// # let account = Pubkey::new_unique();
101    /// svm.assert_account_data_len(&account, 100);
102    /// ```
103    fn assert_account_data_len(&self, account: &Pubkey, expected_len: usize);
104}
105
106impl AssertionHelpers for LiteSVM {
107    fn assert_account_closed(&self, pubkey: &Pubkey) {
108        let account = self.get_account(pubkey);
109        assert!(
110            account.is_none() || (account.as_ref().unwrap().lamports == 0 && account.as_ref().unwrap().data.is_empty()),
111            "Expected account {} to be closed, but it exists with {} lamports and {} bytes of data",
112            pubkey,
113            account.as_ref().map_or(0, |a| a.lamports),
114            account.as_ref().map_or(0, |a| a.data.len())
115        );
116    }
117
118    fn assert_account_exists(&self, pubkey: &Pubkey) {
119        let account = self.get_account(pubkey);
120        assert!(
121            account.is_some(),
122            "Expected account {} to exist, but it doesn't",
123            pubkey
124        );
125    }
126
127    fn assert_token_balance(&self, token_account: &Pubkey, expected: u64) {
128        let account = self
129            .get_account(token_account)
130            .expect(&format!("Token account {} not found", token_account));
131
132        let token_data = spl_token::state::Account::unpack(&account.data)
133            .expect(&format!("Failed to unpack token account {}", token_account));
134
135        assert_eq!(
136            token_data.amount, expected,
137            "Token balance mismatch for account {}. Expected: {}, Actual: {}",
138            token_account, expected, token_data.amount
139        );
140    }
141
142    fn assert_sol_balance(&self, pubkey: &Pubkey, expected: u64) {
143        let account = self.get_account(pubkey);
144        let actual = account.map_or(0, |a| a.lamports);
145        assert_eq!(
146            actual, expected,
147            "SOL balance mismatch for account {}. Expected: {}, Actual: {}",
148            pubkey, expected, actual
149        );
150    }
151
152    fn assert_mint_supply(&self, mint: &Pubkey, expected: u64) {
153        let account = self
154            .get_account(mint)
155            .expect(&format!("Mint {} not found", mint));
156
157        let mint_data = spl_token::state::Mint::unpack(&account.data)
158            .expect(&format!("Failed to unpack mint {}", mint));
159
160        assert_eq!(
161            mint_data.supply, expected,
162            "Mint supply mismatch for {}. Expected: {}, Actual: {}",
163            mint, expected, mint_data.supply
164        );
165    }
166
167    fn assert_account_owner(&self, account: &Pubkey, expected_owner: &Pubkey) {
168        let acc = self
169            .get_account(account)
170            .expect(&format!("Account {} not found", account));
171
172        assert_eq!(
173            &acc.owner, expected_owner,
174            "Account owner mismatch for {}. Expected: {}, Actual: {}",
175            account, expected_owner, acc.owner
176        );
177    }
178
179    fn assert_account_data_len(&self, account: &Pubkey, expected_len: usize) {
180        let acc = self
181            .get_account(account)
182            .expect(&format!("Account {} not found", account));
183
184        assert_eq!(
185            acc.data.len(),
186            expected_len,
187            "Account data length mismatch for {}. Expected: {}, Actual: {}",
188            account,
189            expected_len,
190            acc.data.len()
191        );
192    }
193}