Files
hermes-agent/tests/scripts/test_icon_generation_exit.py
ethernet 4188301624 fix(build): propagate icon and queued-open failures
Icon generation reported errors but returned success. Aggregate target
write and verification failures into exit 1, while processing later
targets. Keep rendering dependencies in the isolated build group.

A synchronous open error consumed a slot. Returning that slot alone
still let a deferred throw suppress an earlier callback and stall the
queue. Schedule queue draining outside completed callbacks and retain
the original exception.

Verified real clean-source generation and structural checks for all
35 targets, plus a real write failure through the Node/uv runner.
Native Windows child tests cover immediate and deferred open errors.
POSIX descriptor-limit cases are explicit skips here, not passes.
No signed package or native macOS acceptance is claimed.
2026-09-09 18:38:26 -04:00

51 lines
2.0 KiB
Python

"""Icon generation reports per-target failures without hiding later targets."""
import importlib.util
import io
import sys
from pathlib import Path
from types import ModuleType
import pytest
from PIL import Image
@pytest.mark.parametrize("failure", [None, "render", "directory", "verify"])
def test_write_status_includes_every_target(tmp_path, monkeypatch, capsys, failure):
# The renderer is build-only. This test injects failures at its byte boundary.
monkeypatch.setitem(sys.modules, "resvg_py", ModuleType("resvg_py"))
script = Path(__file__).resolve().parents[2] / "scripts" / "generate_icons.py"
spec = importlib.util.spec_from_file_location("icon_generator_under_test", script)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
monkeypatch.setattr(module, "ROOT", tmp_path)
monkeypatch.setattr(module, "ensure_masters", lambda: None)
monkeypatch.setattr(sys, "argv", [str(script)])
image = io.BytesIO()
Image.new("RGBA", (2, 2), (0, 0, 0, 0)).save(image, "PNG")
good_bytes = image.getvalue()
first = "blocked/icon.png" if failure == "directory" else "first.png"
if failure == "directory":
(tmp_path / "blocked").write_text("not a directory", encoding="utf-8")
monkeypatch.setattr(module, "TARGETS", [(first, "png", "first"), ("last.png", "png", "last")])
def target_bytes(kind, target):
if target == "first":
if failure == "render":
raise RuntimeError("injected render failure")
if failure == "verify":
return b"not an image"
return good_bytes
monkeypatch.setattr(module, "target_bytes", target_bytes)
code = 0
try:
module.main()
except SystemExit as stopped:
code = stopped.code
assert bool(code) is (failure is not None)
assert (tmp_path / "last.png").read_bytes() == good_bytes
output = capsys.readouterr().out
assert "last.png: PNG (2, 2)" in output
assert ("FAILED" in output) is (failure is not None)