125 lines
3.5 KiB
Rust
125 lines
3.5 KiB
Rust
use {
|
|
solana_banks_client::BanksClient,
|
|
solana_program_test::{processor, ProgramTest},
|
|
solana_sdk::{
|
|
account_info::AccountInfo,
|
|
entrypoint::ProgramResult,
|
|
hash::Hash,
|
|
instruction::Instruction,
|
|
msg,
|
|
pubkey::Pubkey,
|
|
rent::Rent,
|
|
signature::{Keypair, Signer},
|
|
system_instruction,
|
|
transaction::Transaction,
|
|
},
|
|
};
|
|
|
|
#[allow(clippy::unnecessary_wraps)]
|
|
fn process_instruction(
|
|
_program_id: &Pubkey,
|
|
_accounts: &[AccountInfo],
|
|
_input: &[u8],
|
|
) -> ProgramResult {
|
|
msg!("Processing instruction");
|
|
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 context = 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 context.banks_client,
|
|
&context.payer,
|
|
context.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);
|
|
instructions.push(Instruction::new_with_bincode(*program_id, &[0], vec![]));
|
|
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());
|
|
}
|
|
}
|