feat: add native Tomie adapter and strict import compatibility checks
This commit is contained in:
1 parent
c8d83b3fe7
commit
57a4edcbfd
45 files changed
+2985
-71
No files matched your search
@@ -0,0 +1,74 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def test_native_translation_and_mod_edits_rebuild_the_same_vm_input(tmp_path, monkeypatch):
|
||||
from app import mods
|
||||
from app.config import get_settings
|
||||
from app.converter.naninovel import _convert_package
|
||||
from app.converter.nani_package import Package, text_records
|
||||
from app.converter.tomie_format import unpack_modules
|
||||
from app.converter.tomie_profile import PROFILE
|
||||
from app.translation import apply_changes, text_index, locale_tables
|
||||
monkeypatch.setenv("DATA_DIR", str(tmp_path / "data"))
|
||||
get_settings.cache_clear()
|
||||
package = Package(profile=PROFILE, defaults={"points": 3}, function_data={"names": ["Tomie"]})
|
||||
|
||||
def script(name, label, commands):
|
||||
return {"name": name, "lines": [{"line": 1, "label": label, "commands": commands}]}
|
||||
|
||||
package.scripts = {
|
||||
"StartGameSetting": script("StartGameSetting", "Start", [
|
||||
{"op": "PrintText", "args": {"Text": {"template": "Points: {points}"}}},
|
||||
{"op": "ExitToTitle", "args": {}}]),
|
||||
"MessagePlay": script("MessagePlay", "Start", [{"op": "Return", "args": {}}]),
|
||||
"AppScreen": script("AppScreen", "Start", [{"op": "Stop", "args": {}}]),
|
||||
}
|
||||
package.texts = text_records("Tips", "tip:Title|Description {points}", "Tips")
|
||||
media = {key: {} for key in ("backgrounds", "characters", "textures", "videos", "audio", "fonts")}
|
||||
monkeypatch.setattr("app.converter.tomie_assets.export_media", lambda *_: ({}, media, {}))
|
||||
try:
|
||||
result = _convert_package(tmp_path, tmp_path / "work", lambda _: None, package)
|
||||
index = text_index(result.manifest)
|
||||
assert {line.source for line in index.lines} == {"Points: {points}", "Title", "Description {points}"}
|
||||
line = next(line for line in index.lines if line.source.startswith("Points:"))
|
||||
translated = apply_changes(result.manifest, "ru", lines={line.tid: {"t": "Баллы: {points}"}})
|
||||
assert locale_tables(translated, "ru")[0][line.tid]["t"] == "Баллы: {points}"
|
||||
doc = mods.document(translated)
|
||||
mods.validate(doc, translated)
|
||||
node = next(node for module in doc["scripts"].values() for label in module["labels"]
|
||||
for node in label["body"] if node.get("tid") == line.tid)
|
||||
node["what"] = "Score: {points}"
|
||||
updated = mods.store(doc, translated)
|
||||
runtime = unpack_modules(mods.document(updated)["scripts"])
|
||||
assert runtime["StartGameSetting"]["commands"][0]["args"]["Text"] == {"template": "Score: {points}"}
|
||||
module = next(module for module in doc["scripts"].values() if module.get("nani", {}).get("name") == "StartGameSetting")
|
||||
module["labels"][0]["body"].insert(0, {"id": "inserted", "op": "nani_command", "command": {
|
||||
"op": "SetCustomVariable", "args": {"Expression": "points+=1"}}})
|
||||
assert unpack_modules(doc["scripts"])["StartGameSetting"]["labels"]["Start"] == 1
|
||||
mods.validate(doc, translated)
|
||||
node["command"]["op"] = "NativePlugin"
|
||||
with pytest.raises(ValueError, match="NativePlugin"):
|
||||
mods.validate(doc, translated)
|
||||
finally:
|
||||
get_settings.cache_clear()
|
||||
|
||||
|
||||
def test_video_recovery_checks_ranges_and_copies_only_declared_bytes(tmp_path):
|
||||
from app.converter.tomie_assets import recover_object
|
||||
data = tmp_path / "data"
|
||||
out = tmp_path / "out"
|
||||
data.mkdir(); out.mkdir()
|
||||
original = b"header-clip-trailer"
|
||||
(data / "resources.resource").write_bytes(original)
|
||||
tree = {"m_OriginalPath": "Assets/Video/clip.webm", "m_ExternalResources": {
|
||||
"m_Source": "resources.resource", "m_Offset": 7, "m_Size": 4}}
|
||||
obj = SimpleNamespace(type=SimpleNamespace(name="VideoClip"), read=lambda: SimpleNamespace(m_Name="Clip"),
|
||||
read_typetree=lambda: tree)
|
||||
recovered = recover_object(obj, data, out, "video")
|
||||
assert recovered["path"].read_bytes() == b"clip"
|
||||
assert (data / "resources.resource").read_bytes() == original
|
||||
tree["m_ExternalResources"]["m_Size"] = len(original)
|
||||
with pytest.raises(ValueError, match="диапазон"):
|
||||
recover_object(obj, data, out, "invalid")
|
||||
Reference in new issue
Block a user