import subprocess import tempfile import unittest from pathlib import Path from unittest.mock import patch import deploy_tool.environment as environment_module from deploy_tool.environment import check_environment, load_tool_paths, save_tool_paths class EnvironmentTests(unittest.TestCase): def test_reports_installed_command(self): def runner(command): return subprocess.CompletedProcess(command, 0, "java 21\n", "") results = check_environment(runner=runner, checks={"JDK": ["java", "-version"]}) self.assertTrue(results[0].installed) self.assertEqual(results[0].name, "JDK") self.assertEqual(results[0].source, "PATH") self.assertIn("java 21", results[0].version) def test_reports_missing_command(self): def runner(command): raise FileNotFoundError(command[0]) results = check_environment(runner=runner, checks={"MySQL": ["mysql", "--version"]}) self.assertFalse(results[0].installed) self.assertEqual(results[0].name, "MySQL") self.assertIn("未安装", results[0].message) def test_uses_manual_path_when_command_is_not_in_path(self): with tempfile.TemporaryDirectory() as tmp: mysql = Path(tmp) / "mysql.exe" mysql.write_text("", encoding="utf-8") def runner(command): if command[0] == "mysql": raise FileNotFoundError(command[0]) return subprocess.CompletedProcess(command, 0, "mysql 8.4\n", "") results = check_environment( runner=runner, checks={"MySQL": ["mysql", "--version"]}, manual_paths={"MySQL": mysql}, ) self.assertTrue(results[0].installed) self.assertEqual(results[0].source, "手动指定") self.assertEqual(results[0].command[0], str(mysql)) def test_discovers_executable_from_known_search_paths(self): with tempfile.TemporaryDirectory() as tmp: mysql = Path(tmp) / "MySQL" / "MySQL Server 8.4" / "bin" / "mysql.exe" mysql.parent.mkdir(parents=True) mysql.write_text("", encoding="utf-8") def runner(command): if command[0] == "mysql": raise FileNotFoundError(command[0]) return subprocess.CompletedProcess(command, 0, "mysql 8.4\n", "") results = check_environment( runner=runner, checks={"MySQL": ["mysql", "--version"]}, search_roots=[Path(tmp)], ) self.assertTrue(results[0].installed) self.assertEqual(results[0].source, "自动发现") self.assertEqual(results[0].command[0], str(mysql)) def test_does_not_recursively_scan_arbitrary_deep_directories(self): with tempfile.TemporaryDirectory() as tmp: mysql = Path(tmp) / "random" / "deep" / "folder" / "mysql.exe" mysql.parent.mkdir(parents=True) mysql.write_text("", encoding="utf-8") def runner(command): if command[0] == "mysql": raise FileNotFoundError(command[0]) return subprocess.CompletedProcess(command, 0, "mysql 8.4\n", "") results = check_environment( runner=runner, checks={"MySQL": ["mysql", "--version"]}, search_roots=[Path(tmp)], ) self.assertFalse(results[0].installed) def test_saves_and_loads_manual_paths(self): with tempfile.TemporaryDirectory() as tmp: config = Path(tmp) / "tool-paths.json" mysql = Path(tmp) / "mysql.exe" save_tool_paths({"MySQL": mysql}, config) loaded = load_tool_paths(config) self.assertEqual(loaded, {"MySQL": mysql}) def test_tomcat_command_receives_catalina_home(self): with tempfile.TemporaryDirectory() as tmp: catalina = Path(tmp) / "apache-tomcat" / "bin" / "catalina.bat" catalina.parent.mkdir(parents=True) catalina.write_text("@echo off", encoding="utf-8") completed = subprocess.CompletedProcess([str(catalina), "version"], 0, "Tomcat", "") with patch("deploy_tool.environment.subprocess.run", return_value=completed) as run: environment_module._run_command([str(catalina), "version"]) self.assertEqual(run.call_args.kwargs["env"]["CATALINA_HOME"], str(catalina.parent.parent)) if __name__ == "__main__": unittest.main()