Skip to content

Commit 1c7d570

Browse files
committed
Clean up tests
1 parent cf5ac0b commit 1c7d570

19 files changed

+968
-813
lines changed

crates/simulator/src/core.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ pub trait BundleSimulator: Send + Sync {
1212
async fn simulate(&self, request: &SimulationRequest) -> Result<()>;
1313
}
1414

15-
/// Production bundle simulator for Reth
16-
/// This is the Reth-specific implementation
17-
pub struct RethBundleSimulator<E, P>
15+
/// Production bundle simulator implementation
16+
/// Wires the engine and publisher together for bundle simulation
17+
pub struct BundleSimulatorImpl<E, P>
1818
where
1919
E: SimulationEngine,
2020
P: SimulationPublisher,
@@ -23,7 +23,7 @@ where
2323
publisher: P,
2424
}
2525

26-
impl<E, P> RethBundleSimulator<E, P>
26+
impl<E, P> BundleSimulatorImpl<E, P>
2727
where
2828
E: SimulationEngine,
2929
P: SimulationPublisher,
@@ -34,7 +34,7 @@ where
3434
}
3535

3636
#[async_trait]
37-
impl<E, P> BundleSimulator for RethBundleSimulator<E, P>
37+
impl<E, P> BundleSimulator for BundleSimulatorImpl<E, P>
3838
where
3939
E: SimulationEngine + 'static,
4040
P: SimulationPublisher + 'static,

crates/simulator/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use std::sync::Arc;
1515
use tracing::{error, info};
1616

1717
pub use config::SimulatorNodeConfig;
18-
pub use core::{BundleSimulator, RethBundleSimulator};
18+
pub use core::{BundleSimulator, BundleSimulatorImpl};
1919
pub use engine::{RethSimulationEngine, SimulationEngine};
2020
pub use listeners::{ExExEventListener, MempoolEventListener, MempoolListenerConfig};
2121
pub use publisher::{SimulationPublisher, TipsSimulationPublisher};
@@ -24,7 +24,7 @@ pub use worker_pool::SimulationWorkerPool;
2424

2525
// Type aliases for concrete implementations
2626
pub type TipsBundleSimulator<Node> =
27-
RethBundleSimulator<RethSimulationEngine<Node>, TipsSimulationPublisher>;
27+
BundleSimulatorImpl<RethSimulationEngine<Node>, TipsSimulationPublisher>;
2828
pub type TipsExExEventListener<Node> =
2929
ExExEventListener<Node, TipsBundleSimulator<Node>, tips_datastore::PostgresDatastore>;
3030
pub type TipsMempoolEventListener<Node> = MempoolEventListener<Node, TipsBundleSimulator<Node>>;
@@ -47,7 +47,7 @@ async fn init_dependencies<Node>(
4747
database_url: String,
4848
kafka_brokers: String,
4949
kafka_topic: String,
50-
) -> Result<ListenerDependencies<RethBundleSimulator<RethSimulationEngine<Node>, TipsSimulationPublisher>>>
50+
) -> Result<ListenerDependencies<BundleSimulatorImpl<RethSimulationEngine<Node>, TipsSimulationPublisher>>>
5151
where
5252
Node: FullNodeComponents,
5353
<Node as FullNodeComponents>::Evm: ConfigureEvm<NextBlockEnvCtx = OpNextBlockEnvAttributes>,
@@ -75,7 +75,7 @@ where
7575
let engine = RethSimulationEngine::new(Arc::clone(&provider), evm_config);
7676
info!("Simulation engine initialized");
7777

78-
let simulator = RethBundleSimulator::new(engine, publisher);
78+
let simulator = BundleSimulatorImpl::new(engine, publisher);
7979
info!("Core bundle simulator initialized");
8080

