Files
kandev/.github/scripts/bounded-step-summary_test.py
T
Alassane 698ef63e67 ci: bound backend test step summaries (#3410)
Co-authored-by: ayattara <alassane.yattara@savoirfairelinux.com>
Co-authored-by: Carlos Florencio <carlosmflorencio@gmail.com>
2026-09-06 11:35:38 +01:00

156 lines
5.4 KiB
Python

#!/usr/bin/env python3
"""Behavior tests for the bounded GitHub Actions step-summary writer."""
from pathlib import Path
import subprocess
import tempfile
import unittest
REPO_ROOT = Path(__file__).resolve().parents[2]
SCRIPT = REPO_ROOT / ".github" / "scripts" / "bounded-step-summary.py"
class BoundedStepSummaryTest(unittest.TestCase):
def run_writer(self, summary: str, *, max_bytes: int = 983_040) -> bytes:
with tempfile.TemporaryDirectory() as tmp:
tmp_path = Path(tmp)
source = tmp_path / "generated-summary.md"
output = tmp_path / "github-step-summary.md"
source.write_text(summary, encoding="utf-8")
result = subprocess.run(
[
"python3",
str(SCRIPT),
"--input",
str(source),
"--output",
str(output),
"--diagnostics-label",
"backend-test-results-1",
"--diagnostics-url",
"https://github.example.test/kdlbs/kandev/actions/runs/123#artifacts",
"--max-bytes",
str(max_bytes),
],
capture_output=True,
text=True,
check=False,
)
self.assertEqual(result.returncode, 0, result.stderr)
return output.read_bytes()
def test_normal_summary_is_unchanged(self) -> None:
summary = "## 📝 Test results\n\n🔴 `TestWorkspaceFailure` failed\n"
self.assertEqual(self.run_writer(summary), summary.encode("utf-8"))
def test_oversized_summary_is_bounded_explicit_and_utf8_safe(self) -> None:
summary = (
"## 📝 Test results\n\n"
"🔴 `TestWorkspaceFailure` failed\n\n"
"boundary-padding-12"
+ "diagnostic=失敗🔥\n" * 60_000
)
source_bytes = summary.encode("utf-8")
self.assertGreater(len(source_bytes), 1_048_576)
first = self.run_writer(summary)
second = self.run_writer(summary)
rendered = first.decode("utf-8")
self.assertLessEqual(len(first), 983_040)
self.assertEqual(first, second)
self.assertIn("TestWorkspaceFailure", rendered)
self.assertIn("truncated", rendered.lower())
self.assertIn("backend-test-results-1", rendered)
self.assertIn(
"https://github.example.test/kdlbs/kandev/actions/runs/123#artifacts",
rendered,
)
def test_oversized_summary_retains_later_failure_identity(self) -> None:
summary = (
"<h2>📝 Test results</h2>\n"
"<table><tr><td><ul>"
"<li>🔴<code>TestEarlyFailure</code></li>"
"</ul></td></tr></table>\n"
+ "diagnostic=失敗🔥\n" * 200_000
+ "<table><tr><td><ul>"
"<li>🔴<code>TestLaterFailure</code></li>"
"</ul></td></tr></table>\n"
)
rendered = self.run_writer(summary).decode("utf-8")
self.assertIn("TestEarlyFailure", rendered)
self.assertIn("TestLaterFailure", rendered)
def test_invalid_utf8_input_is_rejected(self) -> None:
# Contract coverage for the writer's existing UTF-8 validation.
with tempfile.TemporaryDirectory() as tmp:
tmp_path = Path(tmp)
source = tmp_path / "generated-summary.md"
output = tmp_path / "github-step-summary.md"
source.write_bytes(b"valid prefix\xff")
result = subprocess.run(
[
"python3",
str(SCRIPT),
"--input",
str(source),
"--output",
str(output),
"--diagnostics-label",
"backend-test-results-1",
"--diagnostics-url",
"https://github.example.test/kdlbs/kandev/actions/runs/123#artifacts",
],
capture_output=True,
text=True,
check=False,
)
self.assertNotEqual(result.returncode, 0)
self.assertIn("UnicodeDecodeError", result.stderr)
def test_impossibly_small_max_bytes_is_rejected(self) -> None:
with tempfile.TemporaryDirectory() as tmp:
tmp_path = Path(tmp)
source = tmp_path / "generated-summary.md"
output = tmp_path / "github-step-summary.md"
source.write_text("oversized summary", encoding="utf-8")
result = subprocess.run(
[
"python3",
str(SCRIPT),
"--input",
str(source),
"--output",
str(output),
"--diagnostics-label",
"backend-test-results-1",
"--diagnostics-url",
"https://github.example.test/kdlbs/kandev/actions/runs/123#artifacts",
"--max-bytes",
"1",
],
capture_output=True,
text=True,
check=False,
)
self.assertNotEqual(result.returncode, 0)
self.assertIn(
"max bytes is too small for the truncation notice",
result.stderr,
)
if __name__ == "__main__":
unittest.main()