From 270fa60c01866c4431d540be960b6cd2bc2b9c44 Mon Sep 17 00:00:00 2001 From: historia Date: Fri, 28 Aug 2026 16:52:14 -0400 Subject: feat: run auto-build audio.cpp scripts for macos and windows --- app/tests/test_backends_audiocpp.py | 203 +++++++++++++++++++++++++++++++++++- 1 file changed, 200 insertions(+), 3 deletions(-) (limited to 'app/tests/test_backends_audiocpp.py') diff --git a/app/tests/test_backends_audiocpp.py b/app/tests/test_backends_audiocpp.py index 82d6b88..7f14b68 100644 --- a/app/tests/test_backends_audiocpp.py +++ b/app/tests/test_backends_audiocpp.py @@ -570,6 +570,31 @@ class BackendOptionsTests(unittest.TestCase): self.assertEqual([value for _, value in options], list(make_server.BACKENDS)) + def test_darwin_offers_only_cpu(self): + with patch("sys.platform", "darwin"): + options, default_index = make_server.catalog._backend_options() + self.assertEqual(options, + [("cpu - Apple Metal (recorded as cpu)", "cpu")]) + self.assertEqual(default_index, 0) + + def test_darwin_marks_detected_cpu(self): + with patch("sys.platform", "darwin"): + options, default_index = make_server.catalog._backend_options( + "cpu") + self.assertTrue(options[default_index][0].endswith("[auto-detected]")) + self.assertEqual(options[default_index][1], "cpu") + + def test_windows_build_dir_names_map_to_backends(self): + for name, backend in (("windows-cuda-release", "cuda"), + ("windows-vulkan-release", "vulkan"), + ("windows-cpu-release", "cpu"), + ("windows-hip-release", "hip"), + ("macos-metal-release", "cpu")): + match = make_server.catalog._BACKEND_TOKEN_RE.search(name) + self.assertIsNotNone(match, name) + token = "cpu" if match.group(1) == "metal" else match.group(1) + self.assertEqual(token, backend, name) + class BuildServerConfigTests(unittest.TestCase): def test_single_entry_without_voice_dir(self): @@ -1234,6 +1259,12 @@ class BuildAudiocppTests(unittest.TestCase): self.scripts.mkdir() (self.scripts / "build_linux.sh").write_text("#!/bin/sh\n", encoding="utf-8") + (self.scripts / "build_metal.sh").write_text("#!/bin/bash\n", + encoding="utf-8") + (self.scripts / "build_windows.ps1").write_text("param()\n", + encoding="utf-8") + (self.scripts / "build_windows_hip.ps1").write_text("param()\n", + encoding="utf-8") self.log_dir = Path(self._td.name) / "logs" self.addCleanup(common.drain_post_tui_notices) @@ -1257,14 +1288,84 @@ class BuildAudiocppTests(unittest.TestCase): rc = make_server.build.build_audiocpp(self.checkout, "cuda") self.assertEqual(rc, 0) argv = run.call_args[0][0] - self.assertEqual(argv[:3], ["sh", str(self.scripts / "build_linux.sh"), - "--backend"]) + self.assertEqual(argv[:3], ["bash", str(self.scripts / "build_linux.sh"), + "--backend"]) self.assertIn("cuda", argv) self.assertIn("--target", argv) self.assertIn("audiocpp_server", argv) self.assertIn("--deployment-build", argv) self.assertEqual(run.call_args[1]["cwd"], self.checkout) + def test_darwin_uses_metal_script_without_backend(self): + with patch.object(common, "run_console_subprocess", + return_value=0) as run, \ + patch("sys.platform", "darwin"): + rc = make_server.build.build_audiocpp(self.checkout, "cpu") + self.assertEqual(rc, 0) + argv = run.call_args[0][0] + self.assertEqual(argv[:2], + ["bash", str(self.scripts / "build_metal.sh")]) + self.assertNotIn("--backend", argv) + self.assertIn("--target", argv) + self.assertIn("audiocpp_server", argv) + self.assertIn("--deployment-build", argv) + self.assertEqual(run.call_args[1]["cwd"], self.checkout) + + def test_darwin_cuda_backend_gets_no_arch_flags(self): + with patch.object(common, "run_console_subprocess", + return_value=0) as run, \ + patch("sys.platform", "darwin"): + rc = make_server.build.build_audiocpp(self.checkout, "cuda") + self.assertEqual(rc, 0) + argv = run.call_args[0][0] + self.assertNotIn("--backend", argv) + self.assertNotIn("--cuda-arch", argv) + + def test_windows_uses_powershell_with_preset(self): + with patch.object(common, "run_console_subprocess", + return_value=0) as run, \ + patch("sys.platform", "win32"): + rc = make_server.build.build_audiocpp(self.checkout, "vulkan") + self.assertEqual(rc, 0) + argv = run.call_args[0][0] + self.assertEqual( + argv[:6], ["powershell", "-NoProfile", "-NonInteractive", + "-ExecutionPolicy", "Bypass", "-File"]) + self.assertEqual(argv[6], str(self.scripts / "build_windows.ps1")) + self.assertIn("-Preset", argv) + self.assertIn("windows-vulkan-release", argv) + self.assertIn("-Target", argv) + self.assertIn("audiocpp_server", argv) + self.assertIn("-DeploymentBuild", argv) + self.assertNotIn("-CudaArchitectures", argv) + self.assertEqual(run.call_args[1]["cwd"], self.checkout) + + def test_windows_cuda_arch_uses_powershell_flag(self): + with patch.object(common, "run_console_subprocess", + return_value=0) as run, \ + patch("sys.platform", "win32"), \ + patch.object(make_server.build, "detect_cuda_arch", + return_value="86;89"): + rc = make_server.build.build_audiocpp(self.checkout, "cuda") + self.assertEqual(rc, 0) + argv = run.call_args[0][0] + self.assertIn("windows-cuda-release", argv) + self.assertEqual(argv[-2:], ["-CudaArchitectures", "86;89"]) + + def test_windows_hip_uses_hip_script_and_token_dir(self): + with patch.object(common, "run_console_subprocess", + return_value=0) as run, \ + patch("sys.platform", "win32"): + rc = make_server.build.build_audiocpp(self.checkout, "hip") + self.assertEqual(rc, 0) + argv = run.call_args[0][0] + self.assertEqual(argv[6], + str(self.scripts / "build_windows_hip.ps1")) + self.assertNotIn("-Preset", argv) + self.assertIn("-BuildDir", argv) + self.assertIn("build/windows-hip-release", argv) + self.assertIn("-DeploymentBuild", argv) + def test_missing_script_returns_nonzero(self): for f in self.scripts.iterdir(): f.unlink() @@ -1312,7 +1413,7 @@ class BuildAudiocppTests(unittest.TestCase): notice = notices[0] self.assertIn("failed (exit code 3)", notice) self.assertIn(f"Build log: {logs[0]}", notice) - command = (f"cd {self.checkout} && sh " + command = (f"cd {self.checkout} && bash " f"{self.scripts / 'build_linux.sh'} --backend cuda " "--target audiocpp_server --deployment-build") self.assertIn(command, notice) @@ -1425,6 +1526,66 @@ class BuildAudiocppTests(unittest.TestCase): self.assertNotIn("AUDIOCPP_CUDA_ARCH", notice) +class FindBuildScriptTests(unittest.TestCase): + """Per-platform helper script selection (find_build_script).""" + + def setUp(self): + self._td = tempfile.TemporaryDirectory() + self.addCleanup(self._td.cleanup) + self.checkout = Path(self._td.name) / "audio.cpp" + self.scripts = self.checkout / "scripts" + self.scripts.mkdir(parents=True) + + def _write(self, name): + (self.scripts / name).write_text("#!/bin/sh\n", encoding="utf-8") + + def test_linux_prefers_build_linux(self): + for name in ("build_linux.sh", "build_metal.sh"): + self._write(name) + with patch("sys.platform", "linux"): + self.assertEqual( + make_server.build.find_build_script(self.checkout), + self.scripts / "build_linux.sh") + + def test_darwin_prefers_build_metal(self): + for name in ("build_linux.sh", "build_metal.sh"): + self._write(name) + with patch("sys.platform", "darwin"): + self.assertEqual( + make_server.build.find_build_script(self.checkout), + self.scripts / "build_metal.sh") + + def test_darwin_falls_back_to_first_sh(self): + self._write("build_linux.sh") + with patch("sys.platform", "darwin"): + self.assertEqual( + make_server.build.find_build_script(self.checkout), + self.scripts / "build_linux.sh") + + def test_windows_selects_powershell_scripts(self): + self._write("build_windows.ps1") + self._write("build_windows_hip.ps1") + self._write("build_linux.sh") + with patch("sys.platform", "win32"): + find = make_server.build.find_build_script + self.assertEqual(find(self.checkout), + self.scripts / "build_windows.ps1") + self.assertEqual(find(self.checkout, "cuda"), + self.scripts / "build_windows.ps1") + self.assertEqual(find(self.checkout, "cpu"), + self.scripts / "build_windows.ps1") + self.assertEqual(find(self.checkout, "hip"), + self.scripts / "build_windows_hip.ps1") + + def test_windows_without_scripts_returns_none(self): + self._write("build_linux.sh") + with patch("sys.platform", "win32"): + self.assertIsNone(make_server.build.find_build_script(self.checkout)) + + def test_missing_scripts_dir_returns_none(self): + self.assertIsNone(make_server.build.find_build_script(self.checkout)) + + class DetectCudaArchTests(unittest.TestCase): """detect_cuda_arch: env override, nvidia-smi probe, None fallbacks.""" @@ -2890,3 +3051,39 @@ class LaunchHintTests(unittest.TestCase): out = self._capture(Path("/tmp/acpp"), Path("/tmp/acpp/server.json")) self.assertIn("Build it first", out) self.assertNotIn("Start the server with:", out) + + def _checkout_with_script(self, script_name): + td = tempfile.TemporaryDirectory() + self.addCleanup(td.cleanup) + checkout = Path(td.name) + scripts = checkout / "scripts" + scripts.mkdir() + (scripts / script_name).write_text("#!/bin/sh\n", encoding="utf-8") + return checkout + + def test_linux_hint_uses_bash_and_backend_flag(self): + checkout = self._checkout_with_script("build_linux.sh") + script = checkout / "scripts" / "build_linux.sh" + out = self._capture(checkout, checkout / "server.json") + self.assertIn(f"bash {script} --backend " + "--target audiocpp_server --deployment-build", out) + + def test_darwin_hint_uses_metal_without_backend(self): + checkout = self._checkout_with_script("build_metal.sh") + script = checkout / "scripts" / "build_metal.sh" + with patch("sys.platform", "darwin"): + out = self._capture(checkout, checkout / "server.json") + self.assertIn(f"bash {script} --target audiocpp_server " + "--deployment-build", out) + self.assertNotIn("--backend", out) + + def test_windows_hint_names_powershell_and_presets(self): + checkout = self._checkout_with_script("build_windows.ps1") + script = checkout / "scripts" / "build_windows.ps1" + with patch("sys.platform", "win32"): + out = self._capture(checkout, checkout / "server.json") + self.assertIn(f"powershell -NoProfile -ExecutionPolicy Bypass " + f"-File {script} -Preset windows-cuda-release " + "-Target audiocpp_server -DeploymentBuild", out) + self.assertIn("windows-cpu-release", out) + self.assertIn("build_windows_hip.ps1", out) -- cgit v1.2.3