use super::{COVERAGE_MANIFEST, COVERAGE_MANIFEST_VERSION, SnippetCoverageLedger};
use std::collections::{BTreeMap, BTreeSet};
use std::path::{Component, Path, PathBuf};
use std::sync::{Mutex, OnceLock};
type LedgerSnapshots = Mutex<BTreeMap<PathBuf, BTreeSet<PathBuf>>>;
static PRE_RUN_LEDGERS: OnceLock<LedgerSnapshots> = OnceLock::new();
fn snapshots() -> &'static LedgerSnapshots {
PRE_RUN_LEDGERS.get_or_init(|| Mutex::new(BTreeMap::new()))
}
pub fn snapshot_pre_run_ledger(output_root: &Path) {
let mut snapshots = match snapshots().lock() {
Ok(snapshots) => snapshots,
Err(poisoned) => poisoned.into_inner(),
};
if snapshots.contains_key(output_root) {
return;
}
let owned = read_owned_paths(output_root);
tracing::debug!(
target: "alef::e2e::snippets::ownership",
root = %output_root.display(),
recorded = owned.len(),
"snapshotted pre-run snippet ownership ledger"
);
snapshots.insert(output_root.to_path_buf(), owned);
}
pub fn is_ledger_owned_snippet_path(base_dir: &Path, path: &Path) -> bool {
if !is_markdown(path) {
return false;
}
let snapshots = match snapshots().lock() {
Ok(snapshots) => snapshots,
Err(poisoned) => poisoned.into_inner(),
};
snapshots.iter().any(|(output_root, owned)| {
path.strip_prefix(base_dir.join(output_root))
.is_ok_and(|relative| owned.contains(relative))
})
}
fn read_owned_paths(output_root: &Path) -> BTreeSet<PathBuf> {
let manifest = output_root.join(COVERAGE_MANIFEST);
let Ok(bytes) = std::fs::read(&manifest) else {
return BTreeSet::new();
};
let ledger: SnippetCoverageLedger = match serde_json::from_slice(&bytes) {
Ok(ledger) => ledger,
Err(error) => {
tracing::warn!(
target: "alef::e2e::snippets::ownership",
manifest = %manifest.display(),
"snippet coverage ledger is unreadable, so no pre-existing snippet can prove alef \
ownership this run: {error}"
);
return BTreeSet::new();
}
};
if ledger.format_version != COVERAGE_MANIFEST_VERSION {
tracing::warn!(
target: "alef::e2e::snippets::ownership",
manifest = %manifest.display(),
found = ledger.format_version,
expected = COVERAGE_MANIFEST_VERSION,
"snippet coverage ledger version is unsupported, so it establishes no ownership"
);
return BTreeSet::new();
}
ledger
.generated_metadata
.into_iter()
.map(|entry| entry.path)
.filter(|path| is_claimable_entry(path))
.collect()
}
fn is_claimable_entry(path: &Path) -> bool {
is_markdown(path)
&& path
.components()
.all(|component| matches!(component, Component::Normal(_)))
}
fn is_markdown(path: &Path) -> bool {
path.extension().and_then(|extension| extension.to_str()) == Some("md")
}
#[cfg(test)]
mod tests {
use super::super::{GeneratedSnippetMetadata, SnippetCoverageKey};
use super::*;
use crate::e2e::fixture::SideEffectClass;
fn metadata(path: &str) -> GeneratedSnippetMetadata {
GeneratedSnippetMetadata {
key: SnippetCoverageKey {
fixture_id: "example".into(),
language: "python".into(),
},
path: PathBuf::from(path),
language: "python".into(),
target: "python".into(),
session: "python".into(),
requires: Vec::new(),
side_effect: SideEffectClass::Safe,
}
}
fn ledger(version: u32, paths: &[&str]) -> SnippetCoverageLedger {
SnippetCoverageLedger {
format_version: version,
generated_paths: paths.iter().map(PathBuf::from).collect(),
generated_metadata: paths.iter().map(|path| metadata(path)).collect(),
..SnippetCoverageLedger::default()
}
}
fn snapshot(ledger: &SnippetCoverageLedger) -> (tempfile::TempDir, PathBuf) {
let base = tempfile::tempdir().expect("temporary base directory");
let output_root = PathBuf::from("docs/snippets");
let absolute_root = base.path().join(&output_root);
std::fs::create_dir_all(&absolute_root).expect("create snippet root");
std::fs::write(
absolute_root.join(COVERAGE_MANIFEST),
serde_json::to_vec(ledger).expect("serialize ledger"),
)
.expect("write ledger");
snapshot_pre_run_ledger(&absolute_root);
(base, absolute_root)
}
#[test]
fn a_path_the_previous_run_recorded_is_claimable() {
let (base, root) = snapshot(&ledger(COVERAGE_MANIFEST_VERSION, &["python/chat/smoke.md"]));
assert!(is_ledger_owned_snippet_path(
base.path(),
&root.join("python/chat/smoke.md")
));
}
#[test]
fn a_hand_written_snippet_under_the_same_root_is_not_claimable() {
let (base, root) = snapshot(&ledger(COVERAGE_MANIFEST_VERSION, &["python/chat/smoke.md"]));
assert!(
!is_ledger_owned_snippet_path(base.path(), &root.join("legacy/migration-guide.md")),
"an unrecorded snippet under the snippet root must never be claimed"
);
assert!(
!is_ledger_owned_snippet_path(base.path(), &root.join("python/chat/hand-written.md")),
"an unrecorded snippet in a recorded snippet's own directory must never be claimed"
);
}
#[test]
fn a_non_markdown_ledger_entry_is_never_claimable() {
let (base, root) = snapshot(&ledger(
COVERAGE_MANIFEST_VERSION,
&["packages/java/PublicApi.java", "packages/node/package.json"],
));
assert!(!is_ledger_owned_snippet_path(
base.path(),
&root.join("packages/java/PublicApi.java")
));
assert!(!is_ledger_owned_snippet_path(
base.path(),
&root.join("packages/node/package.json")
));
}
#[test]
fn a_ledger_entry_escaping_its_root_is_never_claimable() {
let (base, root) = snapshot(&ledger(COVERAGE_MANIFEST_VERSION, &["../../README.md"]));
assert!(!is_ledger_owned_snippet_path(
base.path(),
&base.path().join("README.md")
));
assert!(!is_ledger_owned_snippet_path(
base.path(),
&root.join("../../README.md")
));
}
#[test]
fn a_markdown_file_outside_the_snapshotted_root_is_not_claimable() {
let (base, _root) = snapshot(&ledger(COVERAGE_MANIFEST_VERSION, &["python/chat/smoke.md"]));
assert!(!is_ledger_owned_snippet_path(
base.path(),
&base.path().join("docs/other/python/chat/smoke.md")
));
}
#[test]
fn an_unsupported_ledger_version_establishes_no_ownership() {
let (base, root) = snapshot(&ledger(COVERAGE_MANIFEST_VERSION + 1, &["python/chat/smoke.md"]));
assert!(!is_ledger_owned_snippet_path(
base.path(),
&root.join("python/chat/smoke.md")
));
}
#[test]
fn a_corrupt_ledger_establishes_no_ownership() {
let base = tempfile::tempdir().expect("temporary base directory");
let root = base.path().join("docs/snippets");
std::fs::create_dir_all(&root).expect("create snippet root");
std::fs::write(root.join(COVERAGE_MANIFEST), b"{ not json").expect("write corrupt ledger");
snapshot_pre_run_ledger(&root);
assert!(!is_ledger_owned_snippet_path(
base.path(),
&root.join("python/chat/smoke.md")
));
}
#[test]
fn nothing_is_claimable_without_a_snapshot() {
let base = tempfile::tempdir().expect("temporary base directory");
let root = base.path().join("docs/snippets");
std::fs::create_dir_all(&root).expect("create snippet root");
std::fs::write(
root.join(COVERAGE_MANIFEST),
serde_json::to_vec(&ledger(COVERAGE_MANIFEST_VERSION, &["python/chat/smoke.md"])).expect("serialize"),
)
.expect("write ledger");
assert!(!is_ledger_owned_snippet_path(
base.path(),
&root.join("python/chat/smoke.md")
));
}
#[test]
fn a_ledger_rewritten_after_the_snapshot_cannot_widen_ownership() {
let (base, root) = snapshot(&ledger(COVERAGE_MANIFEST_VERSION, &["python/chat/smoke.md"]));
std::fs::write(
root.join(COVERAGE_MANIFEST),
serde_json::to_vec(&ledger(
COVERAGE_MANIFEST_VERSION,
&["python/chat/smoke.md", "python/chat/newly-claimed.md"],
))
.expect("serialize"),
)
.expect("rewrite ledger");
snapshot_pre_run_ledger(&root);
assert!(is_ledger_owned_snippet_path(
base.path(),
&root.join("python/chat/smoke.md")
));
assert!(
!is_ledger_owned_snippet_path(base.path(), &root.join("python/chat/newly-claimed.md")),
"a path this run merely intends to write is not a path a previous run recorded"
);
}
#[test]
fn a_path_present_only_in_generated_paths_is_not_claimable() {
let mut disagreeing = ledger(COVERAGE_MANIFEST_VERSION, &["python/chat/smoke.md"]);
disagreeing
.generated_paths
.push(PathBuf::from("python/chat/metadata-free.md"));
let (base, root) = snapshot(&disagreeing);
assert!(is_ledger_owned_snippet_path(
base.path(),
&root.join("python/chat/smoke.md")
));
assert!(!is_ledger_owned_snippet_path(
base.path(),
&root.join("python/chat/metadata-free.md")
));
}
}