diff --git a/crates/forge-runner/src/context_data.rs b/crates/forge-runner/src/context_data.rs new file mode 100644 index 0000000000..14398aa4df --- /dev/null +++ b/crates/forge-runner/src/context_data.rs @@ -0,0 +1,14 @@ +use camino::Utf8PathBuf; +use cheatnet::runtime_extensions::forge_runtime_extension::contracts_data::ContractsData; +use std::collections::HashMap; + +pub struct ContextData { + pub runtime_data: RuntimeData, + pub workspace_root: Utf8PathBuf, + pub test_artifacts_path: Utf8PathBuf, +} + +pub struct RuntimeData { + pub contracts_data: ContractsData, + pub environment_variables: HashMap, +} diff --git a/crates/forge-runner/src/forge_config.rs b/crates/forge-runner/src/forge_config.rs new file mode 100644 index 0000000000..0110328e44 --- /dev/null +++ b/crates/forge-runner/src/forge_config.rs @@ -0,0 +1,68 @@ +use std::num::NonZeroU32; +use std::sync::Arc; + +#[derive(Debug, PartialEq)] +pub struct ForgeConfig { + pub runner_config: Arc, + pub runtime_config: Arc, + pub output_config: OutputConfig, +} + +#[derive(Debug, PartialEq)] +pub struct RunnerConfig { + pub exit_first: bool, + pub fuzzer_runs: NonZeroU32, + pub fuzzer_seed: u64, +} + +#[derive(Debug, PartialEq)] +pub struct RuntimeConfig { + pub max_n_steps: Option, +} + +#[derive(Debug, PartialEq)] +pub struct OutputConfig { + pub detailed_resources: bool, + pub execution_data_to_save: ExecutionDataToSave, +} + +impl OutputConfig { + #[must_use] + pub fn new(detailed_resources: bool, save_trace_data: bool, build_profile: bool) -> Self { + Self { + detailed_resources, + execution_data_to_save: ExecutionDataToSave::from_flags(save_trace_data, build_profile), + } + } +} + +#[derive(Debug, PartialEq, Clone, Copy)] +pub enum ExecutionDataToSave { + None, + Trace, + /// Profile data requires saved trace data + TraceAndProfile, +} + +impl ExecutionDataToSave { + #[must_use] + pub fn from_flags(save_trace_data: bool, build_profile: bool) -> Self { + if build_profile { + return ExecutionDataToSave::TraceAndProfile; + } + if save_trace_data { + return ExecutionDataToSave::Trace; + } + ExecutionDataToSave::None + } +} + +impl ExecutionDataToSave { + #[must_use] + pub fn is_vm_trace_needed(self) -> bool { + match self { + ExecutionDataToSave::Trace | ExecutionDataToSave::TraceAndProfile => true, + ExecutionDataToSave::None => false, + } + } +} diff --git a/crates/forge-runner/src/lib.rs b/crates/forge-runner/src/lib.rs index 0c361c12c6..322234a773 100644 --- a/crates/forge-runner/src/lib.rs +++ b/crates/forge-runner/src/lib.rs @@ -9,7 +9,6 @@ use anyhow::{anyhow, Result}; use cairo_lang_runner::RunnerError; use cairo_lang_sierra::ids::ConcreteTypeId; use cairo_lang_sierra::program::Function; -use camino::Utf8PathBuf; use futures::stream::FuturesUnordered; use futures::StreamExt; @@ -18,9 +17,8 @@ use build_trace_data::save_trace_data; use profiler_api::run_profiler; use smol_str::SmolStr; -use cheatnet::runtime_extensions::forge_runtime_extension::contracts_data::ContractsData; -use std::collections::HashMap; -use std::num::NonZeroU32; +use crate::context_data::ContextData; +use crate::forge_config::{ExecutionDataToSave, ForgeConfig, RunnerConfig, RuntimeConfig}; use std::sync::Arc; use test_case_summary::{AnyTestCaseSummary, Fuzzing}; use tokio::sync::mpsc::{channel, Sender}; @@ -30,10 +28,12 @@ use universal_sierra_compiler_api::{compile_sierra_to_casm, AssembledProgramWith pub mod build_trace_data; pub mod compiled_runnable; pub mod expected_result; +pub mod forge_config; pub mod profiler_api; pub mod test_case_summary; pub mod test_crate_summary; +pub mod context_data; mod fuzzer; mod gas; mod printing; @@ -52,97 +52,8 @@ pub const BUILTINS: [&str; 8] = [ "System", ]; -#[derive(Debug, PartialEq, Clone, Copy)] -pub enum ExecutionDataToSave { - None, - Trace, - /// Profile data requires saved trace data - TraceAndProfile, -} - -impl ExecutionDataToSave { - #[must_use] - pub fn is_vm_trace_needed(self) -> bool { - match self { - ExecutionDataToSave::Trace | ExecutionDataToSave::TraceAndProfile => true, - ExecutionDataToSave::None => false, - } - } -} - -impl ExecutionDataToSave { - fn from_flags(save_trace_data: bool, build_profile: bool) -> Self { - if build_profile { - return ExecutionDataToSave::TraceAndProfile; - } - if save_trace_data { - return ExecutionDataToSave::Trace; - } - ExecutionDataToSave::None - } -} - -/// Configuration of the test runner -#[derive(Debug, PartialEq)] -#[non_exhaustive] -pub struct RunnerConfig { - pub workspace_root: Utf8PathBuf, - pub exit_first: bool, - pub fuzzer_runs: NonZeroU32, - pub fuzzer_seed: u64, - pub detailed_resources: bool, - pub execution_data_to_save: ExecutionDataToSave, - pub max_n_steps: Option, -} - -impl RunnerConfig { - #[must_use] - #[allow(clippy::too_many_arguments, clippy::fn_params_excessive_bools)] - pub fn new( - workspace_root: Utf8PathBuf, - exit_first: bool, - fuzzer_runs: NonZeroU32, - fuzzer_seed: u64, - detailed_resources: bool, - save_trace_data: bool, - build_profile: bool, - max_n_steps: Option, - ) -> Self { - Self { - workspace_root, - exit_first, - fuzzer_runs, - fuzzer_seed, - detailed_resources, - execution_data_to_save: ExecutionDataToSave::from_flags(save_trace_data, build_profile), - max_n_steps, - } - } -} - -#[non_exhaustive] -#[derive(Debug, Clone)] -pub struct RunnerParams { - contracts_data: ContractsData, - environment_variables: HashMap, -} - -impl RunnerParams { - #[must_use] - pub fn new( - contracts_data: ContractsData, - environment_variables: HashMap, - ) -> Self { - Self { - contracts_data, - environment_variables, - } - } -} - /// Exit status of the runner -#[derive(Debug, PartialEq, Clone)] -#[non_exhaustive] +#[derive(Debug, PartialEq, Clone, Copy)] pub enum RunnerStatus { /// Runner exited without problems Default, @@ -164,8 +75,8 @@ pub enum TestCrateRunResult { pub async fn run_tests_from_crate( tests: CompiledTestCrateRunnable, - runner_config: Arc, - runner_params: Arc, + forge_config: Arc, + context_data: Arc, tests_filter: &impl TestCaseFilter, ) -> Result { let sierra_program = &tests.sierra_program; @@ -208,8 +119,8 @@ pub async fn run_tests_from_crate( args, case, casm_program.clone(), - runner_config.clone(), - runner_params.clone(), + forge_config.clone(), + context_data.clone(), send.clone(), )); } @@ -220,10 +131,10 @@ pub async fn run_tests_from_crate( while let Some(task) = tasks.next().await { let result = task??; - print_test_result(&result, &runner_config); - maybe_save_execution_data(&result, runner_config.execution_data_to_save)?; + print_test_result(&result, forge_config.output_config.detailed_resources); + maybe_save_execution_data(&result, forge_config.output_config.execution_data_to_save)?; - if result.is_failed() && runner_config.exit_first { + if result.is_failed() && forge_config.runner_config.exit_first { interrupted = true; rec.close(); } @@ -270,31 +181,55 @@ fn choose_test_strategy_and_run( args: Vec, case: Arc, casm_program: Arc, - runner_config: Arc, - runner_params: Arc, + forge_config: Arc, + context_data: Arc, send: Sender<()>, ) -> JoinHandle> { + let is_vm_trace_needed = forge_config + .output_config + .execution_data_to_save + .is_vm_trace_needed(); + if args.is_empty() { tokio::task::spawn(async move { - let res = run_test(case, casm_program, runner_config, runner_params, send).await??; + let res = run_test( + case, + casm_program, + forge_config.runtime_config.clone(), + context_data, + is_vm_trace_needed, + send, + ) + .await??; Ok(AnyTestCaseSummary::Single(res)) }) } else { tokio::task::spawn(async move { - let res = - run_with_fuzzing(args, case, casm_program, runner_config, runner_params, send) - .await??; + let res = run_with_fuzzing( + args, + case, + casm_program, + forge_config.runner_config.clone(), + forge_config.runtime_config.clone(), + context_data, + is_vm_trace_needed, + send, + ) + .await??; Ok(AnyTestCaseSummary::Fuzzing(res)) }) } } +#[allow(clippy::too_many_arguments)] fn run_with_fuzzing( args: Vec, case: Arc, casm_program: Arc, runner_config: Arc, - runner_params: Arc, + runtime_config: Arc, + context_data: Arc, + is_vm_trace_needed: bool, send: Sender<()>, ) -> JoinHandle>> { tokio::task::spawn(async move { @@ -331,8 +266,9 @@ fn run_with_fuzzing( args, case.clone(), casm_program.clone(), - runner_config.clone(), - runner_params.clone(), + runtime_config.clone(), + context_data.clone(), + is_vm_trace_needed, send.clone(), fuzzing_send.clone(), )); diff --git a/crates/forge-runner/src/printing.rs b/crates/forge-runner/src/printing.rs index 7a071ac3bb..be5381bd4d 100644 --- a/crates/forge-runner/src/printing.rs +++ b/crates/forge-runner/src/printing.rs @@ -1,13 +1,10 @@ -use crate::{ - test_case_summary::{AnyTestCaseSummary, FuzzingStatistics, TestCaseSummary}, - RunnerConfig, -}; +use crate::test_case_summary::{AnyTestCaseSummary, FuzzingStatistics, TestCaseSummary}; use cheatnet::runtime_extensions::call_to_blockifier_runtime_extension::rpc::UsedResources; use console::style; pub(crate) fn print_test_result( any_test_result: &AnyTestCaseSummary, - runner_config: &RunnerConfig, + print_detailed_resources: bool, ) { if any_test_result.is_skipped() { return; @@ -45,7 +42,7 @@ pub(crate) fn print_test_result( _ => String::new(), }; - let used_resources = match (runner_config.detailed_resources, any_test_result) { + let used_resources = match (print_detailed_resources, any_test_result) { (true, AnyTestCaseSummary::Single(TestCaseSummary::Passed { used_resources, .. })) => { format_detailed_resources(used_resources) } diff --git a/crates/forge-runner/src/running.rs b/crates/forge-runner/src/running.rs index c04a2983c4..6e2b889fd8 100644 --- a/crates/forge-runner/src/running.rs +++ b/crates/forge-runner/src/running.rs @@ -6,9 +6,11 @@ use std::rc::Rc; use std::sync::Arc; use crate::compiled_runnable::ValidatedForkConfig; +use crate::context_data::ContextData; +use crate::forge_config::RuntimeConfig; use crate::gas::calculate_used_gas; use crate::test_case_summary::{Single, TestCaseSummary}; -use crate::{RunnerConfig, RunnerParams, TestCaseRunnable, CACHE_DIR}; +use crate::{TestCaseRunnable, CACHE_DIR}; use anyhow::{bail, ensure, Result}; use blockifier::execution::entry_point::EntryPointExecutionContext; use blockifier::execution::execution_utils::ReadOnlySegments; @@ -56,8 +58,9 @@ use universal_sierra_compiler_api::{ pub fn run_test( case: Arc, casm_program: Arc, - runner_config: Arc, - runner_params: Arc, + runtime_config: Arc, + context_data: Arc, + is_vm_trace_needed: bool, send: Sender<()>, ) -> JoinHandle>> { tokio::task::spawn_blocking(move || { @@ -67,8 +70,14 @@ pub fn run_test( if send.is_closed() { return Ok(TestCaseSummary::Skipped {}); } - let run_result = - run_test_case(vec![], &case, &casm_program, &runner_config, &runner_params); + let run_result = run_test_case( + vec![], + &case, + &casm_program, + &runtime_config, + &context_data, + is_vm_trace_needed, + ); // TODO: code below is added to fix snforge tests // remove it after improve exit-first tests @@ -77,7 +86,12 @@ pub fn run_test( return Ok(TestCaseSummary::Skipped {}); } - extract_test_case_summary(run_result, &case, vec![], &runner_params.contracts_data) + extract_test_case_summary( + run_result, + &case, + vec![], + &context_data.runtime_data.contracts_data, + ) }) } @@ -86,8 +100,9 @@ pub(crate) fn run_fuzz_test( args: Vec, case: Arc, casm_program: Arc, - runner_config: Arc, - runner_params: Arc, + runtime_config: Arc, + context_data: Arc, + is_vm_trace_needed: bool, send: Sender<()>, fuzzing_send: Sender<()>, ) -> JoinHandle>> { @@ -103,8 +118,9 @@ pub(crate) fn run_fuzz_test( args.clone(), &case, &casm_program, - &runner_config, - &runner_params, + &runtime_config, + &context_data, + is_vm_trace_needed, ); // TODO: code below is added to fix snforge tests @@ -114,7 +130,12 @@ pub(crate) fn run_fuzz_test( return Ok(TestCaseSummary::Skipped {}); } - extract_test_case_summary(run_result, &case, args, &runner_params.contracts_data) + extract_test_case_summary( + run_result, + &case, + args, + &context_data.runtime_data.contracts_data, + ) }) } @@ -165,8 +186,9 @@ pub fn run_test_case( args: Vec, case: &TestCaseRunnable, casm_program: &AssembledProgramWithDebugInfo, - runner_config: &Arc, - runner_params: &Arc, + runtime_config: &RuntimeConfig, + context_data: &ContextData, + is_vm_trace_needed: bool, ) -> Result { ensure!( case.available_gas != Some(0), @@ -197,13 +219,13 @@ pub fn run_test_case( let mut state_reader = ExtendedStateReader { dict_state_reader: cheatnet_constants::build_testing_state(), - fork_state_reader: get_fork_state_reader(&runner_config.workspace_root, &case.fork_config)?, + fork_state_reader: get_fork_state_reader(&context_data.workspace_root, &case.fork_config)?, }; let block_info = state_reader.get_block_info()?; let mut context = build_context(&block_info); - if let Some(max_n_steps) = runner_config.max_n_steps { + if let Some(max_n_steps) = runtime_config.max_n_steps { set_max_steps(&mut context, max_n_steps); } let mut execution_resources = ExecutionResources::default(); @@ -223,8 +245,7 @@ pub fn run_test_case( block_info, ..Default::default() }; - cheatnet_state.trace_data.is_vm_trace_needed = - runner_config.execution_data_to_save.is_vm_trace_needed(); + cheatnet_state.trace_data.is_vm_trace_needed = is_vm_trace_needed; let cheatable_runtime = ExtendedRuntime { extension: CheatableStarknetRuntimeExtension { @@ -242,8 +263,8 @@ pub fn run_test_case( extended_runtime: cheatable_runtime, }; let forge_extension = ForgeExtension { - environment_variables: &runner_params.environment_variables, - contracts_data: &runner_params.contracts_data, + environment_variables: &context_data.runtime_data.environment_variables, + contracts_data: &context_data.runtime_data.contracts_data, }; let mut forge_runtime = ExtendedRuntime { diff --git a/crates/forge/src/lib.rs b/crates/forge/src/lib.rs index e6b13feb53..7990caf56f 100644 --- a/crates/forge/src/lib.rs +++ b/crates/forge/src/lib.rs @@ -8,10 +8,12 @@ use std::sync::Arc; use compiled_raw::{CompiledTestCrateRaw, RawForkConfig, RawForkParams}; use forge_runner::test_crate_summary::TestCrateSummary; -use forge_runner::{RunnerConfig, RunnerParams, TestCrateRunResult}; +use forge_runner::TestCrateRunResult; use crate::block_number_map::BlockNumberMap; use forge_runner::compiled_runnable::{CompiledTestCrateRunnable, TestCaseRunnable}; +use forge_runner::context_data::ContextData; +use forge_runner::forge_config::ForgeConfig; use crate::scarb::config::ForkTarget; use crate::test_filter::TestsFilter; @@ -100,8 +102,8 @@ pub async fn run( compiled_test_crates: Vec, package_name: &str, tests_filter: &TestsFilter, - runner_config: Arc, - runner_params: Arc, + forge_config: Arc, + context_data: Arc, fork_targets: &[ForkTarget], block_number_map: &mut BlockNumberMap, ) -> Result> { @@ -135,13 +137,13 @@ pub async fn run( let compiled_test_crate = to_runnable(compiled_test_crate, fork_targets, block_number_map).await?; - let runner_config = runner_config.clone(); - let runner_params = runner_params.clone(); + let forge_config = forge_config.clone(); + let context_data = context_data.clone(); let summary = forge_runner::run_tests_from_crate( compiled_test_crate, - runner_config, - runner_params, + forge_config, + context_data, tests_filter, ) .await?; @@ -172,7 +174,7 @@ pub async fn run( }); if any_fuzz_test_was_run { - pretty_printing::print_test_seed(runner_config.fuzzer_seed); + pretty_printing::print_test_seed(forge_config.runner_config.fuzzer_seed); } Ok(summaries) diff --git a/crates/forge/src/main.rs b/crates/forge/src/main.rs index cf0bbace1d..a7d4b7448e 100644 --- a/crates/forge/src/main.rs +++ b/crates/forge/src/main.rs @@ -1,8 +1,7 @@ use anyhow::{anyhow, Context, Result}; -use camino::Utf8Path; use clap::{Parser, Subcommand, ValueEnum}; use configuration::load_package_config; -use forge::scarb::config::ForgeConfig; +use forge::scarb::config::ForgeConfigFromScarb; use forge::scarb::{ build_contracts_with_scarb, build_test_artifacts_with_scarb, get_test_artifacts_path, load_test_artifacts, @@ -12,7 +11,7 @@ use forge::test_filter::TestsFilter; use forge::{pretty_printing, run}; use forge_runner::test_case_summary::{AnyTestCaseSummary, TestCaseSummary}; use forge_runner::test_crate_summary::TestCrateSummary; -use forge_runner::{RunnerConfig, RunnerParams, CACHE_DIR}; +use forge_runner::CACHE_DIR; use rand::{thread_rng, RngCore}; use scarb_api::{ get_contracts_artifacts_and_source_sierra_paths, @@ -23,6 +22,10 @@ use scarb_ui::args::PackagesFilter; use cheatnet::runtime_extensions::forge_runtime_extension::contracts_data::ContractsData; use forge::block_number_map::BlockNumberMap; +use forge_runner::context_data::{ContextData, RuntimeData}; +use forge_runner::forge_config::{ + ExecutionDataToSave, ForgeConfig, OutputConfig, RunnerConfig, RuntimeConfig, +}; use semver::{Comparator, Op, Version, VersionReq}; use shared::print::print_as_warning; use std::env; @@ -171,7 +174,6 @@ fn extract_failed_tests( #[allow(clippy::too_many_arguments)] #[allow(clippy::fn_params_excessive_bools)] fn combine_configs( - workspace_root: &Utf8Path, exit_first: bool, fuzzer_runs: Option, fuzzer_seed: Option, @@ -179,22 +181,29 @@ fn combine_configs( save_trace_data: bool, build_profile: bool, max_n_steps: Option, - forge_config: &ForgeConfig, -) -> RunnerConfig { - RunnerConfig::new( - workspace_root.to_path_buf(), - exit_first || forge_config.exit_first, - fuzzer_runs - .or(forge_config.fuzzer_runs) - .unwrap_or(default_fuzzer_runs()), - fuzzer_seed - .or(forge_config.fuzzer_seed) - .unwrap_or_else(|| thread_rng().next_u64()), - detailed_resources || forge_config.detailed_resources, - save_trace_data || forge_config.save_trace_data, - build_profile || forge_config.build_profile, - max_n_steps.or(forge_config.max_n_steps), - ) + forge_config_from_scarb: &ForgeConfigFromScarb, +) -> ForgeConfig { + ForgeConfig { + runner_config: Arc::new(RunnerConfig { + exit_first: exit_first || forge_config_from_scarb.exit_first, + fuzzer_runs: fuzzer_runs + .or(forge_config_from_scarb.fuzzer_runs) + .unwrap_or(default_fuzzer_runs()), + fuzzer_seed: fuzzer_seed + .or(forge_config_from_scarb.fuzzer_seed) + .unwrap_or_else(|| thread_rng().next_u64()), + }), + runtime_config: Arc::new(RuntimeConfig { + max_n_steps: max_n_steps.or(forge_config_from_scarb.max_n_steps), + }), + output_config: OutputConfig { + detailed_resources: detailed_resources || forge_config_from_scarb.detailed_resources, + execution_data_to_save: ExecutionDataToSave::from_flags( + save_trace_data || forge_config_from_scarb.save_trace_data, + build_profile || forge_config_from_scarb.build_profile, + ), + }, + } } fn snforge_std_version_requirement() -> VersionReq { @@ -279,10 +288,18 @@ fn test_workspace(args: TestArgs) -> Result { )?; let contracts_data = ContractsData::try_from(contracts)?; - let forge_config = - load_package_config::(&scarb_metadata, &package.id)?; + let context_data = Arc::new(ContextData { + workspace_root: workspace_root.clone(), + test_artifacts_path, + runtime_data: RuntimeData { + contracts_data, + environment_variables: env::vars().collect(), + }, + }); + + let forge_config_from_scarb = + load_package_config::(&scarb_metadata, &package.id)?; let runner_config = Arc::new(combine_configs( - &workspace_root, args.exit_first, args.fuzzer_runs, args.fuzzer_seed, @@ -290,31 +307,32 @@ fn test_workspace(args: TestArgs) -> Result { args.save_trace_data, args.build_profile, args.max_n_steps, - &forge_config, + &forge_config_from_scarb, )); - let runner_params = - Arc::new(RunnerParams::new(contracts_data, env::vars().collect())); + + let test_filter = TestsFilter::from_flags( + args.test_filter.clone(), + args.exact, + args.only_ignored, + args.include_ignored, + args.rerun_failed, + workspace_root.join(CACHE_DIR), + ); let tests_file_summaries = run( compiled_test_crates, &package.name, - &TestsFilter::from_flags( - args.test_filter.clone(), - args.exact, - args.only_ignored, - args.include_ignored, - args.rerun_failed, - workspace_root.join(CACHE_DIR), - ), + &test_filter, runner_config, - runner_params, - &forge_config.fork, + context_data, + &forge_config_from_scarb.fork, &mut block_number_map, ) .await?; all_failed_tests.extend(extract_failed_tests(tests_file_summaries)); } + set_cached_failed_tests_names(&all_failed_tests, &workspace_root.join(CACHE_DIR))?; pretty_printing::print_latest_blocks_numbers( block_number_map.get_url_to_latest_block_number(), @@ -363,13 +381,10 @@ fn main() { #[cfg(test)] mod tests { use super::*; - use camino::Utf8PathBuf; #[test] fn fuzzer_default_seed() { - let workspace_root: Utf8PathBuf = Default::default(); let config = combine_configs( - &workspace_root, false, None, None, @@ -380,7 +395,6 @@ mod tests { &Default::default(), ); let config2 = combine_configs( - &workspace_root, false, None, None, @@ -391,16 +405,17 @@ mod tests { &Default::default(), ); - assert_ne!(config.fuzzer_seed, 0); - assert_ne!(config2.fuzzer_seed, 0); - assert_ne!(config.fuzzer_seed, config2.fuzzer_seed); + assert_ne!(config.runner_config.fuzzer_seed, 0); + assert_ne!(config2.runner_config.fuzzer_seed, 0); + assert_ne!( + config.runner_config.fuzzer_seed, + config2.runner_config.fuzzer_seed + ); } #[test] fn runner_config_default_arguments() { - let workspace_root: Utf8PathBuf = Default::default(); let config = combine_configs( - &workspace_root, false, None, None, @@ -412,22 +427,24 @@ mod tests { ); assert_eq!( config, - RunnerConfig::new( - workspace_root, - false, - default_fuzzer_runs(), - config.fuzzer_seed, - false, - false, - false, - None - ) + ForgeConfig { + runner_config: Arc::new(RunnerConfig { + exit_first: false, + fuzzer_runs: default_fuzzer_runs(), + fuzzer_seed: config.runner_config.fuzzer_seed, + }), + runtime_config: Arc::new(RuntimeConfig { max_n_steps: None }), + output_config: OutputConfig { + detailed_resources: false, + execution_data_to_save: ExecutionDataToSave::None + }, + } ); } #[test] fn runner_config_just_scarb_arguments() { - let config_from_scarb = ForgeConfig { + let config_from_scarb = ForgeConfigFromScarb { exit_first: true, fork: vec![], fuzzer_runs: Some(NonZeroU32::new(1234).unwrap()), @@ -437,10 +454,8 @@ mod tests { build_profile: true, max_n_steps: Some(1_000_000), }; - let workspace_root: Utf8PathBuf = Default::default(); let config = combine_configs( - &workspace_root, false, None, None, @@ -452,24 +467,26 @@ mod tests { ); assert_eq!( config, - RunnerConfig::new( - workspace_root, - true, - NonZeroU32::new(1234).unwrap(), - 500, - true, - true, - true, - Some(1_000_000) - ) + ForgeConfig { + runner_config: Arc::new(RunnerConfig { + exit_first: true, + fuzzer_runs: NonZeroU32::new(1234).unwrap(), + fuzzer_seed: 500, + }), + runtime_config: Arc::new(RuntimeConfig { + max_n_steps: Some(1_000_000) + }), + output_config: OutputConfig { + detailed_resources: true, + execution_data_to_save: ExecutionDataToSave::TraceAndProfile + }, + } ); } #[test] fn runner_config_argument_precedence() { - let workspace_root: Utf8PathBuf = Default::default(); - - let config_from_scarb = ForgeConfig { + let config_from_scarb = ForgeConfigFromScarb { exit_first: false, fork: vec![], fuzzer_runs: Some(NonZeroU32::new(1234).unwrap()), @@ -480,7 +497,6 @@ mod tests { max_n_steps: Some(1234), }; let config = combine_configs( - &workspace_root, true, Some(NonZeroU32::new(100).unwrap()), Some(32), @@ -493,16 +509,20 @@ mod tests { assert_eq!( config, - RunnerConfig::new( - workspace_root, - true, - NonZeroU32::new(100).unwrap(), - 32, - true, - true, - true, - Some(1_000_000) - ) + ForgeConfig { + runner_config: Arc::new(RunnerConfig { + exit_first: true, + fuzzer_runs: NonZeroU32::new(100).unwrap(), + fuzzer_seed: 32, + }), + runtime_config: Arc::new(RuntimeConfig { + max_n_steps: Some(1_000_000) + }), + output_config: OutputConfig { + detailed_resources: true, + execution_data_to_save: ExecutionDataToSave::TraceAndProfile + }, + } ); } } diff --git a/crates/forge/src/scarb.rs b/crates/forge/src/scarb.rs index 4dc9abd474..15c35307a6 100644 --- a/crates/forge/src/scarb.rs +++ b/crates/forge/src/scarb.rs @@ -1,5 +1,5 @@ use crate::compiled_raw::CompiledTestCrateRaw; -use crate::scarb::config::{ForgeConfig, RawForgeConfig}; +use crate::scarb::config::{ForgeConfigFromScarb, RawForgeConfig}; use anyhow::{Context, Result}; use camino::{Utf8Path, Utf8PathBuf}; use configuration::PackageConfig; @@ -8,7 +8,7 @@ use scarb_ui::args::PackagesFilter; pub mod config; -impl PackageConfig for ForgeConfig { +impl PackageConfig for ForgeConfigFromScarb { fn tool_name() -> &'static str { "snforge" } @@ -136,7 +136,7 @@ mod tests { .run() .unwrap(); - let config = load_package_config::( + let config = load_package_config::( &scarb_metadata, &scarb_metadata.workspace.members[0], ) @@ -144,7 +144,7 @@ mod tests { assert_eq!( config, - ForgeConfig { + ForgeConfigFromScarb { exit_first: false, fork: vec![ ForkTarget::new( @@ -191,7 +191,7 @@ mod tests { .run() .unwrap(); - let result = load_package_config::( + let result = load_package_config::( &scarb_metadata, &PackageId::from(String::from("12345679")), ); @@ -220,7 +220,7 @@ mod tests { .run() .unwrap(); - let config = load_package_config::( + let config = load_package_config::( &scarb_metadata, &scarb_metadata.workspace.members[0], ) @@ -256,7 +256,7 @@ mod tests { .current_dir(temp.path()) .run() .unwrap(); - let err = load_package_config::( + let err = load_package_config::( &scarb_metadata, &scarb_metadata.workspace.members[0], ) @@ -288,7 +288,7 @@ mod tests { .current_dir(temp.path()) .run() .unwrap(); - let err = load_package_config::( + let err = load_package_config::( &scarb_metadata, &scarb_metadata.workspace.members[0], ) @@ -319,7 +319,7 @@ mod tests { .run() .unwrap(); - let err = load_package_config::( + let err = load_package_config::( &scarb_metadata, &scarb_metadata.workspace.members[0], ) @@ -352,7 +352,7 @@ mod tests { .run() .unwrap(); - let err = load_package_config::( + let err = load_package_config::( &scarb_metadata, &scarb_metadata.workspace.members[0], ) @@ -384,7 +384,7 @@ mod tests { .unwrap(); env::set_var("ENV_URL_FORK234980670176", "http://some.rpc.url_from_env"); - let config = load_package_config::( + let config = load_package_config::( &scarb_metadata, &scarb_metadata.workspace.members[0], ) @@ -392,7 +392,7 @@ mod tests { assert_eq!( config, - ForgeConfig { + ForgeConfigFromScarb { exit_first: false, fork: vec![ForkTarget::new( "ENV_URL_FORK".to_string(), diff --git a/crates/forge/src/scarb/config.rs b/crates/forge/src/scarb/config.rs index 379966010a..445f09552e 100644 --- a/crates/forge/src/scarb/config.rs +++ b/crates/forge/src/scarb/config.rs @@ -10,7 +10,7 @@ use std::{ #[allow(clippy::module_name_repetitions)] #[allow(clippy::struct_excessive_bools)] #[derive(Debug, PartialEq, Default)] -pub struct ForgeConfig { +pub struct ForgeConfigFromScarb { /// Should runner exit after first failed test pub exit_first: bool, /// How many runs should fuzzer execute @@ -115,7 +115,7 @@ fn validate_raw_fork_config(raw_config: RawForgeConfig) -> Result for ForgeConfig { +impl TryFrom for ForgeConfigFromScarb { type Error = anyhow::Error; fn try_from(value: RawForgeConfig) -> Result { @@ -136,7 +136,7 @@ impl TryFrom for ForgeConfig { )); } - Ok(ForgeConfig { + Ok(ForgeConfigFromScarb { exit_first: value.exit_first, fuzzer_runs: value.fuzzer_runs, fuzzer_seed: value.fuzzer_seed, diff --git a/crates/forge/test_utils/src/running_tests.rs b/crates/forge/test_utils/src/running_tests.rs index 44e75c5512..568b3179ad 100644 --- a/crates/forge/test_utils/src/running_tests.rs +++ b/crates/forge/test_utils/src/running_tests.rs @@ -5,8 +5,11 @@ use forge::block_number_map::BlockNumberMap; use forge::run; use forge::scarb::{get_test_artifacts_path, load_test_artifacts}; use forge::test_filter::TestsFilter; +use forge_runner::context_data::{ContextData, RuntimeData}; +use forge_runner::forge_config::{ + ExecutionDataToSave, ForgeConfig, OutputConfig, RunnerConfig, RuntimeConfig, +}; use forge_runner::test_crate_summary::TestCrateSummary; -use forge_runner::{RunnerConfig, RunnerParams}; use shared::command::CommandExt; use std::num::NonZeroU32; use std::path::PathBuf; @@ -37,20 +40,27 @@ pub fn run_test_case(test: &TestCase) -> Vec { compiled_test_crates, "test_package", &TestsFilter::from_flags(None, false, false, false, false, Default::default()), - Arc::new(RunnerConfig::new( - Utf8PathBuf::from_path_buf(PathBuf::from(tempdir().unwrap().path())).unwrap(), - false, - NonZeroU32::new(256).unwrap(), - 12345, - false, - false, - false, - None, - )), - Arc::new(RunnerParams::new( - ContractsData::try_from(test.contracts().unwrap()).unwrap(), - test.env().clone(), - )), + Arc::new(ForgeConfig { + runner_config: Arc::new(RunnerConfig { + exit_first: false, + fuzzer_runs: NonZeroU32::new(256).unwrap(), + fuzzer_seed: 12345, + }), + runtime_config: Arc::new(RuntimeConfig { max_n_steps: None }), + output_config: OutputConfig { + detailed_resources: false, + execution_data_to_save: ExecutionDataToSave::None, + }, + }), + Arc::new(ContextData { + runtime_data: RuntimeData { + contracts_data: ContractsData::try_from(test.contracts().unwrap()).unwrap(), + environment_variables: test.env().clone(), + }, + workspace_root: Utf8PathBuf::from_path_buf(PathBuf::from(tempdir().unwrap().path())) + .unwrap(), + test_artifacts_path, + }), &[], &mut BlockNumberMap::default(), )) diff --git a/crates/forge/tests/integration/setup_fork.rs b/crates/forge/tests/integration/setup_fork.rs index ed2b0a6c52..5aeb66661c 100644 --- a/crates/forge/tests/integration/setup_fork.rs +++ b/crates/forge/tests/integration/setup_fork.rs @@ -1,4 +1,6 @@ use indoc::formatdoc; + +use std::num::NonZeroU32; use std::path::Path; use std::path::PathBuf; use std::process::Command; @@ -16,7 +18,10 @@ use tokio::runtime::Runtime; use cheatnet::runtime_extensions::forge_runtime_extension::contracts_data::ContractsData; use forge::compiled_raw::RawForkParams; use forge::scarb::{get_test_artifacts_path, load_test_artifacts}; -use forge_runner::{RunnerConfig, RunnerParams}; +use forge_runner::context_data::{ContextData, RuntimeData}; +use forge_runner::forge_config::{ + ExecutionDataToSave, ForgeConfig, OutputConfig, RunnerConfig, RuntimeConfig, +}; use shared::command::CommandExt; use test_utils::runner::{assert_case_output_contains, assert_failed, assert_passed, Contract}; use test_utils::running_tests::run_test_case; @@ -124,20 +129,29 @@ fn fork_aliased_decorator() { compiled_test_crates, "test_package", &TestsFilter::from_flags(None, false, false, false, false, Default::default()), - Arc::new(RunnerConfig::new( - Utf8PathBuf::from_path_buf(PathBuf::from(tempdir().unwrap().path())).unwrap(), - false, - 256.try_into().unwrap(), - 12345, - false, - false, - false, - None, - )), - Arc::new(RunnerParams::new( - ContractsData::try_from(test.contracts().unwrap()).unwrap(), - test.env().clone(), - )), + Arc::new(ForgeConfig { + runner_config: Arc::new(RunnerConfig { + exit_first: false, + fuzzer_runs: NonZeroU32::new(256).unwrap(), + fuzzer_seed: 12345, + }), + runtime_config: Arc::new(RuntimeConfig { max_n_steps: None }), + output_config: OutputConfig { + detailed_resources: false, + execution_data_to_save: ExecutionDataToSave::None, + }, + }), + Arc::new(ContextData { + runtime_data: RuntimeData { + contracts_data: ContractsData::try_from(test.contracts().unwrap()).unwrap(), + environment_variables: test.env().clone(), + }, + workspace_root: Utf8PathBuf::from_path_buf(PathBuf::from( + tempdir().unwrap().path(), + )) + .unwrap(), + test_artifacts_path, + }), &[ForkTarget::new( "FORK_NAME_FROM_SCARB_TOML".to_string(), RawForkParams {