feat(k1): complete primary acquisition lifecycle
This commit is contained in:
@@ -129,6 +129,40 @@ def test_materializer_reuses_only_a_digest_validated_private_cache(tmp_path: Pat
|
||||
assert exporter.calls == 1
|
||||
|
||||
|
||||
def test_materializer_rejects_changed_digest_bound_secondary_artifact(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
command = _command(tmp_path / "source")
|
||||
secondary = command.artifacts[1]
|
||||
expected = _sha256(secondary.path)
|
||||
command = replace(
|
||||
command,
|
||||
artifacts=(
|
||||
command.artifacts[0],
|
||||
replace(secondary, expected_sha256=expected),
|
||||
),
|
||||
)
|
||||
secondary.path.write_text('{"record_type":"tampered","sequence":1}\n', encoding="utf-8")
|
||||
command = replace(
|
||||
command,
|
||||
artifacts=(
|
||||
command.artifacts[0],
|
||||
replace(
|
||||
command.artifacts[1],
|
||||
file_byte_length=secondary.path.stat().st_size,
|
||||
replay_byte_length=secondary.path.stat().st_size,
|
||||
),
|
||||
),
|
||||
)
|
||||
exporter = FakeExporter()
|
||||
materializer = SessionRecordingMaterializer(tmp_path / "private", exporter=exporter)
|
||||
|
||||
with pytest.raises(RecordingMaterializationError, match="digest.*catalog"):
|
||||
materializer.materialize(command)
|
||||
|
||||
assert exporter.calls == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"obsolete_schema",
|
||||
[
|
||||
@@ -286,13 +320,25 @@ def test_materializer_exports_only_validated_prefix_before_crash_tail(
|
||||
metadata = command.primary_artifact.path.with_name("mqtt.metadata.jsonl")
|
||||
with metadata.open("ab") as stream:
|
||||
stream.write(b'{"record_type":"message"')
|
||||
observed: list[tuple[int, int]] = []
|
||||
observed: list[tuple[int, int, set[str]]] = []
|
||||
|
||||
class PrefixExporter(FakeExporter):
|
||||
def __call__(self, source: Path, destination: Path) -> dict[str, object]:
|
||||
def __call__(
|
||||
self,
|
||||
source: Path,
|
||||
destination: Path,
|
||||
*,
|
||||
artifacts: dict[str, Path],
|
||||
) -> dict[str, object]:
|
||||
observed.append(
|
||||
(source.stat().st_size, source.with_name("mqtt.metadata.jsonl").stat().st_size)
|
||||
(
|
||||
source.stat().st_size,
|
||||
artifacts["index"].stat().st_size,
|
||||
set(artifacts),
|
||||
)
|
||||
)
|
||||
assert artifacts["primary"] == source
|
||||
assert all(path.parent == source.parent for path in artifacts.values())
|
||||
return super().__call__(source, destination)
|
||||
|
||||
exporter = PrefixExporter()
|
||||
@@ -300,7 +346,7 @@ def test_materializer_exports_only_validated_prefix_before_crash_tail(
|
||||
|
||||
recording = materializer.materialize(command)
|
||||
|
||||
assert observed == [(committed_raw_bytes, committed_metadata_bytes)]
|
||||
assert observed == [(committed_raw_bytes, committed_metadata_bytes, {"primary", "index"})]
|
||||
assert recording.source_sha256 == hashlib.sha256(b"native-source-recording").hexdigest()
|
||||
assert command.primary_artifact.path.read_bytes().endswith(b"uncommitted-raw-tail")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user