diff --git a/Cargo.lock b/Cargo.lock index 53d31816ed..d106fdbd62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3242,6 +3242,7 @@ dependencies = [ "packages_validation", "project-root", "rand 0.8.5", + "rayon", "regex", "scarb-api", "scarb-metadata", diff --git a/crates/forge-runner/src/package_tests.rs b/crates/forge-runner/src/package_tests.rs index 735fb685f6..34c98270b1 100644 --- a/crates/forge-runner/src/package_tests.rs +++ b/crates/forge-runner/src/package_tests.rs @@ -128,8 +128,9 @@ impl TestDetails { } } +// TODO: Remove in next PRs #[derive(Debug, Clone)] -pub struct TestTarget { +pub struct TestTargetDeprecated { pub tests_location: TestTargetLocation, pub sierra_program: ProgramArtifact, pub sierra_program_path: Arc, @@ -137,9 +138,10 @@ pub struct TestTarget { pub test_cases: Vec>, } -impl TestTarget { +// TODO: Remove in next PRs +impl TestTargetDeprecated { #[tracing::instrument(skip_all, level = "debug")] - pub fn from_raw( + pub fn from_raw_deprecated( test_target_raw: TestTargetRaw, tracked_resource: &ForgeTrackedResource, ) -> Result { @@ -211,3 +213,72 @@ pub struct TestCase { pub name: String, pub config: C, } + +#[derive(Debug, Clone)] +pub struct TestTarget { + pub tests_location: TestTargetLocation, + pub sierra_program: ProgramArtifact, + pub sierra_program_path: Arc, + pub casm_program: Option>, + pub test_cases: Vec, +} + +impl TestTarget { + #[tracing::instrument(skip_all, level = "debug")] + pub fn from_raw(test_target_raw: TestTargetRaw) -> Result> { + macro_rules! by_id { + ($field:ident) => {{ + let temp: HashMap<_, _> = test_target_raw + .sierra_program + .program + .$field + .iter() + .map(|f| (f.id.id, f)) + .collect(); + + temp + }}; + } + let funcs = by_id!(funcs); + let type_declarations = by_id!(type_declarations); + + let sierra_program_registry = + ProgramRegistry::::new(&test_target_raw.sierra_program.program)?; + let type_size_map = get_type_size_map( + &test_target_raw.sierra_program.program, + &sierra_program_registry, + ) + .ok_or_else(|| anyhow!("can not get type size map"))?; + + let default_executables = vec![]; + let debug_info = test_target_raw.sierra_program.debug_info.clone(); + let executables = debug_info + .as_ref() + .and_then(|info| info.executables.get("snforge_internal_test_executable")) + .unwrap_or(&default_executables); + + let test_cases = executables + .par_iter() + .map(|case| { + let func = funcs[&case.id]; + let name = case.debug_name.clone().unwrap().into(); + let test_details = TestDetails::build(func, &type_declarations, &type_size_map); + + Ok(TestCandidate { name, test_details }) + }) + .collect::>()?; + + Ok(TestTarget { + tests_location: test_target_raw.tests_location, + test_cases, + sierra_program: test_target_raw.sierra_program, + sierra_program_path: test_target_raw.sierra_program_path.into(), + casm_program: None, + }) + } +} + +pub struct TestCandidate { + pub name: String, + pub test_details: TestDetails, +} diff --git a/crates/forge-runner/src/package_tests/with_config.rs b/crates/forge-runner/src/package_tests/with_config.rs index 73481e43ea..c74de5cafe 100644 --- a/crates/forge-runner/src/package_tests/with_config.rs +++ b/crates/forge-runner/src/package_tests/with_config.rs @@ -1,4 +1,4 @@ -use super::{TestCase, TestTarget}; +use super::{TestCase, TestTargetDeprecated}; use crate::{ TestCaseIsIgnored, expected_result::{ExpectedPanicValue, ExpectedTestResult}, @@ -9,7 +9,7 @@ use cheatnet::runtime_extensions::forge_config_extension::config::{ }; use conversions::serde::serialize::SerializeToFeltVec; -pub type TestTargetWithConfig = TestTarget; +pub type TestTargetWithConfig = TestTargetDeprecated; pub type TestCaseWithConfig = TestCase; diff --git a/crates/forge-runner/src/package_tests/with_config_resolved.rs b/crates/forge-runner/src/package_tests/with_config_resolved.rs index 0423a75559..b3a744a508 100644 --- a/crates/forge-runner/src/package_tests/with_config_resolved.rs +++ b/crates/forge-runner/src/package_tests/with_config_resolved.rs @@ -1,4 +1,4 @@ -use super::{TestCase, TestTarget}; +use super::{TestCase, TestTargetDeprecated}; use crate::{TestCaseIsIgnored, expected_result::ExpectedTestResult, package_tests::TestDetails}; use anyhow::Result; use cairo_vm::types::program::Program; @@ -9,7 +9,7 @@ use starknet_api::block::BlockNumber; use universal_sierra_compiler_api::representation::RawCasmProgram; use url::Url; -pub type TestTargetWithResolvedConfig = TestTarget; +pub type TestTargetWithResolvedConfig = TestTargetDeprecated; pub type TestCaseWithResolvedConfig = TestCase; diff --git a/crates/forge/Cargo.toml b/crates/forge/Cargo.toml index d003ce2f56..835d1d416d 100644 --- a/crates/forge/Cargo.toml +++ b/crates/forge/Cargo.toml @@ -56,6 +56,7 @@ chrono.workspace = true tracing-subscriber.workspace = true tracing.workspace = true tracing-chrome.workspace = true +rayon.workspace = true [[bin]] name = "snforge" diff --git a/crates/forge/src/run_tests/package.rs b/crates/forge/src/run_tests/package.rs index a647c4186d..10fca94288 100644 --- a/crates/forge/src/run_tests/package.rs +++ b/crates/forge/src/run_tests/package.rs @@ -27,7 +27,8 @@ use console::Style; use forge_runner::{ forge_config::ForgeConfig, package_tests::{ - TestTarget, raw::TestTargetRaw, with_config_resolved::TestTargetWithResolvedConfig, + TestTargetDeprecated, raw::TestTargetRaw, + with_config_resolved::TestTargetWithResolvedConfig, }, test_case_summary::AnyTestCaseSummary, test_target_summary::TestTargetSummary, @@ -145,7 +146,7 @@ async fn test_package_with_config_resolved( let mut test_targets_with_resolved_config = Vec::with_capacity(test_targets.len()); for test_target in test_targets { - let test_target = TestTarget::from_raw( + let test_target = TestTargetDeprecated::from_raw_deprecated( test_target, &forge_config.test_runner_config.tracked_resource, )?; diff --git a/crates/forge/src/run_tests/workspace.rs b/crates/forge/src/run_tests/workspace.rs index a5d9513846..732d428036 100644 --- a/crates/forge/src/run_tests/workspace.rs +++ b/crates/forge/src/run_tests/workspace.rs @@ -2,15 +2,18 @@ use super::package::RunForPackageArgs; use crate::run_tests::messages::latest_blocks_numbers::LatestBlocksNumbersMessage; use crate::run_tests::messages::tests_failure_summary::TestsFailureSummaryMessage; use crate::run_tests::messages::workspace_summary::WorkspaceSummaryMessage; +use crate::scarb::load_test_artifacts; use crate::{ ExitStatus, TestArgs, block_number_map::BlockNumberMap, run_tests::package::run_for_package, scarb::build_artifacts_with_scarb, shared_cache::FailedTestsCache, }; use anyhow::{Context, Result}; use camino::Utf8PathBuf; +use forge_runner::package_tests::{TestCandidate, TestTarget}; use forge_runner::test_case_summary::AnyTestCaseSummary; use forge_runner::{CACHE_DIR, test_target_summary::TestTargetSummary}; use foundry_ui::UI; +use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use scarb_api::{ metadata::{Metadata, PackageMetadata}, target_dir_for_workspace, @@ -42,6 +45,26 @@ impl WorkspaceDirs { } } +type TestTargets = Vec>; + +#[expect(dead_code)] +fn collect_packages_with_tests( + workspace_dirs: &WorkspaceDirs, + packages: &[PackageMetadata], +) -> Result> { + packages + .par_iter() + .map(|package| { + let test_targets_raw = load_test_artifacts(&workspace_dirs.artifacts_dir, package)?; + let test_targets = test_targets_raw + .into_iter() + .map(TestTarget::from_raw) + .collect::>>()?; + Ok((package.clone(), test_targets)) + }) + .collect() +} + #[tracing::instrument(skip_all, level = "debug")] pub async fn run_for_workspace( scarb_metadata: &Metadata,