Files
alkblobs/tests/readme_examples.rs
T
glm-5.3-flash 253d90e875 review(wave-12): the pre-release gate — docs audit, matrix re-run, gates green, specs flipped stable
- docs honesty audit passed: README/CHANGELOG/crate docs vs shipped
  reality; the quick-start fences run against the real API and the
  tables match ADR-013 §4 and the manifest
- two inline fixes from the matrix re-run: tests/readme_examples.rs
  (landed after feature-graph-verification recorded its matrix) was
  breaking every no-sqlite/no-mem build with unconditional
  mem_only/dual_tier_sqlite_local calls — fences now feature-gated to
  the constructors they exercise with per-fn imports; the README pg
  row now clean-skips on unset ALKBLOBS_PG_HOST and defaults to the
  harness values (was a hard connect to localhost:5432)
- one docs-consistency drift miss fixed: AGENTS.md Architecture
  Context bullet still read 'ADRs 001-006 accepted'
- the lifecycle flip: the seven release-facing specs (overview,
  requirements, hashing-and-keys, store-api, backends-and-dispatch,
  gc-and-namespaces, ops-surface) draft -> stable with the dated gate
  note; the architecture README table + Current State + Lifecycle line
  moved with them; open-questions.md stays draft
- wave 12 stamped completed in the implementation plan; AGENTS.md
  status: Phase 1 complete - release-ready, pre-publish

Verification (live pglo-poc harness per AGENTS.md):
- cargo test 209 green; cargo test --all-features 460 green (pg
  columns ran, not skipped)
- clippy default + --all-features (-D warnings) clean; fmt --check
  clean; cargo doc --no-deps zero warnings both configs
- fuzz corpus-replay gate green (7/7)
- cargo publish --dry-run --allow-dirty green (92 files, 2.4MiB)
- feature matrix rows 5-10 re-run green after the readme fix
2026-10-16 11:46:05 +00:00

126 lines
4.1 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::Store;
let store = Store::mem_only();
let content: &[u8] = b"hello, blobs";
let (key, pin) = store
.put(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::{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(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::{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(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();
}