8181
Ok(ListenerDependencies {
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
// Tests for the concrete BundleSimulator implementation
2+
mod common;
3+
4+
use common::builders::*;
5+
use common::fixtures::*;
6+
use common::mocks::*;
7+
use tips_simulator::{core::BundleSimulator, core::BundleSimulatorImpl, SimulationError};
8+
use uuid::Uuid;
9+
10+
#[tokio::test]
11+
async fn test_bundle_simulator_impl_successful_flow() {
12+
// Setup - exercise the concrete BundleSimulator implementation
13+
let bundle_id = Uuid::new_v4();
14+
let expected_result = SimulationResultBuilder::successful()
15+
.with_ids(Uuid::new_v4(), bundle_id)
16+
.with_gas_used(250_000)
17+
.with_execution_time_us(2500)
18+
.build();
19+
20+
let engine = MockSimulationEngine::new().with_result(expected_result.clone());
21+
let publisher = MockSimulationPublisher::new();
22+
let simulator = BundleSimulatorImpl::new(engine.clone(), publisher.clone());
23+
24+
let request = SimulationRequestBuilder::new()
25+
.with_bundle_id(bundle_id)
26+
.with_bundle(bundles::single_tx_bundle())
27+
.build();
28+
29+
// Act - test the actual BundleSimulator trait implementation
30+
let result = simulator.simulate(&request).await;
31+
32+
// Assert
33+
assert!(result.is_ok());
34+
assert_eq!(engine.simulation_count(), 1);
35+
assert_eq!(publisher.published_count(), 1);
36+
37+
let published = publisher.get_published();
38+
assert_eq!(published[0].bundle_id, bundle_id);
39+
assert_eq!(published[0].gas_used, Some(250_000));
40+
assert!(published[0].success);
41+
}
42+
43+
#[tokio::test]
44+
async fn test_bundle_simulator_impl_engine_failure() {
45+
// Test that the concrete BundleSimulator handles engine failures
46+
let bundle_id = Uuid::new_v4();
47+
let engine = MockSimulationEngine::new().fail_next_with(SimulationError::OutOfGas);
48+
let publisher = MockSimulationPublisher::new();
49+
let simulator = BundleSimulatorImpl::new(engine.clone(), publisher.clone());
50+
51+
let request = SimulationRequestBuilder::new()
52+
.with_bundle_id(bundle_id)
53+
.build();
54+
55+
// Act
56+
let result = simulator.simulate(&request).await;
57+
58+
// Assert - simulate() should succeed even if the engine simulation fails
59+
assert!(result.is_ok());
60+
assert_eq!(engine.simulation_count(), 1);
61+
assert_eq!(publisher.published_count(), 1);
62+
63+
let published = publisher.get_published();
64+
assert!(!published[0].success);
65+
assert!(published[0].error_reason.is_some());
66+
}
67+
68+
#[tokio::test]
69+
async fn test_bundle_simulator_impl_publisher_failure() {
70+
// Test that the concrete BundleSimulator handles publisher failures gracefully
71+
let engine = MockSimulationEngine::new();
72+
let publisher = MockSimulationPublisher::new().fail_next();
73+
let simulator = BundleSimulatorImpl::new(engine.clone(), publisher.clone());
74+
75+
let request = SimulationRequestBuilder::new().build();
76+
77+
// Act - should complete without error even if publisher fails
78+
let result = simulator.simulate(&request).await;
79+
80+
// Assert
81+
assert!(result.is_ok());
82+
assert_eq!(engine.simulation_count(), 1);
83+
assert_eq!(publisher.published_count(), 0); // Publisher failed
84+
}
85+
86+
#[tokio::test]
87+
async fn test_bundle_simulator_impl_multiple_simulations() {
88+
// Test the concrete BundleSimulator with multiple sequential simulations
89+
let engine = MockSimulationEngine::new();
90+
let publisher = MockSimulationPublisher::new();
91+
let simulator = BundleSimulatorImpl::new(engine.clone(), publisher.clone());
92+
93+
// Run multiple simulations with different bundle IDs
94+
for i in 0..3 {
95+
let bundle_id = Uuid::new_v4();
96+
let result = SimulationResultBuilder::successful()
97+
.with_ids(Uuid::new_v4(), bundle_id)
98+
.with_gas_used(100_000 + i * 50_000)
99+
.build();
100+
101+
let _ = engine.clone().with_result(result);
102+
103+
let request = SimulationRequestBuilder::new()
104+
.with_bundle_id(bundle_id)
105+
.with_bundle(
106+
TestBundleBuilder::new()
107+
.with_simple_transaction(&[i as u8, 0x01, 0x02])
108+
.build(),
109+
)
110+
.build();
111+
112+
let sim_result = simulator.simulate(&request).await;
113+
assert!(sim_result.is_ok());
114+
}
115+
116+
// Verify all simulations were processed
117+
assert_eq!(engine.simulation_count(), 3);
118+
assert_eq!(publisher.published_count(), 3);
119+
120+
let published = publisher.get_published();
121+
assert_eq!(published.len(), 3);
122+
for (i, result) in published.iter().enumerate() {
123+
assert!(result.success);
124+
assert_eq!(result.gas_used, Some(100_000 + i as u64 * 50_000));
125+
}
126+
}
127+
128+
#[tokio::test]
129+
async fn test_bundle_simulator_impl_various_error_types() {
130+
// Test the concrete BundleSimulator with different types of simulation errors
131+
let errors = vec![
132+
SimulationError::Revert {
133+
reason: "Contract reverted".to_string(),
134+
},
135+
SimulationError::InvalidNonce {
136+
tx_index: 1,
137+
expected: 10,
138+
actual: 5,
139+
},
140+
SimulationError::InsufficientBalance {
141+
tx_index: 0,
142+
required: alloy_primitives::U256::from(1000000),
143+
available: alloy_primitives::U256::from(500000),
144+
},
145+
SimulationError::StateAccessError {
146+
message: "RPC timeout".to_string(),
147+
},
148+
SimulationError::Timeout,
149+
];
150+
151+
for (_i, error) in errors.into_iter().enumerate() {
152+
let engine = MockSimulationEngine::new().fail_next_with(error.clone());
153+
let publisher = MockSimulationPublisher::new();
154+
let simulator = BundleSimulatorImpl::new(engine.clone(), publisher.clone());
155+
156+
let request = SimulationRequestBuilder::new()
157+
.with_bundle_id(Uuid::new_v4())
158+
.build();
159+
160+
let result = simulator.simulate(&request).await;
161+
assert!(result.is_ok());
162+
163+
let published = publisher.get_published();
164+
assert_eq!(published.len(), 1);
165+
assert!(!published[0].success);
166+
167+
let error_msg = published[0].error_reason.as_ref().unwrap();
168+
match error {
169+
SimulationError::Revert { .. } => assert!(error_msg.contains("reverted")),
170+
SimulationError::InvalidNonce { .. } => assert!(error_msg.contains("nonce")),
171+
SimulationError::InsufficientBalance { .. } => assert!(error_msg.contains("balance")),
172+
SimulationError::StateAccessError { .. } => assert!(error_msg.contains("State access")),
173+
SimulationError::Timeout => assert!(error_msg.contains("timed out")),
174+
_ => {}
175+
}
176+
}
177+
}
178+

crates/simulator/tests/common/builders.rs

Lines changed: 3 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
#![allow(dead_code)]
2+
13
/// Test data builders for creating complex test scenarios
4+
25
use alloy_primitives::{Address, Bytes, B256, U256};
36
use alloy_rpc_types_mev::EthSendBundle;
47
use std::collections::HashMap;
@@ -277,51 +280,3 @@ impl ScenarioBuilder {
277280
}
278281
}
279282

280-
#[cfg(test)]
281-
mod tests {
282-
use super::*;
283-
284-
#[test]
285-
fn test_bundle_builder() {
286-
let bundle = TestBundleBuilder::new()
287-
.with_simple_transaction(&[0x01, 0x02])
288-
.with_simple_transaction(&[0x03, 0x04])
289-
.with_block_number(18_500_000)
290-
.with_timestamps(1000, 2000)
291-
.build();
292-
293-
assert_eq!(bundle.txs.len(), 2);
294-
assert_eq!(bundle.block_number, 18_500_000);
295-
assert_eq!(bundle.min_timestamp, Some(1000));
296-
assert_eq!(bundle.max_timestamp, Some(2000));
297-
}
298-
299-
#[test]
300-
fn test_result_builder() {
301-
let bundle_id = Uuid::new_v4();
302-
let result = SimulationResultBuilder::successful()
303-
.with_ids(Uuid::new_v4(), bundle_id)
304-
.with_gas_used(200_000)
305-
.with_state_change(Address::random(), U256::from(1), U256::from(100))
306-
.build();
307-
308-
assert!(result.success);
309-
assert_eq!(result.bundle_id, bundle_id);
310-
assert_eq!(result.gas_used, Some(200_000));
311-
assert!(!result.state_diff.is_empty());
312-
}
313-
314-
#[test]
315-
fn test_scenario_builder() {
316-
let requests = ScenarioBuilder::new()
317-
.with_block(19_000_000, B256::random())
318-
.add_simple_bundle(2)
319-
.add_simple_bundle(3)
320-
.build_requests();
321-
322-
assert_eq!(requests.len(), 2);
323-
assert_eq!(requests[0].block_number, 19_000_000);
324-
assert_eq!(requests[0].bundle.txs.len(), 2);
325-
assert_eq!(requests[1].bundle.txs.len(), 3);
326-
}
327-
}

crates/simulator/tests/common/fixtures.rs

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
#![allow(dead_code)]
2+
13
/// Test fixtures and pre-configured test data
4+
25
use alloy_primitives::Bytes;
36
use alloy_rpc_types_mev::EthSendBundle;
47

@@ -141,38 +144,3 @@ pub mod scenarios {
141144
}
142145
}
143146

