Core tests make a throwaway blob store with blobs::scratch
blobs, store and portable each built a BlobStore in a temp directory their own way: pid+tag twice, a uuid once. blobs::scratch(tag) is that, with a counter, so two tests can never share a directory even if they pick the same tag. The desktop's and ffi's temp-dir helpers stay, one per crate: sharing them would need a test-util feature on the core crate. DRY pass #2, batch 2, F9 (#5372). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+19
-14
@@ -215,18 +215,23 @@ pub fn serve(path: &str, query: Option<&str>) -> (u16, String, Vec<u8>) {
|
||||
(200, content_type_for(&claimed), bytes)
|
||||
}
|
||||
|
||||
/// A blob store in a fresh throwaway directory, for any core test that needs one.
|
||||
/// No tempfile dependency for one fixture: the process id and a counter keep
|
||||
/// concurrent tests and runs apart, and `tag` says whose it was.
|
||||
#[cfg(test)]
|
||||
pub(crate) fn scratch(tag: &str) -> BlobStore {
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
static SEQ: AtomicU32 = AtomicU32::new(0);
|
||||
let n = SEQ.fetch_add(1, Ordering::Relaxed);
|
||||
let dir = std::env::temp_dir().join(format!("ts-blobs-{}-{n}-{tag}", std::process::id()));
|
||||
let _ = fs::remove_dir_all(&dir);
|
||||
BlobStore::new(dir).expect("scratch blob store")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// A blob store in a throwaway directory. No tempfile dependency for one test
|
||||
/// fixture — the process id keeps concurrent runs apart.
|
||||
fn store(tag: &str) -> BlobStore {
|
||||
let dir = std::env::temp_dir().join(format!("ts-blobs-{}-{tag}", std::process::id()));
|
||||
let _ = fs::remove_dir_all(&dir);
|
||||
BlobStore::new(dir).expect("store")
|
||||
}
|
||||
|
||||
/// sha256("hello") — a fixed vector, so a broken digest can't agree with itself.
|
||||
const HELLO: &str = "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824";
|
||||
|
||||
@@ -237,7 +242,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn stores_and_reads_back() {
|
||||
let store = store("roundtrip");
|
||||
let store = scratch("roundtrip");
|
||||
assert!(!store.has(HELLO));
|
||||
store.store(HELLO, b"hello").expect("store");
|
||||
assert!(store.has(HELLO));
|
||||
@@ -248,7 +253,7 @@ mod tests {
|
||||
fn refuses_bytes_that_dont_match_the_hash() {
|
||||
// A corrupted or substituted transfer must never be filed under a name that
|
||||
// claims it's genuine.
|
||||
let store = store("mismatch");
|
||||
let store = scratch("mismatch");
|
||||
let err = store.store(HELLO, b"goodbye").expect_err("must reject");
|
||||
assert!(err.contains("integrity"), "got {err}");
|
||||
assert!(!store.has(HELLO), "nothing should have been written");
|
||||
@@ -257,7 +262,7 @@ mod tests {
|
||||
#[test]
|
||||
fn rejects_a_hash_that_could_escape_the_directory() {
|
||||
// The hash arrives from a server response and becomes a filename.
|
||||
let store = store("traversal");
|
||||
let store = scratch("traversal");
|
||||
assert!(store.path("../../etc/passwd").is_none());
|
||||
assert!(store.store("../../etc/passwd", b"x").is_err());
|
||||
assert!(store.path("").is_none());
|
||||
@@ -267,7 +272,7 @@ mod tests {
|
||||
#[test]
|
||||
fn accepts_an_uppercase_hash() {
|
||||
// The wire format isn't guaranteed to be lowercase; the filename is.
|
||||
let store = store("case");
|
||||
let store = scratch("case");
|
||||
store
|
||||
.store(&HELLO.to_ascii_uppercase(), b"hello")
|
||||
.expect("store");
|
||||
@@ -329,14 +334,14 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn put_files_bytes_under_their_own_hash() {
|
||||
let store = store("put");
|
||||
let store = scratch("put");
|
||||
assert_eq!(store.put(b"hello").expect("put"), HELLO);
|
||||
assert_eq!(store.read(HELLO).as_deref(), Some(&b"hello"[..]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_blob_reads_as_none() {
|
||||
let store = store("missing");
|
||||
let store = scratch("missing");
|
||||
assert!(store.read(HELLO).is_none());
|
||||
assert!(!store.has(HELLO));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user