use beamr::module::ModuleRegistry;
use beamr::scheduler::{Scheduler, SchedulerConfig};
use crate::branch::{BranchRefStore, SnapshotRegistry};
use crate::db::{Database, DatabaseConfig};
use crate::shard::router::{ShardMode, ShardRouter, shard_dir};
use std::error::Error;
use std::sync::Arc;
use std::time::Duration;
use super::journal;
type TestResult = Result<(), Box<dyn Error>>;
const TIMEOUT: Duration = Duration::from_secs(5);
fn config(data_dir: &std::path::Path) -> DatabaseConfig {
DatabaseConfig {
data_dir: data_dir.to_path_buf(),
shard_count: 1,
distributed: None,
executor_threads: None,
}
}
fn scheduler() -> Result<Arc<Scheduler>, Box<dyn Error>> {
Scheduler::new(SchedulerConfig::default(), Arc::new(ModuleRegistry::new()))
.map(Arc::new)
.map_err(|message| -> Box<dyn Error> { message.into() })
}
#[test]
fn r4d_causal_retry_data_dir() -> TestResult {
let _guard = journal::test_guard();
let temp = tempfile::tempdir()?;
let data_dir = temp.path().join("db");
journal::arm_failpoint();
assert!(
Database::create(config(&data_dir)).is_err(),
"the injected data_dir fence failure must refuse the first create"
);
let database = Database::create(config(&data_dir))?;
assert!(data_dir.join("config.json").exists());
drop(database);
Ok(())
}
#[test]
fn r4d_causal_retry_refs_dir() -> TestResult {
let _guard = journal::test_guard();
let temp = tempfile::tempdir()?;
let refs = temp.path().join("refs");
journal::arm_failpoint();
assert!(
BranchRefStore::open(&refs).is_err(),
"the injected refs-dir fence failure must refuse the first open"
);
drop(BranchRefStore::open(&refs)?);
Ok(())
}
#[test]
fn r4d_causal_retry_snapshot_dir() -> TestResult {
let _guard = journal::test_guard();
let temp = tempfile::tempdir()?;
let path = temp.path().join("meta").join("registry.bin");
journal::arm_failpoint();
assert!(
SnapshotRegistry::open(&path).is_err(),
"the injected containing-dir fence failure must refuse the first open"
);
drop(SnapshotRegistry::open(&path)?);
Ok(())
}
#[test]
fn r4d_causal_retry_l1_materialise() -> TestResult {
let _guard = journal::test_guard();
let temp = tempfile::tempdir()?;
let router = ShardRouter::new(
scheduler()?,
temp.path(),
4,
crate::tree::TreePolicy::V1_DEFAULT,
ShardMode::Create,
crate::db::root_advance::RootAdvanceSeam::new(),
)
.ok_or("non-zero shard_count")?;
journal::arm_failpoint();
assert!(
router.handle_for_shard(0).is_err(),
"the injected data_dir fence failure must refuse the first materialisation"
);
router
.handle_for_shard(0)
.map_err(|error| -> Box<dyn Error> { error.message.into() })?;
assert!(shard_dir(temp.path(), 0).is_dir());
assert_eq!(router.materialised_shard_ids(), vec![0]);
router.shutdown_all(TIMEOUT);
Ok(())
}