"""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()