light_program_test/
litesvm_extensions.rs1use litesvm::LiteSVM;
2use solana_account::ReadableAccount;
3use solana_sdk::{account::Account, pubkey::Pubkey};
4
5pub trait LiteSvmExtensions {
10 fn get_program_accounts(&self, program_id: &Pubkey) -> Vec<(Pubkey, Account)>;
23}
24
25impl LiteSvmExtensions for LiteSVM {
26 fn get_program_accounts(&self, program_id: &Pubkey) -> Vec<(Pubkey, Account)> {
27 self.accounts_db()
28 .inner
29 .iter()
30 .filter(|(_, account)| account.owner() == program_id)
31 .map(|(pubkey, account)| (*pubkey, Account::from(account.clone())))
32 .collect()
33 }
34}
35
36#[cfg(test)]
37mod tests {
38 use solana_sdk::{
39 native_token::LAMPORTS_PER_SOL,
40 signature::{Keypair, Signer},
41 system_instruction::{create_account, transfer},
42 system_program,
43 transaction::{Transaction, VersionedTransaction},
44 };
45
46 use super::*;
47
48 #[test]
49 fn test_get_program_accounts() {
50 let mut svm = LiteSVM::new();
51 let payer_keypair = Keypair::new();
52 let payer = payer_keypair.pubkey();
53
54 svm.airdrop(&payer, 10 * LAMPORTS_PER_SOL).unwrap();
56
57 let baseline_system_accounts = svm.get_program_accounts(&system_program::id());
59 let baseline_count = baseline_system_accounts.len();
60
61 let num_system_accounts = 5;
63 let mut system_owned_accounts = vec![];
64
65 for i in 0..num_system_accounts {
66 let new_account_keypair = Keypair::new();
67 let new_account = new_account_keypair.pubkey();
68 let space = 10 + i;
69 let rent_amount = svm.minimum_balance_for_rent_exemption(space);
70
71 let instruction = create_account(
72 &payer,
73 &new_account,
74 rent_amount,
75 space as u64,
76 &system_program::id(),
77 );
78
79 let tx = Transaction::new_signed_with_payer(
80 &[instruction],
81 Some(&payer),
82 &[&payer_keypair, &new_account_keypair],
83 svm.latest_blockhash(),
84 );
85
86 svm.send_transaction(VersionedTransaction::from(tx))
87 .unwrap();
88 system_owned_accounts.push((new_account, rent_amount, space));
89 }
90
91 let custom_program_id = Pubkey::new_unique();
93 let num_custom_accounts = 3;
94 let mut custom_owned_accounts = vec![];
95
96 for i in 0..num_custom_accounts {
97 let new_account_keypair = Keypair::new();
98 let new_account = new_account_keypair.pubkey();
99 let space = 20 + i * 2;
100 let rent_amount = svm.minimum_balance_for_rent_exemption(space);
101
102 let instruction = create_account(
103 &payer,
104 &new_account,
105 rent_amount,
106 space as u64,
107 &custom_program_id,
108 );
109
110 let tx = Transaction::new_signed_with_payer(
111 &[instruction],
112 Some(&payer),
113 &[&payer_keypair, &new_account_keypair],
114 svm.latest_blockhash(),
115 );
116
117 svm.send_transaction(VersionedTransaction::from(tx))
118 .unwrap();
119 custom_owned_accounts.push((new_account, rent_amount, space));
120 }
121
122 for i in 0..3 {
124 let to = Pubkey::new_unique();
125 let amount = (i + 1) * 1000;
126 let instruction = transfer(&payer, &to, amount);
127 let tx = Transaction::new_signed_with_payer(
128 &[instruction],
129 Some(&payer),
130 &[&payer_keypair],
131 svm.latest_blockhash(),
132 );
133 svm.send_transaction(VersionedTransaction::from(tx))
134 .unwrap();
135 }
136
137 let system_accounts = svm.get_program_accounts(&system_program::id());
139
140 let expected_count = baseline_count + num_system_accounts + 3;
142 assert_eq!(
143 system_accounts.len(),
144 expected_count,
145 "Expected {} system accounts (baseline {} + {} created + 3 transfers), got {}",
146 expected_count,
147 baseline_count,
148 num_system_accounts,
149 system_accounts.len()
150 );
151
152 for (pubkey, expected_lamports, expected_space) in &system_owned_accounts {
154 let found = system_accounts
155 .iter()
156 .find(|(pk, _)| pk == pubkey)
157 .expect("System account should be found");
158
159 assert_eq!(found.1.lamports, *expected_lamports);
160 assert_eq!(found.1.data.len(), *expected_space);
161 assert_eq!(found.1.owner, system_program::id());
162 }
163
164 for (pubkey, _, _) in &system_owned_accounts {
166 let individual_account = svm.get_account(pubkey).unwrap();
167 let from_program_accounts =
168 system_accounts.iter().find(|(pk, _)| pk == pubkey).unwrap();
169
170 assert_eq!(
171 individual_account.lamports,
172 from_program_accounts.1.lamports
173 );
174 assert_eq!(individual_account.data, from_program_accounts.1.data);
175 assert_eq!(individual_account.owner, from_program_accounts.1.owner);
176 }
177
178 let custom_accounts = svm.get_program_accounts(&custom_program_id);
180 assert_eq!(custom_accounts.len(), num_custom_accounts);
181
182 for (pubkey, expected_lamports, expected_space) in &custom_owned_accounts {
184 let found = custom_accounts
185 .iter()
186 .find(|(pk, _)| pk == pubkey)
187 .expect("Custom account should be found");
188
189 assert_eq!(found.1.lamports, *expected_lamports);
190 assert_eq!(found.1.data.len(), *expected_space);
191 assert_eq!(found.1.owner, custom_program_id);
192 }
193
194 let nonexistent_program = Pubkey::new_unique();
196 let no_accounts = svm.get_program_accounts(&nonexistent_program);
197 assert_eq!(no_accounts.len(), 0);
198 }
199}