Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 129 additions & 6 deletions crates/storage/db-api/src/mock.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
//! Mock database
//! Mock database implementation for testing and development.
//!
//! Provides lightweight mock implementations of database traits. All operations
//! are no-ops that return default values without persisting data.

use crate::{
common::{IterPairResult, PairResult, ValueOnlyResult},
Expand All @@ -15,78 +18,140 @@ use crate::{
use core::ops::Bound;
use std::{collections::BTreeMap, ops::RangeBounds};

/// Mock database used for testing with inner `BTreeMap` structure
/// Mock database implementation for testing and development.
///
/// Provides a lightweight implementation of the [`Database`] trait suitable
/// for testing scenarios where actual database operations are not required.
#[derive(Clone, Debug, Default)]
pub struct DatabaseMock {
/// Main data. TODO (Make it table aware)
/// Internal data storage using a `BTreeMap`.
///
/// TODO: Make the mock database table-aware by properly utilizing
/// this data structure to simulate realistic database behavior during testing.
pub data: BTreeMap<Vec<u8>, Vec<u8>>,
}

impl Database for DatabaseMock {
type TX = TxMock;
type TXMut = TxMock;

/// Creates a new read-only transaction.
///
/// This always succeeds and returns a default [`TxMock`] instance.
/// The mock transaction doesn't actually perform any database operations.
fn tx(&self) -> Result<Self::TX, DatabaseError> {
Ok(TxMock::default())
}

/// Creates a new read-write transaction.
///
/// This always succeeds and returns a default [`TxMock`] instance.
/// The mock transaction doesn't actually perform any database operations.
fn tx_mut(&self) -> Result<Self::TXMut, DatabaseError> {
Ok(TxMock::default())
}
}

impl DatabaseMetrics for DatabaseMock {}

/// Mock read only tx
/// Mock transaction implementation for testing and development.
///
/// Implements both [`DbTx`] and [`DbTxMut`] traits. All operations are no-ops
/// that return success or default values, suitable for testing database operations
/// without side effects.
#[derive(Debug, Clone, Default)]
pub struct TxMock {
/// Table representation
/// Internal table representation (currently unused).
_table: BTreeMap<Vec<u8>, Vec<u8>>,
}

impl DbTx for TxMock {
type Cursor<T: Table> = CursorMock;
type DupCursor<T: DupSort> = CursorMock;

/// Retrieves a value by key from the specified table.
///
/// **Mock behavior**: Always returns `None` regardless of the key.
/// This simulates a table with no data, which is typical for testing
/// scenarios where you want to verify that read operations are called
/// correctly without actually storing data.
fn get<T: Table>(&self, _key: T::Key) -> Result<Option<T::Value>, DatabaseError> {
Ok(None)
}

/// Retrieves a value by encoded key from the specified table.
///
/// **Mock behavior**: Always returns `None` regardless of the encoded key.
/// This is equivalent to [`get`] but works with pre-encoded keys.
fn get_by_encoded_key<T: Table>(
&self,
_key: &<T::Key as Encode>::Encoded,
) -> Result<Option<T::Value>, DatabaseError> {
Ok(None)
}

/// Commits the transaction.
///
/// **Mock behavior**: Always returns `Ok(true)`, indicating successful commit.
/// No actual data is persisted since this is a mock implementation.
fn commit(self) -> Result<bool, DatabaseError> {
Ok(true)
}

/// Aborts the transaction.
///
/// **Mock behavior**: No-op. Since no data is actually stored in the mock,
/// there's nothing to rollback.
fn abort(self) {}

/// Creates a read-only cursor for the specified table.
///
/// **Mock behavior**: Returns a default [`CursorMock`] that will not
/// iterate over any data (all cursor operations return `None`).
fn cursor_read<T: Table>(&self) -> Result<Self::Cursor<T>, DatabaseError> {
Ok(CursorMock { _cursor: 0 })
}

/// Creates a read-only duplicate cursor for the specified duplicate sort table.
///
/// **Mock behavior**: Returns a default [`CursorMock`] that will not
/// iterate over any data (all cursor operations return `None`).
fn cursor_dup_read<T: DupSort>(&self) -> Result<Self::DupCursor<T>, DatabaseError> {
Ok(CursorMock { _cursor: 0 })
}

/// Returns the number of entries in the specified table.
///
/// **Mock behavior**: Returns the length of the internal `_table` `BTreeMap`,
/// which is typically 0 since no data is actually stored.
fn entries<T: Table>(&self) -> Result<usize, DatabaseError> {
Ok(self._table.len())
}

/// Disables long read transaction safety checks.
///
/// **Mock behavior**: No-op. This is a performance optimization that
/// doesn't apply to the mock implementation.
fn disable_long_read_transaction_safety(&mut self) {}
}

impl DbTxMut for TxMock {
type CursorMut<T: Table> = CursorMock;
type DupCursorMut<T: DupSort> = CursorMock;

/// Inserts or updates a key-value pair in the specified table.
///
/// **Mock behavior**: Always returns `Ok(())` without actually storing
/// the data. This allows tests to verify that write operations are called
/// correctly without side effects.
fn put<T: Table>(&self, _key: T::Key, _value: T::Value) -> Result<(), DatabaseError> {
Ok(())
}

/// Deletes a key-value pair from the specified table.
///
/// **Mock behavior**: Always returns `Ok(true)`, indicating successful
/// deletion, without actually removing any data.
fn delete<T: Table>(
&self,
_key: T::Key,
Expand All @@ -95,56 +160,88 @@ impl DbTxMut for TxMock {
Ok(true)
}

/// Clears all entries from the specified table.
///
/// **Mock behavior**: Always returns `Ok(())` without actually clearing
/// any data. This simulates successful table clearing for testing purposes.
fn clear<T: Table>(&self) -> Result<(), DatabaseError> {
Ok(())
}

/// Creates a write cursor for the specified table.
///
/// **Mock behavior**: Returns a default [`CursorMock`] that will not
/// iterate over any data and all write operations will be no-ops.
fn cursor_write<T: Table>(&self) -> Result<Self::CursorMut<T>, DatabaseError> {
Ok(CursorMock { _cursor: 0 })
}

/// Creates a write duplicate cursor for the specified duplicate sort table.
///
/// **Mock behavior**: Returns a default [`CursorMock`] that will not
/// iterate over any data and all write operations will be no-ops.
fn cursor_dup_write<T: DupSort>(&self) -> Result<Self::DupCursorMut<T>, DatabaseError> {
Ok(CursorMock { _cursor: 0 })
}
}

impl TableImporter for TxMock {}

/// Cursor that iterates over table
/// Mock cursor implementation for testing and development.
///
/// Implements all cursor traits. All operations are no-ops that return empty
/// results, suitable for testing cursor operations without side effects.
#[derive(Debug)]
pub struct CursorMock {
/// Internal cursor position (currently unused).
_cursor: u32,
}

impl<T: Table> DbCursorRO<T> for CursorMock {
/// Moves to the first entry in the table.
/// **Mock behavior**: Always returns `None`.
fn first(&mut self) -> PairResult<T> {
Ok(None)
}

/// Seeks to an exact key match.
/// **Mock behavior**: Always returns `None`.
fn seek_exact(&mut self, _key: T::Key) -> PairResult<T> {
Ok(None)
}

/// Seeks to the first key greater than or equal to the given key.
/// **Mock behavior**: Always returns `None`.
fn seek(&mut self, _key: T::Key) -> PairResult<T> {
Ok(None)
}

/// Moves to the next entry.
/// **Mock behavior**: Always returns `None`.
fn next(&mut self) -> PairResult<T> {
Ok(None)
}

/// Moves to the previous entry.
/// **Mock behavior**: Always returns `None`.
fn prev(&mut self) -> PairResult<T> {
Ok(None)
}

/// Moves to the last entry in the table.
/// **Mock behavior**: Always returns `None`.
fn last(&mut self) -> PairResult<T> {
Ok(None)
}

/// Returns the current entry without moving the cursor.
/// **Mock behavior**: Always returns `None`.
fn current(&mut self) -> PairResult<T> {
Ok(None)
}

/// Creates a forward walker starting from the given key.
/// **Mock behavior**: Returns an empty walker that won't iterate over any data.
fn walk(&mut self, start_key: Option<T::Key>) -> Result<Walker<'_, T, Self>, DatabaseError> {
let start: IterPairResult<T> = match start_key {
Some(key) => <Self as DbCursorRO<T>>::seek(self, key).transpose(),
Expand All @@ -154,6 +251,8 @@ impl<T: Table> DbCursorRO<T> for CursorMock {
Ok(Walker::new(self, start))
}

/// Creates a range walker for the specified key range.
/// **Mock behavior**: Returns an empty walker that won't iterate over any data.
fn walk_range(
&mut self,
range: impl RangeBounds<T::Key>,
Expand All @@ -176,6 +275,8 @@ impl<T: Table> DbCursorRO<T> for CursorMock {
Ok(RangeWalker::new(self, start, end_key))
}

/// Creates a backward walker starting from the given key.
/// **Mock behavior**: Returns an empty walker that won't iterate over any data.
fn walk_back(
&mut self,
start_key: Option<T::Key>,
Expand All @@ -189,18 +290,26 @@ impl<T: Table> DbCursorRO<T> for CursorMock {
}

impl<T: DupSort> DbDupCursorRO<T> for CursorMock {
/// Moves to the next duplicate entry.
/// **Mock behavior**: Always returns `None`.
fn next_dup(&mut self) -> PairResult<T> {
Ok(None)
}

/// Moves to the next entry with a different key.
/// **Mock behavior**: Always returns `None`.
fn next_no_dup(&mut self) -> PairResult<T> {
Ok(None)
}

/// Moves to the next duplicate value.
/// **Mock behavior**: Always returns `None`.
fn next_dup_val(&mut self) -> ValueOnlyResult<T> {
Ok(None)
}

/// Seeks to a specific key-subkey combination.
/// **Mock behavior**: Always returns `None`.
fn seek_by_key_subkey(
&mut self,
_key: <T as Table>::Key,
Expand All @@ -209,6 +318,8 @@ impl<T: DupSort> DbDupCursorRO<T> for CursorMock {
Ok(None)
}

/// Creates a duplicate walker for the specified key and subkey.
/// **Mock behavior**: Returns an empty walker that won't iterate over any data.
fn walk_dup(
&mut self,
_key: Option<<T>::Key>,
Expand All @@ -219,6 +330,8 @@ impl<T: DupSort> DbDupCursorRO<T> for CursorMock {
}

impl<T: Table> DbCursorRW<T> for CursorMock {
/// Inserts or updates a key-value pair at the current cursor position.
/// **Mock behavior**: Always succeeds without modifying any data.
fn upsert(
&mut self,
_key: <T as Table>::Key,
Expand All @@ -227,6 +340,8 @@ impl<T: Table> DbCursorRW<T> for CursorMock {
Ok(())
}

/// Inserts a key-value pair at the current cursor position.
/// **Mock behavior**: Always succeeds without modifying any data.
fn insert(
&mut self,
_key: <T as Table>::Key,
Expand All @@ -235,6 +350,8 @@ impl<T: Table> DbCursorRW<T> for CursorMock {
Ok(())
}

/// Appends a key-value pair at the end of the table.
/// **Mock behavior**: Always succeeds without modifying any data.
fn append(
&mut self,
_key: <T as Table>::Key,
Expand All @@ -243,16 +360,22 @@ impl<T: Table> DbCursorRW<T> for CursorMock {
Ok(())
}

/// Deletes the entry at the current cursor position.
/// **Mock behavior**: Always succeeds without modifying any data.
fn delete_current(&mut self) -> Result<(), DatabaseError> {
Ok(())
}
}

impl<T: DupSort> DbDupCursorRW<T> for CursorMock {
/// Deletes all duplicate entries at the current cursor position.
/// **Mock behavior**: Always succeeds without modifying any data.
fn delete_current_duplicates(&mut self) -> Result<(), DatabaseError> {
Ok(())
}

/// Appends a duplicate key-value pair.
/// **Mock behavior**: Always succeeds without modifying any data.
fn append_dup(&mut self, _key: <T>::Key, _value: <T>::Value) -> Result<(), DatabaseError> {
Ok(())
}
Expand Down
Loading