use super::{
ForkStrategy, StoreFileKind, COMPACT_SOURCE_EXTENSION, CURSOR_DIRECTORY, KEYSET_FILENAME,
};
use crate::store::segment::SegmentId;
use std::path::Path;
#[test]
fn from_path_classifies_the_keyset_file_as_its_exact_kind() {
assert_eq!(
StoreFileKind::from_path(Path::new(KEYSET_FILENAME)),
StoreFileKind::Keyset,
"the bare keyset filename must classify as Keyset"
);
assert_eq!(
StoreFileKind::from_path(Path::new("/data/store-a/keyset.fbatk")),
StoreFileKind::Keyset,
"a full keyset path must classify by its file name"
);
assert_eq!(
StoreFileKind::from_path(Path::new("keyset.fbatk.bak")),
StoreFileKind::Other,
"only the exact keyset file name is the keyset — no filename folklore"
);
}
#[test]
fn should_clear_from_snapshot_destination_discriminates_store_artifacts_from_other() {
let segment_id = SegmentId::from_stem("0").expect("base-10 stem parses");
assert!(
StoreFileKind::Segment(segment_id).should_clear_from_snapshot_destination(),
"a store segment MUST be cleared from a snapshot destination before copy"
);
assert!(
!StoreFileKind::Other.should_clear_from_snapshot_destination(),
"a foreign (Other) file must NOT be cleared from a snapshot destination"
);
assert!(
!StoreFileKind::Keyset.should_clear_from_snapshot_destination(),
"the crypto-shred keyset must NOT be cleared from a snapshot destination"
);
}
#[test]
fn should_clear_from_fork_destination_discriminates_store_artifacts_from_other() {
assert!(
!StoreFileKind::Other.should_clear_from_fork_destination(),
"a foreign (Other) file must NOT be cleared from a fork destination"
);
let segment_id = SegmentId::from_stem("0").expect("base-10 stem parses");
assert!(
StoreFileKind::Segment(segment_id).should_clear_from_fork_destination(),
"a store segment MUST be cleared from a fork destination before copy"
);
}
#[test]
fn from_path_classifies_every_store_file_by_its_exact_name_or_extension() {
use crate::store::cold_start::checkpoint::CHECKPOINT_FILENAME;
use crate::store::cold_start::mmap::MMAP_INDEX_FILENAME;
use crate::store::cold_start::rebuild::COMPACTION_MARKER_FILENAME;
use crate::store::hidden_ranges::VISIBILITY_RANGES_FILENAME;
use crate::store::index::idemp::IDEMP_FILENAME;
use crate::store::segment::SEGMENT_EXTENSION;
let segment_path = format!("42.{SEGMENT_EXTENSION}");
assert_eq!(
StoreFileKind::from_path(Path::new(&segment_path)),
StoreFileKind::Segment(SegmentId::from_stem("42").expect("stem parses")),
"a well-formed segment filename must classify as Segment with its id"
);
let malformed_path = format!("not-a-number.{SEGMENT_EXTENSION}");
assert!(
matches!(
StoreFileKind::from_path(Path::new(&malformed_path)),
StoreFileKind::MalformedSegment(_)
),
"a `.fbat` with a non-numeric stem must classify as MalformedSegment"
);
let compact_path = format!("7.{COMPACT_SOURCE_EXTENSION}");
assert_eq!(
StoreFileKind::from_path(Path::new(&compact_path)),
StoreFileKind::CompactSource,
"the compact-source extension must classify as CompactSource"
);
for (name, expected) in [
(VISIBILITY_RANGES_FILENAME, StoreFileKind::VisibilityRanges),
(CHECKPOINT_FILENAME, StoreFileKind::Checkpoint),
(MMAP_INDEX_FILENAME, StoreFileKind::MmapIndex),
(IDEMP_FILENAME, StoreFileKind::IdempotencyStore),
(
COMPACTION_MARKER_FILENAME,
StoreFileKind::PendingCompactionMarker,
),
(CURSOR_DIRECTORY, StoreFileKind::CursorDirectory),
(KEYSET_FILENAME, StoreFileKind::Keyset),
] {
assert_eq!(
StoreFileKind::from_path(Path::new(name)),
expected,
"{name} must classify as {expected:?}"
);
}
assert_eq!(
StoreFileKind::from_path(Path::new("README.md")),
StoreFileKind::Other,
"an unrecognised filename must classify as Other, not any store artifact"
);
}
#[test]
fn segment_id_is_some_only_for_segment_kinds() {
let id = SegmentId::from_stem("13").expect("stem parses");
assert_eq!(
StoreFileKind::Segment(id).segment_id(),
Some(id),
"a Segment must yield its own id"
);
assert_eq!(
StoreFileKind::VisibilityRanges.segment_id(),
None,
"a non-segment kind must yield None"
);
assert_eq!(
StoreFileKind::Keyset.segment_id(),
None,
"the keyset kind has no segment id"
);
}
#[test]
fn should_copy_into_snapshot_selects_only_the_durable_authorities() {
let id = SegmentId::from_stem("1").expect("stem parses");
for kind in [
StoreFileKind::Segment(id),
StoreFileKind::VisibilityRanges,
StoreFileKind::IdempotencyStore,
StoreFileKind::PendingCompactionMarker,
] {
assert!(
kind.should_copy_into_snapshot(),
"{kind:?} is a durable authority and MUST be copied into a snapshot"
);
}
for kind in [
StoreFileKind::Checkpoint,
StoreFileKind::MmapIndex,
StoreFileKind::Keyset,
StoreFileKind::Other,
] {
assert!(
!kind.should_copy_into_snapshot(),
"{kind:?} must NOT be copied into a snapshot"
);
}
}
#[test]
fn fork_strategy_partitions_segments_by_active_boundary_and_maps_each_kind() {
let active = 5u64;
let older = SegmentId::from_stem("4").expect("stem parses");
let at = SegmentId::from_stem("5").expect("stem parses");
let newer = SegmentId::from_stem("6").expect("stem parses");
assert_eq!(
StoreFileKind::Segment(older).fork_strategy(active),
ForkStrategy::ShareIfPossible,
"a sealed segment below the active id is shareable"
);
assert_eq!(
StoreFileKind::Segment(at).fork_strategy(active),
ForkStrategy::DeepCopyAlways,
"the active segment (== boundary) must be deep-copied"
);
assert_eq!(
StoreFileKind::Segment(newer).fork_strategy(active),
ForkStrategy::Exclude,
"a segment above the active id matches no share/copy arm and is excluded"
);
assert_eq!(
StoreFileKind::VisibilityRanges.fork_strategy(active),
ForkStrategy::DeepCopyAlways,
"visibility ranges are a durable authority: deep-copied into a fork"
);
assert_eq!(
StoreFileKind::Checkpoint.fork_strategy(active),
ForkStrategy::CacheRegenerable,
"the checkpoint is a regenerable cache in a fork"
);
assert_eq!(
StoreFileKind::MmapIndex.fork_strategy(active),
ForkStrategy::CacheRegenerable,
"the mmap index is a regenerable cache in a fork"
);
assert_eq!(
StoreFileKind::Keyset.fork_strategy(active),
ForkStrategy::Exclude,
"the keyset is excluded from Stage-B fork copy"
);
assert_eq!(
StoreFileKind::Other.fork_strategy(active),
ForkStrategy::Exclude,
"a foreign file is excluded from a fork"
);
}