#![allow(dead_code, unused_imports)]
pub mod test_epoch;
pub mod test_storage;
use crate::api::KeyEncodingId;
use crate::bplustree::NodeView;
use crate::bplustree::transaction::WriteTransaction;
use crate::bplustree::tree::{BPlusTree, SharedBPlusTree};
use crate::database::metadata::Metadata;
use crate::keyfmt::KeyFormat;
use crate::keyfmt::raw::RawFormat;
use crate::page::LeafPage;
use crate::storage::epoch::EpochManager;
use crate::storage::file_page_storage::FilePageStorage;
use crate::storage::metadata_manager::MetadataManager;
use crate::storage::paged_node_storage::PagedNodeStorage;
use crate::storage::{HasEpoch, NodeStorage, PageStorage};
use std::sync::Arc;
use tempfile::TempDir;
const TEST_META_A: u64 = 0;
const TEST_META_B: u64 = 1;
const TEST_TREE_ID: u64 = 1;
pub struct TestHarness<S, P>
where
S: NodeStorage + HasEpoch + Send + Sync + 'static,
P: PageStorage + Send + Sync + 'static,
{
pub tree: Arc<BPlusTree<S, P>>,
pub storage: Arc<S>,
}
#[cfg(any(test, feature = "testing"))]
pub fn test_tree<S>(storage: S, order: u64) -> TestHarness<S, S>
where
S: NodeStorage + PageStorage + HasEpoch + Send + Sync + 'static,
{
let storage = Arc::new(storage);
let epoch_mgr = storage.epoch_mgr().clone();
let meta = fake_metadata(order);
let tree = BPlusTree::open(
Arc::clone(&storage),
Arc::clone(&storage),
meta,
TEST_META_A,
TEST_META_B,
KeyFormat::Raw(RawFormat),
KeyEncodingId::RawBytes,
epoch_mgr,
);
TestHarness {
tree: Arc::new(tree),
storage,
}
}
#[cfg(any(test, feature = "testing"))]
pub fn test_tree_with_epoch<S>(
storage: S,
epoch_mgr: Arc<EpochManager>,
order: u64,
) -> TestHarness<S, S>
where
S: NodeStorage + PageStorage + HasEpoch + Send + Sync + 'static,
{
let storage = Arc::new(storage);
let meta = fake_metadata(order);
let tree = BPlusTree::open(
Arc::clone(&storage),
Arc::clone(&storage),
meta,
TEST_META_A,
TEST_META_B,
KeyFormat::Raw(RawFormat),
KeyEncodingId::RawBytes,
epoch_mgr,
);
TestHarness {
tree: Arc::new(tree),
storage,
}
}
#[cfg(any(test, feature = "testing"))]
pub fn test_trx<S, P>(tree: SharedBPlusTree<S, P>) -> WriteTransaction
where
S: NodeStorage + HasEpoch + Send + Sync + 'static,
P: PageStorage + Send + Sync + 'static,
{
WriteTransaction::new(tree.clone())
}
#[cfg(any(test, feature = "testing"))]
pub fn make_tree(
dir: &TempDir,
order: u64,
) -> anyhow::Result<SharedBPlusTree<PagedNodeStorage<FilePageStorage>, FilePageStorage>> {
let data_path = dir.path().join("data.db");
let manifest_path = dir.path().join("data.manifest");
let meta_path = dir.path().join("meta.db");
let node_storage = Arc::new(PagedNodeStorage::<FilePageStorage>::new(
&data_path,
&manifest_path,
)?);
let page_storage = Arc::new(FilePageStorage::open(&meta_path)?);
let key_format = KeyFormat::Raw(RawFormat);
let root_view = NodeView::Leaf {
page: LeafPage::new(key_format),
page_id: None,
};
let root_id = node_storage
.write_node_view(&root_view)
.map_err(|e| anyhow::anyhow!("write root: {e}"))?;
let init_meta = Metadata {
root_node_id: root_id,
id: TEST_TREE_ID,
txn_id: 1,
height: 1,
order,
size: 0,
checksum: 0,
};
MetadataManager::commit_metadata_with_object(&*page_storage, TEST_META_A, &init_meta)?;
MetadataManager::commit_metadata_with_object(&*page_storage, TEST_META_B, &init_meta)?;
let epoch_mgr = node_storage.epoch_mgr().clone();
let tree = BPlusTree::open(
node_storage,
page_storage,
init_meta,
TEST_META_A,
TEST_META_B,
key_format,
KeyEncodingId::RawBytes,
epoch_mgr,
);
Ok(SharedBPlusTree::new(tree))
}
#[cfg(any(test, feature = "testing"))]
pub fn load_tree(
dir: &TempDir,
) -> anyhow::Result<SharedBPlusTree<PagedNodeStorage<FilePageStorage>, FilePageStorage>> {
let data_path = dir.path().join("data.db");
let manifest_path = dir.path().join("data.manifest");
let meta_path = dir.path().join("meta.db");
let node_storage = Arc::new(PagedNodeStorage::<FilePageStorage>::new(
&data_path,
&manifest_path,
)?);
let page_storage = Arc::new(FilePageStorage::open(&meta_path)?);
let meta = MetadataManager::read_active_meta(&*page_storage, TEST_META_A, TEST_META_B)?;
let epoch_mgr = node_storage.epoch_mgr().clone();
let tree = BPlusTree::open(
node_storage,
page_storage,
meta,
TEST_META_A,
TEST_META_B,
KeyFormat::Raw(RawFormat),
KeyEncodingId::RawBytes,
epoch_mgr,
);
Ok(SharedBPlusTree::new(tree))
}
fn fake_metadata(order: u64) -> Metadata {
Metadata {
root_node_id: 0,
id: TEST_TREE_ID,
txn_id: 1,
height: 1,
order,
size: 0,
checksum: 0,
}
}