Add a way to skip tests if they don't match the target

This commit is contained in:
Omar Abdulla
2025-07-22 09:07:01 +03:00
parent a0248b58f3
commit 5c957e5ac1
8 changed files with 63 additions and 30 deletions
+30 -26
View File
@@ -26,6 +26,7 @@ use revive_dt_format::case::CaseIdx;
use revive_dt_format::input::{Calldata, Expected, ExpectedOutput, Method};
use revive_dt_format::metadata::{ContractInstance, ContractPathAndIdentifier};
use revive_dt_format::{input::Input, metadata::Metadata, mode::SolcMode};
use revive_dt_node::Node;
use revive_dt_node_interaction::EthereumNode;
use revive_dt_report::reporter::{CompilationTask, Report, Span};
use revive_solc_json_interface::SolcStandardJsonOutput;
@@ -435,16 +436,15 @@ where
// Additionally, what happens if the compiler filter doesn't match? Do we consider that the
// transaction should succeed? Do we just ignore the expectation?
let error_span =
tracing::error_span!("Exception failed", ?tracing_result, ?execution_receipt,);
let _guard = error_span.enter();
// Handling the receipt state assertion.
let expected = !expectation.exception;
let actual = execution_receipt.status();
if actual != expected {
tracing::error!(
?execution_receipt,
expected,
actual,
"Transaction status assertion failed",
);
tracing::error!(expected, actual, "Transaction status assertion failed",);
anyhow::bail!(
"Transaction status assertion failed - Expected {expected} but got {actual}",
);
@@ -457,7 +457,11 @@ where
.map(Bytes::from)?;
let actual = tracing_result.output.clone().unwrap_or_default();
if !expected.starts_with(&actual) {
tracing::error!(?execution_receipt, %expected, %actual, "Calldata assertion failed");
tracing::error!(
%expected,
%actual,
"Calldata assertion failed"
);
anyhow::bail!("Calldata assertion failed - Expected {expected} but got {actual}",);
}
}
@@ -468,12 +472,7 @@ where
let expected = expected_events.len();
let actual = execution_receipt.logs().len();
if actual != expected {
tracing::error!(
?execution_receipt,
expected,
actual,
"Event count assertion failed",
);
tracing::error!(expected, actual, "Event count assertion failed",);
anyhow::bail!(
"Event count assertion failed - Expected {expected} but got {actual}",
);
@@ -489,7 +488,6 @@ where
let actual = actual_event.address();
if actual != expected {
tracing::error!(
?execution_receipt,
%expected,
%actual,
"Event emitter assertion failed",
@@ -511,12 +509,7 @@ where
.calldata(self.deployed_contracts.entry(case_idx).or_default(), node)?;
let actual = actual_topic.to_vec();
if actual != expected {
tracing::error!(
?execution_receipt,
?expected,
?actual,
"Event topics assertion failed",
);
tracing::error!(?expected, ?actual, "Event topics assertion failed",);
anyhow::bail!(
"Event topics assertion failed - Expected {expected:?} but got {actual:?}",
);
@@ -530,12 +523,7 @@ where
.map(Bytes::from)?;
let actual = &actual_event.data().data;
if !expected.starts_with(actual) {
tracing::error!(
?execution_receipt,
?expected,
?actual,
"Event value assertion failed",
);
tracing::error!(?expected, ?actual, "Event value assertion failed",);
anyhow::bail!(
"Event value assertion failed - Expected {expected:?} but got {actual:?}",
);
@@ -649,6 +637,22 @@ where
let tracing_span = tracing::info_span!("Handling metadata file");
let _guard = tracing_span.enter();
// We only execute this input if it's valid for the leader and the follower. Otherwise, we
// skip it with a warning.
if !self
.leader_node
.matches_target(self.metadata.targets.as_deref())
|| !self
.follower_node
.matches_target(self.metadata.targets.as_deref())
{
tracing::warn!(
targets = ?self.metadata.targets,
"Either the leader or follower node do not support the targets of the file"
);
return execution_result;
}
for mode in self.metadata.solc_modes() {
let tracing_span = tracing::info_span!("With solc mode", solc_mode = ?mode);
let _guard = tracing_span.enter();
+2 -2
View File
@@ -5,7 +5,7 @@
use revive_dt_compiler::{SolidityCompiler, revive_resolc, solc};
use revive_dt_config::TestingPlatform;
use revive_dt_node::{geth, kitchensink::KitchensinkNode};
use revive_dt_node::{Node, geth, kitchensink::KitchensinkNode};
use revive_dt_node_interaction::EthereumNode;
pub mod common;
@@ -15,7 +15,7 @@ pub mod driver;
///
/// For this we need a blockchain node implementation and a compiler.
pub trait Platform {
type Blockchain: EthereumNode;
type Blockchain: EthereumNode + Node;
type Compiler: SolidityCompiler;
/// Returns the matching [TestingPlatform] of the [revive_dt_config::Arguments].
+9 -1
View File
@@ -26,7 +26,15 @@ impl Case {
.enumerate()
.map(move |(idx, mut input)| {
if idx + 1 == inputs_len {
input.expected = self.expected.clone();
if input.expected.is_none() {
input.expected = self.expected.clone();
}
// TODO: What does it mean for us to have an `expected` field on the case itself
// but the final input also has an expected field that doesn't match the one on
// the case? What are we supposed to do with that final expected field on the
// case?
input
} else {
input
+1 -1
View File
@@ -324,7 +324,7 @@ impl Input {
chain_state_provider: &impl EthereumNode,
) -> anyhow::Result<TransactionRequest> {
let input_data = self.encoded_input(deployed_contracts, chain_state_provider)?;
let transaction_request = TransactionRequest::default();
let transaction_request = TransactionRequest::default().from(self.caller);
match self.method {
Method::Deployer => Ok(transaction_request.with_deploy_code(input_data)),
_ => Ok(transaction_request
+1
View File
@@ -48,6 +48,7 @@ impl Deref for MetadataFile {
#[derive(Debug, Default, Deserialize, Clone, Eq, PartialEq)]
pub struct Metadata {
pub targets: Option<Vec<String>>,
pub cases: Vec<Case>,
pub contracts: Option<BTreeMap<ContractInstance, ContractPathAndIdentifier>>,
// TODO: Convert into wrapper types for clarity.
+8
View File
@@ -510,6 +510,14 @@ impl Node for Instance {
.stdout;
Ok(String::from_utf8_lossy(&output).into())
}
#[tracing::instrument(skip_all, fields(geth_node_id = self.id))]
fn matches_target(&self, targets: Option<&[String]>) -> bool {
match targets {
None => true,
Some(targets) => targets.iter().any(|str| str.as_str() == "evm"),
}
}
}
impl Drop for Instance {
+8
View File
@@ -584,6 +584,14 @@ impl Node for KitchensinkNode {
.stdout;
Ok(String::from_utf8_lossy(&output).into())
}
#[tracing::instrument(skip_all, fields(kitchensink_node_id = self.id))]
fn matches_target(&self, targets: Option<&[String]>) -> bool {
match targets {
None => true,
Some(targets) => targets.iter().any(|str| str.as_str() == "pvm"),
}
}
}
impl Drop for KitchensinkNode {
+4
View File
@@ -35,4 +35,8 @@ pub trait Node: EthereumNode {
/// Returns the node version.
fn version(&self) -> anyhow::Result<String>;
/// Given a list of targets from the metadata file, this function determines if the metadata
/// file can be ran on this node or not.
fn matches_target(&self, targets: Option<&[String]>) -> bool;
}