use autumn_web::cache::coherence::{self, DependencyProvenance, model_key};
use {{crate_name}} as _;
#[test]
fn the_app_is_provably_cache_coherent() {
let manifest = coherence::audit();
assert!(
manifest.violations.is_empty(),
"the build gate would fail:\n{}",
coherence::format_diagnostic(&manifest.violations)
);
}
#[test]
fn the_coherence_manifest_is_emitted_as_a_build_artifact() {
let manifest = coherence::audit();
let json: serde_json::Value = serde_json::from_str(&manifest.to_json()).unwrap();
assert_eq!(json["schema_version"], 1);
let reads = json["dimensions"]["cached_reads"]["entries"]
.as_array()
.unwrap();
let entry = reads
.iter()
.find(|e| e["id"].as_str().unwrap().ends_with("cached_project_count"))
.expect("the app's cached read must be in the manifest");
assert_eq!(entry["provenance"], "declared");
assert!(
entry["reads"]
.as_array()
.unwrap()
.iter()
.any(|m| model_key(m.as_str().unwrap()) == "Project")
);
let mutations = json["dimensions"]["mutations"]["entries"]
.as_array()
.unwrap();
assert!(
mutations
.iter()
.any(|m| m["name"] == "ProjectRepository::save" && m["table"] == "projects")
);
assert!(
json["dimensions"]["invalidations"]["entries"]
.as_array()
.unwrap()
.iter()
.any(|e| e["mutation"] == "ProjectRepository::save"
&& e["read"]
.as_str()
.unwrap()
.ends_with("cached_project_count"))
);
}
#[test]
fn removing_the_invalidation_edge_turns_the_build_red() {
let reads = coherence::registered_reads();
let mut mutations = coherence::registered_mutations();
for mutation in &mut mutations {
if mutation.repository == "ProjectRepository" {
mutation.invalidates.clear();
}
}
let findings = coherence::check(&reads, &mutations);
assert!(
!findings.is_empty(),
"the gate must catch the staleness bug the edge was covering"
);
let diagnostic = coherence::format_diagnostic(&findings);
assert!(diagnostic.contains("cached_project_count"), "{diagnostic}");
assert!(
diagnostic.contains("ProjectRepository::save"),
"{diagnostic}"
);
assert!(diagnostic.contains("Project"), "{diagnostic}");
assert!(diagnostic.contains("invalidates("), "{diagnostic}");
}
#[test]
fn the_apps_cached_read_declares_rather_than_guesses_its_dependencies() {
let read = coherence::registered_reads()
.into_iter()
.find(|r| r.id.ends_with("cached_project_count"))
.expect("cached_project_count must register itself");
assert_eq!(read.provenance, DependencyProvenance::Declared);
assert!(read.acknowledged_stale.is_none());
}
#[test]
fn the_app_emits_its_manifest_in_dump_mode_without_a_database() {
let output = std::process::Command::new(env!("CARGO_BIN_EXE_{{crate_name}}"))
.env("AUTUMN_DUMP_CACHE_COHERENCE", "1")
.env_remove("DATABASE_URL")
.output()
.expect("the app binary must run");
assert!(
output.status.success(),
"dump mode must exit 0; stderr:\n{}",
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
let manifest = coherence::parse_manifest_dump(&stdout)
.unwrap_or_else(|| panic!("no manifest on the marker line; stdout was:\n{stdout}"));
assert_eq!(manifest.schema_version, 1);
assert!(
manifest.violations.is_empty(),
"the shipped app must audit clean through the real dump path:\n{}",
coherence::format_diagnostic(&manifest.violations)
);
assert!(
manifest
.dimensions
.cached_reads
.entries
.iter()
.any(|e| e.id.ends_with("cached_project_count")),
"the app's cached read must survive the process boundary"
);
assert!(
manifest
.dimensions
.mutations
.entries
.iter()
.any(|e| e.name == "ProjectRepository::save"),
"so must its write surface"
);
}