Skip to content

Commit

Permalink
Changes after review. Cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
grandizzy committed Jun 5, 2024
1 parent 6233ae6 commit ba7cea9
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 93 deletions.
55 changes: 0 additions & 55 deletions crates/cli/src/utils/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,61 +157,6 @@ pub fn init_progress(len: u64, label: &str) -> indicatif::ProgressBar {
pb
}

/// Creates progress object and progress bar.
#[macro_export]
macro_rules! init_tests_progress {
($tests_len:expr,$threads_no:expr) => {{
let progress = MultiProgress::new();
let pb = progress.add(indicatif::ProgressBar::new($tests_len as u64));
pb.set_style(
indicatif::ProgressStyle::with_template("{bar:40.cyan/blue} {pos:>7}/{len:7} {msg}")
.unwrap()
.progress_chars("##-"),
);
pb.set_message(format!("completed (with {} threads)", $threads_no as u64));
(progress, pb)
}};
}

/// Creates progress entry for test suite, having `[spinner] Test suite name` format.
#[macro_export]
macro_rules! init_test_suite_progress {
($overall_progress:expr, $suite_name:expr) => {{
let pb = $overall_progress.add(indicatif::ProgressBar::new_spinner());
pb.set_style(
indicatif::ProgressStyle::with_template("{spinner} {wide_msg:.bold.dim}")
.unwrap()
.tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈ "),
);
pb.set_message(format!("{} ", $suite_name));
pb.enable_steady_tick(Duration::from_millis(100));
pb
}};
}

/// Creates progress entry for fuzz tests.
/// Set the prefix and total number of runs. Message is updated during execution with current phase.
/// Test progress is placed under test suite progress entry so all tests within suite are grouped.
#[macro_export]
macro_rules! init_fuzz_test_progress {
($progress:expr, $test_name:expr, $runs:expr) => {{
let test_progress = $progress.map(|(overall_progress, suite_progress)| {
let pb = overall_progress
.insert_after(suite_progress, indicatif::ProgressBar::new($runs as u64));
pb.set_style(
indicatif::ProgressStyle::with_template(
" ↪ {prefix:.bold.dim}: [{pos}/{len}]{msg} Runs",
)
.unwrap()
.tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈ "),
);
pb.set_prefix(format!("{}", $test_name));
pb
});
test_progress
}};
}

