program-test: Expose bank task to fix fuzzing (#14908)
* program-test: Expose bank task to fix fuzzing * Run cargo fmt and clippy * Remove unnecessary print in test * Review feedback * Transition to AtomicBool
This commit is contained in:
118
program-test/tests/fuzz.rs
Normal file
118
program-test/tests/fuzz.rs
Normal file
@ -0,0 +1,118 @@
|
||||
use {
|
||||
solana_banks_client::BanksClient,
|
||||
solana_program::{
|
||||
account_info::AccountInfo, entrypoint::ProgramResult, hash::Hash, pubkey::Pubkey,
|
||||
rent::Rent,
|
||||
},
|
||||
solana_program_test::{processor, ProgramTest},
|
||||
solana_sdk::{
|
||||
signature::Keypair, signature::Signer, system_instruction, transaction::Transaction,
|
||||
},
|
||||
};
|
||||
|
||||
// Dummy process instruction required to instantiate ProgramTest
|
||||
#[allow(clippy::unnecessary_wraps)]
|
||||
fn process_instruction(
|
||||
_program_id: &Pubkey,
|
||||
_accounts: &[AccountInfo],
|
||||
_input: &[u8],
|
||||
) -> ProgramResult {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simulate_fuzz() {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
let program_id = Pubkey::new_unique();
|
||||
// Initialize and start the test network
|
||||
let program_test = ProgramTest::new(
|
||||
"program-test-fuzz",
|
||||
program_id,
|
||||
processor!(process_instruction),
|
||||
);
|
||||
|
||||
let (mut banks_client, payer, last_blockhash) =
|
||||
rt.block_on(async { program_test.start().await });
|
||||
|
||||
// the honggfuzz `fuzz!` macro does not allow for async closures,
|
||||
// so we have to use the runtime directly to run async functions
|
||||
rt.block_on(async {
|
||||
run_fuzz_instructions(
|
||||
&[1, 2, 3, 4, 5],
|
||||
&mut banks_client,
|
||||
&payer,
|
||||
last_blockhash,
|
||||
&program_id,
|
||||
)
|
||||
.await
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simulate_fuzz_with_context() {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
let program_id = Pubkey::new_unique();
|
||||
// Initialize and start the test network
|
||||
let program_test = ProgramTest::new(
|
||||
"program-test-fuzz",
|
||||
program_id,
|
||||
processor!(process_instruction),
|
||||
);
|
||||
|
||||
let mut test_state = rt.block_on(async { program_test.start_with_context().await });
|
||||
|
||||
// the honggfuzz `fuzz!` macro does not allow for async closures,
|
||||
// so we have to use the runtime directly to run async functions
|
||||
rt.block_on(async {
|
||||
run_fuzz_instructions(
|
||||
&[1, 2, 3, 4, 5],
|
||||
&mut test_state.banks_client,
|
||||
&test_state.payer,
|
||||
test_state.last_blockhash,
|
||||
&program_id,
|
||||
)
|
||||
.await
|
||||
});
|
||||
}
|
||||
|
||||
async fn run_fuzz_instructions(
|
||||
fuzz_instruction: &[u8],
|
||||
banks_client: &mut BanksClient,
|
||||
payer: &Keypair,
|
||||
last_blockhash: Hash,
|
||||
program_id: &Pubkey,
|
||||
) {
|
||||
let mut instructions = vec![];
|
||||
let mut signer_keypairs = vec![];
|
||||
for &i in fuzz_instruction {
|
||||
let keypair = Keypair::new();
|
||||
let instruction = system_instruction::create_account(
|
||||
&payer.pubkey(),
|
||||
&keypair.pubkey(),
|
||||
Rent::default().minimum_balance(i as usize),
|
||||
i as u64,
|
||||
program_id,
|
||||
);
|
||||
instructions.push(instruction);
|
||||
signer_keypairs.push(keypair);
|
||||
}
|
||||
// Process transaction on test network
|
||||
let mut transaction = Transaction::new_with_payer(&instructions, Some(&payer.pubkey()));
|
||||
let signers = [payer]
|
||||
.iter()
|
||||
.copied()
|
||||
.chain(signer_keypairs.iter())
|
||||
.collect::<Vec<&Keypair>>();
|
||||
transaction.partial_sign(&signers, last_blockhash);
|
||||
|
||||
banks_client.process_transaction(transaction).await.unwrap();
|
||||
for keypair in signer_keypairs {
|
||||
let account = banks_client
|
||||
.get_account(keypair.pubkey())
|
||||
.await
|
||||
.expect("account exists")
|
||||
.unwrap();
|
||||
assert!(account.lamports > 0);
|
||||
assert!(!account.data.is_empty());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user