144-
#[cfg(test)]
145-
mod tests {
146-
use super::*;
147-
148-
#[test]
149-
fn test_fixture_addresses() {
150-
assert_ne!(*addresses::ALICE, *addresses::BOB);
151-
assert_ne!(*addresses::CONTRACT_A, *addresses::CONTRACT_B);
152-
}
153-
154-
#[test]
155-
fn test_fixture_bundles() {
156-
let single = bundles::single_tx_bundle();
157-
assert_eq!(single.txs.len(), 1);
158-
159-
let multi = bundles::multi_tx_bundle();
160-
assert_eq!(multi.txs.len(), 3);
161-
162-
let large = bundles::large_bundle(100);
163-
assert_eq!(large.txs.len(), 100);
164-
}
165-
166-
#[test]
167-
fn test_fixture_scenarios() {
168-
let request = scenarios::basic_simulation();
169-
assert_eq!(request.block_number, blocks::BLOCK_18M);
170-
assert_eq!(request.bundle.txs.len(), 1);
171-
172-
let interaction = scenarios::contract_interaction();
173-
assert_eq!(interaction.bundle.txs.len(), 3);
174-
175-
let large_scenario = scenarios::large_bundle_scenario();
176-
assert_eq!(large_scenario.bundle.txs.len(), 100);
177-
}
178-
}

crates/simulator/tests/common/mock_bundle_simulator.rs

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![allow(dead_code)]
2+
13
use crate::common::mocks::{MockSimulationEngine, MockSimulationPublisher};
24
use async_trait::async_trait;
35
use eyre::Result;
@@ -55,25 +57,3 @@ impl BundleSimulator for MockBundleSimulator {
5557
}
5658
}
5759

58-
#[cfg(test)]
59-
mod tests {
60-
use super::*;
61-
use crate::common;
62-
63-
#[tokio::test]
64-
async fn test_mock_bundle_simulator() {
65-
let engine = MockSimulationEngine::new();
66-
let publisher = MockSimulationPublisher::new();
67-
let simulator = MockBundleSimulator::new(engine.clone(), publisher.clone());
68-
69-
let bundle = common::create_test_bundle(1, 18_000_000);
70-
let request = common::create_test_request(bundle);
71-
72-
// Use the clean trait interface
73-
let result = simulator.simulate(&request).await;
74-
75-
assert!(result.is_ok());
76-
assert_eq!(engine.simulation_count(), 1);
77-
assert_eq!(publisher.published_count(), 1);
78-
}
79-
}

0 commit comments

Comments
 (0)