Files
cmbot/tests/test_launcher.py
T

94 lines
3.9 KiB
Python

"""Tests for the launcher — no GUI/network. The launcher only seeds config and
applies a pre-staged update (downloading lives in services.installer/the app)."""
import json
import os
import shutil
import sys
import tempfile
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent / "src"))
import launcher
from services import installer
class _Base(unittest.TestCase):
def setUp(self):
self.tmp = Path(tempfile.mkdtemp())
self.root = self.tmp / "install"
self.app = self.root / "app"
(self.app / "config").mkdir(parents=True)
(self.app / "CMBot.exe").write_text("OLD-1.0.0", encoding="ascii")
(self.app / "version.txt").write_text("1.0.0", encoding="ascii")
(self.app / "config" / "app_config.json").write_text(
json.dumps({"update_source": "http://x"}), encoding="utf-8")
(self.app / "config" / "templates.json").write_text("{}", encoding="utf-8")
(self.app / "config" / "ai_models.json").write_text(
json.dumps({"models": [{"name": "factory"}]}), encoding="utf-8")
self.data = self.tmp / "data"
self._prev = os.environ.get("CMBOT_DATA_DIR")
os.environ["CMBOT_DATA_DIR"] = str(self.data)
def tearDown(self):
if self._prev is None:
os.environ.pop("CMBOT_DATA_DIR", None)
else:
os.environ["CMBOT_DATA_DIR"] = self._prev
shutil.rmtree(str(self.tmp), ignore_errors=True)
def _stage(self, version, body):
s = installer.staged_app(self.root)
s.mkdir(parents=True, exist_ok=True)
(s / "CMBot.exe").write_text(body, encoding="ascii")
(s / "version.txt").write_text(version, encoding="ascii")
class TestSeed(_Base):
def test_seed_copies_when_missing(self):
launcher.seed_defaults(self.app, self.data)
self.assertTrue((self.data / "config" / "app_config.json").exists())
self.assertTrue((self.data / "config" / "templates.json").exists())
self.assertTrue((self.data / "config" / "ai_models.json").exists())
def test_seed_does_not_overwrite(self):
(self.data / "config").mkdir(parents=True)
(self.data / "config" / "app_config.json").write_text('{"update_source":"USER"}', encoding="utf-8")
(self.data / "config" / "ai_models.json").write_text(
json.dumps({"models": [{"name": "user"}]}), encoding="utf-8")
launcher.seed_defaults(self.app, self.data)
kept = json.loads((self.data / "config" / "app_config.json").read_text(encoding="utf-8"))
self.assertEqual(kept["update_source"], "USER")
kept_models = json.loads((self.data / "config" / "ai_models.json").read_text(encoding="utf-8"))
self.assertEqual(kept_models["models"][0]["name"], "user")
class TestRun(_Base):
def test_applies_staged_update_then_launches(self):
self._stage("1.1.0", "NEW-1.1.0")
rc = launcher.run(self.root, no_launch=True)
self.assertEqual(rc, 0)
self.assertEqual((self.app / "version.txt").read_text(encoding="ascii"), "1.1.0")
self.assertEqual((self.app / "CMBot.exe").read_text(encoding="ascii"), "NEW-1.1.0")
self.assertEqual((installer.old_dir(self.root) / "version.txt").read_text(encoding="ascii"), "1.0.0")
def test_no_staged_just_launches(self):
rc = launcher.run(self.root, no_launch=True)
self.assertEqual(rc, 0)
self.assertEqual((self.app / "version.txt").read_text(encoding="ascii"), "1.0.0")
self.assertFalse(installer.old_dir(self.root).exists())
def test_seeds_config_into_data_root(self):
launcher.run(self.root, no_launch=True)
self.assertTrue((self.data / "config" / "app_config.json").exists())
def test_missing_exe_returns_error(self):
(self.app / "CMBot.exe").unlink()
rc = launcher.run(self.root, no_launch=True)
self.assertEqual(rc, 1)
if __name__ == "__main__":
unittest.main()