test: add deterministic runtime config chain race regression
This commit is contained in:
@@ -560,3 +560,52 @@ test.each(["leaf", "ancestor"] as const)("actual harness rejects canonical %s sw
|
||||
})).toThrow();
|
||||
} finally { rmSync(f.root, { recursive: true, force: true }); }
|
||||
});
|
||||
|
||||
|
||||
test("actual harness rejects a workspace chain swap between config and manifest traversal", () => {
|
||||
const f = fixture();
|
||||
try {
|
||||
const lease = f.factory.acquireSession(f.snapshotPath);
|
||||
const python = join(process.cwd(), "..", "harness", ".venv", "bin", "python");
|
||||
const helper = join(process.cwd(), "..", "harness", "tht");
|
||||
const workspaceRoot = join(f.factoryInput.dataRoot, "sessions", workspace);
|
||||
const code = `import os,sys
|
||||
from pathlib import Path
|
||||
sys.path.insert(0, sys.argv[3])
|
||||
from tht.config import ConfigError, _read_runtime_config_source
|
||||
config_path = Path(sys.argv[1])
|
||||
workspace = Path(sys.argv[2])
|
||||
revision = config_path.stem
|
||||
|
||||
def swap_workspace_chain():
|
||||
moved = Path(str(workspace) + ".moved")
|
||||
os.rename(workspace, moved)
|
||||
(workspace / "preprocessing").mkdir(parents=True, mode=0o700)
|
||||
for name, leaf in (("runtime-config", revision + ".yaml"),
|
||||
("runtime-config-manifests", revision + ".json")):
|
||||
source = moved / "preprocessing" / name
|
||||
destination = workspace / "preprocessing" / name
|
||||
original_inode = os.stat(source).st_ino
|
||||
original_leaf_inode = os.stat(source / leaf).st_ino
|
||||
os.rename(source, destination)
|
||||
assert os.stat(destination).st_ino == original_inode
|
||||
assert os.stat(destination / leaf).st_ino == original_leaf_inode
|
||||
|
||||
try:
|
||||
_read_runtime_config_source(
|
||||
config_path,
|
||||
between_config_and_manifest_traversal=swap_workspace_chain,
|
||||
)
|
||||
except ConfigError:
|
||||
print("rejected")
|
||||
else:
|
||||
raise SystemExit("secure reader accepted a replaced workspace chain")
|
||||
`;
|
||||
const output = execFileSync(python, ["-c", code, lease.path, workspaceRoot, helper], {
|
||||
cwd: join(process.cwd(), "..", "harness"),
|
||||
env: { ...process.env, THT_RUNTIME_CONFIG_MANIFEST_SHA256: lease.manifestSha256 },
|
||||
encoding: "utf8",
|
||||
});
|
||||
expect(output.trim()).toBe("rejected");
|
||||
} finally { rmSync(f.root, { recursive: true, force: true }); }
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user