feat: browser access (allowed_origins, CORS with Private Network Access), job cancel, Tomie/Unity adapters, benchmark

Includes earlier uncommitted work: Tomie and Unity adapters, benchmark, structured output, call metrics.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
mrleo1nidandClaude Sonnet 5.5 committed 2026-10-25 18:59:28 +03:00
1 parent 13492929c6
commit f49ee90477
32 files changed
+2799 -51

No files matched your search

+148
View File
@@ -0,0 +1,148 @@
import base64
import hashlib
import json
from pathlib import Path
import struct
import tempfile
import unittest
from unittest.mock import patch
from local_translator.benchmark import write_json
from local_translator.tomie import STATE, append_managed_records, atomic_copy, digest, inside, install, original_sources, patch_catalog, patch_lock, restore, rewrite_dictionary
class DictionaryTests(unittest.TestCase):
def test_missing_runtime_graphics_labels_are_added_as_managed_records(self):
key = "Naninovel.UI.GameSettingsGraphicsDropdown.GraphicOption5"
result = append_managed_records("Key: Value\r\n", {key: "Очень высокое"})
self.assertEqual(result, f"Key: Value\r\n{key}: Очень высокое\r\n")
with self.assertRaises(ValueError):
append_managed_records(result, {key: "Duplicate"})
with self.assertRaises(ValueError):
append_managed_records("Key: Value", {key: "A\nB"})
def test_preserves_keys_whitespace_comments_and_crlf(self):
source = '; comment\r\nMenu.Load: LOAD\r\nOther: value: extra\r\n'
result = rewrite_dictionary(source, {"Menu.Load": "ЗАГРУЗИТЬ"})
self.assertEqual(result, '; comment\r\nMenu.Load: ЗАГРУЗИТЬ\r\nOther: value: extra\r\n')
def test_unknown_duplicate_and_multiline_values_rejected(self):
for source, replacements in [("Key: A", {"Other": "B"}), ("Key: A\nKey: B", {"Key": "В"}), ("Key: A", {"Key": "А\nБ"})]:
with self.assertRaises(ValueError):
rewrite_dictionary(source, replacements)
def test_catalog_offsets_preserved_and_crc_actually_updated(self):
old_hash, new_hash = "a" * 32, "b" * 32
record = json.dumps({"m_Hash": old_hash, "m_Crc": 2659166264, "m_BundleSize": 37229646}, separators=(",", ":")).encode("utf-16-le")
payload = b"header" + struct.pack("<I", len(record)) + record + b"unrelated-second-record"
document = {"m_ExtraDataString": base64.b64encode(payload).decode(), "other": "keep"}
result, before, after = patch_catalog(document, old_hash, 12345, 36999999, new_hash)
raw = base64.b64decode(result["m_ExtraDataString"])
self.assertEqual(len(raw), len(payload))
self.assertTrue(raw.endswith(b"unrelated-second-record"))
self.assertEqual(before["m_Crc"], 2659166264)
self.assertEqual(after["m_Crc"], 12345)
self.assertEqual(after["m_Hash"], new_hash)
self.assertEqual(result["other"], "keep")
with self.assertRaises(ValueError):
patch_catalog(document, old_hash, 12345, 999999999, new_hash)
class InstallerTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.root = Path(self.temp.name)
self.game = self.root / "game"
self.package = self.root / "package"
self.game.mkdir()
(self.game / "TomieWGM.exe").write_bytes(b"fake executable, never run")
self.records = []
for name in ("data.unity3d", "StreamingAssets/aa/catalog.json"):
relative = Path("TomieWGM_Data") / name
original = self.game / relative
payload = self.package / "payload" / relative
original.parent.mkdir(parents=True, exist_ok=True)
payload.parent.mkdir(parents=True, exist_ok=True)
original.write_bytes(("original " + name).encode())
payload.write_bytes(("translated " + name).encode())
self.records.append({"path": relative.as_posix(), "before": digest(original), "after": digest(payload)})
write_json(self.package / "manifest.json", {"id": "patch-1", "files": self.records})
def tearDown(self):
self.temp.cleanup()
def test_install_is_idempotent_and_restore_is_byte_exact(self):
install(self.package, self.game, lambda: False)
state = json.loads((self.game / STATE).read_text(encoding="utf-8"))
self.assertEqual(state["phase"], "installed")
for row in state["files"]:
self.assertEqual(digest(self.game / row["path"]), row["after"])
self.assertEqual(digest(self.game / row["backup"]), row["before"])
install(self.package, self.game, lambda: False)
restore(self.game, lambda: False)
for row in self.records:
self.assertEqual(digest(self.game / row["path"]), row["before"])
self.assertEqual(json.loads((self.game / STATE).read_text())["phase"], "restored")
def test_running_game_blocks_both_actions(self):
with self.assertRaises(RuntimeError):
install(self.package, self.game, lambda: True)
with self.assertRaises(RuntimeError):
restore(self.game, lambda: True)
self.assertFalse((self.game / STATE).exists())
def test_foreign_original_and_damaged_payload_are_rejected_before_writes(self):
target = self.game / self.records[-1]["path"]
target.write_bytes(b"foreign mod")
with self.assertRaises(ValueError):
install(self.package, self.game, lambda: False)
self.assertEqual(digest(self.game / self.records[0]["path"]), self.records[0]["before"])
target.write_bytes(b"original StreamingAssets/aa/catalog.json")
(self.package / "payload" / self.records[-1]["path"]).write_bytes(b"tampered")
with self.assertRaises(ValueError):
install(self.package, self.game, lambda: False)
self.assertFalse((self.game / STATE).exists())
def test_partial_install_failure_rolls_back_already_replaced_files(self):
def fail_second(source, target, expected):
if Path(source).resolve().is_relative_to((self.package / "payload").resolve()) and Path(target).name == "catalog.json":
raise OSError("simulated disk failure")
return atomic_copy(source, target, expected)
with patch("local_translator.tomie.atomic_copy", fail_second), self.assertRaises(OSError):
install(self.package, self.game, lambda: False)
self.assertEqual(json.loads((self.game / STATE).read_text())["phase"], "restored")
for row in self.records:
self.assertEqual(digest(self.game / row["path"]), row["before"])
def test_restore_refuses_to_overwrite_new_foreign_changes(self):
install(self.package, self.game, lambda: False)
target = self.game / self.records[0]["path"]
target.write_bytes(b"new unrelated mod")
with self.assertRaises(ValueError):
restore(self.game, lambda: False)
self.assertEqual(target.read_bytes(), b"new unrelated mod")
def test_paths_and_concurrent_installers_are_guarded(self):
for relative in ("../outside", str(self.root.resolve())):
with self.assertRaises(ValueError):
inside(self.game, relative)
with patch_lock(self.game):
with self.assertRaises(RuntimeError):
with patch_lock(self.game):
self.fail("Two installers acquired one lock")
def test_rebuild_uses_verified_original_backups_without_changing_installed_game(self):
install(self.package, self.game, lambda: False)
inputs = [self.game.resolve() / row["path"] for row in self.records]
sources, live_hashes = original_sources(self.game.resolve(), inputs)
for row, path in zip(self.records, inputs):
self.assertEqual(digest(sources[path]), row["before"])
self.assertEqual(live_hashes[path], row["after"])
self.assertEqual(digest(path), row["after"])
inputs[0].write_bytes(b"foreign edit")
with self.assertRaises(ValueError):
original_sources(self.game.resolve(), inputs)
if __name__ == "__main__":
unittest.main()