#![allow(dead_code)]
use std::collections::BTreeSet;
use std::io::Cursor;
use std::path::{Path, PathBuf};
use std::pin::Pin as StdPin;
use std::sync::Arc;
use std::task::{Context, Poll};
use std::time::Duration;
use parking_lot::Mutex;
use sha2::{Digest as _, Sha256};
use tokio::io::{AsyncRead, ReadBuf};
use crate::factory::StoreFactory;
use alkblobs::{
Algorithm, EntryMeta, Error, GcAbortCause, Key, LivenessRegistration, LivenessSource,
ProtectCallback, Store, StoreMode, DEFAULT_DISPATCH_THRESHOLD,
};
#[derive(Default)]
pub(crate) struct SetSource {
live: Mutex<BTreeSet<Key>>,
}
impl SetSource {
pub(crate) fn register(store: &Store) -> Arc<SetSource> {
let source = Arc::new(SetSource::default());
let _ = store.register_liveness_source(LivenessRegistration::InProcess(
Arc::clone(&source) as Arc<dyn LivenessSource>,
));
source
}
pub(crate) fn add(&self, key: Key) {
self.live.lock().insert(key);
}
pub(crate) fn remove(&self, key: &Key) {
self.live.lock().remove(key);
}
}
impl LivenessSource for SetSource {
fn live_keys(&self) -> Vec<Key> {
self.live.lock().iter().cloned().collect()
}
fn contains(&self, key: &Key) -> bool {
self.live.lock().contains(key)
}
}
#[derive(Default)]
pub(crate) struct SetProtect {
set: Mutex<Option<Vec<Key>>>,
}
impl SetProtect {
pub(crate) fn set_keys(&self, keys: Vec<Key>) {
*self.set.lock() = Some(keys);
}
pub(crate) fn fail(&self) {
*self.set.lock() = None;
}
}
impl ProtectCallback for SetProtect {
fn protect(&self) -> Option<Vec<Key>> {
self.set.lock().clone()
}
}
pub(crate) struct LatchProtect {
pub(crate) entered: std::sync::mpsc::Sender<()>,
pub(crate) release: Mutex<Option<std::sync::mpsc::Receiver<()>>>,
}
impl ProtectCallback for LatchProtect {
fn protect(&self) -> Option<Vec<Key>> {
self.entered.send(()).ok();
let receiver = self.release.lock().take();
if let Some(receiver) = receiver {
let _ = receiver.recv();
}
Some(Vec::new())
}
}
pub(crate) struct Chunked {
data: Vec<u8>,
cursor: usize,
sizes: std::collections::VecDeque<usize>,
}
impl Chunked {
pub(crate) fn new(data: &[u8], sizes: &[usize]) -> Chunked {
Chunked {
data: data.to_vec(),
cursor: 0,
sizes: sizes.iter().copied().collect(),
}
}
}
impl AsyncRead for Chunked {
fn poll_read(
mut self: StdPin<&mut Self>,
_cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
if self.cursor >= self.data.len() || buf.remaining() == 0 {
return Poll::Ready(Ok(()));
}
let remaining = self.data.len() - self.cursor;
let wanted = self
.sizes
.front()
.copied()
.unwrap_or(remaining)
.min(remaining)
.min(buf.remaining());
buf.put_slice(&self.data[self.cursor..self.cursor + wanted]);
self.cursor += wanted;
if let Some(front) = self.sizes.front_mut() {
*front -= wanted;
if *front == 0 {
self.sizes.pop_front();
}
}
Poll::Ready(Ok(()))
}
}
pub(crate) struct Failing {
data: Vec<u8>,
cursor: usize,
fail_after: usize,
}
impl Failing {
pub(crate) fn new(data: &[u8], fail_after: usize) -> Failing {
Failing {
data: data.to_vec(),
cursor: 0,
fail_after,
}
}
}
impl AsyncRead for Failing {
fn poll_read(
mut self: StdPin<&mut Self>,
_cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
let message = "stream failure (conformance fixture)";
if self.cursor >= self.fail_after {
return Poll::Ready(Err(std::io::Error::other(message)));
}
let wanted = (self.data.len() - self.cursor)
.min(self.fail_after - self.cursor)
.min(buf.remaining());
if wanted == 0 {
return Poll::Ready(Err(std::io::Error::other(message)));
}
buf.put_slice(&self.data[self.cursor..self.cursor + wanted]);
self.cursor += wanted;
Poll::Ready(Ok(()))
}
}
struct Unreadable;
impl AsyncRead for Unreadable {
fn poll_read(
self: StdPin<&mut Self>,
_cx: &mut Context<'_>,
_buf: &mut ReadBuf<'_>,
) -> Poll<std::io::Result<()>> {
Poll::Ready(Err(std::io::Error::other(
"the Unreadable stream must never be read (conformance fixture)",
)))
}
}
fn matrix() -> Vec<Vec<u8>> {
vec![
Vec::new(),
b"x".to_vec(),
b"the conformance round-trip content".to_vec(),
(0..137u32).map(|i| (i % 251) as u8).collect(),
(0..4096u32).map(|i| (i % 199) as u8).collect(),
(0..65537u32).map(|i| (i % 173) as u8).collect(),
]
}
pub(crate) fn patterned(len: usize, modulus: u32) -> Vec<u8> {
(0..len as u32).map(|i| (i % modulus) as u8).collect()
}
fn git_tree_loose_form(body: &[u8]) -> Vec<u8> {
let mut loose = format!("tree {}\0", body.len()).into_bytes();
loose.extend_from_slice(body);
loose
}
fn git_tree_bodies() -> Vec<Vec<u8>> {
let entry_body = |name: &str, oid_len: usize| {
let mut body = format!("100644 {}\0", name).into_bytes();
body.extend((0..oid_len).map(|_| 7u8));
body
};
vec![entry_body("f", 20), entry_body(&"x".repeat(1000), 32)]
}
pub(crate) fn assert_exact_counts(report: &alkblobs::SweepReport) {
assert_eq!(
report.candidates_staged,
report.deleted + report.cancelled_by_arbitration,
"the completed sweep's counts are exact over the staged set"
);
}
pub(crate) fn committed_file_count(root: &Path) -> usize {
fn walk(dir: &Path, out: &mut Vec<PathBuf>) {
let Ok(entries) = std::fs::read_dir(dir) else {
return;
};
for entry in entries.flatten() {
let Ok(kind) = entry.file_type() else {
continue;
};
let path = entry.path();
if kind.is_dir() {
if path.file_name().and_then(|n| n.to_str()) == Some("staging") {
continue;
}
walk(&path, out);
} else if kind.is_file() {
out.push(path);
}
}
}
let mut files = Vec::new();
walk(root, &mut files);
files.len()
}
pub(crate) fn staging_file_count(root: &Path) -> usize {
match std::fs::read_dir(root.join("staging")) {
Ok(entries) => entries.count(),
Err(_) => 0,
}
}
pub(crate) fn slice_digest(bytes: &[u8]) -> [u8; 32] {
Sha256::digest(bytes).into()
}
pub async fn round_trip_puts_and_gets_are_byte_identical<F: StoreFactory>(factory: &F) {
let store = factory
.open()
.await
.expect("open vends a fresh, isolated store");
for content in matrix() {
let len = content.len() as u64;
let canonical = Key::derive(&content, len);
for declared in [Some(len), None] {
let (key, pin) = store
.put(declared, Cursor::new(content.as_slice()))
.await
.expect("put publishes");
assert_eq!(key, canonical, "the canonical derivation addresses the put");
let (got_len, blob) = store
.get(&key.as_bytes())
.await
.expect("get succeeds")
.expect("the entry is present");
assert_eq!(got_len, len, "the tuple carries the entry length");
assert_eq!(blob.len(), len, "the stream's metadata length agrees");
assert_eq!(
blob.read_at(0, len).await.expect("the whole window reads"),
content,
"whole-blob round-trip is byte-identical"
);
if len > 2 {
assert_eq!(
blob.read_at(1, len - 2)
.await
.expect("the inner window reads"),
content[1..(len - 2) as usize + 1],
"a bounded window reads the matching inner slice"
);
}
drop(pin);
}
}
for (algorithm, body) in [
(Algorithm::GitObjectSha1, git_tree_bodies()[0].clone()),
(Algorithm::GitObjectSha256, git_tree_bodies()[1].clone()),
] {
let loose = git_tree_loose_form(&body);
let expected: Key = algorithm.derive(&loose, loose.len() as u64).into();
let (key, pin) = store
.put_git_object(algorithm, loose.len() as u64, Cursor::new(loose.as_slice()))
.await
.expect("the git-object put publishes");
assert_eq!(
key, expected,
"the family's preimage-identity derivation addresses the put"
);
let (got_len, blob) = store
.get(&key.as_bytes())
.await
.expect("get succeeds")
.expect("the family entry is present");
assert_eq!(got_len, loose.len() as u64);
assert_eq!(
blob.read_at(0, got_len)
.await
.expect("the whole window reads"),
loose,
"the family entry's round-trip is byte-identical (the stored value \
is the loose form)"
);
drop(pin);
}
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
pub async fn dedup_identical_content_is_one_pool_entry<F: StoreFactory>(factory: &F) {
let store = factory
.open()
.await
.expect("open vends a fresh, isolated store");
SetSource::register(&store);
let content = b"deduplicated content".to_vec();
let canonical = Key::derive(&content, content.len() as u64);
let (key, first) = store
.put(Some(content.len() as u64), Cursor::new(content.as_slice()))
.await
.expect("the fresh put publishes");
let (reput, second) = store
.put(Some(content.len() as u64), Cursor::new(content.as_slice()))
.await
.expect("the same-path re-put publishes");
assert_eq!(key, canonical);
assert_eq!(reput, canonical, "one derivation, one address");
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(report.aborted, None);
assert_eq!(
report.candidates_staged, 0,
"one pool entry, both refcounts composing under the same lock"
);
drop(first);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
report.candidates_staged, 0,
"the re-put's pin protects exactly as a fresh put's"
);
drop(second);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(report.deleted, 1, "exactly one pool entry all along");
assert!(!store.has(&canonical.as_bytes()).await.unwrap());
let cross = b"deduplicated across the put paths".to_vec();
let cross_canonical = Key::derive(&cross, cross.len() as u64);
let (key, first) = store
.put(Some(cross.len() as u64), Cursor::new(cross.as_slice()))
.await
.expect("the known-length put publishes");
let (reput, second) = store
.put(None, Cursor::new(cross.as_slice()))
.await
.expect("the unknown-length re-put publishes");
assert_eq!(key, cross_canonical);
assert_eq!(reput, cross_canonical, "one pool entry across the paths");
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(report.candidates_staged, 0, "both refcounts compose");
drop(second);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
report.candidates_staged, 0,
"the re-put's pin protects exactly as a fresh put's (other drop order)"
);
drop(first);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(report.deleted, 1, "exactly one pool entry all along");
assert!(!store.has(&cross_canonical.as_bytes()).await.unwrap());
let body = &git_tree_bodies()[0];
let loose = git_tree_loose_form(body);
let family_canonical: Key = Algorithm::GitObjectSha1
.derive(&loose, loose.len() as u64)
.into();
let (key, first) = store
.put_git_object(
Algorithm::GitObjectSha1,
loose.len() as u64,
Cursor::new(loose.as_slice()),
)
.await
.expect("the family put publishes");
drop(first);
let (reput, second) = store
.put_git_object(
Algorithm::GitObjectSha1,
loose.len() as u64,
Cursor::new(loose.as_slice()),
)
.await
.expect("the family re-put publishes");
assert_eq!(key, family_canonical);
assert_eq!(reput, family_canonical, "one oid, one address");
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
report.candidates_staged, 0,
"the family re-put's pin protects exactly as a fresh put's does"
);
drop(second);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(report.deleted, 1, "exactly one family entry all along");
assert!(!store.has(&family_canonical.as_bytes()).await.unwrap());
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
pub async fn stage_hygiene_zero_residue_on_failure_exactly_one_entry_on_success<F: StoreFactory>(
factory: &F,
) {
let store = factory
.open()
.await
.expect("open vends a fresh, isolated store");
SetSource::register(&store);
let content = patterned(200, 167);
let canonical = Key::derive(&content, content.len() as u64);
let err = store
.put(Some(content.len() as u64), Failing::new(&content, 40))
.await
.expect_err("the failed mid-stream put rejects");
assert!(
matches!(err, Error::Io(_)),
"the stream failure surfaces as Io: {err}"
);
let err = store
.put(None, Failing::new(&content, 40))
.await
.expect_err("the failed unknown-length put rejects");
assert!(
matches!(err, Error::Io(_)),
"the stream failure surfaces as Io: {err}"
);
let err = store
.put(Some(100), Cursor::new(content.as_slice()))
.await
.expect_err("the over-fed mismatch rejects");
assert_eq!(err, Error::Verification, "declared-len mismatch rejects");
let err = store
.put(Some(400), Cursor::new(content.as_slice()))
.await
.expect_err("the under-fed mismatch rejects");
assert_eq!(err, Error::Verification, "declared-len mismatch rejects");
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(report.aborted, None);
assert_eq!(
(
report.candidates_staged,
report.deleted,
report.cancelled_by_arbitration
),
(0, 0, 0),
"zero residue after every failure, both put paths, both failure modes"
);
let (key, pin) = store
.put(Some(content.len() as u64), Cursor::new(content.as_slice()))
.await
.expect("the known-length put publishes");
assert_eq!(key, canonical);
drop(pin);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(report.candidates_staged, report.deleted),
(1, 1),
"exactly one committed entry on success"
);
assert!(!store.has(&canonical.as_bytes()).await.unwrap());
let (key, pin) = store
.put(None, Cursor::new(content.as_slice()))
.await
.expect("the unknown-length put publishes");
assert_eq!(key, canonical);
drop(pin);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(report.candidates_staged, report.deleted),
(1, 1),
"exactly one committed entry on the other put path too"
);
assert!(!store.has(&canonical.as_bytes()).await.unwrap());
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
pub async fn sweep_counts_are_exact_across_the_full_protection_set<F: StoreFactory>(factory: &F) {
let store = factory
.open()
.await
.expect("open vends a fresh, isolated store");
let source = SetSource::register(&store);
let protect = Arc::new(SetProtect::default());
store.register_protect_callback(protect.clone());
let source_live = b"kept by the registered source".to_vec();
let (key_live, _) = store
.put(
Some(source_live.len() as u64),
Cursor::new(source_live.as_slice()),
)
.await
.expect("the source-live entry publishes");
source.add(key_live.clone());
let pinned = b"kept by the pin".to_vec();
let (key_pinned, pin_pinned) = store
.put(None, Cursor::new(pinned.as_slice()))
.await
.expect("the pinned entry publishes");
let protected = b"named by the protect callback".to_vec();
let (key_protected, _) = store
.put(
Some(protected.len() as u64),
Cursor::new(protected.as_slice()),
)
.await
.expect("the protect-named entry publishes");
protect.set_keys(vec![key_protected.clone()]);
let dead_one = b"a dead witness from the known-length path".to_vec();
let (_, pin) = store
.put(
Some(dead_one.len() as u64),
Cursor::new(dead_one.as_slice()),
)
.await
.expect("the first dead entry publishes");
drop(pin);
let dead_two = b"a dead witness from the unknown-length path".to_vec();
let (_, pin) = store
.put(None, Cursor::new(dead_two.as_slice()))
.await
.expect("the second dead entry publishes");
drop(pin);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(report.aborted, None, "correct liveness completes the sweep");
assert_eq!(
(
report.candidates_staged,
report.deleted,
report.cancelled_by_arbitration
),
(2, 2, 0),
"only the two dead entries stage and delete"
);
assert_exact_counts(&report);
assert!(store.has(&key_live.as_bytes()).await.unwrap());
assert!(store.has(&key_pinned.as_bytes()).await.unwrap());
assert!(store.has(&key_protected.as_bytes()).await.unwrap());
for (key, content) in [
(&key_live, &source_live),
(&key_pinned, &pinned),
(&key_protected, &protected),
] {
let (len, blob) = store
.get(&key.as_bytes())
.await
.expect("get succeeds")
.expect("the protected entry is present");
assert_eq!(
blob.read_at(0, len).await.expect("the window reads"),
content.as_slice(),
"the protected entry is byte-identical after the sweep"
);
}
drop(pin_pinned);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(report.aborted, None);
assert_eq!(
(report.candidates_staged, report.deleted),
(1, 1),
"with the pin dropped exactly the formerly pinned entry dies"
);
assert!(!store.has(&key_pinned.as_bytes()).await.unwrap());
assert!(store.has(&key_live.as_bytes()).await.unwrap());
assert!(store.has(&key_protected.as_bytes()).await.unwrap());
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
pub async fn sweep_without_liveness_sources_aborts_and_deletes_nothing<F: StoreFactory>(
factory: &F,
) {
let store = factory
.open()
.await
.expect("open vends a fresh, isolated store");
let content = b"unprotected while no source is registered".to_vec();
let (key, pin) = store
.put(None, Cursor::new(content.as_slice()))
.await
.expect("the entry publishes");
drop(pin);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
report.aborted,
Some(GcAbortCause::NoLivenessSources),
"the safe default aborts as report data"
);
assert_eq!(
(
report.candidates_staged,
report.deleted,
report.cancelled_by_arbitration
),
(0, 0, 0),
"an aborted sweep stages and deletes nothing"
);
assert!(
store.has(&key.as_bytes()).await.unwrap(),
"the entry survives the abort"
);
let (len, blob) = store
.get(&key.as_bytes())
.await
.expect("get succeeds")
.expect("the entry is present");
assert_eq!(
blob.read_at(0, len).await.expect("the window reads"),
content
);
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
pub async fn sweep_with_a_failed_protect_callback_aborts_and_deletes_nothing<F: StoreFactory>(
factory: &F,
) {
let store = factory
.open()
.await
.expect("open vends a fresh, isolated store");
SetSource::register(&store);
let protect = Arc::new(SetProtect::default());
store.register_protect_callback(protect.clone());
protect.fail();
let content = b"dead while the protection source fails to answer".to_vec();
let (key, pin) = store
.put(None, Cursor::new(content.as_slice()))
.await
.expect("the entry publishes");
drop(pin);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
report.aborted,
Some(GcAbortCause::ProtectFailed),
"the failed protection source aborts as report data"
);
assert_eq!(
(
report.candidates_staged,
report.deleted,
report.cancelled_by_arbitration
),
(0, 0, 0),
"an aborted sweep stages and deletes nothing"
);
assert!(
store.has(&key.as_bytes()).await.unwrap(),
"the entry survives the abort"
);
let (len, blob) = store
.get(&key.as_bytes())
.await
.expect("get succeeds")
.expect("the entry is present");
assert_eq!(
blob.read_at(0, len).await.expect("the window reads"),
content
);
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
pub async fn sweep_is_single_flight_the_contended_second_aborts_as_data<F: StoreFactory>(
factory: &F,
) {
let store = factory
.open()
.await
.expect("open vends a fresh, isolated store");
SetSource::register(&store);
let (entered_tx, entered_rx) = std::sync::mpsc::channel::<()>();
let (release_tx, release_rx) = std::sync::mpsc::channel::<()>();
store.register_protect_callback(Arc::new(LatchProtect {
entered: entered_tx,
release: Mutex::new(Some(release_rx)),
}));
let content = b"dead under the contended sweeps".to_vec();
let (key, pin) = store
.put(None, Cursor::new(content.as_slice()))
.await
.expect("the entry publishes");
drop(pin);
let store = Arc::new(store);
let holder = tokio::spawn({
let store = Arc::clone(&store);
async move { store.sweep().await }
});
while entered_rx.recv_timeout(Duration::from_millis(50)).is_err() {
tokio::task::yield_now().await;
}
let second = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
second.aborted,
Some(GcAbortCause::SweeperLock),
"the contended sweeper aborts as report data"
);
assert_eq!(
(
second.candidates_staged,
second.deleted,
second.cancelled_by_arbitration
),
(0, 0, 0),
"the contended sweep stages and deletes nothing"
);
assert!(
store.has(&key.as_bytes()).await.unwrap(),
"the contended sweep deleted nothing"
);
release_tx.send(()).ok();
let report = holder
.await
.expect("the holder task joined")
.expect("sweeps are never errors");
assert_eq!(report.aborted, None, "the lease holder completes");
assert_eq!(
(
report.candidates_staged,
report.deleted,
report.cancelled_by_arbitration
),
(1, 1, 0),
"the lease holder's counts are exact"
);
assert_exact_counts(&report);
assert!(
!store.has(&key.as_bytes()).await.unwrap(),
"the holder's deletion landed after the release"
);
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
pub async fn sweep_racing_a_pinned_put_never_deletes_the_protected_entry<F: StoreFactory>(
factory: &F,
) {
let store = factory
.open()
.await
.expect("open vends a fresh, isolated store");
SetSource::register(&store);
let witness = b"the dead witness the first racing sweep deletes".to_vec();
let (_, pin) = store
.put(None, Cursor::new(witness.as_slice()))
.await
.expect("the witness publishes");
drop(pin);
let rounds: [(Vec<u8>, bool); 4] = [
(b"racing round a, known path".to_vec(), true),
(b"racing round b, unknown path".to_vec(), false),
(patterned(4096, 191), true),
(patterned(4096, 173), false),
];
for (round, (content, known)) in rounds.iter().enumerate() {
let declared = if *known {
Some(content.len() as u64)
} else {
None
};
let (report, put) = tokio::join!(store.sweep(), async {
store.put(declared, Cursor::new(content.as_slice())).await
});
let report = report.expect("sweeps are never errors");
let (key, pin) = put.expect("the racing put publishes");
assert_eq!(
key,
Key::derive(content, content.len() as u64),
"round {round}: the canonical derivation addresses the racing put"
);
assert_eq!(report.aborted, None, "round {round}: the sweep completed");
assert_exact_counts(&report);
let (len, blob) = store
.get(&key.as_bytes())
.await
.expect("get succeeds")
.expect("the racing put's entry survived");
assert_eq!(len, content.len() as u64, "round {round}");
assert_eq!(
blob.read_at(0, len).await.expect("the window reads"),
content.as_slice(),
"round {round}: the published entry is byte-identical"
);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
report.candidates_staged, 0,
"round {round}: the minted pin still protects"
);
drop(pin);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(report.candidates_staged, report.deleted),
(1, 1),
"round {round}: unpinned, exactly one deletion"
);
assert!(!store.has(&key.as_bytes()).await.unwrap());
}
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
pub async fn list_correctness_is_observable_through_sweep_outcomes<F: StoreFactory>(factory: &F) {
let store = factory
.open()
.await
.expect("open vends a fresh, isolated store");
let source = SetSource::register(&store);
let mut keys = Vec::new();
for (index, content) in [
b"kept live by the source, entry one".to_vec(),
b"kept live by the source, entry two".to_vec(),
b"dead at the first sweep, entry three".to_vec(),
b"dead at the first sweep, entry four".to_vec(),
b"dead at the first sweep, entry five".to_vec(),
]
.into_iter()
.enumerate()
{
let declared = if index % 2 == 0 {
Some(content.len() as u64)
} else {
None
};
let (key, pin) = store
.put(declared, Cursor::new(content.as_slice()))
.await
.expect("the entry publishes");
drop(pin);
keys.push(key);
}
source.add(keys[0].clone());
source.add(keys[1].clone());
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(report.aborted, None);
assert_eq!(
(
report.candidates_staged,
report.deleted,
report.cancelled_by_arbitration
),
(3, 3, 0),
"the enumeration staged exactly the three dead entries — complete and \
well-formed in both directions"
);
assert_exact_counts(&report);
assert!(store.has(&keys[0].as_bytes()).await.unwrap());
assert!(store.has(&keys[1].as_bytes()).await.unwrap());
for key in &keys[2..] {
assert!(!store.has(&key.as_bytes()).await.unwrap());
}
source.remove(&keys[1]);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(report.candidates_staged, report.deleted),
(1, 1),
"the newly dead entry is found exactly"
);
assert!(store.has(&keys[0].as_bytes()).await.unwrap());
source.remove(&keys[0]);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(report.candidates_staged, report.deleted),
(1, 1),
"the last entry is found exactly"
);
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
pub async fn stat_reports_len_and_algorithm_without_fetching_content<F: StoreFactory>(factory: &F) {
let store = factory
.open()
.await
.expect("open vends a fresh, isolated store");
for content in matrix() {
let len = content.len() as u64;
let canonical = Key::derive(&content, len);
for declared in [Some(len), None] {
let (key, pin) = store
.put(declared, Cursor::new(content.as_slice()))
.await
.expect("put publishes");
drop(pin);
assert_eq!(key, canonical);
let meta = store
.stat(&key.as_bytes())
.await
.expect("stat succeeds")
.expect("the entry is present");
assert_eq!(
meta,
EntryMeta {
len,
algorithm: Algorithm::GitBlobSha256,
},
"stat carries the entry length and the key's algorithm"
);
assert_eq!(
store
.stat(&key.as_bytes())
.await
.expect("stat succeeds again"),
Some(meta),
"stat is a pure probe"
);
}
}
for (algorithm, body) in [
(Algorithm::GitObjectSha1, git_tree_bodies()[0].clone()),
(Algorithm::GitObjectSha256, git_tree_bodies()[1].clone()),
] {
let loose = git_tree_loose_form(&body);
let (key, pin) = store
.put_git_object(algorithm, loose.len() as u64, Cursor::new(loose.as_slice()))
.await
.expect("the git-object put publishes");
drop(pin);
let meta = store
.stat(&key.as_bytes())
.await
.expect("stat succeeds")
.expect("the family entry is present");
assert_eq!(
meta,
EntryMeta {
len: loose.len() as u64,
algorithm,
},
"the family entry's stat carries the stored-preimage length — \
the loose form, git's header included (ADR-018 §Decision 3)"
);
}
let absent = b"stat never sees this content".to_vec();
let absent = Key::derive(&absent, absent.len() as u64);
assert_eq!(
store.stat(&absent.as_bytes()).await.expect("stat succeeds"),
None,
"a both-tier miss is None, never an error"
);
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
const KV_ONLY_REJECTION: &str = "kv-only mode rejects an over-threshold put";
const MAX_BOUNDARY_MATERIALIZATION: u64 = 8 * 1024 * 1024;
async fn probe_rejects(store: &Store, len: u64) -> bool {
match store.put(Some(len), Unreadable).await {
Err(err) => err.to_string().contains(KV_ONLY_REJECTION),
Ok(_) => panic!("the Unreadable probe stream can never publish"),
}
}
pub async fn kv_only_mode_rejects_over_threshold_puts_at_put_time<F: StoreFactory>(factory: &F) {
let store = factory
.open()
.await
.expect("open vends a fresh, isolated store");
assert_eq!(
store.mode(),
StoreMode::KvOnly,
"the row runs against a kv-only factory (ADR-011 §4's mode vocabulary)"
);
SetSource::register(&store);
assert!(
probe_rejects(&store, u64::MAX).await,
"the kv-only factory must declare a threshold below u64::MAX for this \
row to apply"
);
let mut low = 0u64;
let mut high = u64::MAX;
while high - low > 1 {
let mid = low + (high - low) / 2;
if probe_rejects(&store, mid).await {
high = mid;
} else {
low = mid;
}
}
let rejecting = high;
let threshold = rejecting - 1;
assert!(
threshold <= MAX_BOUNDARY_MATERIALIZATION,
"the kv-only factory's threshold must keep the boundary legs \
materializable (≤ {MAX_BOUNDARY_MATERIALIZATION}); got {threshold}"
);
let err = store
.put(Some(u64::MAX), Unreadable)
.await
.expect_err("the over-threshold known-length put rejects");
assert!(
err.to_string().contains(KV_ONLY_REJECTION),
"the immediate rejection carries the mode's message: {err}"
);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(
report.candidates_staged,
report.deleted,
report.cancelled_by_arbitration
),
(0, 0, 0),
"zero residue after the immediate rejection"
);
let content: Vec<u8> = (0..threshold)
.map(|i| (i % 199) as u8)
.chain(std::iter::once(7))
.collect();
assert_eq!(content.len() as u64, rejecting);
let err = store
.put(None, Chunked::new(&content, &[7; 64]))
.await
.expect_err("the over-threshold unknown-length put rejects at mid-stream");
assert!(
err.to_string().contains(KV_ONLY_REJECTION) && err.to_string().contains("streamed"),
"the overflow rejection is the mode's, mid-stream: {err}"
);
let report = store.sweep().await.expect("sweeps are never errors");
assert_eq!(
(
report.candidates_staged,
report.deleted,
report.cancelled_by_arbitration
),
(0, 0, 0),
"zero residue after the mid-stream rejection"
);
let at = (0..threshold).map(|i| (i % 251) as u8).collect::<Vec<u8>>();
let at_canonical = Key::derive(&at, threshold);
let (key, pin) = store
.put(Some(threshold), Cursor::new(at.as_slice()))
.await
.expect("the at-threshold known-length put lands");
assert_eq!(key, at_canonical);
drop(pin);
assert!(store.has(&at_canonical.as_bytes()).await.unwrap());
let other: Vec<u8> = (0..threshold).map(|i| (i % 173) as u8).collect();
let other_canonical = Key::derive(&other, threshold);
let (key, pin) = store
.put(None, Chunked::new(&other, &[11; 512]))
.await
.expect("the at-threshold unknown-length put lands");
assert_eq!(key, other_canonical);
drop(pin);
assert!(store.has(&other_canonical.as_bytes()).await.unwrap());
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}
pub async fn mem_only_mode_accepts_every_length_on_both_put_paths<F: StoreFactory>(factory: &F) {
let store = factory
.open()
.await
.expect("open vends a fresh, isolated store");
assert_eq!(
store.mode(),
StoreMode::MemOnly,
"the row runs against a mem-only factory (ADR-011 §4's mode vocabulary)"
);
let content = patterned(DEFAULT_DISPATCH_THRESHOLD as usize + 7, 191);
let canonical = Key::derive(&content, content.len() as u64);
for declared in [Some(content.len() as u64), None] {
let (key, pin) = store
.put(declared, Cursor::new(content.as_slice()))
.await
.expect("mem-only accepts the over-default-threshold put");
assert_eq!(key, canonical, "one canonical entry across both paths");
drop(pin);
}
let (len, blob) = store
.get(&canonical.as_bytes())
.await
.expect("get succeeds")
.expect("the entry is present");
assert_eq!(len, content.len() as u64);
assert_eq!(
blob.read_at(0, len).await.expect("the window reads"),
content,
"the sole engine holds the whole artifact byte-identical"
);
drop(store);
factory.teardown().await.expect("teardown is idempotent");
}