Mod for TikTok 47.1.3 (arm64) in Material 3 style: bottom bar, profile menu, TikTok settings and comments; downloads without the watermark; switches for ads, live streams and the Shop tab; badges of other mods next to names and the niche mod badge (members service); app icons; mod settings screen. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
109 lines
3.7 KiB
Python
109 lines
3.7 KiB
Python
"""Run the platform-independent settings contract on a real JVM.
|
|
|
|
The Android file adapter is compiled against android.jar, not executed under
|
|
desktop stubs. Device/storage integration belongs to the later APK stage.
|
|
"""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
import shutil
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
PACKAGE = ROOT / "src" / "lihont" / "two" / "settings"
|
|
HARNESS = ROOT / "tests" / "java" / "lihont" / "two" / "settings" / "SettingsModelTest.java"
|
|
|
|
|
|
class SettingsModelTest(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.javac = shutil.which("javac")
|
|
cls.java = shutil.which("java")
|
|
if not cls.javac or not cls.java:
|
|
raise RuntimeError("Settings model tests require a JDK with java and javac")
|
|
cls.temporary = tempfile.TemporaryDirectory(prefix="lihont-settings-tests-")
|
|
cls.addClassCleanup(cls.temporary.cleanup)
|
|
cls.classes = Path(cls.temporary.name) / "classes"
|
|
cls.classes.mkdir()
|
|
cls.environment = dict(os.environ)
|
|
cls.environment.pop("JAVA_TOOL_OPTIONS", None)
|
|
cls.run_command([
|
|
cls.javac, "--release", "17", "-encoding", "UTF-8", "-d", str(cls.classes),
|
|
str(PACKAGE / "ModSettings.java"),
|
|
str(PACKAGE / "SettingsCodec.java"),
|
|
str(PACKAGE / "SettingsRepository.java"),
|
|
str(HARNESS),
|
|
])
|
|
|
|
@classmethod
|
|
def run_command(cls, command):
|
|
result = subprocess.run(
|
|
command, capture_output=True, text=True, encoding="utf-8",
|
|
env=cls.environment, timeout=60,
|
|
)
|
|
if result.returncode:
|
|
raise AssertionError(
|
|
f"Command failed with exit {result.returncode}: {command[0]}\n"
|
|
+ result.stdout + result.stderr
|
|
)
|
|
return result
|
|
|
|
def run_scenario(self, name):
|
|
result = self.run_command([
|
|
self.java, "-cp", str(self.classes),
|
|
"lihont.two.settings.SettingsModelTest", name,
|
|
])
|
|
self.assertEqual(result.stdout.strip(), "PASS " + name)
|
|
|
|
def test_defaults_and_region_warning(self):
|
|
self.run_scenario("defaults")
|
|
|
|
def test_all_iso_countries_roundtrip(self):
|
|
self.run_scenario("countries")
|
|
|
|
def test_typed_inputs_reject_invalid_values(self):
|
|
self.run_scenario("validation")
|
|
|
|
def test_restart_policy(self):
|
|
self.run_scenario("restart")
|
|
|
|
def test_valid_json_and_portable_roundtrip(self):
|
|
self.run_scenario("codec")
|
|
|
|
def test_invalid_documents_are_rejected(self):
|
|
self.run_scenario("invalid")
|
|
|
|
def test_settings_persist_across_repository_instances(self):
|
|
self.run_scenario("persistence")
|
|
|
|
def test_active_snapshot_and_noop_write(self):
|
|
self.run_scenario("snapshot")
|
|
|
|
def test_reset_restores_defaults_and_persists_them(self):
|
|
self.run_scenario("reset")
|
|
|
|
def test_invalid_imports_preserve_memory_and_disk(self):
|
|
self.run_scenario("atomicImport")
|
|
|
|
def test_io_failures_are_visible_and_preserve_previous_settings(self):
|
|
self.run_scenario("ioFailures")
|
|
|
|
def test_corrupt_or_future_stored_data_is_not_overwritten(self):
|
|
self.run_scenario("corruptStorage")
|
|
|
|
def test_android_adapter_compiles_against_android_api(self):
|
|
android_jar = ROOT / "tools" / "android.jar"
|
|
self.assertTrue(android_jar.is_file(), "tools/android.jar must be available")
|
|
self.run_command([
|
|
self.javac, "--release", "17", "-encoding", "UTF-8",
|
|
"-cp", str(android_jar) + os.pathsep + str(self.classes),
|
|
"-d", str(self.classes), str(PACKAGE / "AndroidSettingsStorage.java"),
|
|
])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|