diff --git a/concore_cli/commands/doctor.py b/concore_cli/commands/doctor.py index 254edfd..0204583 100644 --- a/concore_cli/commands/doctor.py +++ b/concore_cli/commands/doctor.py @@ -35,6 +35,19 @@ "Windows": "winget install -e --id Python.Python.3.11", }, }, + "Java (javac)": { + "names": { + "posix": ["javac"], + "windows": ["javac"], + }, + "version_flag": "-version", + "config_keys": ["JAVACEXE", "JAVACWIN"], + "install_hints": { + "Linux": "sudo apt install default-jdk", + "Darwin": "brew install openjdk", + "Windows": "winget install -e --id EclipseAdoptium.Temurin.17.JDK", + }, + }, "Verilog (iverilog)": { "names": { "posix": ["iverilog"], @@ -277,8 +290,13 @@ def doctor_check(console): else: hint = tool_def["install_hints"].get(plat_name, "") hint_str = f" (install: {hint})" if hint else "" - # Docker, MATLAB, Verilog are optional - show as warning - if tool_label in ("MATLAB", "Verilog (iverilog)", "Docker"): + # Optional tools - show as warning + if tool_label in ( + "MATLAB", + "Verilog (iverilog)", + "Docker", + "Java (javac)", + ): console.print( f" [yellow]![/yellow] {tool_label} -> Not found{hint_str}" ) diff --git a/tests/test_doctor.py b/tests/test_doctor.py index e9ec584..0c2d950 100644 --- a/tests/test_doctor.py +++ b/tests/test_doctor.py @@ -6,9 +6,11 @@ from click.testing import CliRunner from concore_cli.cli import cli from concore_cli.commands.doctor import ( + TOOL_DEFINITIONS, + _check_package, _detect_tool, _get_platform_key, - _check_package, + _get_version, _resolve_concore_path, doctor_check, ) @@ -209,5 +211,48 @@ def test_doctor_with_concore_sudo(self, mock_path): self.assertIsInstance(result, bool) +class TestJavaDoctor(unittest.TestCase): + """Tests for Java toolchain support in concore doctor.""" + + def test_tool_definitions_include_java(self): + """TOOL_DEFINITIONS must include Java (javac).""" + self.assertIn("Java (javac)", TOOL_DEFINITIONS) + + java_def = TOOL_DEFINITIONS["Java (javac)"] + self.assertEqual(java_def["version_flag"], "-version") + self.assertEqual(java_def["config_keys"], ["JAVACEXE", "JAVACWIN"]) + self.assertIn("javac", java_def["names"]["posix"]) + self.assertIn("javac", java_def["names"]["windows"]) + + def test_doctor_output_mentions_java(self): + """Doctor command output should include Java section.""" + runner = CliRunner() + result = runner.invoke(cli, ["doctor"]) + self.assertIn("Java (javac)", result.output) + + @patch("shutil.which") + def test_detect_java_when_present(self, mock_which): + """Should detect javac when available.""" + mock_which.side_effect = lambda cmd: ( + "/usr/bin/javac" if cmd == "javac" else None + ) + path, name = _detect_tool(TOOL_DEFINITIONS["Java (javac)"]["names"]["posix"]) + self.assertEqual(path, "/usr/bin/javac") + self.assertEqual(name, "javac") + + @patch("subprocess.run") + def test_get_version_javac_stderr_fallback(self, mock_run): + """javac -version outputs to stderr on older JDKs; ensure fallback works.""" + from unittest.mock import MagicMock + + mock_res = MagicMock() + mock_res.stdout = "" + mock_res.stderr = "javac 1.8.0_292\n" + mock_run.return_value = mock_res + + ver = _get_version("/usr/bin/javac", "-version") + self.assertEqual(ver, "javac 1.8.0_292") + + if __name__ == "__main__": unittest.main()