import json import os import subprocess import sys import tempfile import textwrap import unittest from pathlib import Path PROJECT_ROOT = Path("/Users/chick/.Hermes/workspace/DbusSmsForward") BASE_ENV = {**os.environ, "PYTHONPATH": str(PROJECT_ROOT / "src")} class DeployInstallerTests(unittest.TestCase): def test_env_check_command_supports_json_output(self): with tempfile.TemporaryDirectory() as tmpdir: root = Path(tmpdir) config_path = root / "config.json" messages_path = root / "messages.json" messages_path.write_text("[]", encoding="utf-8") config_path.write_text( json.dumps( { "forwarding": {"device_name": "router-json"}, "notifications": {"console": {"enabled": True}}, "sms_source": {"kind": "file", "path": str(messages_path)}, }, ensure_ascii=False, ), encoding="utf-8", ) result = subprocess.run( [ sys.executable, "-m", "dbussmsforward.cli", "env-check", "--config", str(config_path), "--format", "json", ], cwd=str(PROJECT_ROOT), env=BASE_ENV, capture_output=True, text=True, check=False, ) self.assertEqual(result.returncode, 0, msg=result.stderr) payload = json.loads(result.stdout) self.assertEqual(payload["summary"]["failed"], 0) self.assertEqual(payload["summary"]["status"], "ok") self.assertTrue(any(item["name"] == "sms_source.path" for item in payload["results"])) def test_debian_installer_runs_env_check_and_writes_json_report(self): with tempfile.TemporaryDirectory() as tmpdir: root = Path(tmpdir) fakebin = root / "fakebin" fakebin.mkdir() systemctl_log = root / "systemctl.log" (fakebin / "systemctl").write_text( "#!/bin/sh\n" f"printf '%s\\n' \"$*\" >> {systemctl_log}\n", encoding="utf-8", ) (fakebin / "systemctl").chmod(0o755) config_dir = root / "etc" / "dbussmsforward" config_dir.mkdir(parents=True) messages_path = root / "var" / "dbussmsforward-messages.json" messages_path.parent.mkdir(parents=True) messages_path.write_text("[]", encoding="utf-8") (config_dir / "appsettings.json").write_text( json.dumps( { "forwarding": {"device_name": "debian-installer-test"}, "notifications": {"console": {"enabled": True}}, "sms_source": {"kind": "file", "path": str(messages_path)}, }, ensure_ascii=False, ), encoding="utf-8", ) result = subprocess.run( ["sh", "deploy/debian/install.sh"], cwd=str(PROJECT_ROOT), env={ **BASE_ENV, "ROOT_DIR": str(root), "PATH": f"{fakebin}:{os.environ.get('PATH', '')}", }, capture_output=True, text=True, check=False, ) self.assertEqual(result.returncode, 0, msg=result.stderr) report_path = config_dir / "install-env-check.json" self.assertTrue(report_path.exists()) payload = json.loads(report_path.read_text(encoding="utf-8")) self.assertEqual(payload["summary"]["failed"], 0) logged = systemctl_log.read_text(encoding="utf-8") self.assertIn("daemon-reload", logged) self.assertIn("enable dbussmsforward", logged) def test_openwrt_installer_blocks_when_env_check_fails(self): with tempfile.TemporaryDirectory() as tmpdir: root = Path(tmpdir) config_dir = root / "etc" / "dbussmsforward" config_dir.mkdir(parents=True) (config_dir / "appsettings.json").write_text( json.dumps( { "notifications": { "autman_push": { "enabled": True, "api_url": "", "access_token": "", } }, "sms_source": { "kind": "modemmanager", "modem_object_path": "auto", "system_bus_address": "unix:path=/tmp/definitely-missing-bus.sock", }, }, ensure_ascii=False, ), encoding="utf-8", ) result = subprocess.run( ["sh", "deploy/openwrt/install.sh"], cwd=str(PROJECT_ROOT), env={ **BASE_ENV, "ROOT_DIR": str(root), "SKIP_SERVICE_ENABLE": "1", }, capture_output=True, text=True, check=False, ) self.assertNotEqual(result.returncode, 0) self.assertIn("Environment check failed", result.stderr) report_path = config_dir / "install-env-check.json" self.assertTrue(report_path.exists()) payload = json.loads(report_path.read_text(encoding="utf-8")) self.assertGreater(payload["summary"]["failed"], 0) if __name__ == "__main__": unittest.main()