Skip to content

Commit

Permalink
chore: threads and show_progress per profile config (#8341)
Browse files Browse the repository at this point in the history
* chore: allow max threads and show progress set per profile

* Changes after review: max_threads to threads/jobs

* Use short -j for jobs instead json

* Update crates/config/README.md

Co-authored-by: DaniPopes <[email protected]>

* Use usize for number of threads

---------

Co-authored-by: DaniPopes <[email protected]>
  • Loading branch information
grandizzy and DaniPopes committed Jul 4, 2024
1 parent 63b407f commit 042b490
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 13 deletions.
4 changes: 4 additions & 0 deletions crates/config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ no_match_contract = "Bar"
match_path = "*/Foo*"
no_match_path = "*/Bar*"
no_match_coverage = "Baz"
# Number of threads to use. Not set or zero specifies the number of logical cores.
threads = 0
# whether to show test execution progress
show_progress = true
ffi = false
always_use_create_2_factory = false
prompt_timeout = 120
Expand Down
6 changes: 6 additions & 0 deletions crates/config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,10 @@ pub struct Config {
pub coverage_pattern_inverse: Option<RegexWrapper>,
/// Path where last test run failures are recorded.
pub test_failures_file: PathBuf,
/// Max concurrent threads to use.
pub threads: Option<usize>,
/// Whether to show test execution progress.
pub show_progress: bool,
/// Configuration for fuzz testing
pub fuzz: FuzzConfig,
/// Configuration for invariant testing
Expand Down Expand Up @@ -2083,6 +2087,8 @@ impl Default for Config {
path_pattern_inverse: None,
coverage_pattern_inverse: None,
test_failures_file: "cache/test-failures".into(),
threads: None,
show_progress: false,
fuzz: FuzzConfig::new("cache/fuzz".into()),
invariant: InvariantConfig::new("cache/invariant".into()),
always_use_create_2_factory: false,
Expand Down
34 changes: 21 additions & 13 deletions crates/forge/bin/cmd/test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub struct TestArgs {
allow_failure: bool,

/// Output test results in JSON format.
#[arg(long, short, help_heading = "Display options")]
#[arg(long, help_heading = "Display options")]
json: bool,

/// Stop running tests after the first failure.
Expand Down Expand Up @@ -113,8 +113,8 @@ pub struct TestArgs {

/// Max concurrent threads to use.
/// Default value is the number of available CPUs.
#[arg(long)]
pub max_threads: Option<u64>,
#[arg(long, short = 'j', visible_alias = "jobs")]
pub threads: Option<usize>,

/// Show test execution progress.
#[arg(long)]
Expand Down Expand Up @@ -236,17 +236,17 @@ impl TestArgs {
///
/// Returns the test results for all matching tests.
pub async fn execute_tests(self) -> Result<TestOutcome> {
// Merge all configs.
let (mut config, mut evm_opts) = self.load_config_and_evm_opts_emit_warnings()?;

// Set number of max threads to execute tests.
// If not specified then the number of threads determined by rayon will be used.
if let Some(test_threads) = self.max_threads {
if let Some(test_threads) = config.threads {
trace!(target: "forge::test", "execute tests with {} max threads", test_threads);
rayon::ThreadPoolBuilder::new().num_threads(test_threads as usize).build_global()?;
rayon::ThreadPoolBuilder::new().num_threads(test_threads).build_global()?;
}

// Merge all configs
let (mut config, mut evm_opts) = self.load_config_and_evm_opts_emit_warnings()?;

// Explicitly enable isolation for gas reports for more correct gas accounting
// Explicitly enable isolation for gas reports for more correct gas accounting.
if self.gas_report {
evm_opts.isolate = true;
} else {
Expand Down Expand Up @@ -289,15 +289,15 @@ impl TestArgs {
.profiles(profiles)
.build(&output, project_root)?;

// Determine print verbosity and executor verbosity
// Determine print verbosity and executor verbosity.
let verbosity = evm_opts.verbosity;
if self.gas_report && evm_opts.verbosity < 3 {
evm_opts.verbosity = 3;
}

let env = evm_opts.evm_env().await?;

// Prepare the test builder
// Prepare the test builder.
let should_debug = self.debug.is_some();
let config = Arc::new(config);
let runner = MultiContractRunnerBuilder::new(config.clone())
Expand Down Expand Up @@ -325,7 +325,7 @@ impl TestArgs {
let outcome = self.run_tests(runner, config, verbosity, &filter).await?;

if should_debug {
// Get first non-empty suite result. We will have only one such entry
// Get first non-empty suite result. We will have only one such entry.
let Some((_, test_result)) = outcome
.results
.iter()
Expand Down Expand Up @@ -390,7 +390,7 @@ impl TestArgs {
// Run tests.
let (tx, rx) = channel::<(String, SuiteResult)>();
let timer = Instant::now();
let show_progress = self.show_progress;
let show_progress = config.show_progress;
let handle = tokio::task::spawn_blocking({
let filter = filter.clone();
move || runner.test(&filter, tx, show_progress)
Expand Down Expand Up @@ -627,6 +627,14 @@ impl Provider for TestArgs {
dict.insert("etherscan_api_key".to_string(), etherscan_api_key.to_string().into());
}

if self.show_progress {
dict.insert("show_progress".to_string(), true.into());
}

if let Some(threads) = self.threads {
dict.insert("threads".to_string(), threads.into());
}

Ok(Map::from([(Config::selected_profile(), dict)]))
}
}
Expand Down
2 changes: 2 additions & 0 deletions crates/forge/tests/cli/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ forgetest!(can_extract_config_values, |prj, cmd| {
path_pattern_inverse: None,
coverage_pattern_inverse: None,
test_failures_file: "test-cache/test-failures".into(),
threads: None,
show_progress: false,
fuzz: FuzzConfig {
runs: 1000,
max_test_rejects: 100203,
Expand Down

0 comments on commit 042b490

Please sign in to comment.