Skip to content

Commit

Permalink
Program Test: Fix invoke_builtin_function unwinding (#2632)
Browse files Browse the repository at this point in the history
  • Loading branch information
andreisilviudragnea authored Aug 23, 2024
1 parent 1588bca commit 52e7329
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 8 deletions.
28 changes: 20 additions & 8 deletions program-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ use {
fs::File,
io::{self, Read},
mem::transmute,
panic::AssertUnwindSafe,
path::{Path, PathBuf},
sync::{
atomic::{AtomicBool, Ordering},
Expand Down Expand Up @@ -140,12 +141,25 @@ pub fn invoke_builtin_function(
unsafe { deserialize(&mut parameter_bytes.as_slice_mut()[0] as *mut u8) };

// Execute the program
builtin_function(program_id, &account_infos, input).map_err(|err| {
let err = InstructionError::from(u64::from(err));
stable_log::program_failure(&log_collector, program_id, &err);
let err: Box<dyn std::error::Error> = Box::new(err);
err
})?;
match std::panic::catch_unwind(AssertUnwindSafe(|| {
builtin_function(program_id, &account_infos, input)
})) {
Ok(program_result) => {
program_result.map_err(|program_error| {
let err = InstructionError::from(u64::from(program_error));
stable_log::program_failure(&log_collector, program_id, &err);
let err: Box<dyn std::error::Error> = Box::new(err);
err
})?;
}
Err(_panic_error) => {
let err = InstructionError::ProgramFailedToComplete;
stable_log::program_failure(&log_collector, program_id, &err);
let err: Box<dyn std::error::Error> = Box::new(err);
Err(err)?;
}
};

stable_log::program_success(&log_collector, program_id);

// Lookup table for AccountInfo
Expand Down Expand Up @@ -724,8 +738,6 @@ impl ProgramTest {

// If SBF is not required (i.e., we were invoked with `test`), use the provided
// processor function as is.
//
// TODO: figure out why tests hang if a processor panics when running native code.
(false, _, Some(builtin_function)) => {
self.add_builtin_program(program_name, program_id, builtin_function)
}
Expand Down
42 changes: 42 additions & 0 deletions program-test/tests/panic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use {
solana_program_test::{processor, ProgramTest},
solana_sdk::{
account_info::AccountInfo,
entrypoint::ProgramResult,
instruction::{Instruction, InstructionError},
pubkey::Pubkey,
signature::Signer,
transaction::{Transaction, TransactionError},
},
};

fn panic(_program_id: &Pubkey, _accounts: &[AccountInfo], _input: &[u8]) -> ProgramResult {
panic!("I panicked");
}

#[tokio::test]
async fn panic_test() {
let program_id = Pubkey::new_unique();

let program_test = ProgramTest::new("panic", program_id, processor!(panic));

let context = program_test.start_with_context().await;

let instruction = Instruction::new_with_bytes(program_id, &[], vec![]);

let transaction = Transaction::new_signed_with_payer(
&[instruction],
Some(&context.payer.pubkey()),
&[&context.payer],
context.last_blockhash,
);
assert_eq!(
context
.banks_client
.process_transaction(transaction)
.await
.unwrap_err()
.unwrap(),
TransactionError::InstructionError(0, InstructionError::ProgramFailedToComplete)
);
}

0 comments on commit 52e7329

Please sign in to comment.