Files
endorphin-aster-vm/crates/host/tests/metadata.rs
T
codex-bot e52d2e1e4b
Verify databases and deploy Aster VM / verify-and-deploy (push) Successful in 7m25s
Separate database connections from file-backed host information and document handoff
2026-10-19 02:07:36 +08:00

132 lines
4.6 KiB
Rust

use host::MetadataStore;
#[test]
fn missing_reads_do_not_create_state() {
let temporary = tempfile::tempdir().unwrap();
let directory = temporary.path().join("state");
let store = MetadataStore::new(&directory).unwrap();
assert_eq!(store.get("missing").unwrap(), None);
assert!(!directory.exists());
}
#[test]
fn utf8_values_survive_reopening_and_same_key_replacement() {
let temporary = tempfile::tempdir().unwrap();
let directory = temporary.path().join("日本語");
let store = MetadataStore::new(&directory).unwrap();
store.put("host.version", "0.1.0").unwrap();
store.put("project.note", "日本語・中文・😀").unwrap();
let reopened = MetadataStore::new(&directory).unwrap();
assert_eq!(
reopened.get("project.note").unwrap().as_deref(),
Some("日本語・中文・😀")
);
reopened.put("host.version", "0.2.0").unwrap();
assert_eq!(store.get("host.version").unwrap().as_deref(), Some("0.2.0"));
assert_eq!(
store.get("project.note").unwrap().as_deref(),
Some("日本語・中文・😀")
);
let record: serde_json::Value =
serde_json::from_slice(&std::fs::read(directory.join("project.note.json")).unwrap())
.unwrap();
assert_eq!(record["format_version"], 1);
assert_eq!(record["key"], "project.note");
}
#[test]
fn keys_cannot_escape_the_state_directory() {
let temporary = tempfile::tempdir().unwrap();
let directory = temporary.path().join("state");
let store = MetadataStore::new(&directory).unwrap();
for key in [
"",
"../outside",
"/outside",
"nested/key",
"nested\\key",
".hidden",
"日本語",
] {
assert!(store.put(key, "invalid").is_err(), "{key}");
assert!(store.get(key).is_err(), "{key}");
}
assert!(store.put(&"x".repeat(129), "invalid").is_err());
assert!(!directory.exists());
}
#[test]
fn corrupt_or_mismatched_records_fail_without_being_rewritten() {
let temporary = tempfile::tempdir().unwrap();
let store = MetadataStore::new(temporary.path()).unwrap();
let path = temporary.path().join("host.version.json");
for bytes in [
b"not-json".as_slice(),
b"\xff".as_slice(),
br#"{"format_version":2,"key":"host.version","value":"old"}"#.as_slice(),
br#"{"format_version":1,"key":"wrong","value":"old"}"#.as_slice(),
] {
std::fs::write(&path, bytes).unwrap();
assert!(store.get("host.version").is_err());
assert_eq!(std::fs::read(&path).unwrap(), bytes);
}
}
#[test]
fn concurrent_replacements_expose_complete_records_and_preserve_other_keys() {
let temporary = tempfile::tempdir().unwrap();
let store = MetadataStore::new(temporary.path()).unwrap();
store.put("independent", "keep").unwrap();
let a = "a".repeat(8192);
let b = "b".repeat(8192);
store.put("shared", &a).unwrap();
std::thread::scope(|scope| {
for value in [&a, &b] {
let store = &store;
scope.spawn(move || {
for _ in 0..8 {
store.put("shared", value).unwrap();
}
});
}
for _ in 0..64 {
let value = store.get("shared").unwrap().unwrap();
assert!(value == a || value == b);
}
});
assert_eq!(store.get("independent").unwrap().as_deref(), Some("keep"));
assert!(std::fs::read_dir(temporary.path()).unwrap().all(|entry| {
!entry
.unwrap()
.file_name()
.to_string_lossy()
.ends_with(".tmp")
}));
}
#[test]
fn legacy_import_is_repeatable_and_preserves_newer_file_values() {
let temporary = tempfile::tempdir().unwrap();
let store = MetadataStore::new(temporary.path()).unwrap();
store.put("host.version", "new").unwrap();
let input =
br#"[{"key":"host.version","value":"old"},{"key":"project.note","value":"legacy"}]"#;
assert_eq!(store.import_missing(input.as_slice()).unwrap(), 1);
assert_eq!(store.import_missing(input.as_slice()).unwrap(), 0);
assert_eq!(store.get("host.version").unwrap().as_deref(), Some("new"));
assert_eq!(
store.get("project.note").unwrap().as_deref(),
Some("legacy")
);
}
#[test]
fn invalid_import_keys_are_rejected_before_any_record_is_written() {
let temporary = tempfile::tempdir().unwrap();
let directory = temporary.path().join("state");
let store = MetadataStore::new(&directory).unwrap();
let input = br#"[{"key":"valid","value":"keep"},{"key":"../outside","value":"invalid"}]"#;
assert!(store.import_missing(input.as_slice()).is_err());
assert!(!directory.exists());
}