|
@@ -166,8 +166,23 @@ def _assert_concurrent_report_pairs(
|
|
|
actual_markers.add(marker)
|
|
actual_markers.add(marker)
|
|
|
assert f"- Model: `{marker}`" in markdown
|
|
assert f"- Model: `{marker}`" in markdown
|
|
|
assert actual_markers == set(markers)
|
|
assert actual_markers == set(markers)
|
|
|
- assert list(output_dir.glob("*.lock")) == []
|
|
|
|
|
- assert list(output_dir.glob("*.tmp")) == []
|
|
|
|
|
|
|
+ _assert_no_publication_artifacts(output_dir)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def _assert_no_publication_artifacts(output_dir: Path) -> None:
|
|
|
|
|
+ leftovers = [
|
|
|
|
|
+ path.name
|
|
|
|
|
+ for path in output_dir.iterdir()
|
|
|
|
|
+ if path.name.endswith((".tmp", ".lock"))
|
|
|
|
|
+ or "placeholder" in path.name
|
|
|
|
|
+ ]
|
|
|
|
|
+ assert leftovers == []
|
|
|
|
|
+ report_paths = [
|
|
|
|
|
+ path
|
|
|
|
|
+ for path in output_dir.iterdir()
|
|
|
|
|
+ if path.suffix in {".json", ".md"}
|
|
|
|
|
+ ]
|
|
|
|
|
+ assert all(path.stat().st_size > 0 for path in report_paths)
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
@pytest.mark.parametrize(
|
|
@@ -586,219 +601,309 @@ def test_atomic_write_creates_matching_unique_json_and_markdown_paths(tmp_path:
|
|
|
assert markdown_path.name == f"{timestamp}-1.md"
|
|
assert markdown_path.name == f"{timestamp}-1.md"
|
|
|
assert json.loads(json_path.read_text()) == report.model_dump(mode="json")
|
|
assert json.loads(json_path.read_text()) == report.model_dump(mode="json")
|
|
|
assert markdown_path.read_text() == reporting.render_markdown(report)
|
|
assert markdown_path.read_text() == reporting.render_markdown(report)
|
|
|
- assert list(tmp_path.glob("*.tmp")) == []
|
|
|
|
|
|
|
+ _assert_no_publication_artifacts(tmp_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
-def test_second_placeholder_collision_cleans_first_and_uses_suffix(
|
|
|
|
|
|
|
+def test_json_created_immediately_before_link_wins_and_writer_retries(
|
|
|
tmp_path: Path,
|
|
tmp_path: Path,
|
|
|
|
|
+ monkeypatch: pytest.MonkeyPatch,
|
|
|
):
|
|
):
|
|
|
reporting = _reporting_module()
|
|
reporting = _reporting_module()
|
|
|
timestamp = "20260714T011223Z"
|
|
timestamp = "20260714T011223Z"
|
|
|
|
|
+ external_json = tmp_path / f"{timestamp}.json"
|
|
|
|
|
+ real_link = reporting.os.link
|
|
|
|
|
+ link_calls = 0
|
|
|
|
|
+
|
|
|
|
|
+ def create_before_link(source: Path, destination: Path) -> None:
|
|
|
|
|
+ nonlocal link_calls
|
|
|
|
|
+ link_calls += 1
|
|
|
|
|
+ destination = Path(destination)
|
|
|
|
|
+ if link_calls == 1:
|
|
|
|
|
+ destination.write_text("external json")
|
|
|
|
|
+ real_link(source, destination)
|
|
|
|
|
+
|
|
|
|
|
+ monkeypatch.setattr(reporting.os, "link", create_before_link)
|
|
|
|
|
+
|
|
|
|
|
+ json_path, markdown_path = reporting.write_benchmark_report(
|
|
|
|
|
+ _marker_report("json-link-collision"),
|
|
|
|
|
+ tmp_path,
|
|
|
|
|
+ timestamp=timestamp,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ assert link_calls == 3
|
|
|
|
|
+ assert external_json.read_text() == "external json"
|
|
|
|
|
+ assert not (tmp_path / f"{timestamp}.md").exists()
|
|
|
|
|
+ assert json_path.name == f"{timestamp}-1.json"
|
|
|
|
|
+ assert markdown_path.name == f"{timestamp}-1.md"
|
|
|
|
|
+ _assert_no_publication_artifacts(tmp_path)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def test_json_replaced_immediately_before_link_wins_and_writer_retries(
|
|
|
|
|
+ tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
|
|
|
+):
|
|
|
|
|
+ reporting = _reporting_module()
|
|
|
|
|
+ timestamp = "20260714T011224Z"
|
|
|
|
|
+ external_json = tmp_path / f"{timestamp}.json"
|
|
|
|
|
+ external_json.write_text("old external json")
|
|
|
|
|
+ replacement = tmp_path / "competitor-replacement.json"
|
|
|
|
|
+ real_link = reporting.os.link
|
|
|
|
|
+ real_replace = reporting.os.replace
|
|
|
|
|
+ link_calls = 0
|
|
|
|
|
+
|
|
|
|
|
+ def replace_before_link(source: Path, destination: Path) -> None:
|
|
|
|
|
+ nonlocal link_calls
|
|
|
|
|
+ link_calls += 1
|
|
|
|
|
+ destination = Path(destination)
|
|
|
|
|
+ if link_calls == 1:
|
|
|
|
|
+ replacement.write_text("new external json")
|
|
|
|
|
+ real_replace(replacement, destination)
|
|
|
|
|
+ real_link(source, destination)
|
|
|
|
|
+
|
|
|
|
|
+ monkeypatch.setattr(reporting.os, "link", replace_before_link)
|
|
|
|
|
+
|
|
|
|
|
+ json_path, markdown_path = reporting.write_benchmark_report(
|
|
|
|
|
+ _marker_report("json-link-replacement"),
|
|
|
|
|
+ tmp_path,
|
|
|
|
|
+ timestamp=timestamp,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ assert link_calls == 3
|
|
|
|
|
+ assert external_json.read_text() == "new external json"
|
|
|
|
|
+ assert json_path.name == f"{timestamp}-1.json"
|
|
|
|
|
+ assert markdown_path.name == f"{timestamp}-1.md"
|
|
|
|
|
+ _assert_no_publication_artifacts(tmp_path)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+@pytest.mark.parametrize("collision_kind", ["create", "replace"])
|
|
|
|
|
+def test_markdown_link_conflict_removes_owned_json_link_and_retries(
|
|
|
|
|
+ tmp_path: Path,
|
|
|
|
|
+ monkeypatch: pytest.MonkeyPatch,
|
|
|
|
|
+ collision_kind: str,
|
|
|
|
|
+):
|
|
|
|
|
+ reporting = _reporting_module()
|
|
|
|
|
+ timestamp = "20260714T011225Z"
|
|
|
|
|
+ base_json = tmp_path / f"{timestamp}.json"
|
|
|
external_markdown = tmp_path / f"{timestamp}.md"
|
|
external_markdown = tmp_path / f"{timestamp}.md"
|
|
|
- external_markdown.write_text("external markdown")
|
|
|
|
|
|
|
+ replacement = tmp_path / "competitor-replacement.md"
|
|
|
|
|
+ real_link = reporting.os.link
|
|
|
|
|
+ real_replace = reporting.os.replace
|
|
|
|
|
+ link_calls = 0
|
|
|
|
|
+
|
|
|
|
|
+ if collision_kind == "replace":
|
|
|
|
|
+ external_markdown.write_text("old external markdown")
|
|
|
|
|
+
|
|
|
|
|
+ def conflict_on_markdown(source: Path, destination: Path) -> None:
|
|
|
|
|
+ nonlocal link_calls
|
|
|
|
|
+ link_calls += 1
|
|
|
|
|
+ destination = Path(destination)
|
|
|
|
|
+ if destination == external_markdown:
|
|
|
|
|
+ if collision_kind == "replace":
|
|
|
|
|
+ replacement.write_text("external markdown")
|
|
|
|
|
+ real_replace(replacement, destination)
|
|
|
|
|
+ else:
|
|
|
|
|
+ destination.write_text("external markdown")
|
|
|
|
|
+ real_link(source, destination)
|
|
|
|
|
+
|
|
|
|
|
+ monkeypatch.setattr(reporting.os, "link", conflict_on_markdown)
|
|
|
|
|
|
|
|
json_path, markdown_path = reporting.write_benchmark_report(
|
|
json_path, markdown_path = reporting.write_benchmark_report(
|
|
|
- _marker_report("second-placeholder-collision"),
|
|
|
|
|
|
|
+ _marker_report("markdown-link-collision"),
|
|
|
tmp_path,
|
|
tmp_path,
|
|
|
timestamp=timestamp,
|
|
timestamp=timestamp,
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+ assert link_calls == 4
|
|
|
|
|
+ assert not base_json.exists()
|
|
|
assert external_markdown.read_text() == "external markdown"
|
|
assert external_markdown.read_text() == "external markdown"
|
|
|
- assert not (tmp_path / f"{timestamp}.json").exists()
|
|
|
|
|
assert json_path.name == f"{timestamp}-1.json"
|
|
assert json_path.name == f"{timestamp}-1.json"
|
|
|
assert markdown_path.name == f"{timestamp}-1.md"
|
|
assert markdown_path.name == f"{timestamp}-1.md"
|
|
|
- assert list(tmp_path.glob("*.lock")) == []
|
|
|
|
|
|
|
+ _assert_no_publication_artifacts(tmp_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
-def test_atomic_write_removes_temps_and_published_half_on_replace_failure(
|
|
|
|
|
- tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
|
|
|
|
|
|
+def test_markdown_conflict_does_not_remove_replaced_json_target(
|
|
|
|
|
+ tmp_path: Path,
|
|
|
|
|
+ monkeypatch: pytest.MonkeyPatch,
|
|
|
):
|
|
):
|
|
|
reporting = _reporting_module()
|
|
reporting = _reporting_module()
|
|
|
- report = reporting.build_benchmark_report(
|
|
|
|
|
- _config(), [_run()], mock=True
|
|
|
|
|
|
|
+ timestamp = "20260714T011226Z"
|
|
|
|
|
+ base_json = tmp_path / f"{timestamp}.json"
|
|
|
|
|
+ base_markdown = tmp_path / f"{timestamp}.md"
|
|
|
|
|
+ competitor_json = tmp_path / "competitor.json"
|
|
|
|
|
+ real_link = reporting.os.link
|
|
|
|
|
+ real_replace = reporting.os.replace
|
|
|
|
|
+
|
|
|
|
|
+ def replace_json_before_markdown_conflict(
|
|
|
|
|
+ source: Path,
|
|
|
|
|
+ destination: Path,
|
|
|
|
|
+ ) -> None:
|
|
|
|
|
+ destination = Path(destination)
|
|
|
|
|
+ if destination == base_markdown:
|
|
|
|
|
+ competitor_json.write_text("external json")
|
|
|
|
|
+ real_replace(competitor_json, base_json)
|
|
|
|
|
+ base_markdown.write_text("external markdown")
|
|
|
|
|
+ real_link(source, destination)
|
|
|
|
|
+
|
|
|
|
|
+ monkeypatch.setattr(
|
|
|
|
|
+ reporting.os,
|
|
|
|
|
+ "link",
|
|
|
|
|
+ replace_json_before_markdown_conflict,
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ json_path, markdown_path = reporting.write_benchmark_report(
|
|
|
|
|
+ _marker_report("replaced-json-before-cleanup"),
|
|
|
|
|
+ tmp_path,
|
|
|
|
|
+ timestamp=timestamp,
|
|
|
)
|
|
)
|
|
|
|
|
+
|
|
|
|
|
+ assert base_json.read_text() == "external json"
|
|
|
|
|
+ assert base_markdown.read_text() == "external markdown"
|
|
|
|
|
+ assert json_path.name == f"{timestamp}-1.json"
|
|
|
|
|
+ assert markdown_path.name == f"{timestamp}-1.md"
|
|
|
|
|
+ _assert_no_publication_artifacts(tmp_path)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def test_link_exception_cleans_only_owned_links_and_temps(
|
|
|
|
|
+ tmp_path: Path,
|
|
|
|
|
+ monkeypatch: pytest.MonkeyPatch,
|
|
|
|
|
+):
|
|
|
|
|
+ reporting = _reporting_module()
|
|
|
|
|
+ timestamp = "20260714T011227Z"
|
|
|
|
|
+ base_json = tmp_path / f"{timestamp}.json"
|
|
|
|
|
+ base_markdown = tmp_path / f"{timestamp}.md"
|
|
|
|
|
+ competitor_json = tmp_path / "competitor.json"
|
|
|
|
|
+ real_link = reporting.os.link
|
|
|
real_replace = reporting.os.replace
|
|
real_replace = reporting.os.replace
|
|
|
- calls = 0
|
|
|
|
|
|
|
|
|
|
- def fail_second_replace(source: Path, destination: Path) -> None:
|
|
|
|
|
- nonlocal calls
|
|
|
|
|
- calls += 1
|
|
|
|
|
- if calls == 2:
|
|
|
|
|
- raise OSError("simulated markdown publish failure")
|
|
|
|
|
- real_replace(source, destination)
|
|
|
|
|
|
|
+ def fail_markdown_link(source: Path, destination: Path) -> None:
|
|
|
|
|
+ destination = Path(destination)
|
|
|
|
|
+ if destination == base_markdown:
|
|
|
|
|
+ competitor_json.write_text("external json")
|
|
|
|
|
+ real_replace(competitor_json, base_json)
|
|
|
|
|
+ base_markdown.write_text("external markdown")
|
|
|
|
|
+ raise OSError("simulated markdown link failure")
|
|
|
|
|
+ real_link(source, destination)
|
|
|
|
|
|
|
|
- monkeypatch.setattr(reporting.os, "replace", fail_second_replace)
|
|
|
|
|
|
|
+ monkeypatch.setattr(reporting.os, "link", fail_markdown_link)
|
|
|
|
|
|
|
|
with pytest.raises(
|
|
with pytest.raises(
|
|
|
reporting.BenchmarkReportWriteError,
|
|
reporting.BenchmarkReportWriteError,
|
|
|
match="failed to write benchmark reports",
|
|
match="failed to write benchmark reports",
|
|
|
):
|
|
):
|
|
|
reporting.write_benchmark_report(
|
|
reporting.write_benchmark_report(
|
|
|
- report,
|
|
|
|
|
|
|
+ _marker_report("link-exception"),
|
|
|
tmp_path,
|
|
tmp_path,
|
|
|
- timestamp="20260714T010203Z",
|
|
|
|
|
|
|
+ timestamp=timestamp,
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
- assert list(tmp_path.iterdir()) == []
|
|
|
|
|
|
|
+ assert base_json.read_text() == "external json"
|
|
|
|
|
+ assert base_markdown.read_text() == "external markdown"
|
|
|
|
|
+ _assert_no_publication_artifacts(tmp_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
-def test_temp_fsync_failure_removes_owned_temp_and_placeholders(
|
|
|
|
|
|
|
+def test_link_interrupt_cleans_owned_links_and_temps_before_propagating(
|
|
|
tmp_path: Path,
|
|
tmp_path: Path,
|
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
|
):
|
|
):
|
|
|
reporting = _reporting_module()
|
|
reporting = _reporting_module()
|
|
|
|
|
+ real_link = reporting.os.link
|
|
|
|
|
+ link_calls = 0
|
|
|
|
|
|
|
|
- def failing_fsync(file_descriptor: int) -> None:
|
|
|
|
|
- del file_descriptor
|
|
|
|
|
- raise OSError("simulated temp fsync failure")
|
|
|
|
|
|
|
+ def interrupt_markdown_link(source: Path, destination: Path) -> None:
|
|
|
|
|
+ nonlocal link_calls
|
|
|
|
|
+ link_calls += 1
|
|
|
|
|
+ if link_calls == 2:
|
|
|
|
|
+ raise KeyboardInterrupt
|
|
|
|
|
+ real_link(source, destination)
|
|
|
|
|
|
|
|
- monkeypatch.setattr(reporting.os, "fsync", failing_fsync)
|
|
|
|
|
|
|
+ monkeypatch.setattr(reporting.os, "link", interrupt_markdown_link)
|
|
|
|
|
|
|
|
- with pytest.raises(
|
|
|
|
|
- reporting.BenchmarkReportWriteError,
|
|
|
|
|
- match="failed to write benchmark reports",
|
|
|
|
|
- ):
|
|
|
|
|
|
|
+ with pytest.raises(KeyboardInterrupt):
|
|
|
reporting.write_benchmark_report(
|
|
reporting.write_benchmark_report(
|
|
|
- _marker_report("temp-fsync-failure"),
|
|
|
|
|
|
|
+ _marker_report("link-interrupt"),
|
|
|
tmp_path,
|
|
tmp_path,
|
|
|
- timestamp="20260714T012334Z",
|
|
|
|
|
|
|
+ timestamp="20260714T011228Z",
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
assert list(tmp_path.iterdir()) == []
|
|
assert list(tmp_path.iterdir()) == []
|
|
|
|
|
|
|
|
|
|
|
|
|
-def test_second_placeholder_failure_removes_first_placeholder(
|
|
|
|
|
|
|
+def test_temp_fsync_failure_removes_owned_temps(
|
|
|
tmp_path: Path,
|
|
tmp_path: Path,
|
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
|
):
|
|
):
|
|
|
reporting = _reporting_module()
|
|
reporting = _reporting_module()
|
|
|
- original_open = reporting.os.open
|
|
|
|
|
- timestamp = "20260714T040506Z"
|
|
|
|
|
- markdown_path = tmp_path / f"{timestamp}.md"
|
|
|
|
|
|
|
|
|
|
- def failing_open(path, flags, mode=0o777):
|
|
|
|
|
- if Path(path) == markdown_path:
|
|
|
|
|
- raise OSError("simulated second placeholder failure")
|
|
|
|
|
- return original_open(path, flags, mode)
|
|
|
|
|
|
|
+ def failing_fsync(file_descriptor: int) -> None:
|
|
|
|
|
+ del file_descriptor
|
|
|
|
|
+ raise OSError("simulated temp fsync failure")
|
|
|
|
|
|
|
|
- monkeypatch.setattr(reporting.os, "open", failing_open)
|
|
|
|
|
|
|
+ monkeypatch.setattr(reporting.os, "fsync", failing_fsync)
|
|
|
|
|
|
|
|
with pytest.raises(
|
|
with pytest.raises(
|
|
|
reporting.BenchmarkReportWriteError,
|
|
reporting.BenchmarkReportWriteError,
|
|
|
match="failed to write benchmark reports",
|
|
match="failed to write benchmark reports",
|
|
|
):
|
|
):
|
|
|
reporting.write_benchmark_report(
|
|
reporting.write_benchmark_report(
|
|
|
- _marker_report("reservation-failure"),
|
|
|
|
|
|
|
+ _marker_report("temp-fsync-failure"),
|
|
|
tmp_path,
|
|
tmp_path,
|
|
|
- timestamp=timestamp,
|
|
|
|
|
|
|
+ timestamp="20260714T012334Z",
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
assert list(tmp_path.iterdir()) == []
|
|
assert list(tmp_path.iterdir()) == []
|
|
|
|
|
|
|
|
|
|
|
|
|
-def test_reservation_uses_final_placeholders_without_sidecar_lock(
|
|
|
|
|
- tmp_path: Path,
|
|
|
|
|
- monkeypatch: pytest.MonkeyPatch,
|
|
|
|
|
-):
|
|
|
|
|
- reporting = _reporting_module()
|
|
|
|
|
- timestamp = "20260714T050607Z"
|
|
|
|
|
- first_temp_written = threading.Event()
|
|
|
|
|
- allow_publish = threading.Event()
|
|
|
|
|
- original_write_text = reporting._write_text
|
|
|
|
|
- first_write = True
|
|
|
|
|
-
|
|
|
|
|
- def paused_write(path: Path, content: str) -> tuple[int, int]:
|
|
|
|
|
- nonlocal first_write
|
|
|
|
|
- identity = original_write_text(path, content)
|
|
|
|
|
- if first_write:
|
|
|
|
|
- first_write = False
|
|
|
|
|
- first_temp_written.set()
|
|
|
|
|
- assert allow_publish.wait(timeout=10)
|
|
|
|
|
- return identity
|
|
|
|
|
-
|
|
|
|
|
- monkeypatch.setattr(reporting, "_write_text", paused_write)
|
|
|
|
|
- with ThreadPoolExecutor(max_workers=1) as executor:
|
|
|
|
|
- future = executor.submit(
|
|
|
|
|
- reporting.write_benchmark_report,
|
|
|
|
|
- _marker_report("placeholder-owner"),
|
|
|
|
|
- tmp_path,
|
|
|
|
|
- timestamp=timestamp,
|
|
|
|
|
- )
|
|
|
|
|
- assert first_temp_written.wait(timeout=10)
|
|
|
|
|
- json_placeholder = tmp_path / f"{timestamp}.json"
|
|
|
|
|
- markdown_placeholder = tmp_path / f"{timestamp}.md"
|
|
|
|
|
- try:
|
|
|
|
|
- assert json_placeholder.exists()
|
|
|
|
|
- assert markdown_placeholder.exists()
|
|
|
|
|
- assert json_placeholder.read_bytes() == b""
|
|
|
|
|
- assert markdown_placeholder.read_bytes() == b""
|
|
|
|
|
- assert list(tmp_path.glob("*.lock")) == []
|
|
|
|
|
- finally:
|
|
|
|
|
- allow_publish.set()
|
|
|
|
|
- json_path, markdown_path = future.result(timeout=10)
|
|
|
|
|
-
|
|
|
|
|
- assert json_path == json_placeholder
|
|
|
|
|
- assert markdown_path == markdown_placeholder
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-@pytest.mark.parametrize("competed_suffix", [".json", ".md"])
|
|
|
|
|
-def test_external_replacement_of_reserved_final_is_not_overwritten_or_deleted(
|
|
|
|
|
|
|
+def test_both_temps_are_complete_and_fsynced_before_first_link(
|
|
|
tmp_path: Path,
|
|
tmp_path: Path,
|
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
|
- competed_suffix: str,
|
|
|
|
|
):
|
|
):
|
|
|
reporting = _reporting_module()
|
|
reporting = _reporting_module()
|
|
|
- timestamp = "20260714T060708Z"
|
|
|
|
|
- first_temp_written = threading.Event()
|
|
|
|
|
- allow_publish = threading.Event()
|
|
|
|
|
- original_write_text = reporting._write_text
|
|
|
|
|
- first_write = True
|
|
|
|
|
-
|
|
|
|
|
- def paused_write(path: Path, content: str) -> tuple[int, int]:
|
|
|
|
|
- nonlocal first_write
|
|
|
|
|
- identity = original_write_text(path, content)
|
|
|
|
|
- if first_write:
|
|
|
|
|
- first_write = False
|
|
|
|
|
- first_temp_written.set()
|
|
|
|
|
- assert allow_publish.wait(timeout=10)
|
|
|
|
|
- return identity
|
|
|
|
|
|
|
+ timestamp = "20260714T040506Z"
|
|
|
|
|
+ real_fsync = reporting.os.fsync
|
|
|
|
|
+ real_link = reporting.os.link
|
|
|
|
|
+ fsync_calls = 0
|
|
|
|
|
+ link_calls = 0
|
|
|
|
|
+
|
|
|
|
|
+ def record_fsync(file_descriptor: int) -> None:
|
|
|
|
|
+ nonlocal fsync_calls
|
|
|
|
|
+ fsync_calls += 1
|
|
|
|
|
+ real_fsync(file_descriptor)
|
|
|
|
|
+
|
|
|
|
|
+ def inspect_before_link(source: Path, destination: Path) -> None:
|
|
|
|
|
+ nonlocal link_calls
|
|
|
|
|
+ link_calls += 1
|
|
|
|
|
+ temp_paths = sorted(tmp_path.glob("*.tmp"))
|
|
|
|
|
+ assert len(temp_paths) == 2
|
|
|
|
|
+ assert all(path.stat().st_size > 0 for path in temp_paths)
|
|
|
|
|
+ assert fsync_calls == 2
|
|
|
|
|
+ real_link(source, destination)
|
|
|
|
|
+
|
|
|
|
|
+ monkeypatch.setattr(reporting.os, "fsync", record_fsync)
|
|
|
|
|
+ monkeypatch.setattr(reporting.os, "link", inspect_before_link)
|
|
|
|
|
|
|
|
- monkeypatch.setattr(reporting, "_write_text", paused_write)
|
|
|
|
|
- competed_path = tmp_path / f"{timestamp}{competed_suffix}"
|
|
|
|
|
- competitor_temp = tmp_path / f"competitor{competed_suffix}"
|
|
|
|
|
- competitor_content = b"external competitor content"
|
|
|
|
|
|
|
+ json_path, markdown_path = reporting.write_benchmark_report(
|
|
|
|
|
+ _marker_report("complete-temps"),
|
|
|
|
|
+ tmp_path,
|
|
|
|
|
+ timestamp=timestamp,
|
|
|
|
|
+ )
|
|
|
|
|
|
|
|
- with ThreadPoolExecutor(max_workers=1) as executor:
|
|
|
|
|
- future = executor.submit(
|
|
|
|
|
- reporting.write_benchmark_report,
|
|
|
|
|
- _marker_report("must-not-overwrite"),
|
|
|
|
|
- tmp_path,
|
|
|
|
|
- timestamp=timestamp,
|
|
|
|
|
- )
|
|
|
|
|
- assert first_temp_written.wait(timeout=10)
|
|
|
|
|
- competitor_temp.write_bytes(competitor_content)
|
|
|
|
|
- reporting.os.replace(competitor_temp, competed_path)
|
|
|
|
|
- allow_publish.set()
|
|
|
|
|
- with pytest.raises(
|
|
|
|
|
- reporting.BenchmarkReportWriteError,
|
|
|
|
|
- match="failed to write benchmark reports",
|
|
|
|
|
- ):
|
|
|
|
|
- future.result(timeout=10)
|
|
|
|
|
-
|
|
|
|
|
- assert competed_path.read_bytes() == competitor_content
|
|
|
|
|
- other_suffix = ".md" if competed_suffix == ".json" else ".json"
|
|
|
|
|
- assert not (tmp_path / f"{timestamp}{other_suffix}").exists()
|
|
|
|
|
- assert list(tmp_path.glob("*.lock")) == []
|
|
|
|
|
- assert list(tmp_path.glob("*.tmp")) == []
|
|
|
|
|
|
|
+ assert link_calls == 2
|
|
|
|
|
+ assert json.loads(json_path.read_text())["target"]["model"] == "complete-temps"
|
|
|
|
|
+ assert "- Model: `complete-temps`" in markdown_path.read_text()
|
|
|
|
|
+ _assert_no_publication_artifacts(tmp_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+@pytest.mark.parametrize("stress_round", range(3))
|
|
|
def test_concurrent_thread_writers_reserve_distinct_matching_pairs(
|
|
def test_concurrent_thread_writers_reserve_distinct_matching_pairs(
|
|
|
tmp_path: Path,
|
|
tmp_path: Path,
|
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
|
|
|
+ stress_round: int,
|
|
|
):
|
|
):
|
|
|
reporting = _reporting_module()
|
|
reporting = _reporting_module()
|
|
|
writer_count = 8
|
|
writer_count = 8
|
|
|
- markers = [f"thread-writer-{index}" for index in range(writer_count)]
|
|
|
|
|
|
|
+ markers = [
|
|
|
|
|
+ f"thread-{stress_round}-writer-{index}"
|
|
|
|
|
+ for index in range(writer_count)
|
|
|
|
|
+ ]
|
|
|
first_temp_barrier = threading.Barrier(writer_count, timeout=15)
|
|
first_temp_barrier = threading.Barrier(writer_count, timeout=15)
|
|
|
original_write_text = reporting._write_text
|
|
original_write_text = reporting._write_text
|
|
|
thread_state = threading.local()
|
|
thread_state = threading.local()
|
|
@@ -818,7 +923,7 @@ def test_concurrent_thread_writers_reserve_distinct_matching_pairs(
|
|
|
lambda marker: reporting.write_benchmark_report(
|
|
lambda marker: reporting.write_benchmark_report(
|
|
|
_marker_report(marker),
|
|
_marker_report(marker),
|
|
|
tmp_path,
|
|
tmp_path,
|
|
|
- timestamp="20260714T020304Z",
|
|
|
|
|
|
|
+ timestamp=f"20260714T02030{stress_round}Z",
|
|
|
),
|
|
),
|
|
|
markers,
|
|
markers,
|
|
|
)
|
|
)
|
|
@@ -828,12 +933,17 @@ def test_concurrent_thread_writers_reserve_distinct_matching_pairs(
|
|
|
_assert_concurrent_report_pairs(tmp_path, markers)
|
|
_assert_concurrent_report_pairs(tmp_path, markers)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+@pytest.mark.parametrize("stress_round", range(2))
|
|
|
def test_concurrent_process_writers_reserve_distinct_matching_pairs(
|
|
def test_concurrent_process_writers_reserve_distinct_matching_pairs(
|
|
|
tmp_path: Path,
|
|
tmp_path: Path,
|
|
|
|
|
+ stress_round: int,
|
|
|
):
|
|
):
|
|
|
context = multiprocessing.get_context("spawn")
|
|
context = multiprocessing.get_context("spawn")
|
|
|
writer_count = 4
|
|
writer_count = 4
|
|
|
- markers = [f"process-writer-{index}" for index in range(writer_count)]
|
|
|
|
|
|
|
+ markers = [
|
|
|
|
|
+ f"process-{stress_round}-writer-{index}"
|
|
|
|
|
+ for index in range(writer_count)
|
|
|
|
|
+ ]
|
|
|
first_temp_barrier = context.Barrier(writer_count, timeout=20)
|
|
first_temp_barrier = context.Barrier(writer_count, timeout=20)
|
|
|
result_queue = context.Queue()
|
|
result_queue = context.Queue()
|
|
|
processes = [
|
|
processes = [
|
|
@@ -842,7 +952,7 @@ def test_concurrent_process_writers_reserve_distinct_matching_pairs(
|
|
|
args=(
|
|
args=(
|
|
|
str(tmp_path),
|
|
str(tmp_path),
|
|
|
marker,
|
|
marker,
|
|
|
- "20260714T030405Z",
|
|
|
|
|
|
|
+ f"20260714T03040{stress_round}Z",
|
|
|
first_temp_barrier,
|
|
first_temp_barrier,
|
|
|
result_queue,
|
|
result_queue,
|
|
|
),
|
|
),
|