# Copyright (c) 2026 Krzysztof Rudnicki. MIT licence. """The single subprocess site: every way a command can fail, reported as one. The property under test is that nothing here raises and nothing looks like it worked when it did not. An exit code that lied is what put ffmpeg in this codebase's history, so "ok" has to mean ok. """ from __future__ import annotations import stat from pathlib import Path from typing import TYPE_CHECKING from signal_bot.external import DEFAULT_TIMEOUT, run if TYPE_CHECKING: import pytest def _script(tmp_path: Path, name: str, body: str) -> str: path = tmp_path / name path.write_text(f"#!/usr/bin/env python3\nimport sys\n{body}\n", encoding="utf-8") path.chmod(path.stat().st_mode | stat.S_IEXEC) return str(path) def test_a_command_that_succeeds_reports_its_output(tmp_path: Path) -> None: script = _script(tmp_path, "ok", 'sys.stdout.write("hello")') result = run([script]) assert result.ok assert result.stdout == "hello" def test_arguments_are_passed_through(tmp_path: Path) -> None: script = _script(tmp_path, "echo", 'sys.stdout.write(" ".join(sys.argv[1:]))') assert run([script, "-all=", "-o", "out.jpg"]).stdout == "-all= -o out.jpg" def test_a_nonzero_exit_is_not_ok(tmp_path: Path, caplog: pytest.LogCaptureFixture) -> None: script = _script(tmp_path, "fails", 'sys.stderr.write("no")\nsys.exit(3)') result = run([script]) assert not result.ok assert "exited 3" in caplog.text def test_a_binary_that_is_not_there_is_not_ok(tmp_path: Path) -> None: result = run([str(tmp_path / "nothing-here")]) assert not result.ok assert result.stdout == "" def test_a_command_that_hangs_is_killed_and_not_ok(tmp_path: Path) -> None: script = _script(tmp_path, "hangs", "import time\ntime.sleep(30)") result = run([script], timeout=0.2) assert not result.ok def test_the_failure_log_never_prints_the_command_output( tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """exiftool prints tag *values* on failure; a journal must not carry them.""" script = _script(tmp_path, "leaks", 'sys.stdout.write("GPS 52.2297 21.0122")\nsys.exit(1)') run([script]) assert "52.2297" not in caplog.text def test_the_default_timeout_is_long_enough_for_a_video() -> None: assert DEFAULT_TIMEOUT >= 30 def test_it_is_the_only_module_that_imports_subprocess() -> None: """Two files may shell out, and the list is closed. A further file would need a third S603 exemption, and the point of naming them here is that adding one is a visible decision rather than a habit that spreads. tool/venv_bootstrap.py is the second, added on kuhy's call of 2026-08-31. It cannot route through this module: it installs the package this module is part of, and runs on an interpreter where that package does not import yet. That is the only reason it qualifies -- being inconvenient is not. """ here = Path(__file__).resolve() root = here.parent.parent importers = sorted( str(path.relative_to(root)) for directory in ("signal_bot", "fake_signal", "tool", "scripts", "tests") for path in (root / directory).rglob("*.py") # This file names the import in order to look for it. if path != here and "import subprocess" in path.read_text(encoding="utf-8") ) assert importers == ["signal_bot/external.py", "tool/venv_bootstrap.py"]