Skip to content

Commit

Permalink
🐛 (store failed txs): Store failex txs
Browse files Browse the repository at this point in the history
  • Loading branch information
lukacan committed May 3, 2024
1 parent 7eb533f commit dead3a1
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 127 deletions.
7 changes: 5 additions & 2 deletions crates/client/derive/fuzz_test_executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub fn fuzz_test_executor(input: TokenStream) -> TokenStream {
match tx_result {
Ok(_) => {
#[cfg(fuzzing_with_stats)]
stats_logger.increase_successfully_invoked(self.to_context_string());
stats_logger.increase_successful(self.to_context_string());

snaphot.capture_after(client).unwrap();
let (acc_before, acc_after) = snaphot.get_snapshot()
Expand All @@ -76,7 +76,10 @@ pub fn fuzz_test_executor(input: TokenStream) -> TokenStream {
},
Err(e) => {
#[cfg(fuzzing_with_stats)]
stats_logger.output_serialized();
{
stats_logger.increase_failed(self.to_context_string());
stats_logger.output_serialized();
}
let mut raw_accounts = snaphot.get_raw_pre_ix_accounts();
ix.tx_error_handler(e, data, &mut raw_accounts)?
}
Expand Down
54 changes: 36 additions & 18 deletions crates/client/src/commander.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,28 +327,34 @@ impl Commander {
let fuzz_end = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(false));
let fuzz_end_clone = std::sync::Arc::clone(&fuzz_end);

tokio::spawn(async move {
let mut stats_logger = FuzzingStatistics::new();

let mut lines = reader.lines();
loop {
// Why the lock ??
// I`m not sure what happens if the fuzzing sessions is still active
// however the reader already read all the lines. I think that would bring us
// to the scenario where this reading task ends prematurely.
if fuzz_end_clone.load(std::sync::atomic::Ordering::SeqCst) {
break;
}
while let Ok(Some(line)) = lines.next_line().await {
stats_logger.insert_serialized(&line);
let stats_handle: tokio::task::JoinHandle<Result<FuzzingStatistics, std::io::Error>> =
tokio::spawn(async move {
let mut stats_logger = FuzzingStatistics::new();

let mut lines = reader.lines();
loop {
let _line = lines.next_line().await;
match _line {
Ok(__line) => match __line {
Some(content) => {
stats_logger.insert_serialized(&content);
}
None => {
if fuzz_end_clone.load(std::sync::atomic::Ordering::SeqCst) {
break;
}
}
},
Err(e) => return Err(e),
}
}
}
stats_logger.show_table();
});
Ok(stats_logger)
});

tokio::select! {
res = child.wait() =>{
fuzz_end.store(true, std::sync::atomic::Ordering::SeqCst);

match res {
Ok(status) => {
if !status.success() {
Expand All @@ -359,10 +365,22 @@ impl Commander {
}
},
_ = signal::ctrl_c() => {
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
fuzz_end.store(true, std::sync::atomic::Ordering::SeqCst);
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;

},
}
let stats_result = stats_handle
.await
.expect("Unable to obtain Statistics Handle");
match stats_result {
Ok(stats_result) => {
stats_result.show_table();
}
Err(e) => {
println!("Statistics thread exited with the Error: {}", e);
}
}
}

/// Runs fuzzer on the given target.
Expand Down
42 changes: 33 additions & 9 deletions crates/client/src/fuzzer/fuzzing_stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use std::collections::HashMap;
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct IterationStats {
pub invoked: u64,
pub successfully_invoked: u64,
pub successful: u64,
pub failed: u64,
}

/// Manages and aggregates statistics for fuzzing instructions.
Expand Down Expand Up @@ -38,22 +39,38 @@ impl FuzzingStatistics {
.and_modify(|iterations_stats| iterations_stats.invoked += 1)
.or_insert(IterationStats {
invoked: 1,
successfully_invoked: 0,
successful: 0,
failed: 0,
});
}
/// Increments the successful invocation count for a given instruction.
/// # Arguments
/// * `instruction` - The instruction to increment the successful count for.
pub fn increase_successfully_invoked(&mut self, instruction: String) {
pub fn increase_successful(&mut self, instruction: String) {
self.instructions
.entry(instruction)
.and_modify(|iterations_stats| iterations_stats.successfully_invoked += 1)
.and_modify(|iterations_stats| iterations_stats.successful += 1)
.or_insert(
// this should not occure as instruction has to be invoked
// and then successfully_invoked
IterationStats {
invoked: 1,
successfully_invoked: 1,
successful: 1,
failed: 0,
},
);
}
pub fn increase_failed(&mut self, instruction: String) {
self.instructions
.entry(instruction)
.and_modify(|iterations_stats| iterations_stats.failed += 1)
.or_insert(
// this should not occure as instruction has to be invoked
// and then unsuccessfully_invoked
IterationStats {
invoked: 1,
successful: 0,
failed: 1,
},
);
}
Expand All @@ -70,21 +87,28 @@ impl FuzzingStatistics {
.entry(key)
.and_modify(|instruction_stats| {
instruction_stats.invoked += value.invoked;
instruction_stats.successfully_invoked += value.successfully_invoked;
instruction_stats.successful += value.successful;
instruction_stats.failed += value.failed;
})
.or_insert_with(|| IterationStats {
invoked: value.invoked,
successfully_invoked: value.successfully_invoked,
successful: value.successful,
failed: value.failed,
});
}
}
}
/// Displays the collected statistics in a formatted table.
pub fn show_table(&self) {
let mut table = Table::new();
table.add_row(row!["Instruction", "Invoked", "Successfully Invoked"]);
table.add_row(row!["Instruction", "Invoked", "Successful", "Failed"]);
for (instruction, stats) in &self.instructions {
table.add_row(row![instruction, stats.invoked, stats.successfully_invoked]);
table.add_row(row![
instruction,
stats.invoked,
stats.successful,
stats.failed
]);
}
table.printstd();
}
Expand Down
7 changes: 2 additions & 5 deletions crates/client/src/test_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -690,18 +690,15 @@ impl TestGenerator {
let gitignore_path = construct_path!(self.root, GIT_IGNORE);
if gitignore_path.exists() {
let file = File::open(&gitignore_path)?;
for line in io::BufReader::new(file).lines().flatten() {
for line in io::BufReader::new(file).lines().map_while(Result::ok) {
if line == ignored_path {
// INFO do not add the ignored path again if it is already in the .gitignore file
println!("{SKIP} [{GIT_IGNORE}], already contains [{ignored_path}]");

return;
}
}
let file = OpenOptions::new()
.write(true)
.append(true)
.open(gitignore_path);
let file = OpenOptions::new().append(true).open(gitignore_path);

if let Ok(mut file) = file {
writeln!(file, "{}", ignored_path)?;
Expand Down
Loading

0 comments on commit dead3a1

Please sign in to comment.