56 lines
1.5 KiB
Python
56 lines
1.5 KiB
Python
from __future__ import annotations
|
|
|
|
import importlib
|
|
|
|
import pytest
|
|
import structlog.testing
|
|
|
|
import opensquilla.tools.builtin as builtin
|
|
|
|
_REAL_IMPORT_MODULE = importlib.import_module
|
|
|
|
|
|
def _reload_builtin_with_failure(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
failing_module: str,
|
|
) -> None:
|
|
def _fake_import(name: str, package: str | None = None):
|
|
if name == f"opensquilla.tools.builtin.{failing_module}":
|
|
raise RuntimeError(f"{failing_module} import failed")
|
|
return _REAL_IMPORT_MODULE(name, package)
|
|
|
|
monkeypatch.setattr(importlib, "import_module", _fake_import)
|
|
importlib.reload(builtin)
|
|
|
|
|
|
def _restore_builtin(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
monkeypatch.undo()
|
|
importlib.reload(builtin)
|
|
|
|
|
|
def test_nonfatal_builtin_import_failure_logs_and_continues(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
try:
|
|
with structlog.testing.capture_logs() as captured:
|
|
_reload_builtin_with_failure(monkeypatch, "web")
|
|
finally:
|
|
_restore_builtin(monkeypatch)
|
|
|
|
assert any(
|
|
event["event"] == "builtin_tool.import_failed" and event["module"] == "web"
|
|
for event in captured
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize("module", ["shell", "patch", "filesystem"])
|
|
def test_fatal_builtin_import_failures_propagate(
|
|
module: str,
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
try:
|
|
with pytest.raises(RuntimeError, match=f"{module} import failed"):
|
|
_reload_builtin_with_failure(monkeypatch, module)
|
|
finally:
|
|
_restore_builtin(monkeypatch)
|