reth_e2e_test_utils/testsuite/
mod.rs1use crate::{
4 testsuite::actions::{Action, ActionBox},
5 NodeBuilderHelper, PayloadAttributesBuilder,
6};
7use alloy_primitives::B256;
8use eyre::Result;
9use jsonrpsee::http_client::HttpClient;
10use reth_engine_local::LocalPayloadAttributesBuilder;
11use reth_node_api::{NodeTypes, PayloadTypes};
12use reth_payload_builder::PayloadId;
13use std::{collections::HashMap, marker::PhantomData};
14pub mod actions;
15pub mod setup;
16use crate::testsuite::setup::Setup;
17use alloy_rpc_types_engine::{ForkchoiceState, PayloadAttributes};
18use reth_rpc_builder::auth::AuthServerHandle;
19
20#[cfg(test)]
21mod examples;
22
23#[derive(Debug)]
25pub struct NodeClient {
26 pub rpc: HttpClient,
28 pub engine: AuthServerHandle,
30}
31
32impl NodeClient {
33 pub const fn new(rpc: HttpClient, engine: AuthServerHandle) -> Self {
35 Self { rpc, engine }
36 }
37}
38
39#[derive(Debug, Clone)]
41pub struct LatestBlockInfo {
42 pub hash: B256,
44 pub number: u64,
46}
47#[derive(Debug)]
49pub struct Environment<I> {
50 pub node_clients: Vec<NodeClient>,
52 _phantom: PhantomData<I>,
54 pub latest_block_info: Option<LatestBlockInfo>,
56 pub last_producer_idx: Option<usize>,
58 pub payload_attributes: HashMap<u64, PayloadAttributes>,
60 pub latest_header_time: u64,
62 pub block_timestamp_increment: u64,
64 pub payload_id_history: HashMap<u64, PayloadId>,
66 pub next_payload_id: Option<PayloadId>,
68 pub latest_fork_choice_state: ForkchoiceState,
70 pub latest_payload_built: Option<PayloadAttributes>,
72 pub latest_payload_executed: Option<PayloadAttributes>,
74 pub slots_to_safe: u64,
76 pub slots_to_finalized: u64,
78}
79
80impl<I> Default for Environment<I> {
81 fn default() -> Self {
82 Self {
83 node_clients: vec![],
84 _phantom: Default::default(),
85 latest_block_info: None,
86 last_producer_idx: None,
87 payload_attributes: Default::default(),
88 latest_header_time: 0,
89 block_timestamp_increment: 2,
90 payload_id_history: HashMap::new(),
91 next_payload_id: None,
92 latest_fork_choice_state: ForkchoiceState::default(),
93 latest_payload_built: None,
94 latest_payload_executed: None,
95 slots_to_safe: 0,
96 slots_to_finalized: 0,
97 }
98 }
99}
100
101#[expect(missing_debug_implementations)]
103#[derive(Default)]
104pub struct TestBuilder<I> {
105 setup: Option<Setup<I>>,
106 actions: Vec<ActionBox<I>>,
107 env: Environment<I>,
108}
109
110impl<I: 'static> TestBuilder<I> {
111 pub fn new() -> Self {
113 Self { setup: None, actions: Vec::new(), env: Default::default() }
114 }
115
116 pub fn with_setup(mut self, setup: Setup<I>) -> Self {
118 self.setup = Some(setup);
119 self
120 }
121
122 pub fn with_action<A>(mut self, action: A) -> Self
124 where
125 A: Action<I>,
126 {
127 self.actions.push(ActionBox::<I>::new(action));
128 self
129 }
130
131 pub fn with_actions<II, A>(mut self, actions: II) -> Self
133 where
134 II: IntoIterator<Item = A>,
135 A: Action<I>,
136 {
137 self.actions.extend(actions.into_iter().map(ActionBox::new));
138 self
139 }
140
141 pub async fn run<N>(mut self) -> Result<()>
143 where
144 N: NodeBuilderHelper,
145 LocalPayloadAttributesBuilder<N::ChainSpec>: PayloadAttributesBuilder<
146 <<N as NodeTypes>::Payload as PayloadTypes>::PayloadAttributes,
147 >,
148 {
149 let mut setup = self.setup.take();
150
151 if let Some(ref mut s) = setup {
152 s.apply::<N>(&mut self.env).await?;
153 }
154
155 let actions = std::mem::take(&mut self.actions);
156
157 for action in actions {
158 action.execute(&mut self.env).await?;
159 }
160
161 drop(setup);
164
165 Ok(())
166 }
167}