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