Skip to content

Commit

Permalink
Merge pull request #127 from Ackee-Blockchain/fix/fuzz-test-executor-…
Browse files Browse the repository at this point in the history
…error-handling

♻️ Refactored fuzz test executor error handling
  • Loading branch information
lukacan authored Feb 21, 2024
2 parents a8d2529 + 045c640 commit 16b253d
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 133 deletions.
76 changes: 35 additions & 41 deletions crates/client/derive/fuzz_test_executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,54 +13,48 @@ pub fn fuzz_test_executor(input: TokenStream) -> TokenStream {
let variant_name = &variant.ident;
quote! {
#enum_name::#variant_name (ix) => {
let (mut signers, metas) =
if let Ok(acc) = ix.get_accounts(client, &mut accounts.borrow_mut())
.map_err(|e| e.with_origin(Origin::Instruction(self.to_context_string()))) {
acc
} else {
return Ok(());
};
let mut snaphot = Snapshot::new(&metas, ix);
// this can return FuzzClientErrorWithOrigin
snaphot.capture_before(client).unwrap();
let data =
if let Ok(data) = ix.get_data(client, &mut accounts.borrow_mut())
.map_err(|e| e.with_origin(Origin::Instruction(self.to_context_string()))) {
data
} else {
return Ok(());
let (mut signers, metas) = ix.get_accounts(client, &mut accounts.borrow_mut())
.map_err(|e| e.with_origin(Origin::Instruction(self.to_context_string())))
.expect("Accounts calculation expect");

let mut snaphot = Snapshot::new(&metas, ix);
snaphot.capture_before(client).unwrap();

let data = ix.get_data(client, &mut accounts.borrow_mut())
.map_err(|e| e.with_origin(Origin::Instruction(self.to_context_string())))
.expect("Data calculation expect");

let ixx = Instruction {
program_id,
accounts: metas.clone(),
data: data.data(),
};
let ixx = Instruction {
program_id,
accounts: metas.clone(),
data: data.data(),
};
let mut transaction =
Transaction::new_with_payer(&[ixx], Some(&client.payer().pubkey()));
signers.push(client.payer().clone());
let sig: Vec<&Keypair> = signers.iter().collect();
transaction.sign(&sig, client.get_last_blockhash());

let res = client.process_transaction(transaction)
.map_err(|e| e.with_origin(Origin::Instruction(self.to_context_string())));
let mut transaction =
Transaction::new_with_payer(&[ixx], Some(&client.payer().pubkey()));

// this can return FuzzClientErrorWithOrigin
snaphot.capture_after(client).unwrap();
let (acc_before, acc_after) = snaphot.get_snapshot()
.map_err(|e| e.with_origin(Origin::Instruction(self.to_context_string()))).unwrap(); // we want to panic if we cannot unwrap to cause a crash
signers.push(client.payer().clone());
let sig: Vec<&Keypair> = signers.iter().collect();
transaction.sign(&sig, client.get_last_blockhash());

if let Err(e) = ix.check(acc_before, acc_after, data).map_err(|e| e.with_origin(Origin::Instruction(self.to_context_string()))) {
eprintln!(
"CRASH DETECTED! Custom check after the {} instruction did not pass!",
self.to_context_string());
panic!("{}", e)
}
let tx_res = client.process_transaction(transaction)
.map_err(|e| e.with_origin(Origin::Instruction(self.to_context_string())));

if tx_res.is_ok() {
snaphot.capture_after(client).unwrap();
let (acc_before, acc_after) = snaphot.get_snapshot()
.map_err(|e| e.with_origin(Origin::Instruction(self.to_context_string())))
.expect("Snapshot deserialization expect"); // we want to panic if we cannot unwrap to cause a crash

if res.is_err() {
return Ok(());
if let Err(e) = ix.check(acc_before, acc_after, data).map_err(|e| e.with_origin(Origin::Instruction(self.to_context_string()))) {
eprintln!(
"CRASH DETECTED! Custom check after the {} instruction did not pass!",
self.to_context_string());
panic!("{}", e)
}
}
}
}
}
});

