sleep.rpy tests `... before_sleeping=2` (assignment) in an elif; sleep.rpyc holds the same text, so Ren'Py cannot compile that branch either. Builds can now carry exact-line patches pinned by the SHA-256 of the line and the build fingerprint; this one restores `==2`. Anything else stays strict. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
74 lines
3.3 KiB
Python
74 lines
3.3 KiB
Python
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from app.converter.compatibility import Issue
|
|
from app.games import registry
|
|
from app.games.base import GameProfile
|
|
from app.games.tomie.defects import KNOWN_DEFECTS, split_known
|
|
|
|
|
|
def test_builtin_profiles_are_registered():
|
|
ids = {profile.id for profile in registry.all_profiles()}
|
|
assert {"renpy", "naninovel", "tomie/expansion-1.3801"} <= ids
|
|
assert registry.for_runtime("tomie/1").id == "tomie/expansion-1.3801"
|
|
assert registry.for_runtime(None) is None
|
|
assert registry.for_runtime("unknown/9") is None
|
|
|
|
|
|
def test_specific_profile_wins_over_engine_profile(tmp_path, monkeypatch):
|
|
assert registry.select("naninovel", tmp_path).id == "naninovel" # hash does not match
|
|
monkeypatch.setattr("app.games.tomie.identify", lambda root: "tomie/expansion-1.3801")
|
|
assert registry.select("naninovel", tmp_path).id == "tomie/expansion-1.3801"
|
|
assert registry.select("renpy", tmp_path).id == "renpy"
|
|
assert registry.select("godot", tmp_path) is None
|
|
|
|
|
|
def test_new_profile_can_be_registered_once(monkeypatch):
|
|
monkeypatch.setattr(registry, "_PROFILES", list(registry.all_profiles()))
|
|
|
|
class Custom(GameProfile):
|
|
id = "custom/game-1"
|
|
engine = "naninovel"
|
|
specific = True
|
|
|
|
def claims(self, root: Path) -> bool:
|
|
return root.name == "Custom"
|
|
|
|
registry.register(Custom())
|
|
assert registry.select("naninovel", Path("x/Custom")).id == "custom/game-1"
|
|
assert registry.select("naninovel", Path("x/Other")).id == "naninovel"
|
|
with pytest.raises(ValueError, match="уже зарегистрирован"):
|
|
registry.register(Custom())
|
|
|
|
|
|
def test_known_defects_are_waived_only_up_to_the_recorded_count():
|
|
(code, message, script), allowed = next(iter(KNOWN_DEFECTS.items()))
|
|
known_issue = Issue(code, message, f"{script}:10")
|
|
blocking, known = split_known([known_issue] * (allowed + 1))
|
|
assert len(known) == allowed and len(blocking) == 1
|
|
new = Issue("missing_target", "Не найден переход Nowhere.Start", "Common:1")
|
|
blocking, known = split_known([new, known_issue])
|
|
assert blocking == [new] and known == [known_issue]
|
|
same_message_other_script = Issue(code, message, "SomewhereElse:1")
|
|
assert split_known([same_message_other_script])[0] == [same_message_other_script]
|
|
|
|
|
|
def test_known_build_line_patch_requires_the_exact_line():
|
|
import hashlib
|
|
|
|
from app.games import renpy_builds
|
|
|
|
wrong = ' elif wake_up_after_sex=="spitroast" and number_of_people_had_sex_with_before_sleeping=2:'
|
|
fixed = wrong.replace("=2:", "==2:")
|
|
assert hashlib.sha256(wrong.encode()).hexdigest() in renpy_builds.BUILDS[
|
|
"bb19a33af00324fa027a629c052aee885e72f1b7bee7074403a5b9e20c69e2d8"]["lines"]["sleep.rpy"]
|
|
source = f"label a:\r\n{wrong}\r\n pass\r\n"
|
|
assert renpy_builds.prepare_source("renpy/the-only-doe-0.05", "Sleep.rpy", source) == \
|
|
f"label a:\r\n{fixed}\r\n pass\r\n"
|
|
# another build, another file, or an edited line stays untouched
|
|
assert renpy_builds.prepare_source(None, "sleep.rpy", source) == source
|
|
assert renpy_builds.prepare_source("renpy/the-only-doe-0.05", "other.rpy", source) == source
|
|
edited = source.replace("spitroast", "other")
|
|
assert renpy_builds.prepare_source("renpy/the-only-doe-0.05", "sleep.rpy", edited) == edited
|