mirror of
https://github.com/pezkuwichain/revive-differential-tests.git
synced 2026-04-26 01:37:59 +00:00
133 lines
4.5 KiB
Rust
133 lines
4.5 KiB
Rust
use alloy::primitives::Address;
|
|
use schemars::JsonSchema;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use revive_dt_common::{
|
|
macros::define_wrapper_type,
|
|
types::{Mode, ParsedMode},
|
|
};
|
|
|
|
use crate::steps::*;
|
|
|
|
#[derive(Debug, Default, Serialize, Deserialize, Clone, Eq, PartialEq, JsonSchema)]
|
|
pub struct Case {
|
|
/// An optional name of the test case.
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub name: Option<String>,
|
|
|
|
/// An optional comment on the case which has no impact on the execution in any way.
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub comment: Option<String>,
|
|
|
|
/// This represents a mode that has been parsed from test metadata.
|
|
///
|
|
/// Mode strings can take the following form (in pseudo-regex):
|
|
///
|
|
/// ```text
|
|
/// [YEILV][+-]? (M[0123sz])? <semver>?
|
|
/// ```
|
|
///
|
|
/// If this is provided then it takes higher priority than the modes specified in the metadata
|
|
/// file.
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub modes: Option<Vec<ParsedMode>>,
|
|
|
|
/// The set of steps to run as part of this test case.
|
|
#[serde(rename = "inputs")]
|
|
pub steps: Vec<Step>,
|
|
|
|
/// An optional name of the group of tests that this test belongs to.
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub group: Option<String>,
|
|
|
|
/// An optional set of expectations and assertions to make about the transaction after it ran.
|
|
///
|
|
/// If this is not specified then the only assertion that will be ran is that the transaction
|
|
/// was successful.
|
|
///
|
|
/// This expectation that's on the case itself will be attached to the final step of the case.
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub expected: Option<Expected>,
|
|
|
|
/// An optional boolean which defines if the case as a whole should be ignored. If null then the
|
|
/// case will not be ignored.
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub ignore: Option<bool>,
|
|
}
|
|
|
|
impl Case {
|
|
pub fn steps_iterator(&self) -> impl Iterator<Item = Step> {
|
|
let steps_len = self.steps.len();
|
|
self.steps
|
|
.clone()
|
|
.into_iter()
|
|
.enumerate()
|
|
.map(move |(idx, mut step)| {
|
|
let Step::FunctionCall(ref mut input) = step else {
|
|
return step;
|
|
};
|
|
|
|
if idx + 1 == steps_len {
|
|
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?
|
|
|
|
step
|
|
} else {
|
|
step
|
|
}
|
|
})
|
|
}
|
|
|
|
pub fn steps_iterator_for_benchmarks(
|
|
&self,
|
|
default_repeat_count: usize,
|
|
) -> Box<dyn Iterator<Item = Step> + '_> {
|
|
let contains_repeat = self
|
|
.steps_iterator()
|
|
.any(|step| matches!(&step, Step::Repeat(..)));
|
|
if contains_repeat {
|
|
Box::new(self.steps_iterator()) as Box<_>
|
|
} else {
|
|
Box::new(std::iter::once(Step::Repeat(Box::new(RepeatStep {
|
|
comment: None,
|
|
repeat: default_repeat_count,
|
|
steps: self.steps_iterator().collect(),
|
|
})))) as Box<_>
|
|
}
|
|
}
|
|
|
|
pub fn solc_modes(&self) -> Vec<Mode> {
|
|
match &self.modes {
|
|
Some(modes) => ParsedMode::many_to_modes(modes.iter()).collect(),
|
|
None => Mode::all().cloned().collect(),
|
|
}
|
|
}
|
|
|
|
pub fn deployer_address(&self) -> Address {
|
|
self.steps
|
|
.iter()
|
|
.filter_map(|step| match step {
|
|
Step::FunctionCall(input) => input.caller.as_address().copied(),
|
|
Step::BalanceAssertion(..) => None,
|
|
Step::StorageEmptyAssertion(..) => None,
|
|
Step::Repeat(..) => None,
|
|
Step::AllocateAccount(..) => None,
|
|
})
|
|
.next()
|
|
.unwrap_or(FunctionCallStep::default_caller_address())
|
|
}
|
|
}
|
|
|
|
define_wrapper_type!(
|
|
/// A wrapper type for the index of test cases found in metadata file.
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
|
#[serde(transparent)]
|
|
pub struct CaseIdx(usize) impl Display, FromStr;
|
|
);
|