Files
mrleo1nid f9eb5c1212
CI / frontend (push) Failing after 15s
CI / backend (push) Failing after 37s
feat: improve RenPy conversion and support MIST runtime
2026-10-25 23:16:33 +03:00

84 lines
3.8 KiB
Python

import hashlib
import os
from pathlib import Path
import pytest
from app.converter.compatibility import audit_ir, blocking_names
from app.converter.rpy_parser import RpyParser, ScriptData
from app.games import renpy_builds
from app.import_library import check
def parse(source):
data = ScriptData()
data.prescan(source)
RpyParser(data, "script.rpy").parse(source)
audit_ir(data)
return data
def test_mist_engine_calls_are_audited_and_waiting_helpers_propagate():
data = parse('init python:\n def video_player():\n renpy.movie_cutscene("[movieplaying]")\n'
' def wait_for_key():\n return ui.interact()\n'
'label start:\n $ video_player()\n $ result = wait_for_key()\n'
' $ renpy.free_memory()\n $ achievement.clear_all()\n return\n')
assert not data.blockers
assert blocking_names(data) == ["video_player", "wait_for_key"]
def test_gallery_and_runtime_thumbnail_declarations_are_supported():
data = parse('init python:\n gallery = Gallery()\n gallery.button("art")\n'
' gallery.image("art")\n'
' renpy.image("thumb", im.Scale(ImageReference("art"), 384, 216))\n'
' SetMixer("ambiant", 0.5)()\nlabel start:\n return\n')
assert not data.blockers
def test_movie_mask_and_loop_survive_conversion_and_alias_resolution():
from app.converter.pipeline import _resolve_image
data = parse('image effect = Movie(play="effect.mpg", mask="mask.mpg", loop=False)\n'
'label start:\n show effect\n return\n')
assert data.images["effect"] == {"movie": "effect.mpg", "movieMask": "mask.mpg", "movieLoop": False}
missing = set()
image = _resolve_image(data.images["effect"], {"effect.mpg": "effect.webm", "mask.mpg": "mask.webm"}, missing)
assert image == {"movie": "effect.webm", "movieMask": "mask.webm", "movieLoop": False}
assert not missing
def test_unknown_movie_mask_cannot_silently_become_an_opaque_movie():
data = parse('image effect = Movie(play="effect.webm", mask=choose_mask())\n'
'label start:\n show effect\n return\n')
assert any("маска" in message for message in data.blockers)
def test_mist_waivers_do_not_hide_new_or_more_frequent_errors():
data = parse('label start:\n jump robinspent\n jump robinspent\n'
' jump breakfastdialog\n $ unsupported_new_call()\n')
waived = renpy_builds.waive_known(data, "renpy/mist-1.0.3")
assert waived == ["Не найдена цель перехода: breakfastdialog"]
assert data.blockers["Не найдена цель перехода: robinspent"] == 2
assert any("unsupported_new_call" in message for message in data.blockers)
def test_build_content_digest_rejects_same_size_modified_script_archive(tmp_path, monkeypatch):
archive = tmp_path / "scripts.rpa"
archive.write_bytes(b"original")
fingerprint = renpy_builds.fingerprint(tmp_path)
monkeypatch.setitem(renpy_builds.BUILDS, fingerprint, {
"id": "test/content-pinned", "verify": {"scripts.rpa": hashlib.sha256(b"original").hexdigest()}, "defects": {}})
assert renpy_builds.identify(tmp_path) == "test/content-pinned"
archive.write_bytes(b"modified")
assert renpy_builds.fingerprint(tmp_path) == fingerprint
assert renpy_builds.identify(tmp_path) is None
@pytest.mark.skipif(not os.environ.get("PGAMES_MIST_ORIGINAL"), reason="Original MIST distribution is local")
def test_original_mist_passes_with_only_confirmed_author_defects():
report = check(Path(os.environ["PGAMES_MIST_ORIGINAL"]))
assert report["compatible"] and report["hasStart"]
assert report["build"] == "renpy/mist-1.0.3"
assert len(report["knownDefects"]) == 5
assert not report.get("issues")