quote! {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,20 @@ impl FuzzTestExecutor<FuzzAccounts> for FuzzInstruction {
) -> core::result::Result<(), Box<dyn std::error::Error + 'static>> {
match self {
FuzzInstruction::InitVesting(ix) => {
let (mut signers, metas) = if let Ok(acc)
= ix
.get_accounts(client, &mut accounts.borrow_mut())
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
})
{
acc
} else {
return Ok(());
};
let (mut signers, metas) = ix
.get_accounts(client, &mut accounts.borrow_mut())
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
})
.expect("Accounts calculation expect");
let mut snaphot = Snapshot::new(&metas, ix);
snaphot.capture_before(client).unwrap();
let data = if let Ok(data)
= ix
.get_data(client, &mut accounts.borrow_mut())
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
})
{
data
} else {
return Ok(());
};
let data = ix
.get_data(client, &mut accounts.borrow_mut())
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
})
.expect("Data calculation expect");
let ixx = Instruction {
program_id,
accounts: metas.clone(),
Expand All @@ -48,66 +38,55 @@ impl FuzzTestExecutor<FuzzAccounts> for FuzzInstruction {
signers.push(client.payer().clone());
let sig: Vec<&Keypair> = signers.iter().collect();
transaction.sign(&sig, client.get_last_blockhash());
let res = client
let tx_res = client
.process_transaction(transaction)
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
});
snaphot.capture_after(client).unwrap();
let (acc_before, acc_after) = snaphot
.get_snapshot()
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
})
.unwrap();
if let Err(e)
= ix
.check(acc_before, acc_after, data)
if tx_res.is_ok() {
snaphot.capture_after(client).unwrap();
let (acc_before, acc_after) = snaphot
.get_snapshot()
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
})
{
.expect("Snapshot deserialization expect");
if let Err(e)
= ix
.check(acc_before, acc_after, data)
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
})
{
::std::io::_eprint(
format_args!(
"CRASH DETECTED! Custom check after the {0} instruction did not pass!\n",
self.to_context_string(),
),
);
};
{
::core::panicking::panic_display(&e);
{
::std::io::_eprint(
format_args!(
"CRASH DETECTED! Custom check after the {0} instruction did not pass!\n",
self.to_context_string(),
),
);
};
{
::core::panicking::panic_display(&e);
}
}
}
if res.is_err() {
return Ok(());
}
}
FuzzInstruction::WithdrawUnlocked(ix) => {
let (mut signers, metas) = if let Ok(acc)
= ix
.get_accounts(client, &mut accounts.borrow_mut())
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
})
{
acc
} else {
return Ok(());
};
let (mut signers, metas) = ix
.get_accounts(client, &mut accounts.borrow_mut())
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
})
.expect("Accounts calculation expect");
let mut snaphot = Snapshot::new(&metas, ix);
snaphot.capture_before(client).unwrap();
let data = if let Ok(data)
= ix
.get_data(client, &mut accounts.borrow_mut())
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
})
{
data
} else {
return Ok(());
};
let data = ix
.get_data(client, &mut accounts.borrow_mut())
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
})
.expect("Data calculation expect");
let ixx = Instruction {
program_id,
accounts: metas.clone(),
Expand All @@ -120,40 +99,39 @@ impl FuzzTestExecutor<FuzzAccounts> for FuzzInstruction {
signers.push(client.payer().clone());
let sig: Vec<&Keypair> = signers.iter().collect();
transaction.sign(&sig, client.get_last_blockhash());
let res = client
let tx_res = client
.process_transaction(transaction)
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
});
snaphot.capture_after(client).unwrap();
let (acc_before, acc_after) = snaphot
.get_snapshot()
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
})
.unwrap();
if let Err(e)
= ix
.check(acc_before, acc_after, data)
if tx_res.is_ok() {
snaphot.capture_after(client).unwrap();
let (acc_before, acc_after) = snaphot
.get_snapshot()
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
})
{
.expect("Snapshot deserialization expect");
if let Err(e)
= ix
.check(acc_before, acc_after, data)
.map_err(|e| {
e.with_origin(Origin::Instruction(self.to_context_string()))
})
{
::std::io::_eprint(
format_args!(
"CRASH DETECTED! Custom check after the {0} instruction did not pass!\n",
self.to_context_string(),
),
);
};
{
::core::panicking::panic_display(&e);
{
::std::io::_eprint(
format_args!(
"CRASH DETECTED! Custom check after the {0} instruction did not pass!\n",
self.to_context_string(),
),
);
};
{
::core::panicking::panic_display(&e);
}
}
}
if res.is_err() {
return Ok(());
}
}
}
Ok(())
Expand Down

0 comments on commit 16b253d

Please sign in to comment.