|
1 | 1 | use { |
2 | 2 | mollusk_svm::{result::Check, Mollusk}, |
3 | 3 | solana_account::{Account, ReadableAccount}, |
| 4 | + solana_instruction::{AccountMeta, Instruction}, |
4 | 5 | solana_program_error::ProgramError, |
5 | 6 | solana_pubkey::Pubkey, |
6 | 7 | solana_system_interface::error::SystemError, |
@@ -127,69 +128,73 @@ fn test_multiple_transfers_with_persistent_state() { |
127 | 128 | } |
128 | 129 |
|
129 | 130 | #[test] |
130 | | -fn test_account_store_sysvar_account() { |
131 | | - let mollusk = Mollusk::default(); |
132 | | - let context = mollusk.with_context(HashMap::new()); |
133 | | - |
134 | | - // Use Clock sysvar as an example. |
135 | | - let clock_pubkey = solana_sdk_ids::sysvar::clock::id(); |
136 | | - let recipient = Pubkey::new_unique(); |
| 131 | +fn test_account_store_sysvars_and_programs() { |
| 132 | + std::env::set_var("SBF_OUT_DIR", "../target/deploy"); |
| 133 | + |
| 134 | + let program_id = Pubkey::new_unique(); |
| 135 | + let mollusk = Mollusk::new(&program_id, "test_program_primary"); |
| 136 | + let mut context = mollusk.with_context(HashMap::new()); |
| 137 | + |
| 138 | + // `with_context` will already create program accounts, so assert our |
| 139 | + // main program already has an account in the store. |
| 140 | + { |
| 141 | + let store = context.account_store.borrow(); |
| 142 | + let main_program_account = store |
| 143 | + .get(&program_id) |
| 144 | + .expect("Main program account should exist"); |
| 145 | + assert_eq!( |
| 146 | + main_program_account.owner, |
| 147 | + solana_sdk_ids::bpf_loader_upgradeable::id() |
| 148 | + ); |
| 149 | + assert!(main_program_account.executable); |
| 150 | + } |
| 151 | + |
| 152 | + // Add another test program to the test environment. |
| 153 | + let other_program_id = Pubkey::new_unique(); |
| 154 | + context.mollusk.add_program( |
| 155 | + &other_program_id, |
| 156 | + "test_program_cpi_target", |
| 157 | + &mollusk_svm::program::loader_keys::LOADER_V3, |
| 158 | + ); |
137 | 159 |
|
138 | | - // Create an instruction that references the Clock sysvar. |
139 | | - let instruction = solana_instruction::Instruction::new_with_bytes( |
140 | | - solana_sdk_ids::system_program::id(), |
141 | | - &[], |
| 160 | + // Use the "close account" test from our BPF program. |
| 161 | + let key = Pubkey::new_unique(); |
| 162 | + context |
| 163 | + .account_store |
| 164 | + .borrow_mut() |
| 165 | + .insert(key, Account::new(50_000_000, 50, &program_id)); |
| 166 | + let instruction = Instruction::new_with_bytes( |
| 167 | + program_id, |
| 168 | + &[3], |
142 | 169 | vec![ |
143 | | - solana_instruction::AccountMeta::new_readonly(clock_pubkey, false), |
144 | | - solana_instruction::AccountMeta::new(recipient, false), |
| 170 | + AccountMeta::new(key, true), |
| 171 | + AccountMeta::new(solana_sdk_ids::incinerator::id(), false), |
| 172 | + AccountMeta::new_readonly(solana_sdk_ids::system_program::id(), false), |
| 173 | + // Arbitrarily include the `Clock` sysvar account |
| 174 | + AccountMeta::new_readonly(solana_sdk_ids::sysvar::clock::id(), false), |
| 175 | + // Also include our additional program account |
| 176 | + AccountMeta::new_readonly(other_program_id, false), |
145 | 177 | ], |
146 | 178 | ); |
| 179 | + context.process_and_validate_instruction(&instruction, &[Check::success()]); |
147 | 180 |
|
148 | | - // Process the instruction - this should load the Clock sysvar account. |
149 | | - context.process_instruction(&instruction); |
150 | | - |
151 | | - // Verify the Clock sysvar was loaded correctly. |
152 | 181 | let store = context.account_store.borrow(); |
153 | | - let clock_account = store.get(&clock_pubkey).expect("Clock sysvar should exist"); |
154 | 182 |
|
155 | | - // Verify it has the expected owner. |
| 183 | + // Verify clock sysvar was loaded. |
| 184 | + let clock_account = store |
| 185 | + .get(&solana_sdk_ids::sysvar::clock::id()) |
| 186 | + .expect("Clock sysvar should exist"); |
156 | 187 | assert_eq!(clock_account.owner, solana_sdk_ids::sysvar::id()); |
157 | | - // Verify it has data (Clock sysvar should have serialized Clock data). |
158 | | - assert!(!clock_account.data.is_empty()); |
159 | | -} |
160 | | - |
161 | | -#[test] |
162 | | -fn test_account_store_program_account() { |
163 | | - // Use the System Program as an example. |
164 | | - let program_id = solana_sdk_ids::system_program::id(); |
165 | | - let mollusk = Mollusk::default(); |
166 | 188 |
|
167 | | - let context = mollusk.with_context(HashMap::new()); |
168 | | - let recipient = Pubkey::new_unique(); |
169 | | - |
170 | | - // Create an instruction that references the program account. |
171 | | - let instruction = solana_instruction::Instruction::new_with_bytes( |
172 | | - solana_sdk_ids::bpf_loader_upgradeable::id(), |
173 | | - &[], |
174 | | - vec![ |
175 | | - solana_instruction::AccountMeta::new_readonly(program_id, false), |
176 | | - solana_instruction::AccountMeta::new(recipient, false), |
177 | | - ], |
| 189 | + // Verify our additional program was loaded. |
| 190 | + let additional_program_account = store |
| 191 | + .get(&other_program_id) |
| 192 | + .expect("Additional program account should exist"); |
| 193 | + assert_eq!( |
| 194 | + additional_program_account.owner, |
| 195 | + mollusk_svm::program::loader_keys::LOADER_V3 |
178 | 196 | ); |
179 | | - |
180 | | - // Process the instruction - this should load the program account. |
181 | | - context.process_instruction(&instruction); |
182 | | - |
183 | | - // Verify the program account was loaded correctly |
184 | | - let store = context.account_store.borrow(); |
185 | | - let program_account = store |
186 | | - .get(&program_id) |
187 | | - .expect("Program account should exist"); |
188 | | - |
189 | | - // Verify it has the expected owner (native loader for builtins). |
190 | | - assert_eq!(program_account.owner, solana_sdk_ids::native_loader::id()); |
191 | | - // Verify it's marked as executable. |
192 | | - assert!(program_account.executable); |
| 197 | + assert!(additional_program_account.executable); |
193 | 198 | } |
194 | 199 |
|
195 | 200 | #[test] |
|
0 commit comments