fix(e2e): close worker environment review gaps

This commit is contained in:
2026-09-22 23:28:28 +09:00
parent 0869ef0cc6
commit a689072756
7 changed files with 509 additions and 959 deletions
+70 -17
View File
@@ -140,25 +140,11 @@ impl FsRuntimeStore {
})?;
}
let snapshot_exists = root.join(RUNTIME_FILE).is_file();
let workers_dir = root.join(WORKERS_DIR);
if !snapshot_exists
&& workers_dir.is_dir()
&& fs::read_dir(&workers_dir)
.map_err(|source| RuntimeError::StoreIo {
operation: "inspect uninitialized runtime store",
path: workers_dir.clone(),
source,
})?
.next()
.is_some()
{
return Err(RuntimeError::StoreCorrupt {
operation: "open runtime store",
path: root,
message: "Worker records exist without a Runtime snapshot".to_string(),
});
if root_existed && !snapshot_exists {
validate_fresh_runtime_store_layout(&root)?;
}
let workers_dir = root.join(WORKERS_DIR);
fs::create_dir_all(&workers_dir).map_err(|source| RuntimeError::StoreIo {
operation: "create runtime store",
path: workers_dir,
@@ -362,6 +348,38 @@ impl FsRuntimeStore {
}
}
fn validate_fresh_runtime_store_layout(root: &Path) -> Result<(), RuntimeError> {
let entries = fs::read_dir(root).map_err(|source| RuntimeError::StoreIo {
operation: "inspect uninitialized runtime store",
path: root.to_path_buf(),
source,
})?;
for entry in entries {
let entry = entry.map_err(|source| RuntimeError::StoreIo {
operation: "inspect uninitialized runtime store",
path: root.to_path_buf(),
source,
})?;
let file_type = entry.file_type().map_err(|source| RuntimeError::StoreIo {
operation: "inspect uninitialized runtime store entry",
path: entry.path(),
source,
})?;
if entry.file_name() == "auth.toml" && file_type.is_file() {
continue;
}
return Err(RuntimeError::StoreCorrupt {
operation: "open runtime store",
path: root.to_path_buf(),
message: format!(
"unexpected persistence `{}` exists without a Runtime snapshot",
entry.file_name().to_string_lossy()
),
});
}
Ok(())
}
fn acquire_runtime_store_owner_lock(
root: &Path,
) -> Result<Arc<RuntimeStoreOwnerLock>, RuntimeError> {
@@ -2173,6 +2191,41 @@ mod tests {
);
}
#[test]
fn snapshotless_directory_rejects_non_auth_persistence() {
for unexpected in ["events.jsonl", "unknown.json"] {
let parent = tempfile::tempdir().unwrap();
let root = parent.path().join("runtime");
fs::create_dir_all(&root).unwrap();
fs::write(root.join("auth.toml"), b"fixture auth material").unwrap();
fs::write(root.join(unexpected), b"must remain").unwrap();
let error = FsRuntimeStore::open_or_create(root.clone(), "runtime-test").unwrap_err();
assert!(matches!(
error,
RuntimeError::StoreCorrupt { path, .. } if path == root
));
assert_eq!(fs::read(root.join(unexpected)).unwrap(), b"must remain");
assert!(!root.join(WORKERS_DIR).exists());
}
}
#[test]
fn orphan_archive_without_runtime_snapshot_is_rejected() {
let parent = tempfile::tempdir().unwrap();
let root = parent.path().join("runtime");
fs::create_dir_all(root.join(ORPHANED_WORKERS_DIR).join("worker-a")).unwrap();
let error = FsRuntimeStore::open_or_create(root.clone(), "runtime-test").unwrap_err();
assert!(matches!(
error,
RuntimeError::StoreCorrupt { path, .. } if path == root
));
assert!(root.join(ORPHANED_WORKERS_DIR).join("worker-a").is_dir());
}
#[test]
fn worker_records_without_runtime_snapshot_are_rejected() {
let parent = tempfile::tempdir().unwrap();