Files
alkblobs/tests/readme_examples.rs
T
glm-5.3-flash 441b2aa836 feat(store): the one derivation-explicit put seam — put_as alone (ADR-020 §Decision 5, wave 14)
- put_as(algorithm, len: Option<u64>, stream) is the facade's sole
  public write surface; put, put_git_object, put_known, and the
  matches! family restriction are deleted outright (no shim, 0.x)
- put_in_batch takes the algorithm parameter (batch, algorithm, len,
  stream); the one seam routes every member
- Digest::derive, Key::derive, Digest::from_git_oid_hex deleted;
  explicit construction is Algorithm::derive / Key::from_bytes over
  the physical encoding
- the put_unknown fleet arm honors its threaded algorithm parameter
  (the put.rs:360 re-hardcode), pinned by a live pg-lo fleet test
- the unknown-length arm retained per §Decision 3; its identity-family
  form pinned (buffer + staged routes land the known-length key)
- the seam-guard test transforms: blob algorithms are legal at the
  seam; put_as lands the canonical blob derivation (git vectors)
- caller sweep: ~250 sites across src/, tests/, and the conformance
  columns; the ops put handler's store arm rides the seam's blob arm
  canonically until the put-handler task (§Decision 4)
- fuzz key_encoding target: the from_git_oid_hex arm dies with the
  constructor; seed regeneration a no-op diff; corpus-replay gate green

Verified: cargo test (default), cargo test --all-features server-less
and against the live pglo-poc harness, both clippy variants (-D
warnings), cargo fmt --check, cargo doc --no-deps, the fuzz
corpus-replay gate.
2026-10-18 22:29:16 +00:00

138 lines
4.4 KiB
Rust

//! The README quick start's verification: each fence's call shape
//! compiles and runs against the real API as an async test (the
//! filesystem arguments are minted per-run instead of the README's
//! literal `./` paths, so the suite never writes the repo root). Each
//! fence is feature-gated to the constructor it exercises (mem, the
//! sqlite default, the postgres kv-only form) — the same gate the
//! constructor carries — so the file compiles on every matrix build;
//! the pg row additionally needs its live harness (`ALKBLOBS_PG_*`
//! env — unset means a clean skip, the conformance columns'
//! harness convention), like the conformance pg columns.
#[cfg(feature = "mem")]
#[tokio::test]
async fn readme_quick_start_mem() {
use alkblobs::{Algorithm, Store};
let store = Store::mem_only();
let content: &[u8] = b"hello, blobs";
let (key, pin) = store
.put_as(
Algorithm::GitBlobSha256,
Some(content.len() as u64),
std::io::Cursor::new(content),
)
.await
.unwrap();
let (len, blob) = store.get(&key.as_bytes()).await.unwrap().unwrap();
assert_eq!(blob.read_at(0, len).await.unwrap(), content);
drop(pin);
let report = store.sweep().await.unwrap();
assert!(report.aborted.is_some());
assert_eq!(report.deleted, 0);
}
#[cfg(feature = "sqlite")]
#[tokio::test]
async fn readme_quick_start_sqlite_local() {
use alkblobs::{Algorithm, Store, DEFAULT_DISPATCH_THRESHOLD};
use std::time::Duration;
let dir = std::env::temp_dir().join(format!("alkblobs-readme-sqlite-{}", std::process::id()));
std::fs::create_dir_all(&dir).unwrap();
let store = Store::dual_tier_sqlite_local(
dir.join("./blobs.db"),
dir.join("./blobs-root"),
DEFAULT_DISPATCH_THRESHOLD,
Duration::from_secs(300),
)
.await
.unwrap();
let content: &[u8] = b"durable path";
let (key, _pin) = store
.put_as(
Algorithm::GitBlobSha256,
Some(content.len() as u64),
std::io::Cursor::new(content),
)
.await
.unwrap();
assert!(store.has(&key.as_bytes()).await.unwrap());
std::fs::remove_dir_all(&dir).unwrap();
}
#[cfg(feature = "postgres")]
#[tokio::test]
async fn readme_quick_start_postgres_kv_only() {
use alkblobs::{Algorithm, PgOpts, Store, DEFAULT_DISPATCH_THRESHOLD};
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::Duration;
let host = match std::env::var("ALKBLOBS_PG_HOST") {
Ok(v) if !v.is_empty() => v,
_ => {
eprintln!(
"skipping (no postgres harness server): set ALKBLOBS_PG_HOST/PORT/USER/PASSWORD/DB"
);
return;
}
};
let port = std::env::var("ALKBLOBS_PG_PORT")
.ok()
.filter(|v| !v.is_empty())
.unwrap_or_else(|| "15432".to_string());
let user = std::env::var("ALKBLOBS_PG_USER")
.ok()
.filter(|v| !v.is_empty())
.unwrap_or_else(|| "postgres".to_string());
let password = std::env::var("ALKBLOBS_PG_PASSWORD")
.ok()
.filter(|v| !v.is_empty())
.unwrap_or_else(|| "poc".to_string());
let db = std::env::var("ALKBLOBS_PG_DB")
.ok()
.filter(|v| !v.is_empty())
.unwrap_or_else(|| "blobs".to_string());
let dsn = format!("host={host} port={port} user={user} password={password} dbname={db}");
static SEQ: AtomicU64 = AtomicU64::new(0);
let schema = format!(
"alkblobs_readme_pg_kv_{}_{}",
std::process::id(),
SEQ.fetch_add(1, Ordering::Relaxed)
);
let store = Store::kv_only_postgres(
&dsn,
PgOpts {
schema: schema.clone(),
..PgOpts::default()
},
DEFAULT_DISPATCH_THRESHOLD,
Duration::from_secs(300),
)
.await
.unwrap();
let content: &[u8] = b"pool-backed path";
let (key, _pin) = store
.put_as(
Algorithm::GitBlobSha256,
Some(content.len() as u64),
std::io::Cursor::new(content),
)
.await
.unwrap();
assert!(store.has(&key.as_bytes()).await.unwrap());
let (client, conn) = tokio_postgres::connect(&dsn, tokio_postgres::NoTls)
.await
.unwrap();
tokio::spawn(conn);
let drop_schema = format!("DROP SCHEMA {schema} CASCADE");
client.batch_execute(&drop_schema).await.unwrap();
}