{
let cache_key = CacheKey {
- platform_key: P::config_id().to_string(),
- compiler_version: compiler_version.clone(),
- metadata_file_path: metadata_file_path.as_ref().to_path_buf(),
+ platform_key: P::config_id(),
+ compiler_version: compiler.version().clone(),
+ metadata_file_path,
solc_mode: mode.clone(),
};
let compilation_callback = || {
- let compiler_path = compiler_path.clone();
- let compiler_version = compiler_version.clone();
- let compilation_success_report_callback = compilation_success_report_callback.clone();
async move {
compile_contracts::(
metadata
.directory()
.context("Failed to get metadata directory while preparing compilation")?,
- compiler_path,
- compiler_version,
metadata
.files_to_compile()
.context("Failed to enumerate files to compile from metadata")?,
- mode,
+ &mode,
deployed_libraries,
- compilation_success_report_callback,
- compilation_failure_report_callback,
+ compiler,
+ reporter,
)
.map(|compilation_result| compilation_result.map(CacheValue::new))
.await
@@ -153,12 +122,15 @@ impl CachedCompiler {
// Lock this specific cache key such that we do not get inconsistent state. We want
// that when multiple cases come in asking for the compilation artifacts then they
// don't all trigger a compilation if there's a cache miss. Hence, the lock here.
- let read_guard = CACHE_KEY_LOCK.read().await;
+ let read_guard = self.cache_key_lock.read().await;
let mutex = match read_guard.get(&cache_key).cloned() {
- Some(value) => value,
+ Some(value) => {
+ drop(read_guard);
+ value
+ }
None => {
drop(read_guard);
- CACHE_KEY_LOCK
+ self.cache_key_lock
.write()
.await
.entry(cache_key.clone())
@@ -168,15 +140,29 @@ impl CachedCompiler {
};
let _guard = mutex.lock().await;
- match self.0.get(&cache_key).await {
+ match self.artifacts_cache.get(&cache_key).await {
Some(cache_value) => {
- compilation_success_report_callback(
- compiler_version.clone(),
- compiler_path,
- true,
- None,
- cache_value.compiler_output.clone(),
- );
+ if deployed_libraries.is_some() {
+ reporter
+ .report_post_link_contracts_compilation_succeeded_event(
+ compiler.version().clone(),
+ compiler.path(),
+ true,
+ None,
+ cache_value.compiler_output.clone(),
+ )
+ .expect("Can't happen");
+ } else {
+ reporter
+ .report_pre_link_contracts_compilation_succeeded_event(
+ compiler.version().clone(),
+ compiler.path(),
+ true,
+ None,
+ cache_value.compiler_output.clone(),
+ )
+ .expect("Can't happen");
+ }
cache_value.compiler_output
}
None => {
@@ -189,38 +175,24 @@ impl CachedCompiler {
}
};
- Ok((compiled_contracts, compiler_version))
+ Ok(compiled_contracts)
}
}
-#[allow(clippy::too_many_arguments)]
async fn compile_contracts(
metadata_directory: impl AsRef,
- compiler_path: impl AsRef,
- compiler_version: Version,
mut files_to_compile: impl Iterator- ,
mode: &Mode,
deployed_libraries: Option<&HashMap>,
- compilation_success_report_callback: impl Fn(
- Version,
- PathBuf,
- bool,
- Option,
- CompilerOutput,
- ),
- compilation_failure_report_callback: impl Fn(
- Option,
- Option,
- Option,
- String,
- ),
+ compiler: &P::Compiler,
+ reporter: &ExecutionSpecificReporter,
) -> Result {
let all_sources_in_dir = FilesWithExtensionIterator::new(metadata_directory.as_ref())
.with_allowed_extension("sol")
.with_use_cached_fs(true)
.collect::>();
- let compiler = Compiler::::new()
+ let compilation = Compiler::new()
.with_allow_path(metadata_directory)
// Handling the modes
.with_optimization(mode.optimize_setting)
@@ -228,14 +200,6 @@ async fn compile_contracts(
// Adding the contract sources to the compiler.
.try_then(|compiler| {
files_to_compile.try_fold(compiler, |compiler, path| compiler.with_source(path))
- })
- .inspect_err(|err| {
- compilation_failure_report_callback(
- Some(compiler_version.clone()),
- Some(compiler_path.as_ref().to_path_buf()),
- None,
- format!("{err:#}"),
- )
})?
// Adding the deployed libraries to the compiler.
.then(|compiler| {
@@ -253,27 +217,55 @@ async fn compile_contracts(
})
});
- let compiler_input = compiler.input();
- let compiler_output = compiler
- .try_build(compiler_path.as_ref())
- .await
- .inspect_err(|err| {
- compilation_failure_report_callback(
- Some(compiler_version.clone()),
- Some(compiler_path.as_ref().to_path_buf()),
- Some(compiler_input.clone()),
- format!("{err:#}"),
- )
- })
- .context("Failed to configure compiler with sources and options")?;
- compilation_success_report_callback(
- compiler_version,
- compiler_path.as_ref().to_path_buf(),
- false,
- Some(compiler_input),
- compiler_output.clone(),
- );
- Ok(compiler_output)
+ let input = compilation.input().clone();
+ let output = compilation.try_build(compiler).await;
+
+ match (output.as_ref(), deployed_libraries.is_some()) {
+ (Ok(output), true) => {
+ reporter
+ .report_post_link_contracts_compilation_succeeded_event(
+ compiler.version().clone(),
+ compiler.path(),
+ false,
+ input,
+ output.clone(),
+ )
+ .expect("Can't happen");
+ }
+ (Ok(output), false) => {
+ reporter
+ .report_pre_link_contracts_compilation_succeeded_event(
+ compiler.version().clone(),
+ compiler.path(),
+ false,
+ input,
+ output.clone(),
+ )
+ .expect("Can't happen");
+ }
+ (Err(err), true) => {
+ reporter
+ .report_post_link_contracts_compilation_failed_event(
+ compiler.version().clone(),
+ compiler.path().to_path_buf(),
+ input,
+ format!("{err:#}"),
+ )
+ .expect("Can't happen");
+ }
+ (Err(err), false) => {
+ reporter
+ .report_pre_link_contracts_compilation_failed_event(
+ compiler.version().clone(),
+ compiler.path().to_path_buf(),
+ input,
+ format!("{err:#}"),
+ )
+ .expect("Can't happen");
+ }
+ }
+
+ output
}
struct ArtifactsCache {
@@ -297,7 +289,7 @@ impl ArtifactsCache {
}
#[instrument(level = "debug", skip_all, err)]
- pub async fn insert(&self, key: &CacheKey, value: &CacheValue) -> Result<()> {
+ pub async fn insert(&self, key: &CacheKey<'_>, value: &CacheValue) -> Result<()> {
let key = bson::to_vec(key).context("Failed to serialize cache key (bson)")?;
let value = bson::to_vec(value).context("Failed to serialize cache value (bson)")?;
cacache::write(self.path.as_path(), key.encode_hex(), value)
@@ -308,7 +300,7 @@ impl ArtifactsCache {
Ok(())
}
- pub async fn get(&self, key: &CacheKey) -> Option {
+ pub async fn get(&self, key: &CacheKey<'_>) -> Option {
let key = bson::to_vec(key).ok()?;
let value = cacache::read(self.path.as_path(), key.encode_hex())
.await
@@ -320,7 +312,7 @@ impl ArtifactsCache {
#[instrument(level = "debug", skip_all, err)]
pub async fn get_or_insert_with(
&self,
- key: &CacheKey,
+ key: &CacheKey<'_>,
callback: impl AsyncFnOnce() -> Result,
) -> Result {
match self.get(key).await {
@@ -338,20 +330,20 @@ impl ArtifactsCache {
}
}
-#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
-struct CacheKey {
+#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
+struct CacheKey<'a> {
/// The platform name that this artifact was compiled for. For example, this could be EVM or
/// PVM.
- platform_key: String,
+ platform_key: &'a TestingPlatform,
/// The version of the compiler that was used to compile the artifacts.
compiler_version: Version,
/// The path of the metadata file that the compilation artifacts are for.
- metadata_file_path: PathBuf,
+ metadata_file_path: &'a Path,
/// The mode that the compilation artifacts where compiled with.
- solc_mode: Mode,
+ solc_mode: Cow<'a, Mode>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
diff --git a/crates/core/src/lib.rs b/crates/core/src/lib.rs
index 1e5e5c9..b729b42 100644
--- a/crates/core/src/lib.rs
+++ b/crates/core/src/lib.rs
@@ -19,7 +19,7 @@ pub trait Platform {
type Compiler: SolidityCompiler;
/// Returns the matching [TestingPlatform] of the [revive_dt_config::Arguments].
- fn config_id() -> TestingPlatform;
+ fn config_id() -> &'static TestingPlatform;
}
#[derive(Default)]
@@ -29,8 +29,8 @@ impl Platform for Geth {
type Blockchain = geth::GethNode;
type Compiler = solc::Solc;
- fn config_id() -> TestingPlatform {
- TestingPlatform::Geth
+ fn config_id() -> &'static TestingPlatform {
+ &TestingPlatform::Geth
}
}
@@ -41,7 +41,7 @@ impl Platform for Kitchensink {
type Blockchain = KitchensinkNode;
type Compiler = revive_resolc::Resolc;
- fn config_id() -> TestingPlatform {
- TestingPlatform::Kitchensink
+ fn config_id() -> &'static TestingPlatform {
+ &TestingPlatform::Kitchensink
}
}
diff --git a/crates/core/src/main.rs b/crates/core/src/main.rs
index 40d3203..da46d98 100644
--- a/crates/core/src/main.rs
+++ b/crates/core/src/main.rs
@@ -1,6 +1,7 @@
mod cached_compiler;
use std::{
+ borrow::Cow,
collections::{BTreeMap, HashMap},
io::{BufWriter, Write, stderr},
path::Path,
@@ -16,19 +17,20 @@ use anyhow::Context;
use clap::Parser;
use futures::stream;
use futures::{Stream, StreamExt};
-use indexmap::IndexMap;
+use indexmap::{IndexMap, indexmap};
use revive_dt_node_interaction::EthereumNode;
use revive_dt_report::{
NodeDesignation, ReportAggregator, Reporter, ReporterEvent, TestCaseStatus,
TestSpecificReporter, TestSpecifier,
};
+use serde_json::{Value, json};
use temp_dir::TempDir;
-use tokio::{join, try_join};
-use tracing::{debug, info, info_span, instrument};
+use tokio::try_join;
+use tracing::{debug, error, info, info_span, instrument};
use tracing_appender::non_blocking::WorkerGuard;
use tracing_subscriber::{EnvFilter, FmtSubscriber};
-use revive_dt_common::types::Mode;
+use revive_dt_common::{iterators::EitherIter, types::Mode};
use revive_dt_compiler::{CompilerOutput, SolidityCompiler};
use revive_dt_config::*;
use revive_dt_core::{
@@ -48,17 +50,6 @@ use crate::cached_compiler::CachedCompiler;
static TEMP_DIR: LazyLock = LazyLock::new(|| TempDir::new().unwrap());
-/// this represents a single "test"; a mode, path and collection of cases.
-#[derive(Clone, Debug)]
-struct Test<'a> {
- metadata: &'a MetadataFile,
- metadata_file_path: &'a Path,
- mode: Mode,
- case_idx: CaseIdx,
- case: &'a Case,
- reporter: TestSpecificReporter,
-}
-
fn main() -> anyhow::Result<()> {
let (args, _guard) = init_cli().context("Failed to initialize CLI and tracing subscriber")?;
info!(
@@ -93,14 +84,9 @@ fn main() -> anyhow::Result<()> {
})
.collect::>();
- match &args.compile_only {
- Some(platform) => {
- compile_corpus(&args, &tests, platform, reporter, report_aggregator_task).await
- }
- None => execute_corpus(&args, &tests, reporter, report_aggregator_task)
- .await
- .context("Failed to execute corpus")?,
- }
+ execute_corpus(&args, &tests, reporter, report_aggregator_task)
+ .await
+ .context("Failed to execute corpus")?;
Ok(())
};
@@ -185,8 +171,20 @@ where
L::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
F::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
{
- let tests = prepare_tests::(args, metadata_files, reporter.clone());
- let driver_task = start_driver_task::(args, tests)
+ let leader_nodes =
+ NodePool::::new(args).context("Failed to initialize leader node pool")?;
+ let follower_nodes =
+ NodePool::::new(args).context("Failed to initialize follower node pool")?;
+
+ let tests_stream = tests_stream(
+ args,
+ metadata_files.iter(),
+ &leader_nodes,
+ &follower_nodes,
+ reporter.clone(),
+ )
+ .await;
+ let driver_task = start_driver_task::(args, tests_stream)
.await
.context("Failed to start driver task")?;
let cli_reporting_task = start_cli_reporting_task(reporter);
@@ -197,19 +195,21 @@ where
Ok(())
}
-fn prepare_tests<'a, L, F>(
+async fn tests_stream<'a, L, F>(
args: &Arguments,
- metadata_files: &'a [MetadataFile],
+ metadata_files: impl IntoIterator
- + Clone,
+ leader_node_pool: &'a NodePool,
+ follower_node_pool: &'a NodePool,
reporter: Reporter,
-) -> impl Stream
- >
+) -> impl Stream
- >
where
L: Platform,
F: Platform,
L::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
F::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
{
- let filtered_tests = metadata_files
- .iter()
+ let tests = metadata_files
+ .into_iter()
.flat_map(|metadata_file| {
metadata_file
.cases
@@ -219,244 +219,120 @@ where
})
// Flatten over the modes, prefer the case modes over the metadata file modes.
.flat_map(|(metadata_file, case_idx, case)| {
- case.modes
- .as_ref()
- .or(metadata_file.modes.as_ref())
- .map(|modes| ParsedMode::many_to_modes(modes.iter()).collect::>())
- .unwrap_or(Mode::all().collect())
- .into_iter()
- .map(move |mode| (metadata_file, case_idx, case, mode))
- })
- .map(move |(metadata_file, case_idx, case, mode)| Test {
- metadata: metadata_file,
- metadata_file_path: metadata_file.metadata_file_path.as_path(),
- mode: mode.clone(),
- case_idx: CaseIdx::new(case_idx),
- case,
- reporter: reporter.test_specific_reporter(Arc::new(TestSpecifier {
- solc_mode: mode.clone(),
- metadata_file_path: metadata_file.metadata_file_path.clone(),
- case_idx: CaseIdx::new(case_idx),
- })),
- })
- .inspect(|test| {
- test.reporter
- .report_test_case_discovery_event()
- .expect("Can't fail")
- })
- .collect::>()
- .into_iter()
- // Filter the test out if the leader and follower do not support the target.
- .filter(|test| {
- let leader_support =
- ::matches_target(test.metadata.targets.as_deref());
- let follower_support =
- ::matches_target(test.metadata.targets.as_deref());
- let is_allowed = leader_support && follower_support;
+ let reporter = reporter.clone();
- if !is_allowed {
- debug!(
- file_path = %test.metadata.relative_path().display(),
- leader_support,
- follower_support,
- "Target is not supported, throwing metadata file out"
- );
- test
- .reporter
- .report_test_ignored_event(
- "Either the leader or the follower do not support the target desired by the test",
- IndexMap::from_iter([
- (
- "test_desired_targets".to_string(),
- serde_json::to_value(test.metadata.targets.as_ref())
- .expect("Can't fail")
- ),
- (
- "leader_support".to_string(),
- serde_json::to_value(leader_support)
- .expect("Can't fail")
- ),
- (
- "follower_support".to_string(),
- serde_json::to_value(follower_support)
- .expect("Can't fail")
- )
- ])
- )
- .expect("Can't fail");
- }
+ let modes = case.modes.as_ref().or(metadata_file.modes.as_ref());
+ let modes = match modes {
+ Some(modes) => EitherIter::A(
+ ParsedMode::many_to_modes(modes.iter()).map(Cow::<'static, _>::Owned),
+ ),
+ None => EitherIter::B(Mode::all().map(Cow::<'static, _>::Borrowed)),
+ };
- is_allowed
+ modes.into_iter().map(move |mode| {
+ (
+ metadata_file,
+ case_idx,
+ case,
+ mode.clone(),
+ reporter.test_specific_reporter(Arc::new(TestSpecifier {
+ solc_mode: mode.as_ref().clone(),
+ metadata_file_path: metadata_file.metadata_file_path.clone(),
+ case_idx: CaseIdx::new(case_idx),
+ })),
+ )
+ })
})
- // Filter the test out if the metadata file is ignored.
- .filter(|test| {
- if test.metadata.ignore.is_some_and(|ignore| ignore) {
- debug!(
- file_path = %test.metadata.relative_path().display(),
- "Metadata file is ignored, throwing case out"
- );
- test
- .reporter
- .report_test_ignored_event(
- "Metadata file is ignored, therefore all cases are ignored",
- IndexMap::new(),
- )
- .expect("Can't fail");
- false
- } else {
- true
- }
- })
- // Filter the test case if the case is ignored.
- .filter(|test| {
- if test.case.ignore.is_some_and(|ignore| ignore) {
- debug!(
- file_path = %test.metadata.relative_path().display(),
- case_idx = %test.case_idx,
- "Case is ignored, throwing case out"
- );
- test
- .reporter
- .report_test_ignored_event(
- "Case is ignored",
- IndexMap::new(),
- )
- .expect("Can't fail");
- false
- } else {
- true
- }
- })
- // Filtering based on the EVM version compatibility
- .filter(|test| {
- if let Some(evm_version_requirement) = test.metadata.required_evm_version {
- let leader_compatibility = evm_version_requirement
- .matches(&::evm_version());
- let follower_compatibility = evm_version_requirement
- .matches(&::evm_version());
- let is_allowed = leader_compatibility && follower_compatibility;
+ .collect::>();
- if !is_allowed {
+ // Note: before we do any kind of filtering or process the iterator in any way, we need to
+ // inform the report aggregator of all of the cases that were found as it keeps a state of the
+ // test cases for its internal use.
+ for (_, _, _, _, reporter) in tests.iter() {
+ reporter
+ .report_test_case_discovery_event()
+ .expect("Can't fail")
+ }
+
+ stream::iter(tests.into_iter())
+ .filter_map(
+ move |(metadata_file, case_idx, case, mode, reporter)| async move {
+ let leader_compiler = ::new(
+ args,
+ mode.version.clone().map(Into::into),
+ )
+ .await
+ .inspect_err(|err| error!(?err, "Failed to instantiate the leader compiler"))
+ .ok()?;
+
+ let follower_compiler = ::new(
+ args,
+ mode.version.clone().map(Into::into),
+ )
+ .await
+ .inspect_err(|err| error!(?err, "Failed to instantiate the follower compiler"))
+ .ok()?;
+
+ let leader_node = leader_node_pool.round_robbin();
+ let follower_node = follower_node_pool.round_robbin();
+
+ Some(Test:: {
+ metadata: metadata_file,
+ metadata_file_path: metadata_file.metadata_file_path.as_path(),
+ mode: mode.clone(),
+ case_idx: CaseIdx::new(case_idx),
+ case,
+ leader_node,
+ follower_node,
+ leader_compiler,
+ follower_compiler,
+ reporter,
+ })
+ },
+ )
+ .filter_map(move |test| async move {
+ match test.check_compatibility() {
+ Ok(()) => Some(test),
+ Err((reason, additional_information)) => {
debug!(
- file_path = %test.metadata.relative_path().display(),
+ metadata_file_path = %test.metadata.metadata_file_path.display(),
case_idx = %test.case_idx,
- leader_compatibility,
- follower_compatibility,
- "EVM Version is incompatible, throwing case out"
+ mode = %test.mode,
+ reason,
+ additional_information =
+ serde_json::to_string(&additional_information).unwrap(),
+
+ "Ignoring Test Case"
);
- test
- .reporter
+ test.reporter
.report_test_ignored_event(
- "EVM version is incompatible with either the leader or the follower",
- IndexMap::from_iter([
- (
- "test_desired_evm_version".to_string(),
- serde_json::to_value(test.metadata.required_evm_version)
- .expect("Can't fail")
- ),
- (
- "leader_compatibility".to_string(),
- serde_json::to_value(leader_compatibility)
- .expect("Can't fail")
- ),
- (
- "follower_compatibility".to_string(),
- serde_json::to_value(follower_compatibility)
- .expect("Can't fail")
- )
- ])
+ reason.to_string(),
+ additional_information
+ .into_iter()
+ .map(|(k, v)| (k.into(), v))
+ .collect::>(),
)
.expect("Can't fail");
+ None
}
-
- is_allowed
- } else {
- true
}
- });
-
- stream::iter(filtered_tests)
- // Filter based on the compiler compatibility
- .filter_map(move |test| async move {
- let leader_support = does_compiler_support_mode::(args, &test.mode)
- .await
- .ok()
- .unwrap_or(false);
- let follower_support = does_compiler_support_mode::(args, &test.mode)
- .await
- .ok()
- .unwrap_or(false);
- let is_allowed = leader_support && follower_support;
-
- if !is_allowed {
- debug!(
- file_path = %test.metadata.relative_path().display(),
- leader_support,
- follower_support,
- "Compilers do not support this, throwing case out"
- );
- test
- .reporter
- .report_test_ignored_event(
- "Compilers do not support this mode either for the leader or for the follower.",
- IndexMap::from_iter([
- (
- "leader_support".to_string(),
- serde_json::to_value(leader_support)
- .expect("Can't fail")
- ),
- (
- "follower_support".to_string(),
- serde_json::to_value(follower_support)
- .expect("Can't fail")
- )
- ])
- )
- .expect("Can't fail");
- }
-
- is_allowed.then_some(test)
})
}
-async fn does_compiler_support_mode(
- args: &Arguments,
- mode: &Mode,
-) -> anyhow::Result {
- let compiler_version_or_requirement = mode.compiler_version_to_use(args.solc.clone());
- let compiler_path = P::Compiler::get_compiler_executable(args, compiler_version_or_requirement)
- .await
- .context("Failed to obtain compiler executable path")?;
- let compiler_version = P::Compiler::new(compiler_path.clone())
- .version()
- .await
- .context("Failed to query compiler version")?;
-
- Ok(P::Compiler::supports_mode(
- &compiler_version,
- mode.optimize_setting,
- mode.pipeline,
- ))
-}
-
async fn start_driver_task<'a, L, F>(
args: &Arguments,
- tests: impl Stream
- >,
+ tests: impl Stream
- >,
) -> anyhow::Result>
where
L: Platform,
F: Platform,
L::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
F::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
+ L::Compiler: 'a,
+ F::Compiler: 'a,
{
info!("Starting driver task");
- let leader_nodes = Arc::new(
- NodePool::::new(args).context("Failed to initialize leader node pool")?,
- );
- let follower_nodes = Arc::new(
- NodePool::::new(args).context("Failed to initialize follower node pool")?,
- );
let number_concurrent_tasks = args.number_of_concurrent_tasks();
let cached_compiler = Arc::new(
CachedCompiler::new(
@@ -477,38 +353,26 @@ where
// this number will automatically be low enough to address (2). The user can override this.
Some(number_concurrent_tasks),
move |test| {
- let leader_nodes = leader_nodes.clone();
- let follower_nodes = follower_nodes.clone();
let cached_compiler = cached_compiler.clone();
async move {
- let leader_node = leader_nodes.round_robbin();
- let follower_node = follower_nodes.round_robbin();
-
test.reporter
.report_leader_node_assigned_event(
- leader_node.id(),
- L::config_id(),
- leader_node.connection_string(),
+ test.leader_node.id(),
+ *L::config_id(),
+ test.leader_node.connection_string(),
)
.expect("Can't fail");
test.reporter
.report_follower_node_assigned_event(
- follower_node.id(),
- F::config_id(),
- follower_node.connection_string(),
+ test.follower_node.id(),
+ *F::config_id(),
+ test.follower_node.connection_string(),
)
.expect("Can't fail");
let reporter = test.reporter.clone();
- let result = handle_case_driver::(
- test,
- args,
- cached_compiler,
- leader_node,
- follower_node,
- )
- .await;
+ let result = handle_case_driver::(test, cached_compiler).await;
match result {
Ok(steps_executed) => reporter
@@ -615,99 +479,52 @@ async fn start_cli_reporting_task(reporter: Reporter) {
mode = %test.mode,
case_idx = %test.case_idx,
case_name = test.case.name.as_deref().unwrap_or("Unnamed Case"),
- leader_node = leader_node.id(),
- follower_node = follower_node.id(),
+ leader_node = test.leader_node.id(),
+ follower_node = test.follower_node.id(),
)
)]
-async fn handle_case_driver(
- test: Test<'_>,
- config: &Arguments,
- cached_compiler: Arc,
- leader_node: &L::Blockchain,
- follower_node: &F::Blockchain,
+async fn handle_case_driver<'a, L, F>(
+ test: Test<'a, L, F>,
+ cached_compiler: Arc>,
) -> anyhow::Result
where
L: Platform,
F: Platform,
L::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
F::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
+ L::Compiler: 'a,
+ F::Compiler: 'a,
{
let leader_reporter = test
.reporter
- .execution_specific_reporter(leader_node.id(), NodeDesignation::Leader);
+ .execution_specific_reporter(test.leader_node.id(), NodeDesignation::Leader);
let follower_reporter = test
.reporter
- .execution_specific_reporter(follower_node.id(), NodeDesignation::Follower);
+ .execution_specific_reporter(test.follower_node.id(), NodeDesignation::Follower);
let (
- (
- CompilerOutput {
- contracts: leader_pre_link_contracts,
- },
- _,
- ),
- (
- CompilerOutput {
- contracts: follower_pre_link_contracts,
- },
- _,
- ),
+ CompilerOutput {
+ contracts: leader_pre_link_contracts,
+ },
+ CompilerOutput {
+ contracts: follower_pre_link_contracts,
+ },
) = try_join!(
cached_compiler.compile_contracts::(
test.metadata,
test.metadata_file_path,
- &test.mode,
- config,
+ test.mode.clone(),
None,
- |compiler_version, compiler_path, is_cached, compiler_input, compiler_output| {
- leader_reporter
- .report_pre_link_contracts_compilation_succeeded_event(
- compiler_version,
- compiler_path,
- is_cached,
- compiler_input,
- compiler_output,
- )
- .expect("Can't fail")
- },
- |compiler_version, compiler_path, compiler_input, failure_reason| {
- leader_reporter
- .report_pre_link_contracts_compilation_failed_event(
- compiler_version,
- compiler_path,
- compiler_input,
- failure_reason,
- )
- .expect("Can't fail")
- }
+ &test.leader_compiler,
+ &leader_reporter,
),
cached_compiler.compile_contracts::(
test.metadata,
test.metadata_file_path,
- &test.mode,
- config,
+ test.mode.clone(),
None,
- |compiler_version, compiler_path, is_cached, compiler_input, compiler_output| {
- follower_reporter
- .report_pre_link_contracts_compilation_succeeded_event(
- compiler_version,
- compiler_path,
- is_cached,
- compiler_input,
- compiler_output,
- )
- .expect("Can't fail")
- },
- |compiler_version, compiler_path, compiler_input, failure_reason| {
- follower_reporter
- .report_pre_link_contracts_compilation_failed_event(
- compiler_version,
- compiler_path,
- compiler_input,
- failure_reason,
- )
- .expect("Can't fail")
- }
+ &test.follower_compiler,
+ &follower_reporter
)
)
.context("Failed to compile pre-link contracts for leader/follower in parallel")?;
@@ -780,8 +597,8 @@ where
);
let (leader_receipt, follower_receipt) = try_join!(
- leader_node.execute_transaction(leader_tx),
- follower_node.execute_transaction(follower_tx)
+ test.leader_node.execute_transaction(leader_tx),
+ test.follower_node.execute_transaction(follower_tx)
)?;
debug!(
@@ -839,86 +656,40 @@ where
}
let (
- (
- CompilerOutput {
- contracts: leader_post_link_contracts,
- },
- leader_compiler_version,
- ),
- (
- CompilerOutput {
- contracts: follower_post_link_contracts,
- },
- follower_compiler_version,
- ),
+ CompilerOutput {
+ contracts: leader_post_link_contracts,
+ },
+ CompilerOutput {
+ contracts: follower_post_link_contracts,
+ },
) = try_join!(
cached_compiler.compile_contracts::(
test.metadata,
test.metadata_file_path,
- &test.mode,
- config,
+ test.mode.clone(),
leader_deployed_libraries.as_ref(),
- |compiler_version, compiler_path, is_cached, compiler_input, compiler_output| {
- leader_reporter
- .report_post_link_contracts_compilation_succeeded_event(
- compiler_version,
- compiler_path,
- is_cached,
- compiler_input,
- compiler_output,
- )
- .expect("Can't fail")
- },
- |compiler_version, compiler_path, compiler_input, failure_reason| {
- leader_reporter
- .report_post_link_contracts_compilation_failed_event(
- compiler_version,
- compiler_path,
- compiler_input,
- failure_reason,
- )
- .expect("Can't fail")
- }
+ &test.leader_compiler,
+ &leader_reporter,
),
cached_compiler.compile_contracts::(
test.metadata,
test.metadata_file_path,
- &test.mode,
- config,
+ test.mode.clone(),
follower_deployed_libraries.as_ref(),
- |compiler_version, compiler_path, is_cached, compiler_input, compiler_output| {
- follower_reporter
- .report_post_link_contracts_compilation_succeeded_event(
- compiler_version,
- compiler_path,
- is_cached,
- compiler_input,
- compiler_output,
- )
- .expect("Can't fail")
- },
- |compiler_version, compiler_path, compiler_input, failure_reason| {
- follower_reporter
- .report_post_link_contracts_compilation_failed_event(
- compiler_version,
- compiler_path,
- compiler_input,
- failure_reason,
- )
- .expect("Can't fail")
- }
+ &test.follower_compiler,
+ &follower_reporter
)
)
.context("Failed to compile post-link contracts for leader/follower in parallel")?;
let leader_state = CaseState::::new(
- leader_compiler_version,
+ test.leader_compiler.version().clone(),
leader_post_link_contracts,
leader_deployed_libraries.unwrap_or_default(),
leader_reporter,
);
let follower_state = CaseState::::new(
- follower_compiler_version,
+ test.follower_compiler.version().clone(),
follower_post_link_contracts,
follower_deployed_libraries.unwrap_or_default(),
follower_reporter,
@@ -927,8 +698,8 @@ where
let mut driver = CaseDriver::::new(
test.metadata,
test.case,
- leader_node,
- follower_node,
+ test.leader_node,
+ test.follower_node,
leader_state,
follower_state,
);
@@ -957,60 +728,121 @@ async fn execute_corpus(
Ok(())
}
-async fn compile_corpus(
- config: &Arguments,
- tests: &[MetadataFile],
- platform: &TestingPlatform,
- _: Reporter,
- report_aggregator_task: impl Future