Skip to main content

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}