mirror of
https://github.com/pezkuwichain/revive-differential-tests.git
synced 2026-06-12 21:41:10 +00:00
Include contract compilation information in report
This commit is contained in:
Generated
+2
@@ -4588,6 +4588,7 @@ dependencies = [
|
|||||||
name = "revive-dt-report"
|
name = "revive-dt-report"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"alloy-primitives",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"indexmap 2.10.0",
|
"indexmap 2.10.0",
|
||||||
"paste",
|
"paste",
|
||||||
@@ -4600,6 +4601,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_with",
|
"serde_with",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -124,6 +124,14 @@ pub struct Arguments {
|
|||||||
/// Controls if the compilation cache should be invalidated or not.
|
/// Controls if the compilation cache should be invalidated or not.
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
pub invalidate_compilation_cache: bool,
|
pub invalidate_compilation_cache: bool,
|
||||||
|
|
||||||
|
/// Controls if the compiler input is included in the final report.
|
||||||
|
#[clap(long = "report.include-compiler-input")]
|
||||||
|
pub report_include_compiler_input: bool,
|
||||||
|
|
||||||
|
/// Controls if the compiler output is included in the final report.
|
||||||
|
#[clap(long = "report.include-compiler-output")]
|
||||||
|
pub report_include_compiler_output: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Arguments {
|
impl Arguments {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use std::{
|
|||||||
|
|
||||||
use futures::FutureExt;
|
use futures::FutureExt;
|
||||||
use revive_dt_common::iterators::FilesWithExtensionIterator;
|
use revive_dt_common::iterators::FilesWithExtensionIterator;
|
||||||
use revive_dt_compiler::{Compiler, CompilerOutput, Mode, SolidityCompiler};
|
use revive_dt_compiler::{Compiler, CompilerInput, CompilerOutput, Mode, SolidityCompiler};
|
||||||
use revive_dt_config::Arguments;
|
use revive_dt_config::Arguments;
|
||||||
use revive_dt_format::metadata::{ContractIdent, ContractInstance, Metadata};
|
use revive_dt_format::metadata::{ContractIdent, ContractInstance, Metadata};
|
||||||
|
|
||||||
@@ -35,6 +35,7 @@ impl CachedCompiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Compiles or gets the compilation artifacts from the cache.
|
/// Compiles or gets the compilation artifacts from the cache.
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
#[instrument(
|
#[instrument(
|
||||||
level = "debug",
|
level = "debug",
|
||||||
skip_all,
|
skip_all,
|
||||||
@@ -52,6 +53,19 @@ impl CachedCompiler {
|
|||||||
mode: &Mode,
|
mode: &Mode,
|
||||||
config: &Arguments,
|
config: &Arguments,
|
||||||
deployed_libraries: Option<&HashMap<ContractInstance, (ContractIdent, Address, JsonAbi)>>,
|
deployed_libraries: Option<&HashMap<ContractInstance, (ContractIdent, Address, JsonAbi)>>,
|
||||||
|
compilation_success_report_callback: impl Fn(
|
||||||
|
Version,
|
||||||
|
PathBuf,
|
||||||
|
bool,
|
||||||
|
Option<CompilerInput>,
|
||||||
|
CompilerOutput,
|
||||||
|
) + Clone,
|
||||||
|
compilation_failure_report_callback: impl Fn(
|
||||||
|
Option<Version>,
|
||||||
|
Option<PathBuf>,
|
||||||
|
Option<CompilerInput>,
|
||||||
|
String,
|
||||||
|
),
|
||||||
) -> Result<(CompilerOutput, Version)> {
|
) -> Result<(CompilerOutput, Version)> {
|
||||||
static CACHE_KEY_LOCK: Lazy<RwLock<HashMap<CacheKey, Arc<Mutex<()>>>>> =
|
static CACHE_KEY_LOCK: Lazy<RwLock<HashMap<CacheKey, Arc<Mutex<()>>>>> =
|
||||||
Lazy::new(Default::default);
|
Lazy::new(Default::default);
|
||||||
@@ -61,10 +75,21 @@ impl CachedCompiler {
|
|||||||
config,
|
config,
|
||||||
compiler_version_or_requirement,
|
compiler_version_or_requirement,
|
||||||
)
|
)
|
||||||
.await?;
|
.await
|
||||||
|
.inspect_err(|err| {
|
||||||
|
compilation_failure_report_callback(None, None, None, err.to_string())
|
||||||
|
})?;
|
||||||
let compiler_version = <P::Compiler as SolidityCompiler>::new(compiler_path.clone())
|
let compiler_version = <P::Compiler as SolidityCompiler>::new(compiler_path.clone())
|
||||||
.version()
|
.version()
|
||||||
.await?;
|
.await
|
||||||
|
.inspect_err(|err| {
|
||||||
|
compilation_failure_report_callback(
|
||||||
|
None,
|
||||||
|
Some(compiler_path.clone()),
|
||||||
|
None,
|
||||||
|
err.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
let cache_key = CacheKey {
|
let cache_key = CacheKey {
|
||||||
platform_key: P::config_id().to_string(),
|
platform_key: P::config_id().to_string(),
|
||||||
@@ -74,13 +99,19 @@ impl CachedCompiler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let compilation_callback = || {
|
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 {
|
async move {
|
||||||
compile_contracts::<P>(
|
compile_contracts::<P>(
|
||||||
metadata.directory()?,
|
metadata.directory()?,
|
||||||
compiler_path,
|
compiler_path,
|
||||||
|
compiler_version,
|
||||||
metadata.files_to_compile()?,
|
metadata.files_to_compile()?,
|
||||||
mode,
|
mode,
|
||||||
deployed_libraries,
|
deployed_libraries,
|
||||||
|
compilation_success_report_callback,
|
||||||
|
compilation_failure_report_callback,
|
||||||
)
|
)
|
||||||
.map(|compilation_result| compilation_result.map(CacheValue::new))
|
.map(|compilation_result| compilation_result.map(CacheValue::new))
|
||||||
.await
|
.await
|
||||||
@@ -125,10 +156,19 @@ impl CachedCompiler {
|
|||||||
};
|
};
|
||||||
let _guard = mutex.lock().await;
|
let _guard = mutex.lock().await;
|
||||||
|
|
||||||
self.0
|
match self.0.get(&cache_key).await {
|
||||||
.get_or_insert_with(&cache_key, compilation_callback)
|
Some(cache_value) => {
|
||||||
.await
|
compilation_success_report_callback(
|
||||||
.map(|value| value.compiler_output)?
|
compiler_version.clone(),
|
||||||
|
compiler_path,
|
||||||
|
true,
|
||||||
|
None,
|
||||||
|
cache_value.compiler_output.clone(),
|
||||||
|
);
|
||||||
|
cache_value.compiler_output
|
||||||
|
}
|
||||||
|
None => compilation_callback().await?.compiler_output,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -136,19 +176,34 @@ impl CachedCompiler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
async fn compile_contracts<P: Platform>(
|
async fn compile_contracts<P: Platform>(
|
||||||
metadata_directory: impl AsRef<Path>,
|
metadata_directory: impl AsRef<Path>,
|
||||||
compiler_path: impl AsRef<Path>,
|
compiler_path: impl AsRef<Path>,
|
||||||
|
compiler_version: Version,
|
||||||
mut files_to_compile: impl Iterator<Item = PathBuf>,
|
mut files_to_compile: impl Iterator<Item = PathBuf>,
|
||||||
mode: &Mode,
|
mode: &Mode,
|
||||||
deployed_libraries: Option<&HashMap<ContractInstance, (ContractIdent, Address, JsonAbi)>>,
|
deployed_libraries: Option<&HashMap<ContractInstance, (ContractIdent, Address, JsonAbi)>>,
|
||||||
|
compilation_success_report_callback: impl Fn(
|
||||||
|
Version,
|
||||||
|
PathBuf,
|
||||||
|
bool,
|
||||||
|
Option<CompilerInput>,
|
||||||
|
CompilerOutput,
|
||||||
|
),
|
||||||
|
compilation_failure_report_callback: impl Fn(
|
||||||
|
Option<Version>,
|
||||||
|
Option<PathBuf>,
|
||||||
|
Option<CompilerInput>,
|
||||||
|
String,
|
||||||
|
),
|
||||||
) -> Result<CompilerOutput> {
|
) -> Result<CompilerOutput> {
|
||||||
let all_sources_in_dir = FilesWithExtensionIterator::new(metadata_directory.as_ref())
|
let all_sources_in_dir = FilesWithExtensionIterator::new(metadata_directory.as_ref())
|
||||||
.with_allowed_extension("sol")
|
.with_allowed_extension("sol")
|
||||||
.with_use_cached_fs(true)
|
.with_use_cached_fs(true)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
Compiler::<P::Compiler>::new()
|
let compiler = Compiler::<P::Compiler>::new()
|
||||||
.with_allow_path(metadata_directory)
|
.with_allow_path(metadata_directory)
|
||||||
// Handling the modes
|
// Handling the modes
|
||||||
.with_optimization(mode.optimize_setting)
|
.with_optimization(mode.optimize_setting)
|
||||||
@@ -156,6 +211,14 @@ async fn compile_contracts<P: Platform>(
|
|||||||
// Adding the contract sources to the compiler.
|
// Adding the contract sources to the compiler.
|
||||||
.try_then(|compiler| {
|
.try_then(|compiler| {
|
||||||
files_to_compile.try_fold(compiler, |compiler, path| compiler.with_source(path))
|
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,
|
||||||
|
err.to_string(),
|
||||||
|
)
|
||||||
})?
|
})?
|
||||||
// Adding the deployed libraries to the compiler.
|
// Adding the deployed libraries to the compiler.
|
||||||
.then(|compiler| {
|
.then(|compiler| {
|
||||||
@@ -171,9 +234,28 @@ async fn compile_contracts<P: Platform>(
|
|||||||
.fold(compiler, |compiler, (ident, address, path)| {
|
.fold(compiler, |compiler, (ident, address, path)| {
|
||||||
compiler.with_library(path, ident.as_str(), *address)
|
compiler.with_library(path, ident.as_str(), *address)
|
||||||
})
|
})
|
||||||
})
|
});
|
||||||
.try_build(compiler_path)
|
|
||||||
|
let compiler_input = compiler.input();
|
||||||
|
let compiler_output = compiler
|
||||||
|
.try_build(compiler_path.as_ref())
|
||||||
.await
|
.await
|
||||||
|
.inspect_err(|err| {
|
||||||
|
compilation_failure_report_callback(
|
||||||
|
Some(compiler_version.clone()),
|
||||||
|
Some(compiler_path.as_ref().to_path_buf()),
|
||||||
|
Some(compiler_input.clone()),
|
||||||
|
err.to_string(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
compilation_success_report_callback(
|
||||||
|
compiler_version,
|
||||||
|
compiler_path.as_ref().to_path_buf(),
|
||||||
|
false,
|
||||||
|
Some(compiler_input),
|
||||||
|
compiler_output.clone(),
|
||||||
|
);
|
||||||
|
Ok(compiler_output)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ArtifactsCache {
|
struct ArtifactsCache {
|
||||||
|
|||||||
+130
-13
@@ -1,7 +1,7 @@
|
|||||||
mod cached_compiler;
|
mod cached_compiler;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::{BTreeMap, HashMap},
|
||||||
io::{BufWriter, Write, stderr},
|
io::{BufWriter, Write, stderr},
|
||||||
path::Path,
|
path::Path,
|
||||||
sync::{Arc, LazyLock},
|
sync::{Arc, LazyLock},
|
||||||
@@ -19,10 +19,11 @@ use futures::{Stream, StreamExt};
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use revive_dt_node_interaction::EthereumNode;
|
use revive_dt_node_interaction::EthereumNode;
|
||||||
use revive_dt_report::{
|
use revive_dt_report::{
|
||||||
ReportAggregator, Reporter, ReporterEvent, TestCaseStatus, TestSpecificReporter, TestSpecifier,
|
NodeDesignation, ReportAggregator, Reporter, ReporterEvent, TestCaseStatus,
|
||||||
|
TestSpecificReporter, TestSpecifier,
|
||||||
};
|
};
|
||||||
use temp_dir::TempDir;
|
use temp_dir::TempDir;
|
||||||
use tokio::{join, sync::broadcast::Receiver, try_join};
|
use tokio::{join, try_join};
|
||||||
use tracing::{debug, info, info_span, instrument};
|
use tracing::{debug, info, info_span, instrument};
|
||||||
use tracing_appender::non_blocking::WorkerGuard;
|
use tracing_appender::non_blocking::WorkerGuard;
|
||||||
use tracing_subscriber::{EnvFilter, FmtSubscriber};
|
use tracing_subscriber::{EnvFilter, FmtSubscriber};
|
||||||
@@ -181,13 +182,11 @@ where
|
|||||||
L::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
L::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
||||||
F::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
F::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
let reporter_events_rx = reporter.subscribe().await?;
|
let tests = prepare_tests::<L, F>(args, metadata_files, reporter.clone());
|
||||||
|
|
||||||
let tests = prepare_tests::<L, F>(args, metadata_files, reporter);
|
|
||||||
let driver_task = start_driver_task::<L, F>(args, tests).await?;
|
let driver_task = start_driver_task::<L, F>(args, tests).await?;
|
||||||
let cli_reporting_task = start_cli_reporting_task(reporter_events_rx);
|
let cli_reporting_task = start_cli_reporting_task(reporter);
|
||||||
|
|
||||||
let (_, _, rtn) = tokio::join!(cli_reporting_task, driver_task, report_aggregator_task,);
|
let (_, _, rtn) = tokio::join!(cli_reporting_task, driver_task, report_aggregator_task);
|
||||||
rtn?;
|
rtn?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -441,6 +440,8 @@ where
|
|||||||
L::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
L::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
||||||
F::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
F::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
info!("Starting driver task");
|
||||||
|
|
||||||
let leader_nodes = Arc::new(NodePool::<L::Blockchain>::new(args)?);
|
let leader_nodes = Arc::new(NodePool::<L::Blockchain>::new(args)?);
|
||||||
let follower_nodes = Arc::new(NodePool::<F::Blockchain>::new(args)?);
|
let follower_nodes = Arc::new(NodePool::<F::Blockchain>::new(args)?);
|
||||||
let number_concurrent_tasks = args.number_of_concurrent_tasks();
|
let number_concurrent_tasks = args.number_of_concurrent_tasks();
|
||||||
@@ -510,7 +511,10 @@ where
|
|||||||
|
|
||||||
#[allow(clippy::uninlined_format_args)]
|
#[allow(clippy::uninlined_format_args)]
|
||||||
#[allow(irrefutable_let_patterns)]
|
#[allow(irrefutable_let_patterns)]
|
||||||
async fn start_cli_reporting_task(mut aggregator_events_rx: Receiver<ReporterEvent>) {
|
async fn start_cli_reporting_task(reporter: Reporter) {
|
||||||
|
let mut aggregator_events_rx = reporter.subscribe().await.expect("Can't fail");
|
||||||
|
drop(reporter);
|
||||||
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
|
||||||
const GREEN: &str = "\x1B[32m";
|
const GREEN: &str = "\x1B[32m";
|
||||||
@@ -606,6 +610,13 @@ where
|
|||||||
L::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
L::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
||||||
F::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
F::Blockchain: revive_dt_node::Node + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
let leader_reporter = test
|
||||||
|
.reporter
|
||||||
|
.execution_specific_reporter(leader_node.id(), NodeDesignation::Leader);
|
||||||
|
let follower_reporter = test
|
||||||
|
.reporter
|
||||||
|
.execution_specific_reporter(follower_node.id(), NodeDesignation::Follower);
|
||||||
|
|
||||||
let (
|
let (
|
||||||
(
|
(
|
||||||
CompilerOutput {
|
CompilerOutput {
|
||||||
@@ -625,14 +636,56 @@ where
|
|||||||
test.metadata_file_path,
|
test.metadata_file_path,
|
||||||
&test.mode,
|
&test.mode,
|
||||||
config,
|
config,
|
||||||
None
|
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")
|
||||||
|
}
|
||||||
),
|
),
|
||||||
cached_compiler.compile_contracts::<F>(
|
cached_compiler.compile_contracts::<F>(
|
||||||
test.metadata,
|
test.metadata,
|
||||||
test.metadata_file_path,
|
test.metadata_file_path,
|
||||||
&test.mode,
|
&test.mode,
|
||||||
config,
|
config,
|
||||||
None
|
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")
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -740,6 +793,24 @@ where
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if let Some(ref leader_deployed_libraries) = leader_deployed_libraries {
|
||||||
|
leader_reporter.report_libraries_deployed_event(
|
||||||
|
leader_deployed_libraries
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(|(key, (_, address, _))| (key, address))
|
||||||
|
.collect::<BTreeMap<_, _>>(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
if let Some(ref follower_deployed_libraries) = follower_deployed_libraries {
|
||||||
|
follower_reporter.report_libraries_deployed_event(
|
||||||
|
follower_deployed_libraries
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(|(key, (_, address, _))| (key, address))
|
||||||
|
.collect::<BTreeMap<_, _>>(),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
|
||||||
let (
|
let (
|
||||||
(
|
(
|
||||||
@@ -760,14 +831,56 @@ where
|
|||||||
test.metadata_file_path,
|
test.metadata_file_path,
|
||||||
&test.mode,
|
&test.mode,
|
||||||
config,
|
config,
|
||||||
leader_deployed_libraries.as_ref()
|
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")
|
||||||
|
}
|
||||||
),
|
),
|
||||||
cached_compiler.compile_contracts::<F>(
|
cached_compiler.compile_contracts::<F>(
|
||||||
test.metadata,
|
test.metadata,
|
||||||
test.metadata_file_path,
|
test.metadata_file_path,
|
||||||
&test.mode,
|
&test.mode,
|
||||||
config,
|
config,
|
||||||
follower_deployed_libraries.as_ref()
|
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")
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -849,6 +962,8 @@ async fn compile_corpus(
|
|||||||
&mode,
|
&mode,
|
||||||
config,
|
config,
|
||||||
None,
|
None,
|
||||||
|
|_, _, _, _, _| {},
|
||||||
|
|_, _, _, _| {},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@@ -860,6 +975,8 @@ async fn compile_corpus(
|
|||||||
&mode,
|
&mode,
|
||||||
config,
|
config,
|
||||||
None,
|
None,
|
||||||
|
|_, _, _, _, _| {},
|
||||||
|
|_, _, _, _| {},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ use revive_dt_common::cached_fs::read_to_string;
|
|||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use revive_dt_config::Arguments;
|
use revive_dt_config::Arguments;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
use crate::Node;
|
use crate::Node;
|
||||||
|
|
||||||
@@ -63,6 +64,16 @@ where
|
|||||||
|
|
||||||
fn spawn_node<T: Node + Send>(args: &Arguments, genesis: String) -> anyhow::Result<T> {
|
fn spawn_node<T: Node + Send>(args: &Arguments, genesis: String) -> anyhow::Result<T> {
|
||||||
let mut node = T::new(args);
|
let mut node = T::new(args);
|
||||||
|
info!(
|
||||||
|
id = node.id(),
|
||||||
|
connection_string = node.connection_string(),
|
||||||
|
"Spawning node"
|
||||||
|
);
|
||||||
node.spawn(genesis)?;
|
node.spawn(genesis)?;
|
||||||
|
info!(
|
||||||
|
id = node.id(),
|
||||||
|
connection_string = node.connection_string(),
|
||||||
|
"Spawned node"
|
||||||
|
);
|
||||||
Ok(node)
|
Ok(node)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ revive-dt-config = { workspace = true }
|
|||||||
revive-dt-format = { workspace = true }
|
revive-dt-format = { workspace = true }
|
||||||
revive-dt-compiler = { workspace = true }
|
revive-dt-compiler = { workspace = true }
|
||||||
|
|
||||||
|
alloy-primitives = { workspace = true }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
paste = { workspace = true }
|
paste = { workspace = true }
|
||||||
indexmap = { workspace = true, features = ["serde"] }
|
indexmap = { workspace = true, features = ["serde"] }
|
||||||
@@ -21,6 +22,7 @@ serde = { workspace = true }
|
|||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
serde_with = { workspace = true }
|
serde_with = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
|
tracing = { workspace = true }
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|||||||
@@ -4,20 +4,24 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, BTreeSet, HashMap, HashSet},
|
collections::{BTreeMap, BTreeSet, HashMap, HashSet},
|
||||||
fs::OpenOptions,
|
fs::OpenOptions,
|
||||||
|
path::PathBuf,
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use alloy_primitives::Address;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use revive_dt_compiler::Mode;
|
use revive_dt_compiler::{CompilerInput, CompilerOutput, Mode};
|
||||||
use revive_dt_config::{Arguments, TestingPlatform};
|
use revive_dt_config::{Arguments, TestingPlatform};
|
||||||
use revive_dt_format::{case::CaseIdx, corpus::Corpus};
|
use revive_dt_format::{case::CaseIdx, corpus::Corpus, metadata::ContractInstance};
|
||||||
|
use semver::Version;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_with::{DisplayFromStr, serde_as};
|
use serde_with::{DisplayFromStr, serde_as};
|
||||||
use tokio::sync::{
|
use tokio::sync::{
|
||||||
broadcast::{Sender, channel},
|
broadcast::{Sender, channel},
|
||||||
mpsc::{UnboundedReceiver, UnboundedSender, unbounded_channel},
|
mpsc::{UnboundedReceiver, UnboundedSender, unbounded_channel},
|
||||||
};
|
};
|
||||||
|
use tracing::debug;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
@@ -54,7 +58,10 @@ impl ReportAggregator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn aggregate(mut self) -> Result<()> {
|
async fn aggregate(mut self) -> Result<()> {
|
||||||
|
debug!("Starting to aggregate report");
|
||||||
|
|
||||||
while let Some(event) = self.runner_rx.recv().await {
|
while let Some(event) = self.runner_rx.recv().await {
|
||||||
|
debug!(?event, "Received Event");
|
||||||
match event {
|
match event {
|
||||||
RunnerEvent::SubscribeToEvents(event) => {
|
RunnerEvent::SubscribeToEvents(event) => {
|
||||||
self.handle_subscribe_to_events_event(*event);
|
self.handle_subscribe_to_events_event(*event);
|
||||||
@@ -83,8 +90,24 @@ impl ReportAggregator {
|
|||||||
RunnerEvent::FollowerNodeAssigned(event) => {
|
RunnerEvent::FollowerNodeAssigned(event) => {
|
||||||
self.handle_follower_node_assigned_event(*event);
|
self.handle_follower_node_assigned_event(*event);
|
||||||
}
|
}
|
||||||
|
RunnerEvent::PreLinkContractsCompilationSucceeded(event) => {
|
||||||
|
self.handle_pre_link_contracts_compilation_succeeded_event(*event)
|
||||||
|
}
|
||||||
|
RunnerEvent::PostLinkContractsCompilationSucceeded(event) => {
|
||||||
|
self.handle_post_link_contracts_compilation_succeeded_event(*event)
|
||||||
|
}
|
||||||
|
RunnerEvent::PreLinkContractsCompilationFailed(event) => {
|
||||||
|
self.handle_pre_link_contracts_compilation_failed_event(*event)
|
||||||
|
}
|
||||||
|
RunnerEvent::PostLinkContractsCompilationFailed(event) => {
|
||||||
|
self.handle_post_link_contracts_compilation_failed_event(*event)
|
||||||
|
}
|
||||||
|
RunnerEvent::LibrariesDeployed(event) => {
|
||||||
|
self.handle_libraries_deployed_event(*event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
debug!("Report aggregation completed");
|
||||||
|
|
||||||
let file_name = {
|
let file_name = {
|
||||||
let current_timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
|
let current_timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs();
|
||||||
@@ -232,6 +255,113 @@ impl ReportAggregator {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_pre_link_contracts_compilation_succeeded_event(
|
||||||
|
&mut self,
|
||||||
|
event: PreLinkContractsCompilationSucceededEvent,
|
||||||
|
) {
|
||||||
|
let include_input = self.report.config.report_include_compiler_input;
|
||||||
|
let include_output = self.report.config.report_include_compiler_output;
|
||||||
|
|
||||||
|
let execution_information = self.execution_information(&event.execution_specifier);
|
||||||
|
|
||||||
|
let compiler_input = if include_input {
|
||||||
|
event.compiler_input
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let compiler_output = if include_output {
|
||||||
|
Some(event.compiler_output)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
execution_information.pre_link_compilation_status = Some(CompilationStatus::Success {
|
||||||
|
is_cached: event.is_cached,
|
||||||
|
compiler_version: event.compiler_version,
|
||||||
|
compiler_path: event.compiler_path,
|
||||||
|
compiler_input,
|
||||||
|
compiler_output,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_post_link_contracts_compilation_succeeded_event(
|
||||||
|
&mut self,
|
||||||
|
event: PostLinkContractsCompilationSucceededEvent,
|
||||||
|
) {
|
||||||
|
let include_input = self.report.config.report_include_compiler_input;
|
||||||
|
let include_output = self.report.config.report_include_compiler_output;
|
||||||
|
|
||||||
|
let execution_information = self.execution_information(&event.execution_specifier);
|
||||||
|
|
||||||
|
let compiler_input = if include_input {
|
||||||
|
event.compiler_input
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let compiler_output = if include_output {
|
||||||
|
Some(event.compiler_output)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
execution_information.post_link_compilation_status = Some(CompilationStatus::Success {
|
||||||
|
is_cached: event.is_cached,
|
||||||
|
compiler_version: event.compiler_version,
|
||||||
|
compiler_path: event.compiler_path,
|
||||||
|
compiler_input,
|
||||||
|
compiler_output,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_pre_link_contracts_compilation_failed_event(
|
||||||
|
&mut self,
|
||||||
|
event: PreLinkContractsCompilationFailedEvent,
|
||||||
|
) {
|
||||||
|
let include_input = self.report.config.report_include_compiler_input;
|
||||||
|
|
||||||
|
let execution_information = self.execution_information(&event.execution_specifier);
|
||||||
|
|
||||||
|
let compiler_input = if include_input {
|
||||||
|
event.compiler_input
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
execution_information.pre_link_compilation_status = Some(CompilationStatus::Failure {
|
||||||
|
reason: event.reason,
|
||||||
|
compiler_version: event.compiler_version,
|
||||||
|
compiler_path: event.compiler_path,
|
||||||
|
compiler_input,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_post_link_contracts_compilation_failed_event(
|
||||||
|
&mut self,
|
||||||
|
event: PostLinkContractsCompilationFailedEvent,
|
||||||
|
) {
|
||||||
|
let include_input = self.report.config.report_include_compiler_input;
|
||||||
|
|
||||||
|
let execution_information = self.execution_information(&event.execution_specifier);
|
||||||
|
|
||||||
|
let compiler_input = if include_input {
|
||||||
|
event.compiler_input
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
execution_information.post_link_compilation_status = Some(CompilationStatus::Failure {
|
||||||
|
reason: event.reason,
|
||||||
|
compiler_version: event.compiler_version,
|
||||||
|
compiler_path: event.compiler_path,
|
||||||
|
compiler_input,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_libraries_deployed_event(&mut self, event: LibrariesDeployedEvent) {
|
||||||
|
self.execution_information(&event.execution_specifier)
|
||||||
|
.deployed_libraries = Some(event.libraries);
|
||||||
|
}
|
||||||
|
|
||||||
fn test_case_report(&mut self, specifier: &TestSpecifier) -> &mut TestCaseReport {
|
fn test_case_report(&mut self, specifier: &TestSpecifier) -> &mut TestCaseReport {
|
||||||
self.report
|
self.report
|
||||||
.test_case_information
|
.test_case_information
|
||||||
@@ -242,6 +372,21 @@ impl ReportAggregator {
|
|||||||
.entry(specifier.case_idx)
|
.entry(specifier.case_idx)
|
||||||
.or_default()
|
.or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn execution_information(
|
||||||
|
&mut self,
|
||||||
|
specifier: &ExecutionSpecifier,
|
||||||
|
) -> &mut ExecutionInformation {
|
||||||
|
let test_case_report = self.test_case_report(&specifier.test_specifier);
|
||||||
|
match specifier.node_designation {
|
||||||
|
NodeDesignation::Leader => test_case_report
|
||||||
|
.leader_execution_information
|
||||||
|
.get_or_insert_default(),
|
||||||
|
NodeDesignation::Follower => test_case_report
|
||||||
|
.follower_execution_information
|
||||||
|
.get_or_insert_default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[serde_as]
|
#[serde_as]
|
||||||
@@ -287,6 +432,12 @@ pub struct TestCaseReport {
|
|||||||
/// Information related to the follower node assigned to this test case.
|
/// Information related to the follower node assigned to this test case.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub follower_node: Option<TestCaseNodeInformation>,
|
pub follower_node: Option<TestCaseNodeInformation>,
|
||||||
|
/// Information related to the execution on the leader.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub leader_execution_information: Option<ExecutionInformation>,
|
||||||
|
/// Information related to the execution on the follower.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub follower_execution_information: Option<ExecutionInformation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information related to the status of the test. Could be that the test succeeded, failed, or that
|
/// Information related to the status of the test. Could be that the test succeeded, failed, or that
|
||||||
@@ -324,3 +475,57 @@ pub struct TestCaseNodeInformation {
|
|||||||
/// The connection string of the node.
|
/// The connection string of the node.
|
||||||
pub connection_string: String,
|
pub connection_string: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Execution information tied to the leader or the follower.
|
||||||
|
#[derive(Clone, Debug, Default, Serialize)]
|
||||||
|
pub struct ExecutionInformation {
|
||||||
|
/// Information on the pre-link compiled contracts.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub pre_link_compilation_status: Option<CompilationStatus>,
|
||||||
|
/// Information on the post-link compiled contracts.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub post_link_compilation_status: Option<CompilationStatus>,
|
||||||
|
/// Information on the deployed libraries.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
pub deployed_libraries: Option<BTreeMap<ContractInstance, Address>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Information related to compilation
|
||||||
|
#[derive(Clone, Debug, Serialize)]
|
||||||
|
#[serde(tag = "status")]
|
||||||
|
pub enum CompilationStatus {
|
||||||
|
/// The compilation was successful.
|
||||||
|
Success {
|
||||||
|
/// A flag with information on whether the compilation artifacts were cached or not.
|
||||||
|
is_cached: bool,
|
||||||
|
/// The version of the compiler used to compile the contracts.
|
||||||
|
compiler_version: Version,
|
||||||
|
/// The path of the compiler used to compile the contracts.
|
||||||
|
compiler_path: PathBuf,
|
||||||
|
/// The input provided to the compiler to compile the contracts. This is only included if
|
||||||
|
/// the appropriate flag is set in the CLI configuration and if the contracts were not
|
||||||
|
/// cached and the compiler was invoked.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
compiler_input: Option<CompilerInput>,
|
||||||
|
/// The output of the compiler. This is only included if the appropriate flag is set in the
|
||||||
|
/// CLI configurations.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
compiler_output: Option<CompilerOutput>,
|
||||||
|
},
|
||||||
|
/// The compilation failed.
|
||||||
|
Failure {
|
||||||
|
/// The failure reason.
|
||||||
|
reason: String,
|
||||||
|
/// The version of the compiler used to compile the contracts.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
compiler_version: Option<Version>,
|
||||||
|
/// The path of the compiler used to compile the contracts.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
compiler_path: Option<PathBuf>,
|
||||||
|
/// The input provided to the compiler to compile the contracts. This is only included if
|
||||||
|
/// the appropriate flag is set in the CLI configuration and if the contracts were not
|
||||||
|
/// cached and the compiler was invoked.
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
compiler_input: Option<CompilerInput>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
//! Common types and functions used throughout the crate.
|
//! Common types and functions used throughout the crate.
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::{path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
use revive_dt_common::define_wrapper_type;
|
use revive_dt_common::define_wrapper_type;
|
||||||
use revive_dt_compiler::Mode;
|
use revive_dt_compiler::Mode;
|
||||||
use revive_dt_format::case::CaseIdx;
|
use revive_dt_format::case::CaseIdx;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::{DisplayFromStr, serde_as};
|
|
||||||
|
|
||||||
define_wrapper_type!(
|
define_wrapper_type!(
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||||
@@ -15,11 +14,24 @@ define_wrapper_type!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
/// An absolute specifier for a test.
|
/// An absolute specifier for a test.
|
||||||
#[serde_as]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
|
|
||||||
pub struct TestSpecifier {
|
pub struct TestSpecifier {
|
||||||
#[serde_as(as = "DisplayFromStr")]
|
|
||||||
pub solc_mode: Mode,
|
pub solc_mode: Mode,
|
||||||
pub metadata_file_path: PathBuf,
|
pub metadata_file_path: PathBuf,
|
||||||
pub case_idx: CaseIdx,
|
pub case_idx: CaseIdx,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An absolute path for a test that also includes information about the node that it's assigned to
|
||||||
|
/// and whether it's the leader or follower.
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct ExecutionSpecifier {
|
||||||
|
pub test_specifier: Arc<TestSpecifier>,
|
||||||
|
pub node_id: usize,
|
||||||
|
pub node_designation: NodeDesignation,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub enum NodeDesignation {
|
||||||
|
Leader,
|
||||||
|
Follower,
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
//! The types associated with the events sent by the runner to the reporter.
|
//! The types associated with the events sent by the runner to the reporter.
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::{collections::BTreeMap, path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
|
use alloy_primitives::Address;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
use revive_dt_compiler::{CompilerInput, CompilerOutput};
|
||||||
use revive_dt_config::TestingPlatform;
|
use revive_dt_config::TestingPlatform;
|
||||||
use revive_dt_format::corpus::Corpus;
|
|
||||||
use revive_dt_format::metadata::Metadata;
|
use revive_dt_format::metadata::Metadata;
|
||||||
|
use revive_dt_format::{corpus::Corpus, metadata::ContractInstance};
|
||||||
|
use semver::Version;
|
||||||
use tokio::sync::{broadcast, oneshot};
|
use tokio::sync::{broadcast, oneshot};
|
||||||
|
|
||||||
use crate::{ReporterEvent, TestSpecifier, common::MetadataFilePath};
|
use crate::{ExecutionSpecifier, ReporterEvent, TestSpecifier, common::MetadataFilePath};
|
||||||
|
|
||||||
macro_rules! __report_gen__emit_test_specific {
|
macro_rules! __report_gen_emit_test_specific {
|
||||||
(
|
(
|
||||||
$ident:ident,
|
$ident:ident,
|
||||||
$variant_ident:ident,
|
$variant_ident:ident,
|
||||||
@@ -36,21 +39,21 @@ macro_rules! __report_gen__emit_test_specific {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! __report_gen__emit_test_specific_by_parse {
|
macro_rules! __report_gen_emit_test_specific_by_parse {
|
||||||
(
|
(
|
||||||
$ident:ident,
|
$ident:ident,
|
||||||
$variant_ident:ident,
|
$variant_ident:ident,
|
||||||
$skip_field:ident;
|
$skip_field:ident;
|
||||||
$( $bname:ident : $bty:ty, )* ; $( $aname:ident : $aty:ty, )*
|
$( $bname:ident : $bty:ty, )* ; $( $aname:ident : $aty:ty, )*
|
||||||
) => {
|
) => {
|
||||||
__report_gen__emit_test_specific!(
|
__report_gen_emit_test_specific!(
|
||||||
$ident, $variant_ident, $skip_field;
|
$ident, $variant_ident, $skip_field;
|
||||||
$( $bname : $bty, )* ; $( $aname : $aty, )*
|
$( $bname : $bty, )* ; $( $aname : $aty, )*
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! __report_gen__scan_before {
|
macro_rules! __report_gen_scan_before {
|
||||||
(
|
(
|
||||||
$ident:ident, $variant_ident:ident;
|
$ident:ident, $variant_ident:ident;
|
||||||
$( $before:ident : $bty:ty, )*
|
$( $before:ident : $bty:ty, )*
|
||||||
@@ -59,7 +62,7 @@ macro_rules! __report_gen__scan_before {
|
|||||||
$( $after:ident : $aty:ty, )*
|
$( $after:ident : $aty:ty, )*
|
||||||
;
|
;
|
||||||
) => {
|
) => {
|
||||||
__report_gen__emit_test_specific_by_parse!(
|
__report_gen_emit_test_specific_by_parse!(
|
||||||
$ident, $variant_ident, test_specifier;
|
$ident, $variant_ident, test_specifier;
|
||||||
$( $before : $bty, )* ; $( $after : $aty, )*
|
$( $before : $bty, )* ; $( $after : $aty, )*
|
||||||
);
|
);
|
||||||
@@ -71,7 +74,7 @@ macro_rules! __report_gen__scan_before {
|
|||||||
$name:ident : $ty:ty, $( $after:ident : $aty:ty, )*
|
$name:ident : $ty:ty, $( $after:ident : $aty:ty, )*
|
||||||
;
|
;
|
||||||
) => {
|
) => {
|
||||||
__report_gen__scan_before!(
|
__report_gen_scan_before!(
|
||||||
$ident, $variant_ident;
|
$ident, $variant_ident;
|
||||||
$( $before : $bty, )* $name : $ty,
|
$( $before : $bty, )* $name : $ty,
|
||||||
;
|
;
|
||||||
@@ -97,7 +100,7 @@ macro_rules! __report_gen_for_variant {
|
|||||||
$variant_ident:ident;
|
$variant_ident:ident;
|
||||||
$( $field_ident:ident : $field_ty:ty ),+ $(,)?
|
$( $field_ident:ident : $field_ty:ty ),+ $(,)?
|
||||||
) => {
|
) => {
|
||||||
__report_gen__scan_before!(
|
__report_gen_scan_before!(
|
||||||
$ident, $variant_ident;
|
$ident, $variant_ident;
|
||||||
;
|
;
|
||||||
$( $field_ident : $field_ty, )*
|
$( $field_ident : $field_ty, )*
|
||||||
@@ -106,11 +109,99 @@ macro_rules! __report_gen_for_variant {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! keep_if_doc {
|
macro_rules! __report_gen_emit_execution_specific {
|
||||||
(#[doc = $doc:expr]) => {
|
(
|
||||||
#[doc = $doc]
|
$ident:ident,
|
||||||
|
$variant_ident:ident,
|
||||||
|
$skip_field:ident;
|
||||||
|
$( $bname:ident : $bty:ty, )*
|
||||||
|
;
|
||||||
|
$( $aname:ident : $aty:ty, )*
|
||||||
|
) => {
|
||||||
|
paste::paste! {
|
||||||
|
pub fn [< report_ $variant_ident:snake _event >](
|
||||||
|
&self
|
||||||
|
$(, $bname: impl Into<$bty> )*
|
||||||
|
$(, $aname: impl Into<$aty> )*
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
self.report([< $variant_ident Event >] {
|
||||||
|
$skip_field: self.execution_specifier.clone()
|
||||||
|
$(, $bname: $bname.into() )*
|
||||||
|
$(, $aname: $aname.into() )*
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! __report_gen_emit_execution_specific_by_parse {
|
||||||
|
(
|
||||||
|
$ident:ident,
|
||||||
|
$variant_ident:ident,
|
||||||
|
$skip_field:ident;
|
||||||
|
$( $bname:ident : $bty:ty, )* ; $( $aname:ident : $aty:ty, )*
|
||||||
|
) => {
|
||||||
|
__report_gen_emit_execution_specific!(
|
||||||
|
$ident, $variant_ident, $skip_field;
|
||||||
|
$( $bname : $bty, )* ; $( $aname : $aty, )*
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! __report_gen_scan_before_exec {
|
||||||
|
(
|
||||||
|
$ident:ident, $variant_ident:ident;
|
||||||
|
$( $before:ident : $bty:ty, )*
|
||||||
|
;
|
||||||
|
execution_specifier : $skip_ty:ty,
|
||||||
|
$( $after:ident : $aty:ty, )*
|
||||||
|
;
|
||||||
|
) => {
|
||||||
|
__report_gen_emit_execution_specific_by_parse!(
|
||||||
|
$ident, $variant_ident, execution_specifier;
|
||||||
|
$( $before : $bty, )* ; $( $after : $aty, )*
|
||||||
|
);
|
||||||
|
};
|
||||||
|
(
|
||||||
|
$ident:ident, $variant_ident:ident;
|
||||||
|
$( $before:ident : $bty:ty, )*
|
||||||
|
;
|
||||||
|
$name:ident : $ty:ty, $( $after:ident : $aty:ty, )*
|
||||||
|
;
|
||||||
|
) => {
|
||||||
|
__report_gen_scan_before_exec!(
|
||||||
|
$ident, $variant_ident;
|
||||||
|
$( $before : $bty, )* $name : $ty,
|
||||||
|
;
|
||||||
|
$( $after : $aty, )*
|
||||||
|
;
|
||||||
|
);
|
||||||
|
};
|
||||||
|
(
|
||||||
|
$ident:ident, $variant_ident:ident;
|
||||||
|
$( $before:ident : $bty:ty, )*
|
||||||
|
;
|
||||||
|
;
|
||||||
|
) => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! __report_gen_for_variant_exec {
|
||||||
|
(
|
||||||
|
$ident:ident,
|
||||||
|
$variant_ident:ident;
|
||||||
|
) => {};
|
||||||
|
(
|
||||||
|
$ident:ident,
|
||||||
|
$variant_ident:ident;
|
||||||
|
$( $field_ident:ident : $field_ty:ty ),+ $(,)?
|
||||||
|
) => {
|
||||||
|
__report_gen_scan_before_exec!(
|
||||||
|
$ident, $variant_ident;
|
||||||
|
;
|
||||||
|
$( $field_ident : $field_ty, )*
|
||||||
|
;
|
||||||
|
);
|
||||||
};
|
};
|
||||||
( $($_:tt)* ) => {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines the runner-event which is sent from the test runners to the report aggregator.
|
/// Defines the runner-event which is sent from the test runners to the report aggregator.
|
||||||
@@ -149,6 +240,7 @@ macro_rules! define_event {
|
|||||||
) => {
|
) => {
|
||||||
paste::paste! {
|
paste::paste! {
|
||||||
$(#[$enum_meta])*
|
$(#[$enum_meta])*
|
||||||
|
#[derive(Debug)]
|
||||||
$vis enum $ident {
|
$vis enum $ident {
|
||||||
$(
|
$(
|
||||||
$(#[$variant_meta])*
|
$(#[$variant_meta])*
|
||||||
@@ -157,6 +249,7 @@ macro_rules! define_event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$(
|
$(
|
||||||
|
#[derive(Debug)]
|
||||||
$(#[$variant_meta])*
|
$(#[$variant_meta])*
|
||||||
$vis struct [<$variant_ident Event>] {
|
$vis struct [<$variant_ident Event>] {
|
||||||
$(
|
$(
|
||||||
@@ -204,7 +297,6 @@ macro_rules! define_event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$(
|
$(
|
||||||
keep_if_doc!($(#[$variant_meta])*);
|
|
||||||
pub fn [< report_ $variant_ident:snake _event >](&self, $($field_ident: impl Into<$field_ty>),*) -> anyhow::Result<()> {
|
pub fn [< report_ $variant_ident:snake _event >](&self, $($field_ident: impl Into<$field_ty>),*) -> anyhow::Result<()> {
|
||||||
self.report([< $variant_ident Event >] {
|
self.report([< $variant_ident Event >] {
|
||||||
$($field_ident: $field_ident.into()),*
|
$($field_ident: $field_ident.into()),*
|
||||||
@@ -221,6 +313,21 @@ macro_rules! define_event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl [< $ident TestSpecificReporter >] {
|
impl [< $ident TestSpecificReporter >] {
|
||||||
|
pub fn execution_specific_reporter(
|
||||||
|
&self,
|
||||||
|
node_id: impl Into<usize>,
|
||||||
|
node_designation: impl Into<$crate::common::NodeDesignation>
|
||||||
|
) -> [< $ident ExecutionSpecificReporter >] {
|
||||||
|
[< $ident ExecutionSpecificReporter >] {
|
||||||
|
reporter: self.reporter.clone(),
|
||||||
|
execution_specifier: Arc::new($crate::common::ExecutionSpecifier {
|
||||||
|
test_specifier: self.test_specifier.clone(),
|
||||||
|
node_id: node_id.into(),
|
||||||
|
node_designation: node_designation.into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn report(&self, event: impl Into<$ident>) -> anyhow::Result<()> {
|
fn report(&self, event: impl Into<$ident>) -> anyhow::Result<()> {
|
||||||
self.reporter.report(event)
|
self.reporter.report(event)
|
||||||
}
|
}
|
||||||
@@ -229,6 +336,23 @@ macro_rules! define_event {
|
|||||||
__report_gen_for_variant! { $ident, $variant_ident; $( $field_ident : $field_ty ),* }
|
__report_gen_for_variant! { $ident, $variant_ident; $( $field_ident : $field_ty ),* }
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A reporter that's tied to a specific execution of the test case such as execution on
|
||||||
|
/// a specific node like the leader or follower.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct [< $ident ExecutionSpecificReporter >] {
|
||||||
|
$vis reporter: [< $ident Reporter >],
|
||||||
|
$vis execution_specifier: std::sync::Arc<$crate::common::ExecutionSpecifier>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl [< $ident ExecutionSpecificReporter >] {
|
||||||
|
fn report(&self, event: impl Into<$ident>) -> anyhow::Result<()> {
|
||||||
|
self.reporter.report(event)
|
||||||
|
}
|
||||||
|
$(
|
||||||
|
__report_gen_for_variant_exec! { $ident, $variant_ident; $( $field_ident : $field_ty ),* }
|
||||||
|
)*
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -303,7 +427,79 @@ define_event! {
|
|||||||
platform: TestingPlatform,
|
platform: TestingPlatform,
|
||||||
/// The connection string of the node.
|
/// The connection string of the node.
|
||||||
connection_string: String,
|
connection_string: String,
|
||||||
}
|
},
|
||||||
|
/// An event emitted by the runners when the compilation of the contracts has succeeded
|
||||||
|
/// on the pre-link contracts.
|
||||||
|
PreLinkContractsCompilationSucceeded {
|
||||||
|
/// A specifier for the execution that's taking place.
|
||||||
|
execution_specifier: Arc<ExecutionSpecifier>,
|
||||||
|
/// The version of the compiler used to compile the contracts.
|
||||||
|
compiler_version: Version,
|
||||||
|
/// The path of the compiler used to compile the contracts.
|
||||||
|
compiler_path: PathBuf,
|
||||||
|
/// A flag of whether the contract bytecode and ABI were cached or if they were compiled
|
||||||
|
/// anew.
|
||||||
|
is_cached: bool,
|
||||||
|
/// The input provided to the compiler - this is optional and not provided if the
|
||||||
|
/// contracts were obtained from the cache.
|
||||||
|
compiler_input: Option<CompilerInput>,
|
||||||
|
/// The output of the compiler.
|
||||||
|
compiler_output: CompilerOutput
|
||||||
|
},
|
||||||
|
/// An event emitted by the runners when the compilation of the contracts has succeeded
|
||||||
|
/// on the post-link contracts.
|
||||||
|
PostLinkContractsCompilationSucceeded {
|
||||||
|
/// A specifier for the execution that's taking place.
|
||||||
|
execution_specifier: Arc<ExecutionSpecifier>,
|
||||||
|
/// The version of the compiler used to compile the contracts.
|
||||||
|
compiler_version: Version,
|
||||||
|
/// The path of the compiler used to compile the contracts.
|
||||||
|
compiler_path: PathBuf,
|
||||||
|
/// A flag of whether the contract bytecode and ABI were cached or if they were compiled
|
||||||
|
/// anew.
|
||||||
|
is_cached: bool,
|
||||||
|
/// The input provided to the compiler - this is optional and not provided if the
|
||||||
|
/// contracts were obtained from the cache.
|
||||||
|
compiler_input: Option<CompilerInput>,
|
||||||
|
/// The output of the compiler.
|
||||||
|
compiler_output: CompilerOutput
|
||||||
|
},
|
||||||
|
/// An event emitted by the runners when the compilation of the pre-link contract has
|
||||||
|
/// failed.
|
||||||
|
PreLinkContractsCompilationFailed {
|
||||||
|
/// A specifier for the execution that's taking place.
|
||||||
|
execution_specifier: Arc<ExecutionSpecifier>,
|
||||||
|
/// The version of the compiler used to compile the contracts.
|
||||||
|
compiler_version: Option<Version>,
|
||||||
|
/// The path of the compiler used to compile the contracts.
|
||||||
|
compiler_path: Option<PathBuf>,
|
||||||
|
/// The input provided to the compiler - this is optional and not provided if the
|
||||||
|
/// contracts were obtained from the cache.
|
||||||
|
compiler_input: Option<CompilerInput>,
|
||||||
|
/// The failure reason.
|
||||||
|
reason: String,
|
||||||
|
},
|
||||||
|
/// An event emitted by the runners when the compilation of the post-link contract has
|
||||||
|
/// failed.
|
||||||
|
PostLinkContractsCompilationFailed {
|
||||||
|
/// A specifier for the execution that's taking place.
|
||||||
|
execution_specifier: Arc<ExecutionSpecifier>,
|
||||||
|
/// The version of the compiler used to compile the contracts.
|
||||||
|
compiler_version: Option<Version>,
|
||||||
|
/// The path of the compiler used to compile the contracts.
|
||||||
|
compiler_path: Option<PathBuf>,
|
||||||
|
/// The input provided to the compiler - this is optional and not provided if the
|
||||||
|
/// contracts were obtained from the cache.
|
||||||
|
compiler_input: Option<CompilerInput>,
|
||||||
|
/// The failure reason.
|
||||||
|
reason: String,
|
||||||
|
},
|
||||||
|
LibrariesDeployed {
|
||||||
|
/// A specifier for the execution that's taking place.
|
||||||
|
execution_specifier: Arc<ExecutionSpecifier>,
|
||||||
|
/// The addresses of the libraries that were deployed.
|
||||||
|
libraries: BTreeMap<ContractInstance, Address>
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,3 +514,4 @@ impl RunnerEventReporter {
|
|||||||
|
|
||||||
pub type Reporter = RunnerEventReporter;
|
pub type Reporter = RunnerEventReporter;
|
||||||
pub type TestSpecificReporter = RunnerEventTestSpecificReporter;
|
pub type TestSpecificReporter = RunnerEventTestSpecificReporter;
|
||||||
|
pub type ExecutionSpecificReporter = RunnerEventExecutionSpecificReporter;
|
||||||
|
|||||||
Reference in New Issue
Block a user