Compare commits

...

7 Commits

Author SHA1 Message Date
Omar Abdulla f264f2f409 Update the schema 2025-09-22 06:38:24 +03:00
Omar Abdulla 854e7b6a60 Merge remote-tracking branch 'origin/main' into feature/step-path 2025-09-22 06:37:44 +03:00
Omar Abdulla 7b8b1a47c6 Add a step path 2025-09-21 08:09:35 +03:00
Omar Abdulla f54c543c18 Support virtual repeats 2025-09-21 07:44:01 +03:00
Omar Abdulla 736c50a8f0 Update the JSON schema 2025-09-21 07:39:57 +03:00
Omar Abdulla e2fb7a4322 Add support for account allocations 2025-09-21 07:37:07 +03:00
Omar Abdulla 0edfb3a36e Support repetitions in the tool 2025-09-21 05:55:01 +03:00
4 changed files with 79 additions and 14 deletions
+12 -9
View File
@@ -30,7 +30,7 @@ use revive_dt_format::case::Case;
use revive_dt_format::metadata::{ContractIdent, ContractInstance, ContractPathAndIdent}; use revive_dt_format::metadata::{ContractIdent, ContractInstance, ContractPathAndIdent};
use revive_dt_format::steps::{ use revive_dt_format::steps::{
BalanceAssertionStep, Calldata, EtherValue, Expected, ExpectedOutput, FunctionCallStep, Method, BalanceAssertionStep, Calldata, EtherValue, Expected, ExpectedOutput, FunctionCallStep, Method,
StepIdx, StorageEmptyAssertionStep, StepIdx, StepPath, StorageEmptyAssertionStep,
}; };
use revive_dt_format::{metadata::Metadata, steps::Step}; use revive_dt_format::{metadata::Metadata, steps::Step};
use revive_dt_node_interaction::EthereumNode; use revive_dt_node_interaction::EthereumNode;
@@ -83,6 +83,7 @@ impl CaseState {
&mut self, &mut self,
metadata: &Metadata, metadata: &Metadata,
step: &Step, step: &Step,
step_path: &StepPath,
node: &dyn EthereumNode, node: &dyn EthereumNode,
) -> anyhow::Result<StepOutput> { ) -> anyhow::Result<StepOutput> {
match step { match step {
@@ -110,6 +111,7 @@ impl CaseState {
metadata, metadata,
repetition_step.repeat, repetition_step.repeat,
&repetition_step.steps, &repetition_step.steps,
step_path,
node, node,
) )
.await .await
@@ -200,13 +202,15 @@ impl CaseState {
metadata: &Metadata, metadata: &Metadata,
repetitions: usize, repetitions: usize,
steps: &[Step], steps: &[Step],
step_path: &StepPath,
node: &dyn EthereumNode, node: &dyn EthereumNode,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let tasks = (0..repetitions).map(|_| { let tasks = (0..repetitions).map(|_| {
let mut state = self.clone(); let mut state = self.clone();
async move { async move {
for step in steps { for (step_idx, step) in steps.iter().enumerate() {
state.handle_step(metadata, step, node).await?; let step_path = step_path.append(step_idx);
state.handle_step(metadata, step, &step_path, node).await?;
} }
Ok::<(), anyhow::Error>(()) Ok::<(), anyhow::Error>(())
} }
@@ -842,32 +846,31 @@ impl<'a> CaseDriver<'a> {
.enumerate() .enumerate()
.map(|(idx, v)| (StepIdx::new(idx), v)) .map(|(idx, v)| (StepIdx::new(idx), v))
{ {
// Run this step concurrently across all platforms; short-circuit on first failure
let metadata = self.metadata; let metadata = self.metadata;
let step_futs = let step_futures =
self.platform_state self.platform_state
.iter_mut() .iter_mut()
.map(|(node, platform_id, case_state)| { .map(|(node, platform_id, case_state)| {
let platform_id = *platform_id; let platform_id = *platform_id;
let node_ref = *node; let node_ref = *node;
let step_clone = step.clone(); let step = step.clone();
let span = info_span!( let span = info_span!(
"Handling Step", "Handling Step",
%step_idx, %step_idx,
platform = %platform_id, platform = %platform_id,
); );
async move { async move {
let step_path = StepPath::from_iterator([step_idx]);
case_state case_state
.handle_step(metadata, &step_clone, node_ref) .handle_step(metadata, &step, &step_path, node_ref)
.await .await
.map_err(|e| (platform_id, e)) .map_err(|e| (platform_id, e))
} }
.instrument(span) .instrument(span)
}); });
match try_join_all(step_futs).await { match try_join_all(step_futures).await {
Ok(_outputs) => { Ok(_outputs) => {
// All platforms succeeded for this step
steps_executed += 1; steps_executed += 1;
} }
Err((platform_id, error)) => { Err((platform_id, error)) => {
+64 -2
View File
@@ -1,4 +1,4 @@
use std::{collections::HashMap, fmt::Display}; use std::{collections::HashMap, fmt::Display, str::FromStr};
use alloy::{ use alloy::{
eips::BlockNumberOrTag, eips::BlockNumberOrTag,
@@ -46,9 +46,71 @@ pub enum Step {
define_wrapper_type!( define_wrapper_type!(
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct StepIdx(usize) impl Display; pub struct StepIdx(usize) impl Display, FromStr;
); );
define_wrapper_type!(
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(try_from = "String", into = "String")]
pub struct StepPath(Vec<StepIdx>);
);
impl StepPath {
pub fn from_iterator(path: impl IntoIterator<Item = impl Into<StepIdx>>) -> Self {
Self(path.into_iter().map(|value| value.into()).collect())
}
pub fn increment(&self) -> Self {
let mut this = self.clone();
if let Some(last) = this.last_mut() {
last.0 += 1
}
this
}
pub fn append(&self, step_idx: impl Into<StepIdx>) -> Self {
let mut this = self.clone();
this.0.push(step_idx.into());
this
}
}
impl Display for StepPath {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0
.iter()
.map(|idx| idx.to_string())
.collect::<Vec<_>>()
.join(".")
.fmt(f)
}
}
impl FromStr for StepPath {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.split(".")
.map(StepIdx::from_str)
.collect::<anyhow::Result<Vec<_>>>()
.map(Self)
}
}
impl From<StepPath> for String {
fn from(value: StepPath) -> Self {
value.to_string()
}
}
impl TryFrom<String> for StepPath {
type Error = anyhow::Error;
fn try_from(value: String) -> Result<Self, Self::Error> {
value.parse()
}
}
/// This is an input step which is a transaction description that the framework translates into a /// This is an input step which is a transaction description that the framework translates into a
/// transaction and executes on the nodes. /// transaction and executes on the nodes.
#[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq, JsonSchema)] #[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq, JsonSchema)]
+2 -2
View File
@@ -4,7 +4,7 @@ use std::{path::PathBuf, sync::Arc};
use revive_dt_common::{define_wrapper_type, types::PlatformIdentifier}; use revive_dt_common::{define_wrapper_type, types::PlatformIdentifier};
use revive_dt_compiler::Mode; use revive_dt_compiler::Mode;
use revive_dt_format::{case::CaseIdx, steps::StepIdx}; use revive_dt_format::{case::CaseIdx, steps::StepPath};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
define_wrapper_type!( define_wrapper_type!(
@@ -33,5 +33,5 @@ pub struct ExecutionSpecifier {
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct StepExecutionSpecifier { pub struct StepExecutionSpecifier {
pub execution_specifier: Arc<ExecutionSpecifier>, pub execution_specifier: Arc<ExecutionSpecifier>,
pub step_idx: StepIdx, pub step_idx: StepPath,
} }