70 lines
2.6 KiB
Python
70 lines
2.6 KiB
Python
"""The failure-artifact collector (US07-04).
|
|
|
|
CI must be able to explain a randomized failure after the temporary library is
|
|
gone, which means the seed, the database, the journals, the logs, and a complete
|
|
filesystem manifest have to leave the temporary directory before pytest cleans it.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import json
|
|
|
|
from tests._artifacts import collect, manifest
|
|
|
|
|
|
def _library(root):
|
|
(root / "data").mkdir(parents=True)
|
|
(root / "data" / "photo_pipeline.db").write_bytes(b"database bytes")
|
|
(root / "data" / "photo_pipeline.db-wal").write_bytes(b"write ahead log")
|
|
(root / "data" / "uploads").mkdir()
|
|
(root / "data" / "uploads" / "batch.log").write_text("INFO uploaded a.jpg\n")
|
|
(root / "lib").mkdir()
|
|
(root / "lib" / "a.jpg").write_bytes(b"pixels")
|
|
return root
|
|
|
|
|
|
def test_the_manifest_covers_every_file_with_its_hash(tmp_path):
|
|
root = _library(tmp_path / "run")
|
|
entries = {entry["path"]: entry for entry in manifest(root)}
|
|
|
|
assert set(entries) == {
|
|
"data/photo_pipeline.db",
|
|
"data/photo_pipeline.db-wal",
|
|
"data/uploads/batch.log",
|
|
"lib/a.jpg",
|
|
}
|
|
assert entries["lib/a.jpg"]["sha256"] == hashlib.sha256(b"pixels").hexdigest()
|
|
assert entries["lib/a.jpg"]["bytes"] == 6
|
|
|
|
|
|
def test_collect_keeps_the_database_journals_logs_and_seed(tmp_path, monkeypatch):
|
|
root = _library(tmp_path / "run")
|
|
monkeypatch.setenv("PHOTO_PIPELINE_TEST_ARTIFACTS", str(tmp_path / "artifacts"))
|
|
|
|
destination = collect(root, "tests/x.py::test_races[run1]", properties={"race_seed": 1234})
|
|
|
|
seeds = json.loads((destination / "seeds.json").read_text())
|
|
assert seeds["properties"]["race_seed"] == 1234
|
|
assert seeds["test"].endswith("test_races[run1]")
|
|
|
|
kept = {str(p.relative_to(destination / "files")) for p in (destination / "files").rglob("*") if p.is_file()}
|
|
assert kept == {
|
|
"data/photo_pipeline.db",
|
|
"data/photo_pipeline.db-wal",
|
|
"data/uploads/batch.log",
|
|
}, "databases, write-ahead logs, and logs are the diagnosable evidence"
|
|
# The photo itself is never copied out of the library — but it is in the
|
|
# manifest, so a file that went missing is still provable.
|
|
assert any(entry["path"] == "lib/a.jpg" for entry in json.loads((destination / "manifest.json").read_text()))
|
|
|
|
|
|
def test_collecting_twice_for_one_test_is_safe(tmp_path, monkeypatch):
|
|
root = _library(tmp_path / "run")
|
|
monkeypatch.setenv("PHOTO_PIPELINE_TEST_ARTIFACTS", str(tmp_path / "artifacts"))
|
|
|
|
first = collect(root, "tests/x.py::test_a")
|
|
second = collect(root, "tests/x.py::test_a")
|
|
|
|
assert first == second and (second / "manifest.json").exists()
|