/// True if the network calculates gas costs differently.
pub fn has_different_gas_calc(chain_id: u64) -> bool {
if let Some(chain) = Chain::from(chain_id).named() {
Expand Down
1 change: 1 addition & 0 deletions crates/forge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub use multi_runner::{MultiContractRunner, MultiContractRunnerBuilder};
mod runner;
pub use runner::ContractRunner;

mod progress;
pub mod result;

// TODO: remove
Expand Down
38 changes: 15 additions & 23 deletions crates/forge/src/multi_runner.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
//! Forge test runner for multiple contracts.

use crate::{
result::SuiteResult, runner::LIBRARY_DEPLOYER, ContractRunner, TestFilter, TestOptions,
progress::TestsProgress, result::SuiteResult, runner::LIBRARY_DEPLOYER, ContractRunner,
TestFilter, TestOptions,
};
use alloy_json_abi::{Function, JsonAbi};
use alloy_primitives::{Address, Bytes, U256};
use eyre::Result;
use foundry_cli::{init_test_suite_progress, init_tests_progress};
use foundry_common::{get_contract_name, ContractsByArtifact, TestFunctionExt};
use foundry_compilers::{artifacts::Libraries, Artifact, ArtifactId, ProjectCompileOutput};
use foundry_config::Config;
Expand All @@ -15,7 +15,6 @@ use foundry_evm::{
inspectors::CheatsConfig, opts::EvmOpts, revm,
};
use foundry_linking::{LinkOutput, Linker};
use indicatif::{MultiProgress, ProgressBar};
use rayon::prelude::*;
use revm::primitives::SpecId;
use std::{
Expand All @@ -24,7 +23,7 @@ use std::{
fmt::Debug,
path::Path,
sync::{mpsc, Arc},
time::{Duration, Instant},
time::Instant,
};

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -178,15 +177,14 @@ impl MultiContractRunner {
// Create overall tests progress and progress bar.
// Tests progress is passed to test runners for adding individual test suite progress.
// Progress bar is updated each time a test suite ends.
let (tests_progress, progress_bar) =
init_tests_progress!(contracts.len(), rayon::current_num_threads());
let tests_progress = TestsProgress::new(contracts.len(), rayon::current_num_threads());
// Collect test suite results to stream at the end of test run.
let results: Vec<(String, SuiteResult)> = contracts
.par_iter()
.map(|&(id, contract)| {
let _guard = handle.enter();
// Add test suite progress to tests result.
let suite_progress = init_test_suite_progress!(tests_progress, id.name);
tests_progress.inner.lock().start_suite_progress(&id.identifier());

// Run tests, pass tests progress and current test suite progress in order
// to add specific run details.
Expand All @@ -196,22 +194,21 @@ impl MultiContractRunner {
db.clone(),
filter,
&handle,
Some((&tests_progress, &suite_progress)),
Some(&tests_progress),
);

// Print result summary and remove test progress from overall progress.
tests_progress.suspend(|| {
println!("{}\n ↪ {}", id.name.clone(), result.summary());
});
suite_progress.finish_and_clear();
// Increment test progress bar to reflect completed test suite.
progress_bar.inc(1);
tests_progress
.inner
.lock()
.end_suite_progress(&id.identifier(), result.summary());

(id.identifier(), result)
})
.collect();
// Tests completed, remove progress and stream results.
tests_progress.clear().unwrap();
tests_progress.inner.lock().end_progress();

results.iter().for_each(|result| {
let _ = tx.send(result.to_owned());
});
Expand All @@ -231,7 +228,7 @@ impl MultiContractRunner {
db: Backend,
filter: &dyn TestFilter,
handle: &tokio::runtime::Handle,
progress: Option<(&MultiProgress, &ProgressBar)>,
progress: Option<&TestsProgress>,
) -> SuiteResult {
let identifier = artifact_id.identifier();
let mut span_name = identifier.as_str();
Expand Down Expand Up @@ -273,16 +270,11 @@ impl MultiContractRunner {
self.sender,
&self.revert_decoder,
self.debug,
);

let r = runner.run_tests(
filter,
&self.test_options,
self.known_contracts.clone(),
handle,
progress,
);

let r = runner.run_tests(filter, &self.test_options, self.known_contracts.clone(), handle);

debug!(duration=?r.duration, "executed all tests in contract");

r
Expand Down
115 changes: 115 additions & 0 deletions crates/forge/src/progress.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use indicatif::{MultiProgress, ProgressBar};
use parking_lot::Mutex;
use std::{collections::HashMap, sync::Arc, time::Duration};

/// State of [ProgressBar]s displayed for the given test run.
/// Shows progress of all test suites matching filter.
/// For each test within the test suite an individual progress bar is displayed.
/// When a test suite completes, their progress is removed from overall progress and result summary
/// is displayed.
#[derive(Debug)]
pub struct TestsProgressState {
/// Main [MultiProgress] instance showing progress for all test suites.
multi: MultiProgress,
/// Progress bar counting completed / remaining test suites.
overall_progress: ProgressBar,
/// Individual test suites progress.
suites_progress: HashMap<String, ProgressBar>,
}

impl TestsProgressState {
pub fn new(suites_len: usize, threads_no: usize) -> Self {
let multi = MultiProgress::new();
let overall_progress = multi.add(indicatif::ProgressBar::new(suites_len as u64));
overall_progress.set_style(
indicatif::ProgressStyle::with_template("{bar:40.cyan/blue} {pos:>7}/{len:7} {msg}")
.unwrap()
.progress_chars("##-"),
);
overall_progress.set_message(format!("completed (with {} threads)", threads_no as u64));
TestsProgressState { multi, overall_progress, suites_progress: HashMap::default() }
}

/// Creates new test suite progress and add it to overall progress.
pub fn start_suite_progress(&mut self, suite_name: &String) {
let suite_progress = self.multi.add(indicatif::ProgressBar::new_spinner());
suite_progress.set_style(
indicatif::ProgressStyle::with_template("{spinner} {wide_msg:.bold.dim}")
.unwrap()
.tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈ "),
);
suite_progress.set_message(format!("{} ", suite_name));
suite_progress.enable_steady_tick(Duration::from_millis(100));
self.suites_progress.insert(suite_name.to_owned(), suite_progress);
}

/// Prints suite result summary and removes it from overall progress.
pub fn end_suite_progress(&mut self, suite_name: &String, result_summary: String) {
if let Some(suite_progress) = self.suites_progress.get(suite_name) {
self.multi.suspend(|| {
println!("{}\n ↪ {}", suite_name, result_summary);
});
suite_progress.finish_and_clear();
// Increment test progress bar to reflect completed test suite.
self.overall_progress.inc(1);
}
}

/// Creates progress entry for fuzz tests.
/// Set the prefix and total number of runs. Message is updated during execution with current
/// phase. Test progress is placed under test suite progress entry so all tests within suite
/// are grouped.
pub fn start_fuzz_progress(
&mut self,
suite_name: &str,
test_name: &String,
runs: u32,
) -> Option<ProgressBar> {
if let Some(suite_progress) = self.suites_progress.get(suite_name) {
let fuzz_progress =
self.multi.insert_after(suite_progress, ProgressBar::new(runs as u64));
fuzz_progress.set_style(
indicatif::ProgressStyle::with_template(
" ↪ {prefix:.bold.dim}: [{pos}/{len}]{msg} Runs",
)
.unwrap()
.tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈ "),
);
fuzz_progress.set_prefix(test_name.to_string());
Some(fuzz_progress)
} else {
None
}
}

/// Removes overall test progress.
pub fn end_progress(&mut self) {
self.multi.clear().unwrap();
}
}

/// Clonable wrapper around [TestsProgressState].
#[derive(Debug, Clone)]
pub struct TestsProgress {
pub inner: Arc<Mutex<TestsProgressState>>,
}

impl TestsProgress {
pub fn new(suites_len: usize, threads_no: usize) -> Self {
Self { inner: Arc::new(Mutex::new(TestsProgressState::new(suites_len, threads_no))) }
}
}

/// Helper function for creating fuzz test progress bar.
pub fn start_fuzz_progress(
tests_progress: Option<&TestsProgress>,
suite_name: &str,
test_name: &String,
runs: u32,
) -> Option<ProgressBar> {
if let Some(progress) = tests_progress {
progress.inner.lock().start_fuzz_progress(suite_name, test_name, runs)
} else {
None
}
}
Loading

0 comments on commit ba7cea9

Please sign in to comment.