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