diff --git a/crates/forge/bin/cmd/coverage.rs b/crates/forge/bin/cmd/coverage.rs index fc919934f037..66f45b7704c9 100644 --- a/crates/forge/bin/cmd/coverage.rs +++ b/crates/forge/bin/cmd/coverage.rs @@ -1,4 +1,4 @@ -use super::{install, test::FilterArgs}; +use super::{install, test::TestArgs}; use alloy_primitives::{Address, Bytes, U256}; use clap::{Parser, ValueEnum, ValueHint}; use eyre::{Context, Result}; @@ -8,17 +8,15 @@ use forge::{ CoverageReport, CoverageReporter, DebugReporter, LcovReporter, SummaryReporter, }, opts::EvmOpts, - result::SuiteResult, revm::primitives::SpecId, utils::IcPcMap, MultiContractRunnerBuilder, TestOptions, }; use foundry_cli::{ - opts::CoreBuildArgs, p_println, utils::{LoadConfig, STATIC_FUZZ_SEED}, }; -use foundry_common::{compile::ProjectCompiler, evm::EvmArgs, fs}; +use foundry_common::{compile::ProjectCompiler, fs}; use foundry_compilers::{ artifacts::{contract::CompactContractBytecode, Ast, CompactBytecode, CompactDeployedBytecode}, sourcemap::SourceMap, @@ -27,18 +25,14 @@ use foundry_compilers::{ use foundry_config::{Config, SolcReq}; use rustc_hash::FxHashMap; use semver::Version; -use std::{ - collections::HashMap, - path::PathBuf, - sync::{mpsc::channel, Arc}, -}; +use std::{collections::HashMap, path::PathBuf, sync::Arc}; use yansi::Paint; /// A map, keyed by contract ID, to a tuple of the deployment source map and the runtime source map. type SourceMaps = HashMap; // Loads project's figment and merges the build cli arguments into it -foundry_config::impl_figment_convert!(CoverageArgs, opts, evm_opts); +foundry_config::impl_figment_convert!(CoverageArgs, test); /// CLI arguments for `forge coverage`. #[derive(Clone, Debug, Parser)] @@ -72,13 +66,7 @@ pub struct CoverageArgs { include_libs: bool, #[command(flatten)] - filter: FilterArgs, - - #[command(flatten)] - evm_opts: EvmArgs, - - #[command(flatten)] - opts: CoreBuildArgs, + test: TestArgs, } impl CoverageArgs { @@ -86,7 +74,7 @@ impl CoverageArgs { let (mut config, evm_opts) = self.load_config_and_evm_opts_emit_warnings()?; // install missing dependencies - if install::install_missing_dependencies(&mut config, self.build_args().silent) && + if install::install_missing_dependencies(&mut config, self.test.build_args().silent) && config.auto_detect_remappings { // need to re-configure here to also catch additional remappings @@ -100,10 +88,10 @@ impl CoverageArgs { config.ast = true; let (project, output) = self.build(&config)?; - p_println!(!self.opts.silent => "Analysing contracts..."); + p_println!(!self.test.build_args().silent => "Analysing contracts..."); let report = self.prepare(&config, output.clone())?; - p_println!(!self.opts.silent => "Running tests..."); + p_println!(!self.test.build_args().silent => "Running tests..."); self.collect(project, output, report, Arc::new(config), evm_opts).await } @@ -131,7 +119,7 @@ impl CoverageArgs { "Note that \"viaIR\" is only available in Solidity 0.8.13 and above.\n", "See more: https://github.com/foundry-rs/foundry/issues/3357", )); - p_println!(!self.opts.silent => "{msg}"); + p_println!(!self.test.build_args().silent => "{msg}"); // Enable viaIR with minimum optimization // https://github.com/ethereum/solidity/issues/12533#issuecomment-1013073350 @@ -315,10 +303,11 @@ impl CoverageArgs { evm_opts: EvmOpts, ) -> Result<()> { let root = project.paths.root; + let verbosity = evm_opts.verbosity; // Build the contract runner let env = evm_opts.evm_env().await?; - let mut runner = MultiContractRunnerBuilder::new(config.clone()) + let runner = MultiContractRunnerBuilder::new(config.clone()) .initial_balance(evm_opts.initial_balance) .evm_spec(config.evm_spec_id()) .sender(evm_opts.sender) @@ -331,13 +320,13 @@ impl CoverageArgs { .set_coverage(true) .build(&root, output, env, evm_opts)?; - // Run tests - let filter = self.filter; - let (tx, rx) = channel::<(String, SuiteResult)>(); - let handle = tokio::task::spawn_blocking(move || runner.test(&filter, tx)); + let outcome = self + .test + .run_tests(runner, config.clone(), verbosity, &self.test.filter(&config)) + .await?; // Add hit data to the coverage report - let data = rx.into_iter().flat_map(|(_, suite)| { + let data = outcome.results.into_iter().flat_map(|(_, suite)| { let mut hits = Vec::new(); for (_, mut result) in suite.test_results { let Some(hit_maps) = result.coverage.take() else { continue }; @@ -359,7 +348,6 @@ impl CoverageArgs { }); for (artifact_id, hits, is_deployed_code) in data { - // TODO: Note down failing tests if let Some(source_id) = report.get_source_id( artifact_id.version.clone(), artifact_id.source.to_string_lossy().to_string(), @@ -377,14 +365,6 @@ impl CoverageArgs { } } - // Reattach the thread - if let Err(e) = handle.await { - match e.try_into_panic() { - Ok(payload) => std::panic::resume_unwind(payload), - Err(e) => return Err(e.into()), - } - } - // Output final report for report_kind in self.report { match report_kind { @@ -409,11 +389,6 @@ impl CoverageArgs { } Ok(()) } - - /// Returns the flattened [`CoreBuildArgs`] - pub fn build_args(&self) -> &CoreBuildArgs { - &self.opts - } } // TODO: HTML