diff --git a/Libraries/PyKotor/tests/resource/formats/test_mdl_bif_slice_offset.py b/Libraries/PyKotor/tests/resource/formats/test_mdl_bif_slice_offset.py new file mode 100644 index 000000000..e1fdd2fcd --- /dev/null +++ b/Libraries/PyKotor/tests/resource/formats/test_mdl_bif_slice_offset.py @@ -0,0 +1,39 @@ +"""Regression: binary MDL read from a non-zero slice (BIF / chitin-style offset). + +``MDLBinaryReader`` must open the stream at ``offset + 12`` (geometry base) without +an extra ``set_offset(+12)``, which double-counted ``offset`` and broke BIF-sourced MDLs. +""" + +from __future__ import annotations + +from pathlib import Path + +import pytest + +from pykotor.resource.formats.mdl import read_mdl + + +def _smallest_mdl_fixture() -> Path: + candidates = ( + Path(__file__).resolve().parent.parent.parent / "test_files" / "mdl" / "m12aa_c04_cam.mdl", + Path("Libraries/PyKotor/tests/test_files/mdl/m12aa_c04_cam.mdl"), + Path("tests/test_files/mdl/m12aa_c04_cam.mdl"), + ) + for path in candidates: + if path.is_file(): + return path + pytest.skip("MDL fixture m12aa_c04_cam.mdl not found") + + +def test_read_mdl_nonzero_slice_offset_matches_standalone_file() -> None: + """Padded buffer + offset/size must parse identically to reading the file directly.""" + mdl_path = _smallest_mdl_fixture() + raw = mdl_path.read_bytes() + prefix = b"BIFSLICE" * 64 # arbitrary non-MDL padding before the resource + composite = prefix + raw + + direct = read_mdl(mdl_path) + sliced = read_mdl(composite, offset=len(prefix), size=len(raw)) + + assert sliced.name == direct.name + assert len(sliced.all_nodes()) == len(direct.all_nodes()) diff --git a/Libraries/PyKotor/tests/test_resource_json_progress_regressions.py b/Libraries/PyKotor/tests/test_resource_json_progress_regressions.py new file mode 100644 index 000000000..7a0e25200 --- /dev/null +++ b/Libraries/PyKotor/tests/test_resource_json_progress_regressions.py @@ -0,0 +1,45 @@ +"""Regression tests for JSON export progress behavior in automation (CI).""" + +from __future__ import annotations + +import io + +import pytest + +from pykotor.tools.resource_json import _supports_live_progress + + +class _FakeTTYStream(io.StringIO): + """stderr-like stream that claims to be a TTY (common in some CI runners).""" + + def isatty(self) -> bool: + return True + + +def test_supports_live_progress_honors_tty_when_not_ci(monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.delenv("CI", raising=False) + monkeypatch.delenv("GITHUB_ACTIONS", raising=False) + assert _supports_live_progress(_FakeTTYStream()) is True + + +def test_supports_live_progress_ci_env_disables_even_if_stream_is_tty( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.setenv("CI", "true") + assert _supports_live_progress(_FakeTTYStream()) is False + + +def test_supports_live_progress_github_actions_env_disables( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.delenv("CI", raising=False) + monkeypatch.setenv("GITHUB_ACTIONS", "1") + assert _supports_live_progress(_FakeTTYStream()) is False + + +def test_supports_live_progress_non_tty_false_regardless_of_ci( + monkeypatch: pytest.MonkeyPatch, +) -> None: + monkeypatch.delenv("CI", raising=False) + monkeypatch.delenv("GITHUB_ACTIONS", raising=False) + assert _supports_live_progress(io.StringIO()) is False