Include contract compilation information in report

This commit is contained in:
Omar Abdulla
2025-08-25 05:02:19 +03:00
parent 7d87cb9ee8
commit 3d198f4e71
9 changed files with 682 additions and 46 deletions
+92 -10
View File
@@ -9,7 +9,7 @@ use std::{
use futures::FutureExt;
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_format::metadata::{ContractIdent, ContractInstance, Metadata};
@@ -35,6 +35,7 @@ impl CachedCompiler {
}
/// Compiles or gets the compilation artifacts from the cache.
#[allow(clippy::too_many_arguments)]
#[instrument(
level = "debug",
skip_all,
@@ -52,6 +53,19 @@ impl CachedCompiler {
mode: &Mode,
config: &Arguments,
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)> {
static CACHE_KEY_LOCK: Lazy<RwLock<HashMap<CacheKey, Arc<Mutex<()>>>>> =
Lazy::new(Default::default);
@@ -61,10 +75,21 @@ impl CachedCompiler {
config,
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())
.version()
.await?;
.await
.inspect_err(|err| {
compilation_failure_report_callback(
None,
Some(compiler_path.clone()),
None,
err.to_string(),
)
})?;
let cache_key = CacheKey {
platform_key: P::config_id().to_string(),
@@ -74,13 +99,19 @@ impl CachedCompiler {
};
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::<P>(
metadata.directory()?,
compiler_path,
compiler_version,
metadata.files_to_compile()?,
mode,
deployed_libraries,
compilation_success_report_callback,
compilation_failure_report_callback,
)
.map(|compilation_result| compilation_result.map(CacheValue::new))
.await
@@ -125,10 +156,19 @@ impl CachedCompiler {
};
let _guard = mutex.lock().await;
self.0
.get_or_insert_with(&cache_key, compilation_callback)
.await
.map(|value| value.compiler_output)?
match self.0.get(&cache_key).await {
Some(cache_value) => {
compilation_success_report_callback(
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>(
metadata_directory: impl AsRef<Path>,
compiler_path: impl AsRef<Path>,
compiler_version: Version,
mut files_to_compile: impl Iterator<Item = PathBuf>,
mode: &Mode,
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> {
let all_sources_in_dir = FilesWithExtensionIterator::new(metadata_directory.as_ref())
.with_allowed_extension("sol")
.with_use_cached_fs(true)
.collect::<Vec<_>>();
Compiler::<P::Compiler>::new()
let compiler = Compiler::<P::Compiler>::new()
.with_allow_path(metadata_directory)
// Handling the modes
.with_optimization(mode.optimize_setting)
@@ -156,6 +211,14 @@ async fn compile_contracts<P: Platform>(
// 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,
err.to_string(),
)
})?
// Adding the deployed libraries to the compiler.
.then(|compiler| {
@@ -171,9 +234,28 @@ async fn compile_contracts<P: Platform>(
.fold(compiler, |compiler, (ident, address, path)| {
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
.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 {
+130 -13
View File
@@ -1,7 +1,7 @@
mod cached_compiler;
use std::{
collections::HashMap,
collections::{BTreeMap, HashMap},
io::{BufWriter, Write, stderr},
path::Path,
sync::{Arc, LazyLock},
@@ -19,10 +19,11 @@ use futures::{Stream, StreamExt};
use indexmap::IndexMap;
use revive_dt_node_interaction::EthereumNode;
use revive_dt_report::{
ReportAggregator, Reporter, ReporterEvent, TestCaseStatus, TestSpecificReporter, TestSpecifier,
NodeDesignation, ReportAggregator, Reporter, ReporterEvent, TestCaseStatus,
TestSpecificReporter, TestSpecifier,
};
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_appender::non_blocking::WorkerGuard;
use tracing_subscriber::{EnvFilter, FmtSubscriber};
@@ -181,13 +182,11 @@ where
L::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);
let tests = prepare_tests::<L, F>(args, metadata_files, reporter.clone());
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?;
Ok(())
@@ -441,6 +440,8 @@ where
L::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 follower_nodes = Arc::new(NodePool::<F::Blockchain>::new(args)?);
let number_concurrent_tasks = args.number_of_concurrent_tasks();
@@ -510,7 +511,10 @@ where
#[allow(clippy::uninlined_format_args)]
#[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();
const GREEN: &str = "\x1B[32m";
@@ -606,6 +610,13 @@ where
L::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 (
(
CompilerOutput {
@@ -625,14 +636,56 @@ where
test.metadata_file_path,
&test.mode,
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>(
test.metadata,
test.metadata_file_path,
&test.mode,
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 (
(
@@ -760,14 +831,56 @@ where
test.metadata_file_path,
&test.mode,
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>(
test.metadata,
test.metadata_file_path,
&test.mode,
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,
config,
None,
|_, _, _, _, _| {},
|_, _, _, _| {},
)
.await;
}
@@ -860,6 +975,8 @@ async fn compile_corpus(
&mode,
config,
None,
|_, _, _, _, _| {},
|_, _, _, _| {},
)
.await;
}