mirror of
https://github.com/pezkuwichain/revive-differential-tests.git
synced 2026-06-14 09:51:08 +00:00
Add a way to skip tests if they don't match the target
This commit is contained in:
@@ -26,6 +26,7 @@ use revive_dt_format::case::CaseIdx;
|
|||||||
use revive_dt_format::input::{Calldata, Expected, ExpectedOutput, Method};
|
use revive_dt_format::input::{Calldata, Expected, ExpectedOutput, Method};
|
||||||
use revive_dt_format::metadata::{ContractInstance, ContractPathAndIdentifier};
|
use revive_dt_format::metadata::{ContractInstance, ContractPathAndIdentifier};
|
||||||
use revive_dt_format::{input::Input, metadata::Metadata, mode::SolcMode};
|
use revive_dt_format::{input::Input, metadata::Metadata, mode::SolcMode};
|
||||||
|
use revive_dt_node::Node;
|
||||||
use revive_dt_node_interaction::EthereumNode;
|
use revive_dt_node_interaction::EthereumNode;
|
||||||
use revive_dt_report::reporter::{CompilationTask, Report, Span};
|
use revive_dt_report::reporter::{CompilationTask, Report, Span};
|
||||||
use revive_solc_json_interface::SolcStandardJsonOutput;
|
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
|
// Additionally, what happens if the compiler filter doesn't match? Do we consider that the
|
||||||
// transaction should succeed? Do we just ignore the expectation?
|
// 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.
|
// Handling the receipt state assertion.
|
||||||
let expected = !expectation.exception;
|
let expected = !expectation.exception;
|
||||||
let actual = execution_receipt.status();
|
let actual = execution_receipt.status();
|
||||||
if actual != expected {
|
if actual != expected {
|
||||||
tracing::error!(
|
tracing::error!(expected, actual, "Transaction status assertion failed",);
|
||||||
?execution_receipt,
|
|
||||||
expected,
|
|
||||||
actual,
|
|
||||||
"Transaction status assertion failed",
|
|
||||||
);
|
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"Transaction status assertion failed - Expected {expected} but got {actual}",
|
"Transaction status assertion failed - Expected {expected} but got {actual}",
|
||||||
);
|
);
|
||||||
@@ -457,7 +457,11 @@ where
|
|||||||
.map(Bytes::from)?;
|
.map(Bytes::from)?;
|
||||||
let actual = tracing_result.output.clone().unwrap_or_default();
|
let actual = tracing_result.output.clone().unwrap_or_default();
|
||||||
if !expected.starts_with(&actual) {
|
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}",);
|
anyhow::bail!("Calldata assertion failed - Expected {expected} but got {actual}",);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -468,12 +472,7 @@ where
|
|||||||
let expected = expected_events.len();
|
let expected = expected_events.len();
|
||||||
let actual = execution_receipt.logs().len();
|
let actual = execution_receipt.logs().len();
|
||||||
if actual != expected {
|
if actual != expected {
|
||||||
tracing::error!(
|
tracing::error!(expected, actual, "Event count assertion failed",);
|
||||||
?execution_receipt,
|
|
||||||
expected,
|
|
||||||
actual,
|
|
||||||
"Event count assertion failed",
|
|
||||||
);
|
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"Event count assertion failed - Expected {expected} but got {actual}",
|
"Event count assertion failed - Expected {expected} but got {actual}",
|
||||||
);
|
);
|
||||||
@@ -489,7 +488,6 @@ where
|
|||||||
let actual = actual_event.address();
|
let actual = actual_event.address();
|
||||||
if actual != expected {
|
if actual != expected {
|
||||||
tracing::error!(
|
tracing::error!(
|
||||||
?execution_receipt,
|
|
||||||
%expected,
|
%expected,
|
||||||
%actual,
|
%actual,
|
||||||
"Event emitter assertion failed",
|
"Event emitter assertion failed",
|
||||||
@@ -511,12 +509,7 @@ where
|
|||||||
.calldata(self.deployed_contracts.entry(case_idx).or_default(), node)?;
|
.calldata(self.deployed_contracts.entry(case_idx).or_default(), node)?;
|
||||||
let actual = actual_topic.to_vec();
|
let actual = actual_topic.to_vec();
|
||||||
if actual != expected {
|
if actual != expected {
|
||||||
tracing::error!(
|
tracing::error!(?expected, ?actual, "Event topics assertion failed",);
|
||||||
?execution_receipt,
|
|
||||||
?expected,
|
|
||||||
?actual,
|
|
||||||
"Event topics assertion failed",
|
|
||||||
);
|
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"Event topics assertion failed - Expected {expected:?} but got {actual:?}",
|
"Event topics assertion failed - Expected {expected:?} but got {actual:?}",
|
||||||
);
|
);
|
||||||
@@ -530,12 +523,7 @@ where
|
|||||||
.map(Bytes::from)?;
|
.map(Bytes::from)?;
|
||||||
let actual = &actual_event.data().data;
|
let actual = &actual_event.data().data;
|
||||||
if !expected.starts_with(actual) {
|
if !expected.starts_with(actual) {
|
||||||
tracing::error!(
|
tracing::error!(?expected, ?actual, "Event value assertion failed",);
|
||||||
?execution_receipt,
|
|
||||||
?expected,
|
|
||||||
?actual,
|
|
||||||
"Event value assertion failed",
|
|
||||||
);
|
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"Event value assertion failed - Expected {expected:?} but got {actual:?}",
|
"Event value assertion failed - Expected {expected:?} but got {actual:?}",
|
||||||
);
|
);
|
||||||
@@ -649,6 +637,22 @@ where
|
|||||||
let tracing_span = tracing::info_span!("Handling metadata file");
|
let tracing_span = tracing::info_span!("Handling metadata file");
|
||||||
let _guard = tracing_span.enter();
|
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() {
|
for mode in self.metadata.solc_modes() {
|
||||||
let tracing_span = tracing::info_span!("With solc mode", solc_mode = ?mode);
|
let tracing_span = tracing::info_span!("With solc mode", solc_mode = ?mode);
|
||||||
let _guard = tracing_span.enter();
|
let _guard = tracing_span.enter();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
use revive_dt_compiler::{SolidityCompiler, revive_resolc, solc};
|
use revive_dt_compiler::{SolidityCompiler, revive_resolc, solc};
|
||||||
use revive_dt_config::TestingPlatform;
|
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;
|
use revive_dt_node_interaction::EthereumNode;
|
||||||
|
|
||||||
pub mod common;
|
pub mod common;
|
||||||
@@ -15,7 +15,7 @@ pub mod driver;
|
|||||||
///
|
///
|
||||||
/// For this we need a blockchain node implementation and a compiler.
|
/// For this we need a blockchain node implementation and a compiler.
|
||||||
pub trait Platform {
|
pub trait Platform {
|
||||||
type Blockchain: EthereumNode;
|
type Blockchain: EthereumNode + Node;
|
||||||
type Compiler: SolidityCompiler;
|
type Compiler: SolidityCompiler;
|
||||||
|
|
||||||
/// Returns the matching [TestingPlatform] of the [revive_dt_config::Arguments].
|
/// Returns the matching [TestingPlatform] of the [revive_dt_config::Arguments].
|
||||||
|
|||||||
@@ -26,7 +26,15 @@ impl Case {
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
.map(move |(idx, mut input)| {
|
.map(move |(idx, mut input)| {
|
||||||
if idx + 1 == inputs_len {
|
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
|
input
|
||||||
} else {
|
} else {
|
||||||
input
|
input
|
||||||
|
|||||||
@@ -324,7 +324,7 @@ impl Input {
|
|||||||
chain_state_provider: &impl EthereumNode,
|
chain_state_provider: &impl EthereumNode,
|
||||||
) -> anyhow::Result<TransactionRequest> {
|
) -> anyhow::Result<TransactionRequest> {
|
||||||
let input_data = self.encoded_input(deployed_contracts, chain_state_provider)?;
|
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 {
|
match self.method {
|
||||||
Method::Deployer => Ok(transaction_request.with_deploy_code(input_data)),
|
Method::Deployer => Ok(transaction_request.with_deploy_code(input_data)),
|
||||||
_ => Ok(transaction_request
|
_ => Ok(transaction_request
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ impl Deref for MetadataFile {
|
|||||||
|
|
||||||
#[derive(Debug, Default, Deserialize, Clone, Eq, PartialEq)]
|
#[derive(Debug, Default, Deserialize, Clone, Eq, PartialEq)]
|
||||||
pub struct Metadata {
|
pub struct Metadata {
|
||||||
|
pub targets: Option<Vec<String>>,
|
||||||
pub cases: Vec<Case>,
|
pub cases: Vec<Case>,
|
||||||
pub contracts: Option<BTreeMap<ContractInstance, ContractPathAndIdentifier>>,
|
pub contracts: Option<BTreeMap<ContractInstance, ContractPathAndIdentifier>>,
|
||||||
// TODO: Convert into wrapper types for clarity.
|
// TODO: Convert into wrapper types for clarity.
|
||||||
|
|||||||
@@ -510,6 +510,14 @@ impl Node for Instance {
|
|||||||
.stdout;
|
.stdout;
|
||||||
Ok(String::from_utf8_lossy(&output).into())
|
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 {
|
impl Drop for Instance {
|
||||||
|
|||||||
@@ -584,6 +584,14 @@ impl Node for KitchensinkNode {
|
|||||||
.stdout;
|
.stdout;
|
||||||
Ok(String::from_utf8_lossy(&output).into())
|
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 {
|
impl Drop for KitchensinkNode {
|
||||||
|
|||||||
@@ -35,4 +35,8 @@ pub trait Node: EthereumNode {
|
|||||||
|
|
||||||
/// Returns the node version.
|
/// Returns the node version.
|
||||||
fn version(&self) -> anyhow::Result<String>;
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user