use std::{fs, path::PathBuf};
fn read_source(relative_path: &str) -> String {
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
path.push(relative_path);
fs::read_to_string(&path)
.unwrap_or_else(|err| panic!("failed to read {}: {err}", path.display()))
}
fn rust_sources_under(relative_path: &str) -> Vec<PathBuf> {
let mut root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
root.push(relative_path);
let mut sources = Vec::new();
let mut pending = vec![root];
while let Some(path) = pending.pop() {
let entries = fs::read_dir(&path)
.unwrap_or_else(|err| panic!("failed to list {}: {err}", path.display()));
for entry in entries {
let path = entry
.unwrap_or_else(|err| panic!("failed to read directory entry: {err}"))
.path();
if path.is_dir() {
pending.push(path);
} else if path.extension().is_some_and(|extension| extension == "rs") {
sources.push(path);
}
}
}
sources.sort();
sources
}
fn compact_source(source: &str) -> String {
source
.chars()
.filter(|character| !character.is_whitespace())
.collect()
}
#[test]
fn data_store_insert_stays_canonical_row_only() {
let source = read_source("src/db/data/store.rs");
assert!(
source.contains("pub(in crate::db) fn insert(&mut self, key: RawDataKey, row: CanonicalRow) -> Option<RawRow>"),
"DataStore::insert must remain CanonicalRow-only at the production write boundary",
);
assert!(
!source.contains("pub fn insert(&mut self, key: RawDataKey, row: RawRow)"),
"DataStore::insert must not accept RawRow in production code",
);
}
#[test]
fn prepared_row_write_payloads_stay_canonical() {
let prepared_op = read_source("src/db/commit/prepared_op.rs");
let typed_save = read_source("src/db/executor/mutation/save/typed.rs");
let structural_save = read_source("src/db/executor/mutation/save/structural.rs");
assert!(
prepared_op.contains("pub(crate) data_value: Option<CanonicalRow>,"),
"prepared row commit ops must carry CanonicalRow after-images",
);
assert!(
!prepared_op.contains("pub(crate) data_value: Option<RawRow>,"),
"prepared row commit ops must not regress to RawRow after-images",
);
assert!(
typed_save.contains("let row_bytes = CanonicalRow::from_entity(entity)?"),
"typed save after-image construction must stay CanonicalRow-backed",
);
assert!(
structural_save.contains("fn build_structural_after_image_row(\n mode: MutationMode,\n mutation: &MutationInput,\n old_row: Option<&RawRow>,\n ) -> Result<CanonicalRow, InternalError>"),
"structural save after-image builder must return CanonicalRow",
);
}
#[test]
fn value_stays_out_of_persisted_field_contracts() {
let forbidden_impls = [
"implPersistedFieldSlotCodecforValue",
"implPersistedFieldSlotCodecforVec<Value>",
"implPersistedStructuredFieldCodecforValue",
"implPersistedStructuredFieldCodecforVec<Value>",
"implFieldTypeMetaforValue",
"implFieldTypeMetaforVec<Value>",
];
let mut violations = Vec::new();
for path in rust_sources_under("src") {
let source = fs::read_to_string(&path)
.unwrap_or_else(|err| panic!("failed to read {}: {err}", path.display()));
let compact = compact_source(&source);
for forbidden in forbidden_impls {
if compact.contains(forbidden) {
violations.push(format!("{} contains {forbidden}", path.display()));
}
}
}
assert!(
violations.is_empty(),
"Value is runtime-only and must not implement persisted-field contracts:\n{}",
violations.join("\n"),
);
}