mirror of
https://github.com/pezkuwichain/revive-differential-tests.git
synced 2026-06-12 03:01:12 +00:00
fix
This commit is contained in:
@@ -206,9 +206,7 @@ where
|
||||
"Deployed library"
|
||||
);
|
||||
|
||||
let library_address = receipt
|
||||
.contract_address
|
||||
.expect("Failed to deploy the library");
|
||||
let library_address = receipt.contract_address.expect("Failed to deploy the library");
|
||||
|
||||
deployed_libraries.get_or_insert_default().insert(
|
||||
library_instance.clone(),
|
||||
@@ -236,10 +234,8 @@ where
|
||||
})
|
||||
.context("Failed to compile the post-link contracts")?;
|
||||
|
||||
self.execution_state = ExecutionState::new(
|
||||
compiler_output.contracts,
|
||||
deployed_libraries.unwrap_or_default(),
|
||||
);
|
||||
self.execution_state =
|
||||
ExecutionState::new(compiler_output.contracts, deployed_libraries.unwrap_or_default());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -325,11 +321,7 @@ where
|
||||
) -> Result<HashMap<ContractInstance, TransactionReceipt>> {
|
||||
let mut instances_we_must_deploy = IndexMap::<ContractInstance, bool>::new();
|
||||
for instance in step.find_all_contract_instances().into_iter() {
|
||||
if !self
|
||||
.execution_state
|
||||
.deployed_contracts
|
||||
.contains_key(&instance)
|
||||
{
|
||||
if !self.execution_state.deployed_contracts.contains_key(&instance) {
|
||||
instances_we_must_deploy.entry(instance).or_insert(false);
|
||||
}
|
||||
}
|
||||
@@ -341,15 +333,11 @@ where
|
||||
let mut receipts = HashMap::new();
|
||||
for (instance, deploy_with_constructor_arguments) in instances_we_must_deploy.into_iter() {
|
||||
let calldata = deploy_with_constructor_arguments.then_some(&step.calldata);
|
||||
let value = deploy_with_constructor_arguments
|
||||
.then_some(step.value)
|
||||
.flatten();
|
||||
let value = deploy_with_constructor_arguments.then_some(step.value).flatten();
|
||||
|
||||
let caller = {
|
||||
let context = self.default_resolution_context();
|
||||
step.caller
|
||||
.resolve_address(self.resolver.as_ref(), context)
|
||||
.await?
|
||||
step.caller.resolve_address(self.resolver.as_ref(), context).await?
|
||||
};
|
||||
if let (_, _, Some(receipt)) = self
|
||||
.get_or_deploy_contract_instance(&instance, caller, calldata, value)
|
||||
@@ -424,18 +412,13 @@ where
|
||||
};
|
||||
|
||||
// Handling the return data variable assignments.
|
||||
for (variable_name, output_word) in assignments.return_data.iter().zip(
|
||||
tracing_result
|
||||
.output
|
||||
.as_ref()
|
||||
.unwrap_or_default()
|
||||
.to_vec()
|
||||
.chunks(32),
|
||||
) {
|
||||
for (variable_name, output_word) in assignments
|
||||
.return_data
|
||||
.iter()
|
||||
.zip(tracing_result.output.as_ref().unwrap_or_default().to_vec().chunks(32))
|
||||
{
|
||||
let value = U256::from_be_slice(output_word);
|
||||
self.execution_state
|
||||
.variables
|
||||
.insert(variable_name.clone(), value);
|
||||
self.execution_state.variables.insert(variable_name.clone(), value);
|
||||
tracing::info!(
|
||||
variable_name,
|
||||
variable_value = hex::encode(value.to_be_bytes::<32>()),
|
||||
@@ -508,9 +491,8 @@ where
|
||||
})
|
||||
.context("Failed to send message on the watcher's tx")?;
|
||||
|
||||
let res = futures::future::try_join_all(tasks)
|
||||
.await
|
||||
.context("Repetition execution failed")?;
|
||||
let res =
|
||||
futures::future::try_join_all(tasks).await.context("Repetition execution failed")?;
|
||||
Ok(res.into_iter().sum())
|
||||
}
|
||||
|
||||
@@ -533,9 +515,7 @@ where
|
||||
let account = private_key.address();
|
||||
let variable = U256::from_be_slice(account.0.as_slice());
|
||||
|
||||
self.execution_state
|
||||
.variables
|
||||
.insert(variable_name.to_string(), variable);
|
||||
self.execution_state.variables.insert(variable_name.to_string(), variable);
|
||||
|
||||
Ok(1)
|
||||
}
|
||||
@@ -560,10 +540,8 @@ where
|
||||
calldata: Option<&Calldata>,
|
||||
value: Option<EtherValue>,
|
||||
) -> Result<(Address, JsonAbi, Option<TransactionReceipt>)> {
|
||||
if let Some((_, address, abi)) = self
|
||||
.execution_state
|
||||
.deployed_contracts
|
||||
.get(contract_instance)
|
||||
if let Some((_, address, abi)) =
|
||||
self.execution_state.deployed_contracts.get(contract_instance)
|
||||
{
|
||||
info!(
|
||||
|
||||
@@ -606,16 +584,9 @@ where
|
||||
let Some(ContractPathAndIdent {
|
||||
contract_source_path,
|
||||
contract_ident,
|
||||
}) = self
|
||||
.test_definition
|
||||
.metadata
|
||||
.contract_sources()?
|
||||
.remove(contract_instance)
|
||||
}) = self.test_definition.metadata.contract_sources()?.remove(contract_instance)
|
||||
else {
|
||||
anyhow::bail!(
|
||||
"Contract source not found for instance {:?}",
|
||||
contract_instance
|
||||
)
|
||||
anyhow::bail!("Contract source not found for instance {:?}", contract_instance)
|
||||
};
|
||||
|
||||
let Some((code, abi)) = self
|
||||
@@ -625,10 +596,7 @@ where
|
||||
.and_then(|source_file_contracts| source_file_contracts.get(contract_ident.as_ref()))
|
||||
.cloned()
|
||||
else {
|
||||
anyhow::bail!(
|
||||
"Failed to find information for contract {:?}",
|
||||
contract_instance
|
||||
)
|
||||
anyhow::bail!("Failed to find information for contract {:?}", contract_instance)
|
||||
};
|
||||
|
||||
let mut code = match alloy::hex::decode(&code) {
|
||||
@@ -680,10 +648,9 @@ where
|
||||
.reporter
|
||||
.report_contract_deployed_event(contract_instance.clone(), address)?;
|
||||
|
||||
self.execution_state.deployed_contracts.insert(
|
||||
contract_instance.clone(),
|
||||
(contract_ident, address, abi.clone()),
|
||||
);
|
||||
self.execution_state
|
||||
.deployed_contracts
|
||||
.insert(contract_instance.clone(), (contract_ident, address, abi.clone()));
|
||||
|
||||
Ok((address, abi, receipt))
|
||||
}
|
||||
@@ -696,9 +663,7 @@ where
|
||||
match step_address {
|
||||
StepAddress::Address(address) => Ok(*address),
|
||||
StepAddress::ResolvableAddress(resolvable) => {
|
||||
let Some(instance) = resolvable
|
||||
.strip_suffix(".address")
|
||||
.map(ContractInstance::new)
|
||||
let Some(instance) = resolvable.strip_suffix(".address").map(ContractInstance::new)
|
||||
else {
|
||||
bail!("Not an address variable");
|
||||
};
|
||||
@@ -736,15 +701,15 @@ where
|
||||
transaction: TransactionRequest,
|
||||
) -> anyhow::Result<TransactionReceipt> {
|
||||
let node = self.platform_information.node;
|
||||
let transaction_hash = node
|
||||
.submit_transaction(transaction)
|
||||
.await
|
||||
.context("Failed to submit transaction")?;
|
||||
let transaction_hash =
|
||||
node.submit_transaction(transaction).await.context("Failed to submit transaction")?;
|
||||
Span::current().record("transaction_hash", display(transaction_hash));
|
||||
|
||||
info!("Submitted transaction");
|
||||
self.watcher_tx
|
||||
.send(WatcherEvent::SubmittedTransaction { transaction_hash })
|
||||
.send(WatcherEvent::SubmittedTransaction {
|
||||
transaction_hash,
|
||||
})
|
||||
.context("Failed to send the transaction hash to the watcher")?;
|
||||
|
||||
info!("Starting to poll for transaction receipt");
|
||||
|
||||
@@ -44,12 +44,8 @@ pub async fn handle_differential_benchmarks(
|
||||
info!(len = metadata_files.len(), "Discovered metadata files");
|
||||
|
||||
// Discover the list of platforms that the tests should run on based on the context.
|
||||
let platforms = context
|
||||
.platforms
|
||||
.iter()
|
||||
.copied()
|
||||
.map(Into::<&dyn Platform>::into)
|
||||
.collect::<Vec<_>>();
|
||||
let platforms =
|
||||
context.platforms.iter().copied().map(Into::<&dyn Platform>::into).collect::<Vec<_>>();
|
||||
|
||||
// Starting the nodes of the various platforms specified in the context. Note that we use the
|
||||
// node pool since it contains all of the code needed to spawn nodes from A to Z and therefore
|
||||
@@ -96,13 +92,8 @@ pub async fn handle_differential_benchmarks(
|
||||
// Creating the objects that will be shared between the various runs. The cached compiler is the
|
||||
// only one at the current moment of time that's safe to share between runs.
|
||||
let cached_compiler = CachedCompiler::new(
|
||||
context
|
||||
.working_directory
|
||||
.as_path()
|
||||
.join("compilation_cache"),
|
||||
context
|
||||
.compilation_configuration
|
||||
.invalidate_compilation_cache,
|
||||
context.working_directory.as_path().join("compilation_cache"),
|
||||
context.compilation_configuration.invalidate_compilation_cache,
|
||||
)
|
||||
.await
|
||||
.map(Arc::new)
|
||||
@@ -161,9 +152,7 @@ pub async fn handle_differential_benchmarks(
|
||||
watcher.run(),
|
||||
driver.execute_all().inspect(|_| {
|
||||
info!("All transactions submitted - driver completed execution");
|
||||
watcher_tx
|
||||
.send(WatcherEvent::AllTransactionsSubmitted)
|
||||
.unwrap()
|
||||
watcher_tx.send(WatcherEvent::AllTransactionsSubmitted).unwrap()
|
||||
}),
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -80,12 +80,13 @@ impl Watcher {
|
||||
// Subsequent repetition starts are ignored since certain workloads can
|
||||
// contain nested repetitions and therefore there's no use in doing any
|
||||
// action if the repetitions are nested.
|
||||
WatcherEvent::RepetitionStartEvent { .. } => {}
|
||||
WatcherEvent::SubmittedTransaction { transaction_hash } => {
|
||||
watch_for_transaction_hashes
|
||||
.write()
|
||||
.await
|
||||
.insert(transaction_hash);
|
||||
WatcherEvent::RepetitionStartEvent {
|
||||
..
|
||||
} => {}
|
||||
WatcherEvent::SubmittedTransaction {
|
||||
transaction_hash,
|
||||
} => {
|
||||
watch_for_transaction_hashes.write().await.insert(transaction_hash);
|
||||
}
|
||||
WatcherEvent::AllTransactionsSubmitted => {
|
||||
*all_transactions_submitted.write().await = true;
|
||||
@@ -151,15 +152,8 @@ impl Watcher {
|
||||
use std::io::Write;
|
||||
|
||||
let mut stderr = std::io::stderr().lock();
|
||||
writeln!(
|
||||
stderr,
|
||||
"Watcher information for {}",
|
||||
self.platform_identifier
|
||||
)?;
|
||||
writeln!(
|
||||
stderr,
|
||||
"block_number,block_timestamp,mined_gas,block_gas_limit,tx_count"
|
||||
)?;
|
||||
writeln!(stderr, "Watcher information for {}", self.platform_identifier)?;
|
||||
writeln!(stderr, "block_number,block_timestamp,mined_gas,block_gas_limit,tx_count")?;
|
||||
for block in mined_blocks_information {
|
||||
writeln!(
|
||||
stderr,
|
||||
|
||||
@@ -76,7 +76,9 @@ impl<'a> Driver<'a, StepsIterator> {
|
||||
.into_iter()
|
||||
.collect::<BTreeMap<_, _>>();
|
||||
|
||||
Ok(Self { platform_drivers })
|
||||
Ok(Self {
|
||||
platform_drivers,
|
||||
})
|
||||
}
|
||||
|
||||
async fn create_platform_driver(
|
||||
@@ -112,9 +114,7 @@ impl<'a> Driver<'a, StepsIterator> {
|
||||
pub async fn execute_all(mut self) -> Result<usize> {
|
||||
let platform_drivers = std::mem::take(&mut self.platform_drivers);
|
||||
let results = futures::future::try_join_all(
|
||||
platform_drivers
|
||||
.into_values()
|
||||
.map(|driver| driver.execute_all()),
|
||||
platform_drivers.into_values().map(|driver| driver.execute_all()),
|
||||
)
|
||||
.await
|
||||
.context("Failed to execute all of the steps on the driver")?;
|
||||
@@ -210,12 +210,8 @@ where
|
||||
)
|
||||
})
|
||||
.context("Failed to get the contract instances from the metadata file")?;
|
||||
for library_instance in test_definition
|
||||
.metadata
|
||||
.libraries
|
||||
.iter()
|
||||
.flatten()
|
||||
.flat_map(|(_, map)| map.values())
|
||||
for library_instance in
|
||||
test_definition.metadata.libraries.iter().flatten().flat_map(|(_, map)| map.values())
|
||||
{
|
||||
let ContractPathAndIdent {
|
||||
contract_source_path: library_source_path,
|
||||
@@ -252,11 +248,8 @@ where
|
||||
TransactionRequest::default().from(deployer_address),
|
||||
code,
|
||||
);
|
||||
let receipt = platform_information
|
||||
.node
|
||||
.execute_transaction(tx)
|
||||
.await
|
||||
.inspect_err(|err| {
|
||||
let receipt =
|
||||
platform_information.node.execute_transaction(tx).await.inspect_err(|err| {
|
||||
error!(
|
||||
?err,
|
||||
%library_instance,
|
||||
@@ -265,9 +258,7 @@ where
|
||||
)
|
||||
})?;
|
||||
|
||||
let library_address = receipt
|
||||
.contract_address
|
||||
.expect("Failed to deploy the library");
|
||||
let library_address = receipt.contract_address.expect("Failed to deploy the library");
|
||||
|
||||
deployed_libraries.get_or_insert_default().insert(
|
||||
library_instance.clone(),
|
||||
@@ -295,10 +286,7 @@ where
|
||||
})
|
||||
.context("Failed to compile the post-link contracts")?;
|
||||
|
||||
Ok(ExecutionState::new(
|
||||
compiler_output.contracts,
|
||||
deployed_libraries.unwrap_or_default(),
|
||||
))
|
||||
Ok(ExecutionState::new(compiler_output.contracts, deployed_libraries.unwrap_or_default()))
|
||||
}
|
||||
// endregion:Constructors & Initialization
|
||||
|
||||
@@ -392,11 +380,7 @@ where
|
||||
) -> Result<HashMap<ContractInstance, TransactionReceipt>> {
|
||||
let mut instances_we_must_deploy = IndexMap::<ContractInstance, bool>::new();
|
||||
for instance in step.find_all_contract_instances().into_iter() {
|
||||
if !self
|
||||
.execution_state
|
||||
.deployed_contracts
|
||||
.contains_key(&instance)
|
||||
{
|
||||
if !self.execution_state.deployed_contracts.contains_key(&instance) {
|
||||
instances_we_must_deploy.entry(instance).or_insert(false);
|
||||
}
|
||||
}
|
||||
@@ -408,16 +392,13 @@ where
|
||||
let mut receipts = HashMap::new();
|
||||
for (instance, deploy_with_constructor_arguments) in instances_we_must_deploy.into_iter() {
|
||||
let calldata = deploy_with_constructor_arguments.then_some(&step.calldata);
|
||||
let value = deploy_with_constructor_arguments
|
||||
.then_some(step.value)
|
||||
.flatten();
|
||||
let value = deploy_with_constructor_arguments.then_some(step.value).flatten();
|
||||
|
||||
let caller = {
|
||||
let context = self.default_resolution_context();
|
||||
let resolver = self.platform_information.node.resolver().await?;
|
||||
step.caller
|
||||
.resolve_address(resolver.as_ref(), context)
|
||||
.await?
|
||||
let resolved = step.caller.resolve_address(resolver.as_ref(), context).await?;
|
||||
self.platform_information.node.resolve_signer_or_default(resolved)
|
||||
};
|
||||
if let (_, _, Some(receipt)) = self
|
||||
.get_or_deploy_contract_instance(&instance, caller, calldata, value)
|
||||
@@ -445,7 +426,7 @@ where
|
||||
.context("Failed to find deployment receipt for constructor call"),
|
||||
Method::Fallback | Method::FunctionName(_) => {
|
||||
let resolver = self.platform_information.node.resolver().await?;
|
||||
let tx = match step
|
||||
let mut tx = match step
|
||||
.as_transaction(resolver.as_ref(), self.default_resolution_context())
|
||||
.await
|
||||
{
|
||||
@@ -455,6 +436,11 @@ where
|
||||
}
|
||||
};
|
||||
|
||||
// Resolve the signer to ensure we use an address that has keys
|
||||
if let Some(from) = tx.from {
|
||||
tx.from = Some(self.platform_information.node.resolve_signer_or_default(from));
|
||||
}
|
||||
|
||||
self.platform_information.node.execute_transaction(tx).await
|
||||
}
|
||||
}
|
||||
@@ -503,18 +489,13 @@ where
|
||||
};
|
||||
|
||||
// Handling the return data variable assignments.
|
||||
for (variable_name, output_word) in assignments.return_data.iter().zip(
|
||||
tracing_result
|
||||
.output
|
||||
.as_ref()
|
||||
.unwrap_or_default()
|
||||
.to_vec()
|
||||
.chunks(32),
|
||||
) {
|
||||
for (variable_name, output_word) in assignments
|
||||
.return_data
|
||||
.iter()
|
||||
.zip(tracing_result.output.as_ref().unwrap_or_default().to_vec().chunks(32))
|
||||
{
|
||||
let value = U256::from_be_slice(output_word);
|
||||
self.execution_state
|
||||
.variables
|
||||
.insert(variable_name.clone(), value);
|
||||
self.execution_state.variables.insert(variable_name.clone(), value);
|
||||
tracing::info!(
|
||||
variable_name,
|
||||
variable_value = hex::encode(value.to_be_bytes::<32>()),
|
||||
@@ -546,7 +527,10 @@ where
|
||||
expected: Some(Expected::ExpectedMany(expected)),
|
||||
..
|
||||
} => expected.clone(),
|
||||
FunctionCallStep { expected: None, .. } => vec![ExpectedOutput::new().with_success()],
|
||||
FunctionCallStep {
|
||||
expected: None,
|
||||
..
|
||||
} => vec![ExpectedOutput::new().with_success()],
|
||||
};
|
||||
|
||||
// This is a bit of a special case and we have to support it separately on it's own. If it's
|
||||
@@ -562,8 +546,7 @@ where
|
||||
|
||||
futures::stream::iter(expectations.into_iter().map(Ok))
|
||||
.try_for_each_concurrent(None, |expectation| async {
|
||||
self.handle_function_call_assertion_item(receipt, tracing_result, expectation)
|
||||
.await
|
||||
self.handle_function_call_assertion_item(receipt, tracing_result, expectation).await
|
||||
})
|
||||
.await
|
||||
}
|
||||
@@ -664,11 +647,8 @@ where
|
||||
}
|
||||
|
||||
// Handling the topics assertion.
|
||||
for (expected, actual) in expected_event
|
||||
.topics
|
||||
.as_slice()
|
||||
.iter()
|
||||
.zip(actual_event.topics())
|
||||
for (expected, actual) in
|
||||
expected_event.topics.as_slice().iter().zip(actual_event.topics())
|
||||
{
|
||||
let expected = Calldata::new_compound([expected]);
|
||||
if !expected
|
||||
@@ -764,11 +744,8 @@ where
|
||||
.resolve_address(resolver.as_ref(), self.default_resolution_context())
|
||||
.await?;
|
||||
|
||||
let storage = self
|
||||
.platform_information
|
||||
.node
|
||||
.latest_state_proof(address, Default::default())
|
||||
.await?;
|
||||
let storage =
|
||||
self.platform_information.node.latest_state_proof(address, Default::default()).await?;
|
||||
let is_empty = storage.storage_hash == EMPTY_ROOT_HASH;
|
||||
|
||||
let expected = step.is_storage_empty;
|
||||
@@ -818,9 +795,8 @@ where
|
||||
})
|
||||
.map(|driver| driver.execute_all())
|
||||
.collect::<Vec<_>>();
|
||||
let res = futures::future::try_join_all(tasks)
|
||||
.await
|
||||
.context("Repetition execution failed")?;
|
||||
let res =
|
||||
futures::future::try_join_all(tasks).await.context("Repetition execution failed")?;
|
||||
Ok(res.first().copied().unwrap_or_default())
|
||||
}
|
||||
|
||||
@@ -838,9 +814,7 @@ where
|
||||
let account = private_key.address();
|
||||
let variable = U256::from_be_slice(account.0.as_slice());
|
||||
|
||||
self.execution_state
|
||||
.variables
|
||||
.insert(variable_name.to_string(), variable);
|
||||
self.execution_state.variables.insert(variable_name.to_string(), variable);
|
||||
|
||||
Ok(1)
|
||||
}
|
||||
@@ -863,10 +837,8 @@ where
|
||||
calldata: Option<&Calldata>,
|
||||
value: Option<EtherValue>,
|
||||
) -> Result<(Address, JsonAbi, Option<TransactionReceipt>)> {
|
||||
if let Some((_, address, abi)) = self
|
||||
.execution_state
|
||||
.deployed_contracts
|
||||
.get(contract_instance)
|
||||
if let Some((_, address, abi)) =
|
||||
self.execution_state.deployed_contracts.get(contract_instance)
|
||||
{
|
||||
info!(
|
||||
|
||||
@@ -876,6 +848,7 @@ where
|
||||
Ok((*address, abi.clone(), None))
|
||||
} else {
|
||||
info!("Contract instance requires deployment.");
|
||||
|
||||
let (address, abi, receipt) = self
|
||||
.deploy_contract(contract_instance, deployer, calldata, value)
|
||||
.await
|
||||
@@ -907,16 +880,9 @@ where
|
||||
let Some(ContractPathAndIdent {
|
||||
contract_source_path,
|
||||
contract_ident,
|
||||
}) = self
|
||||
.test_definition
|
||||
.metadata
|
||||
.contract_sources()?
|
||||
.remove(contract_instance)
|
||||
}) = self.test_definition.metadata.contract_sources()?.remove(contract_instance)
|
||||
else {
|
||||
anyhow::bail!(
|
||||
"Contract source not found for instance {:?}",
|
||||
contract_instance
|
||||
)
|
||||
anyhow::bail!("Contract source not found for instance {:?}", contract_instance)
|
||||
};
|
||||
|
||||
let Some((code, abi)) = self
|
||||
@@ -926,10 +892,7 @@ where
|
||||
.and_then(|source_file_contracts| source_file_contracts.get(contract_ident.as_ref()))
|
||||
.cloned()
|
||||
else {
|
||||
anyhow::bail!(
|
||||
"Failed to find information for contract {:?}",
|
||||
contract_instance
|
||||
)
|
||||
anyhow::bail!("Failed to find information for contract {:?}", contract_instance)
|
||||
};
|
||||
|
||||
let mut code = match alloy::hex::decode(&code) {
|
||||
@@ -947,13 +910,13 @@ where
|
||||
|
||||
if let Some(calldata) = calldata {
|
||||
let resolver = self.platform_information.node.resolver().await?;
|
||||
let calldata = calldata
|
||||
.calldata(resolver.as_ref(), self.default_resolution_context())
|
||||
.await?;
|
||||
let calldata =
|
||||
calldata.calldata(resolver.as_ref(), self.default_resolution_context()).await?;
|
||||
code.extend(calldata);
|
||||
}
|
||||
|
||||
let tx = {
|
||||
let deployer = self.platform_information.node.resolve_signer_or_default(deployer);
|
||||
let tx = TransactionRequest::default().from(deployer);
|
||||
let tx = match value {
|
||||
Some(ref value) => tx.value(value.into_inner()),
|
||||
@@ -982,10 +945,9 @@ where
|
||||
.reporter
|
||||
.report_contract_deployed_event(contract_instance.clone(), address)?;
|
||||
|
||||
self.execution_state.deployed_contracts.insert(
|
||||
contract_instance.clone(),
|
||||
(contract_ident, address, abi.clone()),
|
||||
);
|
||||
self.execution_state
|
||||
.deployed_contracts
|
||||
.insert(contract_instance.clone(), (contract_ident, address, abi.clone()));
|
||||
|
||||
Ok((address, abi, receipt))
|
||||
}
|
||||
@@ -998,9 +960,7 @@ where
|
||||
match step_address {
|
||||
StepAddress::Address(address) => Ok(*address),
|
||||
StepAddress::ResolvableAddress(resolvable) => {
|
||||
let Some(instance) = resolvable
|
||||
.strip_suffix(".address")
|
||||
.map(ContractInstance::new)
|
||||
let Some(instance) = resolvable.strip_suffix(".address").map(ContractInstance::new)
|
||||
else {
|
||||
bail!("Not an address variable");
|
||||
};
|
||||
|
||||
@@ -7,10 +7,10 @@ use std::{
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use crate::Platform;
|
||||
use anyhow::Context as _;
|
||||
use futures::{FutureExt, StreamExt};
|
||||
use revive_dt_common::types::PrivateKeyAllocator;
|
||||
use crate::Platform;
|
||||
use tokio::sync::{Mutex, RwLock, Semaphore};
|
||||
use tracing::{Instrument, error, info, info_span, instrument};
|
||||
|
||||
@@ -37,12 +37,8 @@ pub async fn handle_differential_tests(
|
||||
info!(len = metadata_files.len(), "Discovered metadata files");
|
||||
|
||||
// Discover the list of platforms that the tests should run on based on the context.
|
||||
let platforms = context
|
||||
.platforms
|
||||
.iter()
|
||||
.copied()
|
||||
.map(Into::<&dyn Platform>::into)
|
||||
.collect::<Vec<_>>();
|
||||
let platforms =
|
||||
context.platforms.iter().copied().map(Into::<&dyn Platform>::into).collect::<Vec<_>>();
|
||||
|
||||
// Starting the nodes of the various platforms specified in the context.
|
||||
let platforms_and_nodes = {
|
||||
@@ -85,13 +81,8 @@ pub async fn handle_differential_tests(
|
||||
|
||||
// Creating everything else required for the driver to run.
|
||||
let cached_compiler = CachedCompiler::new(
|
||||
context
|
||||
.working_directory
|
||||
.as_path()
|
||||
.join("compilation_cache"),
|
||||
context
|
||||
.compilation_configuration
|
||||
.invalidate_compilation_cache,
|
||||
context.working_directory.as_path().join("compilation_cache"),
|
||||
context.compilation_configuration.invalidate_compilation_cache,
|
||||
)
|
||||
.await
|
||||
.map(Arc::new)
|
||||
@@ -101,11 +92,8 @@ pub async fn handle_differential_tests(
|
||||
)));
|
||||
|
||||
// Creating the driver and executing all of the steps.
|
||||
let semaphore = context
|
||||
.concurrency_configuration
|
||||
.concurrency_limit()
|
||||
.map(Semaphore::new)
|
||||
.map(Arc::new);
|
||||
let semaphore =
|
||||
context.concurrency_configuration.concurrency_limit().map(Semaphore::new).map(Arc::new);
|
||||
let running_task_list = Arc::new(RwLock::new(BTreeSet::<usize>::new()));
|
||||
let driver_task = futures::future::join_all(test_definitions.iter().enumerate().map(
|
||||
|(test_id, test_definition)| {
|
||||
@@ -172,20 +160,14 @@ pub async fn handle_differential_tests(
|
||||
))
|
||||
.inspect(|_| {
|
||||
info!("Finished executing all test cases");
|
||||
reporter_clone
|
||||
.report_completion_event()
|
||||
.expect("Can't fail")
|
||||
reporter_clone.report_completion_event().expect("Can't fail")
|
||||
});
|
||||
let cli_reporting_task = start_cli_reporting_task(reporter);
|
||||
|
||||
tokio::task::spawn(async move {
|
||||
loop {
|
||||
let remaining_tasks = running_task_list.read().await;
|
||||
info!(
|
||||
count = remaining_tasks.len(),
|
||||
?remaining_tasks,
|
||||
"Remaining Tests"
|
||||
);
|
||||
info!(count = remaining_tasks.len(), ?remaining_tasks, "Remaining Tests");
|
||||
tokio::time::sleep(Duration::from_secs(10)).await
|
||||
}
|
||||
});
|
||||
@@ -227,7 +209,9 @@ async fn start_cli_reporting_task(reporter: Reporter) {
|
||||
for (case_idx, case_status) in case_status.into_iter() {
|
||||
let _ = write!(buf, "\tCase Index {case_idx:>3}: ");
|
||||
let _ = match case_status {
|
||||
TestCaseStatus::Succeeded { steps_executed } => {
|
||||
TestCaseStatus::Succeeded {
|
||||
steps_executed,
|
||||
} => {
|
||||
number_of_successes += 1;
|
||||
writeln!(
|
||||
buf,
|
||||
@@ -235,7 +219,9 @@ async fn start_cli_reporting_task(reporter: Reporter) {
|
||||
GREEN, BOLD, BOLD_RESET, steps_executed, COLOR_RESET
|
||||
)
|
||||
}
|
||||
TestCaseStatus::Failed { reason } => {
|
||||
TestCaseStatus::Failed {
|
||||
reason,
|
||||
} => {
|
||||
number_of_failures += 1;
|
||||
writeln!(
|
||||
buf,
|
||||
@@ -247,7 +233,10 @@ async fn start_cli_reporting_task(reporter: Reporter) {
|
||||
COLOR_RESET,
|
||||
)
|
||||
}
|
||||
TestCaseStatus::Ignored { reason, .. } => writeln!(
|
||||
TestCaseStatus::Ignored {
|
||||
reason,
|
||||
..
|
||||
} => writeln!(
|
||||
buf,
|
||||
"{}{}Case Ignored{} - Reason: {}{}",
|
||||
GREY,
|
||||
|
||||
@@ -8,10 +8,10 @@ use std::{
|
||||
sync::{Arc, LazyLock},
|
||||
};
|
||||
|
||||
use crate::Platform;
|
||||
use futures::FutureExt;
|
||||
use revive_dt_common::{iterators::FilesWithExtensionIterator, types::CompilerIdentifier};
|
||||
use revive_dt_compiler::{Compiler, CompilerOutput, Mode, SolidityCompiler};
|
||||
use crate::Platform;
|
||||
use revive_dt_format::metadata::{ContractIdent, ContractInstance, Metadata};
|
||||
|
||||
use alloy::{hex::ToHexExt, json_abi::JsonAbi, primitives::Address};
|
||||
@@ -225,9 +225,7 @@ async fn compile_contracts(
|
||||
.flat_map(|value| value.iter())
|
||||
.map(|(instance, (ident, address, abi))| (instance, ident, address, abi))
|
||||
.flat_map(|(_, ident, address, _)| {
|
||||
all_sources_in_dir
|
||||
.iter()
|
||||
.map(move |path| (ident, address, path))
|
||||
all_sources_in_dir.iter().map(move |path| (ident, address, path))
|
||||
})
|
||||
.fold(compiler, |compiler, (ident, address, path)| {
|
||||
compiler.with_library(path, ident.as_str(), *address)
|
||||
@@ -309,19 +307,15 @@ impl ArtifactsCache {
|
||||
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)
|
||||
.await
|
||||
.with_context(|| {
|
||||
format!("Failed to write cache entry under {}", self.path.display())
|
||||
})?;
|
||||
cacache::write(self.path.as_path(), key.encode_hex(), value).await.with_context(|| {
|
||||
format!("Failed to write cache entry under {}", self.path.display())
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get(&self, key: &CacheKey<'_>) -> Option<CacheValue> {
|
||||
let key = bson::to_vec(key).ok()?;
|
||||
let value = cacache::read(self.path.as_path(), key.encode_hex())
|
||||
.await
|
||||
.ok()?;
|
||||
let value = cacache::read(self.path.as_path(), key.encode_hex()).await.ok()?;
|
||||
let value = bson::from_slice::<CacheValue>(&value).ok()?;
|
||||
Some(value)
|
||||
}
|
||||
@@ -370,6 +364,8 @@ struct CacheValue {
|
||||
|
||||
impl CacheValue {
|
||||
pub fn new(compiler_output: CompilerOutput) -> Self {
|
||||
Self { compiler_output }
|
||||
Self {
|
||||
compiler_output,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use crate::Platform;
|
||||
use anyhow::Context as _;
|
||||
use revive_dt_config::*;
|
||||
use crate::Platform;
|
||||
use revive_dt_node_interaction::EthereumNode;
|
||||
|
||||
/// The node pool starts one or more [Node] which then can be accessed
|
||||
@@ -37,10 +37,8 @@ impl NodePool {
|
||||
);
|
||||
}
|
||||
|
||||
let pre_transactions_tasks = nodes
|
||||
.iter_mut()
|
||||
.map(|node| node.pre_transactions())
|
||||
.collect::<Vec<_>>();
|
||||
let pre_transactions_tasks =
|
||||
nodes.iter_mut().map(|node| node.pre_transactions()).collect::<Vec<_>>();
|
||||
futures::future::try_join_all(pre_transactions_tasks)
|
||||
.await
|
||||
.context("Failed to run the pre-transactions task")?;
|
||||
|
||||
@@ -1,28 +1,22 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::Arc;
|
||||
use std::{borrow::Cow, path::Path};
|
||||
use std::{borrow::Cow, collections::BTreeMap, path::Path, sync::Arc};
|
||||
|
||||
use futures::{Stream, StreamExt, stream};
|
||||
use indexmap::{IndexMap, indexmap};
|
||||
use revive_dt_common::iterators::EitherIter;
|
||||
use revive_dt_common::types::PlatformIdentifier;
|
||||
use revive_dt_common::{iterators::EitherIter, types::PlatformIdentifier};
|
||||
use revive_dt_config::Context;
|
||||
use revive_dt_format::mode::ParsedMode;
|
||||
use serde_json::{Value, json};
|
||||
|
||||
use revive_dt_compiler::Mode;
|
||||
use revive_dt_compiler::SolidityCompiler;
|
||||
use revive_dt_compiler::{Mode, SolidityCompiler};
|
||||
use revive_dt_format::{
|
||||
case::{Case, CaseIdx},
|
||||
metadata::MetadataFile,
|
||||
};
|
||||
use revive_dt_node_interaction::EthereumNode;
|
||||
use revive_dt_report::{ExecutionSpecificReporter, Reporter};
|
||||
use revive_dt_report::{TestSpecificReporter, TestSpecifier};
|
||||
use revive_dt_report::{ExecutionSpecificReporter, Reporter, TestSpecificReporter, TestSpecifier};
|
||||
use tracing::{debug, error, info};
|
||||
|
||||
use crate::Platform;
|
||||
use crate::helpers::NodePool;
|
||||
use crate::{Platform, helpers::NodePool};
|
||||
|
||||
pub async fn create_test_definitions_stream<'a>(
|
||||
// This is only required for creating the compiler objects and is not used anywhere else in the
|
||||
@@ -72,72 +66,68 @@ pub async fn create_test_definitions_stream<'a>(
|
||||
// Inform the reporter of each one of the test cases that were discovered which we expect to
|
||||
// run.
|
||||
.inspect(|(_, _, _, _, reporter)| {
|
||||
reporter
|
||||
.report_test_case_discovery_event()
|
||||
.expect("Can't fail");
|
||||
reporter.report_test_case_discovery_event().expect("Can't fail");
|
||||
}),
|
||||
)
|
||||
// Creating the Test Definition objects from all of the various objects we have and creating
|
||||
// their required dependencies (e.g., compiler).
|
||||
.filter_map(
|
||||
move |(metadata_file, case_idx, case, mode, reporter)| async move {
|
||||
let mut platforms = BTreeMap::new();
|
||||
for (platform, node_pool) in platforms_and_nodes.values() {
|
||||
let node = node_pool.round_robbin();
|
||||
let compiler = platform
|
||||
.new_compiler(context.clone(), mode.version.clone().map(Into::into))
|
||||
.await
|
||||
.inspect_err(|err| {
|
||||
error!(
|
||||
?err,
|
||||
platform_identifier = %platform.platform_identifier(),
|
||||
"Failed to instantiate the compiler"
|
||||
)
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
reporter
|
||||
.report_node_assigned_event(
|
||||
node.id(),
|
||||
platform.platform_identifier(),
|
||||
node.connection_string(),
|
||||
.filter_map(move |(metadata_file, case_idx, case, mode, reporter)| async move {
|
||||
let mut platforms = BTreeMap::new();
|
||||
for (platform, node_pool) in platforms_and_nodes.values() {
|
||||
let node = node_pool.round_robbin();
|
||||
let compiler = platform
|
||||
.new_compiler(context.clone(), mode.version.clone().map(Into::into))
|
||||
.await
|
||||
.inspect_err(|err| {
|
||||
error!(
|
||||
?err,
|
||||
platform_identifier = %platform.platform_identifier(),
|
||||
"Failed to instantiate the compiler"
|
||||
)
|
||||
.expect("Can't fail");
|
||||
})
|
||||
.ok()?;
|
||||
|
||||
let reporter =
|
||||
reporter.execution_specific_reporter(node.id(), platform.platform_identifier());
|
||||
|
||||
platforms.insert(
|
||||
reporter
|
||||
.report_node_assigned_event(
|
||||
node.id(),
|
||||
platform.platform_identifier(),
|
||||
TestPlatformInformation {
|
||||
platform: *platform,
|
||||
node,
|
||||
compiler,
|
||||
reporter,
|
||||
},
|
||||
);
|
||||
}
|
||||
node.connection_string(),
|
||||
)
|
||||
.expect("Can't fail");
|
||||
|
||||
Some(TestDefinition {
|
||||
/* Metadata file information */
|
||||
metadata: metadata_file,
|
||||
metadata_file_path: metadata_file.metadata_file_path.as_path(),
|
||||
let reporter =
|
||||
reporter.execution_specific_reporter(node.id(), platform.platform_identifier());
|
||||
|
||||
/* Mode Information */
|
||||
mode: mode.clone(),
|
||||
platforms.insert(
|
||||
platform.platform_identifier(),
|
||||
TestPlatformInformation {
|
||||
platform: *platform,
|
||||
node,
|
||||
compiler,
|
||||
reporter,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/* Case Information */
|
||||
case_idx: CaseIdx::new(case_idx),
|
||||
case,
|
||||
Some(TestDefinition {
|
||||
/* Metadata file information */
|
||||
metadata: metadata_file,
|
||||
metadata_file_path: metadata_file.metadata_file_path.as_path(),
|
||||
|
||||
/* Platform and Node Assignment Information */
|
||||
platforms,
|
||||
/* Mode Information */
|
||||
mode: mode.clone(),
|
||||
|
||||
/* Reporter */
|
||||
reporter,
|
||||
})
|
||||
},
|
||||
)
|
||||
/* Case Information */
|
||||
case_idx: CaseIdx::new(case_idx),
|
||||
case,
|
||||
|
||||
/* Platform and Node Assignment Information */
|
||||
platforms,
|
||||
|
||||
/* Reporter */
|
||||
reporter,
|
||||
})
|
||||
})
|
||||
// Filter out the test cases which are incompatible or that can't run in the current setup.
|
||||
.filter_map(move |test| async move {
|
||||
match test.check_compatibility() {
|
||||
@@ -280,10 +270,7 @@ impl<'a> TestDefinition<'a> {
|
||||
if is_allowed {
|
||||
Ok(())
|
||||
} else {
|
||||
Err((
|
||||
"EVM version is incompatible for the platforms specified",
|
||||
error_map,
|
||||
))
|
||||
Err(("EVM version is incompatible for the platforms specified", error_map))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+20
-39
@@ -3,8 +3,8 @@
|
||||
//! This crate defines the testing configuration and
|
||||
//! provides a helper utility to execute tests.
|
||||
|
||||
pub mod helpers;
|
||||
pub mod differential_tests;
|
||||
pub mod helpers;
|
||||
|
||||
use std::{
|
||||
pin::Pin,
|
||||
@@ -17,9 +17,11 @@ use revive_dt_common::types::*;
|
||||
use revive_dt_compiler::{SolidityCompiler, revive_resolc::Resolc, solc::Solc};
|
||||
use revive_dt_config::*;
|
||||
use revive_dt_node::{
|
||||
Node, node_implementations::geth::GethNode,
|
||||
node_implementations::lighthouse_geth::LighthouseGethNode,
|
||||
node_implementations::substrate::SubstrateNode, node_implementations::zombienet::ZombieNode,
|
||||
Node,
|
||||
node_implementations::{
|
||||
geth::GethNode, lighthouse_geth::LighthouseGethNode, substrate::SubstrateNode,
|
||||
zombienet::ZombieNode,
|
||||
},
|
||||
};
|
||||
use revive_dt_node_interaction::EthereumNode;
|
||||
use tracing::info;
|
||||
@@ -36,11 +38,7 @@ pub trait Platform {
|
||||
|
||||
/// Returns a full identifier for the platform.
|
||||
fn full_identifier(&self) -> (NodeIdentifier, VmIdentifier, CompilerIdentifier) {
|
||||
(
|
||||
self.node_identifier(),
|
||||
self.vm_identifier(),
|
||||
self.compiler_identifier(),
|
||||
)
|
||||
(self.node_identifier(), self.vm_identifier(), self.compiler_identifier())
|
||||
}
|
||||
|
||||
/// Returns the identifier of the node used.
|
||||
@@ -182,9 +180,7 @@ impl Platform for KitchensinkPolkavmResolcPlatform {
|
||||
context: Context,
|
||||
) -> anyhow::Result<JoinHandle<anyhow::Result<Box<dyn EthereumNode + Send + Sync>>>> {
|
||||
let genesis_configuration = AsRef::<GenesisConfiguration>::as_ref(&context);
|
||||
let kitchensink_path = AsRef::<KitchensinkConfiguration>::as_ref(&context)
|
||||
.path
|
||||
.clone();
|
||||
let kitchensink_path = AsRef::<KitchensinkConfiguration>::as_ref(&context).path.clone();
|
||||
let genesis = genesis_configuration.genesis()?.clone();
|
||||
Ok(thread::spawn(move || {
|
||||
let node = SubstrateNode::new(
|
||||
@@ -234,9 +230,7 @@ impl Platform for KitchensinkRevmSolcPlatform {
|
||||
context: Context,
|
||||
) -> anyhow::Result<JoinHandle<anyhow::Result<Box<dyn EthereumNode + Send + Sync>>>> {
|
||||
let genesis_configuration = AsRef::<GenesisConfiguration>::as_ref(&context);
|
||||
let kitchensink_path = AsRef::<KitchensinkConfiguration>::as_ref(&context)
|
||||
.path
|
||||
.clone();
|
||||
let kitchensink_path = AsRef::<KitchensinkConfiguration>::as_ref(&context).path.clone();
|
||||
let genesis = genesis_configuration.genesis()?.clone();
|
||||
Ok(thread::spawn(move || {
|
||||
let node = SubstrateNode::new(
|
||||
@@ -286,9 +280,8 @@ impl Platform for ReviveDevNodePolkavmResolcPlatform {
|
||||
context: Context,
|
||||
) -> anyhow::Result<JoinHandle<anyhow::Result<Box<dyn EthereumNode + Send + Sync>>>> {
|
||||
let genesis_configuration = AsRef::<GenesisConfiguration>::as_ref(&context);
|
||||
let revive_dev_node_path = AsRef::<ReviveDevNodeConfiguration>::as_ref(&context)
|
||||
.path
|
||||
.clone();
|
||||
let revive_dev_node_path =
|
||||
AsRef::<ReviveDevNodeConfiguration>::as_ref(&context).path.clone();
|
||||
let genesis = genesis_configuration.genesis()?.clone();
|
||||
Ok(thread::spawn(move || {
|
||||
let node = SubstrateNode::new(
|
||||
@@ -338,9 +331,8 @@ impl Platform for ReviveDevNodeRevmSolcPlatform {
|
||||
context: Context,
|
||||
) -> anyhow::Result<JoinHandle<anyhow::Result<Box<dyn EthereumNode + Send + Sync>>>> {
|
||||
let genesis_configuration = AsRef::<GenesisConfiguration>::as_ref(&context);
|
||||
let revive_dev_node_path = AsRef::<ReviveDevNodeConfiguration>::as_ref(&context)
|
||||
.path
|
||||
.clone();
|
||||
let revive_dev_node_path =
|
||||
AsRef::<ReviveDevNodeConfiguration>::as_ref(&context).path.clone();
|
||||
let genesis = genesis_configuration.genesis()?.clone();
|
||||
Ok(thread::spawn(move || {
|
||||
let node = SubstrateNode::new(
|
||||
@@ -390,9 +382,8 @@ impl Platform for ZombienetPolkavmResolcPlatform {
|
||||
context: Context,
|
||||
) -> anyhow::Result<JoinHandle<anyhow::Result<Box<dyn EthereumNode + Send + Sync>>>> {
|
||||
let genesis_configuration = AsRef::<GenesisConfiguration>::as_ref(&context);
|
||||
let polkadot_parachain_path = AsRef::<PolkadotParachainConfiguration>::as_ref(&context)
|
||||
.path
|
||||
.clone();
|
||||
let polkadot_parachain_path =
|
||||
AsRef::<PolkadotParachainConfiguration>::as_ref(&context).path.clone();
|
||||
let genesis = genesis_configuration.genesis()?.clone();
|
||||
Ok(thread::spawn(move || {
|
||||
let node = ZombieNode::new(polkadot_parachain_path, context);
|
||||
@@ -438,9 +429,8 @@ impl Platform for ZombienetRevmSolcPlatform {
|
||||
context: Context,
|
||||
) -> anyhow::Result<JoinHandle<anyhow::Result<Box<dyn EthereumNode + Send + Sync>>>> {
|
||||
let genesis_configuration = AsRef::<GenesisConfiguration>::as_ref(&context);
|
||||
let polkadot_parachain_path = AsRef::<PolkadotParachainConfiguration>::as_ref(&context)
|
||||
.path
|
||||
.clone();
|
||||
let polkadot_parachain_path =
|
||||
AsRef::<PolkadotParachainConfiguration>::as_ref(&context).path.clone();
|
||||
let genesis = genesis_configuration.genesis()?.clone();
|
||||
Ok(thread::spawn(move || {
|
||||
let node = ZombieNode::new(polkadot_parachain_path, context);
|
||||
@@ -519,17 +509,8 @@ fn spawn_node<T: Node + EthereumNode + Send + Sync>(
|
||||
mut node: T,
|
||||
genesis: Genesis,
|
||||
) -> anyhow::Result<T> {
|
||||
info!(
|
||||
id = node.id(),
|
||||
connection_string = node.connection_string(),
|
||||
"Spawning node"
|
||||
);
|
||||
node.spawn(genesis)
|
||||
.context("Failed to spawn node process")?;
|
||||
info!(
|
||||
id = node.id(),
|
||||
connection_string = node.connection_string(),
|
||||
"Spawned node"
|
||||
);
|
||||
info!(id = node.id(), connection_string = node.connection_string(), "Spawning node");
|
||||
node.spawn(genesis).context("Failed to spawn node process")?;
|
||||
info!(id = node.id(), connection_string = node.connection_string(), "Spawned node");
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user