reth_db_api/mock.rs
1//! Mock database implementation for testing and development.
2//!
3//! Provides lightweight mock implementations of database traits. All operations
4//! are no-ops that return default values without persisting data.
5
6use crate::{
7 common::{IterPairResult, PairResult, ValueOnlyResult},
8 cursor::{
9 DbCursorRO, DbCursorRW, DbDupCursorRO, DbDupCursorRW, DupWalker, RangeWalker,
10 ReverseWalker, Walker,
11 },
12 database::Database,
13 database_metrics::DatabaseMetrics,
14 table::{DupSort, Encode, Table, TableImporter},
15 transaction::{DbTx, DbTxMut},
16 DatabaseError,
17};
18use core::ops::Bound;
19use std::{collections::BTreeMap, ops::RangeBounds, path::PathBuf};
20
21/// Mock database implementation for testing and development.
22///
23/// Provides a lightweight implementation of the [`Database`] trait suitable
24/// for testing scenarios where actual database operations are not required.
25#[derive(Clone, Debug, Default)]
26pub struct DatabaseMock {
27 /// Internal data storage using a `BTreeMap`.
28 ///
29 /// TODO: Make the mock database table-aware by properly utilizing
30 /// this data structure to simulate realistic database behavior during testing.
31 pub data: BTreeMap<Vec<u8>, Vec<u8>>,
32}
33
34impl Database for DatabaseMock {
35 type TX = TxMock;
36 type TXMut = TxMock;
37
38 /// Creates a new read-only transaction.
39 ///
40 /// This always succeeds and returns a default [`TxMock`] instance.
41 /// The mock transaction doesn't actually perform any database operations.
42 fn tx(&self) -> Result<Self::TX, DatabaseError> {
43 Ok(TxMock::default())
44 }
45
46 /// Creates a new read-write transaction.
47 ///
48 /// This always succeeds and returns a default [`TxMock`] instance.
49 /// The mock transaction doesn't actually perform any database operations.
50 fn tx_mut(&self) -> Result<Self::TXMut, DatabaseError> {
51 Ok(TxMock::default())
52 }
53
54 fn path(&self) -> PathBuf {
55 PathBuf::default()
56 }
57
58 fn oldest_reader_txnid(&self) -> Option<u64> {
59 None
60 }
61
62 fn last_txnid(&self) -> Option<u64> {
63 None
64 }
65}
66
67impl DatabaseMetrics for DatabaseMock {}
68
69/// Mock transaction implementation for testing and development.
70///
71/// Implements both [`DbTx`] and [`DbTxMut`] traits. All operations are no-ops
72/// that return success or default values, suitable for testing database operations
73/// without side effects.
74#[derive(Debug, Clone, Default)]
75pub struct TxMock {
76 /// Internal table representation (currently unused).
77 _table: BTreeMap<Vec<u8>, Vec<u8>>,
78}
79
80impl DbTx for TxMock {
81 type Cursor<T: Table> = CursorMock;
82 type DupCursor<T: DupSort> = CursorMock;
83
84 /// Retrieves a value by key from the specified table.
85 ///
86 /// **Mock behavior**: Always returns `None` regardless of the key.
87 /// This simulates a table with no data, which is typical for testing
88 /// scenarios where you want to verify that read operations are called
89 /// correctly without actually storing data.
90 fn get<T: Table>(&self, _key: T::Key) -> Result<Option<T::Value>, DatabaseError> {
91 Ok(None)
92 }
93
94 /// Retrieves a value by encoded key from the specified table.
95 ///
96 /// **Mock behavior**: Always returns `None` regardless of the encoded key.
97 /// This is equivalent to [`Self::get`] but works with pre-encoded keys.
98 fn get_by_encoded_key<T: Table>(
99 &self,
100 _key: &<T::Key as Encode>::Encoded,
101 ) -> Result<Option<T::Value>, DatabaseError> {
102 Ok(None)
103 }
104
105 /// Commits the transaction.
106 ///
107 /// **Mock behavior**: Always returns `Ok(())`, indicating successful commit.
108 /// No actual data is persisted since this is a mock implementation.
109 fn commit(self) -> Result<(), DatabaseError> {
110 Ok(())
111 }
112
113 /// Aborts the transaction.
114 ///
115 /// **Mock behavior**: No-op. Since no data is actually stored in the mock,
116 /// there's nothing to rollback.
117 fn abort(self) {}
118
119 /// Creates a read-only cursor for the specified table.
120 ///
121 /// **Mock behavior**: Returns a default [`CursorMock`] that will not
122 /// iterate over any data (all cursor operations return `None`).
123 fn cursor_read<T: Table>(&self) -> Result<Self::Cursor<T>, DatabaseError> {
124 Ok(CursorMock { _cursor: 0 })
125 }
126
127 /// Creates a read-only duplicate cursor for the specified duplicate sort table.
128 ///
129 /// **Mock behavior**: Returns a default [`CursorMock`] that will not
130 /// iterate over any data (all cursor operations return `None`).
131 fn cursor_dup_read<T: DupSort>(&self) -> Result<Self::DupCursor<T>, DatabaseError> {
132 Ok(CursorMock { _cursor: 0 })
133 }
134
135 /// Returns the number of entries in the specified table.
136 ///
137 /// **Mock behavior**: Returns the length of the internal `_table` `BTreeMap`,
138 /// which is typically 0 since no data is actually stored.
139 fn entries<T: Table>(&self) -> Result<usize, DatabaseError> {
140 Ok(self._table.len())
141 }
142
143 /// Disables long read transaction safety checks.
144 ///
145 /// **Mock behavior**: No-op. This is a performance optimization that
146 /// doesn't apply to the mock implementation.
147 fn disable_long_read_transaction_safety(&mut self) {}
148}
149
150impl DbTxMut for TxMock {
151 type CursorMut<T: Table> = CursorMock;
152 type DupCursorMut<T: DupSort> = CursorMock;
153
154 /// Inserts or updates a key-value pair in the specified table.
155 ///
156 /// **Mock behavior**: Always returns `Ok(())` without actually storing
157 /// the data. This allows tests to verify that write operations are called
158 /// correctly without side effects.
159 fn put<T: Table>(&self, _key: T::Key, _value: T::Value) -> Result<(), DatabaseError> {
160 Ok(())
161 }
162
163 /// Deletes a key-value pair from the specified table.
164 ///
165 /// **Mock behavior**: Always returns `Ok(true)`, indicating successful
166 /// deletion, without actually removing any data.
167 fn delete<T: Table>(
168 &self,
169 _key: T::Key,
170 _value: Option<T::Value>,
171 ) -> Result<bool, DatabaseError> {
172 Ok(true)
173 }
174
175 /// Clears all entries from the specified table.
176 ///
177 /// **Mock behavior**: Always returns `Ok(())` without actually clearing
178 /// any data. This simulates successful table clearing for testing purposes.
179 fn clear<T: Table>(&self) -> Result<(), DatabaseError> {
180 Ok(())
181 }
182
183 /// Creates a write cursor for the specified table.
184 ///
185 /// **Mock behavior**: Returns a default [`CursorMock`] that will not
186 /// iterate over any data and all write operations will be no-ops.
187 fn cursor_write<T: Table>(&self) -> Result<Self::CursorMut<T>, DatabaseError> {
188 Ok(CursorMock { _cursor: 0 })
189 }
190
191 /// Creates a write duplicate cursor for the specified duplicate sort table.
192 ///
193 /// **Mock behavior**: Returns a default [`CursorMock`] that will not
194 /// iterate over any data and all write operations will be no-ops.
195 fn cursor_dup_write<T: DupSort>(&self) -> Result<Self::DupCursorMut<T>, DatabaseError> {
196 Ok(CursorMock { _cursor: 0 })
197 }
198}
199
200impl TableImporter for TxMock {}
201
202/// Mock cursor implementation for testing and development.
203///
204/// Implements all cursor traits. All operations are no-ops that return empty
205/// results, suitable for testing cursor operations without side effects.
206#[derive(Debug)]
207pub struct CursorMock {
208 /// Internal cursor position (currently unused).
209 _cursor: u32,
210}
211
212impl<T: Table> DbCursorRO<T> for CursorMock {
213 /// Moves to the first entry in the table.
214 /// **Mock behavior**: Always returns `None`.
215 fn first(&mut self) -> PairResult<T> {
216 Ok(None)
217 }
218
219 /// Seeks to an exact key match.
220 /// **Mock behavior**: Always returns `None`.
221 fn seek_exact(&mut self, _key: T::Key) -> PairResult<T> {
222 Ok(None)
223 }
224
225 /// Seeks to the first key greater than or equal to the given key.
226 /// **Mock behavior**: Always returns `None`.
227 fn seek(&mut self, _key: T::Key) -> PairResult<T> {
228 Ok(None)
229 }
230
231 /// Moves to the next entry.
232 /// **Mock behavior**: Always returns `None`.
233 fn next(&mut self) -> PairResult<T> {
234 Ok(None)
235 }
236
237 /// Moves to the previous entry.
238 /// **Mock behavior**: Always returns `None`.
239 fn prev(&mut self) -> PairResult<T> {
240 Ok(None)
241 }
242
243 /// Moves to the last entry in the table.
244 /// **Mock behavior**: Always returns `None`.
245 fn last(&mut self) -> PairResult<T> {
246 Ok(None)
247 }
248
249 /// Returns the current entry without moving the cursor.
250 /// **Mock behavior**: Always returns `None`.
251 fn current(&mut self) -> PairResult<T> {
252 Ok(None)
253 }
254
255 /// Creates a forward walker starting from the given key.
256 /// **Mock behavior**: Returns an empty walker that won't iterate over any data.
257 fn walk(&mut self, start_key: Option<T::Key>) -> Result<Walker<'_, T, Self>, DatabaseError> {
258 let start: IterPairResult<T> = match start_key {
259 Some(key) => <Self as DbCursorRO<T>>::seek(self, key).transpose(),
260 None => <Self as DbCursorRO<T>>::first(self).transpose(),
261 };
262
263 Ok(Walker::new(self, start))
264 }
265
266 /// Creates a range walker for the specified key range.
267 /// **Mock behavior**: Returns an empty walker that won't iterate over any data.
268 fn walk_range(
269 &mut self,
270 range: impl RangeBounds<T::Key>,
271 ) -> Result<RangeWalker<'_, T, Self>, DatabaseError> {
272 let start_key = match range.start_bound() {
273 Bound::Included(key) | Bound::Excluded(key) => Some((*key).clone()),
274 Bound::Unbounded => None,
275 };
276
277 let end_key = match range.end_bound() {
278 Bound::Included(key) | Bound::Excluded(key) => Bound::Included((*key).clone()),
279 Bound::Unbounded => Bound::Unbounded,
280 };
281
282 let start: IterPairResult<T> = match start_key {
283 Some(key) => <Self as DbCursorRO<T>>::seek(self, key).transpose(),
284 None => <Self as DbCursorRO<T>>::first(self).transpose(),
285 };
286
287 Ok(RangeWalker::new(self, start, end_key))
288 }
289
290 /// Creates a backward walker starting from the given key.
291 /// **Mock behavior**: Returns an empty walker that won't iterate over any data.
292 fn walk_back(
293 &mut self,
294 start_key: Option<T::Key>,
295 ) -> Result<ReverseWalker<'_, T, Self>, DatabaseError> {
296 let start: IterPairResult<T> = match start_key {
297 Some(key) => <Self as DbCursorRO<T>>::seek(self, key).transpose(),
298 None => <Self as DbCursorRO<T>>::last(self).transpose(),
299 };
300 Ok(ReverseWalker::new(self, start))
301 }
302}
303
304impl<T: DupSort> DbDupCursorRO<T> for CursorMock {
305 /// Moves to the next duplicate entry.
306 /// **Mock behavior**: Always returns `None`.
307 fn next_dup(&mut self) -> PairResult<T> {
308 Ok(None)
309 }
310
311 /// Moves to the previous duplicate entry.
312 /// **Mock behavior**: Always returns `None`.
313 fn prev_dup(&mut self) -> PairResult<T> {
314 Ok(None)
315 }
316
317 /// Moves to the last duplicate entry.
318 /// **Mock behavior**: Always returns `None`.
319 fn last_dup(&mut self) -> ValueOnlyResult<T> {
320 Ok(None)
321 }
322
323 /// Moves to the next entry with a different key.
324 /// **Mock behavior**: Always returns `None`.
325 fn next_no_dup(&mut self) -> PairResult<T> {
326 Ok(None)
327 }
328
329 /// Moves to the next duplicate value.
330 /// **Mock behavior**: Always returns `None`.
331 fn next_dup_val(&mut self) -> ValueOnlyResult<T> {
332 Ok(None)
333 }
334
335 /// Seeks to a specific key-subkey combination.
336 /// **Mock behavior**: Always returns `None`.
337 fn seek_by_key_subkey(
338 &mut self,
339 _key: <T as Table>::Key,
340 _subkey: <T as DupSort>::SubKey,
341 ) -> ValueOnlyResult<T> {
342 Ok(None)
343 }
344
345 /// Creates a duplicate walker for the specified key and subkey.
346 /// **Mock behavior**: Returns an empty walker that won't iterate over any data.
347 fn walk_dup(
348 &mut self,
349 _key: Option<<T>::Key>,
350 _subkey: Option<<T as DupSort>::SubKey>,
351 ) -> Result<DupWalker<'_, T, Self>, DatabaseError> {
352 Ok(DupWalker { cursor: self, start: None })
353 }
354}
355
356impl<T: Table> DbCursorRW<T> for CursorMock {
357 /// Inserts or updates a key-value pair at the current cursor position.
358 /// **Mock behavior**: Always succeeds without modifying any data.
359 fn upsert(
360 &mut self,
361 _key: <T as Table>::Key,
362 _value: &<T as Table>::Value,
363 ) -> Result<(), DatabaseError> {
364 Ok(())
365 }
366
367 /// Inserts a key-value pair at the current cursor position.
368 /// **Mock behavior**: Always succeeds without modifying any data.
369 fn insert(
370 &mut self,
371 _key: <T as Table>::Key,
372 _value: &<T as Table>::Value,
373 ) -> Result<(), DatabaseError> {
374 Ok(())
375 }
376
377 /// Appends a key-value pair at the end of the table.
378 /// **Mock behavior**: Always succeeds without modifying any data.
379 fn append(
380 &mut self,
381 _key: <T as Table>::Key,
382 _value: &<T as Table>::Value,
383 ) -> Result<(), DatabaseError> {
384 Ok(())
385 }
386
387 /// Deletes the entry at the current cursor position.
388 /// **Mock behavior**: Always succeeds without modifying any data.
389 fn delete_current(&mut self) -> Result<(), DatabaseError> {
390 Ok(())
391 }
392}
393
394impl<T: DupSort> DbDupCursorRW<T> for CursorMock {
395 /// Deletes all duplicate entries at the current cursor position.
396 /// **Mock behavior**: Always succeeds without modifying any data.
397 fn delete_current_duplicates(&mut self) -> Result<(), DatabaseError> {
398 Ok(())
399 }
400
401 /// Appends a duplicate key-value pair.
402 /// **Mock behavior**: Always succeeds without modifying any data.
403 fn append_dup(&mut self, _key: <T>::Key, _value: <T>::Value) -> Result<(), DatabaseError> {
404 Ok(())
405 }
406}