diff options
| author | historia <historiavg@proton.me> | 2026-08-25 03:42:28 -0400 |
|---|---|---|
| committer | historia <historiavg@proton.me> | 2026-08-25 03:42:28 -0400 |
| commit | 0cc01d1da0a629e104202053feb0bb0db91d578d (patch) | |
| tree | 8c52b151cc3457002043d6d499968d34349d7f5f /app/tests/test_backends_audiocpp.py | |
| parent | d6460459ee95d8c2298b029fa4b2dc266e80a0cc (diff) | |
| download | tts-audiobook-generator-0cc01d1da0a629e104202053feb0bb0db91d578d.tar.gz | |
feat(tui): simultaneous build and model download
Diffstat (limited to 'app/tests/test_backends_audiocpp.py')
| -rw-r--r-- | app/tests/test_backends_audiocpp.py | 130 |
1 files changed, 120 insertions, 10 deletions
diff --git a/app/tests/test_backends_audiocpp.py b/app/tests/test_backends_audiocpp.py index 8f79085..2f41131 100644 --- a/app/tests/test_backends_audiocpp.py +++ b/app/tests/test_backends_audiocpp.py @@ -649,6 +649,11 @@ class InstallModelsTests(unittest.TestCase): self.assertTrue(make_server._decide_download(self.checkout, confirm)) confirm.assert_called_once() + def test_decide_download_defaults_to_yes(self): + confirm = MagicMock(return_value=True) + make_server._decide_download(self.checkout, confirm) + self.assertIs(confirm.call_args[0][1], True) + class TranscribeWavDirTests(unittest.TestCase): def setUp(self): @@ -1793,27 +1798,132 @@ if __name__ == "__main__": class SetupScreenTests(unittest.TestCase): """setup_screen: the wizard run on the hub's screen, setup tail via the - in-TUI task view.""" + in-TUI task view (two parallel lanes on a fresh install).""" def test_abort_returns_one_without_executing(self): with patch.object(make_server, "_wizard", return_value=None) as mk_wizard, \ - patch.object(make_server, "_execute_steps") as mk_steps: + patch.object(make_server, "_execute_lanes") as mk_lanes: rc = make_server.setup_screen(None) self.assertEqual(rc, 1) mk_wizard.assert_called_once() - mk_steps.assert_not_called() + mk_lanes.assert_not_called() def test_success_runs_the_tail_in_the_task_view(self): settings = {"audiocpp_dir": Path("/x")} - steps = [make_server.taskview.TaskStep("t", lambda emit, cancel: 0)] + lanes = [make_server.taskview.TaskLane( + "Build", [make_server.taskview.TaskStep("t", lambda emit, cancel: 0)])] with patch.object(make_server, "_wizard", return_value=settings), \ - patch.object(make_server, "_execute_steps", - return_value=steps) as mk_steps, \ - patch.object(make_server.taskview, "run_steps", + patch.object(make_server, "_execute_lanes", + return_value=lanes) as mk_lanes, \ + patch.object(make_server.taskview, "run_lanes", return_value=0) as mk_run: rc = make_server.setup_screen(None) self.assertEqual(rc, 0) - mk_steps.assert_called_once() - self.assertIs(mk_steps.call_args[0][0], settings) + mk_lanes.assert_called_once() + self.assertIs(mk_lanes.call_args[0][0], settings) + self.assertTrue(mk_lanes.call_args[1]["parallel"]) mk_run.assert_called_once() - self.assertEqual(mk_run.call_args[0][2], steps) + self.assertEqual(mk_run.call_args[0][2], lanes) + + +class ExecuteLanesTests(unittest.TestCase): + """_execute_lanes: two lanes (build + configure/download) and the + flattened console order.""" + + def _settings(self, **overrides): + settings = { + "audiocpp_dir": Path("/x"), + "backend": "cuda", + "build": True, + "download": True, + "include_clone": False, + "wav_dir": None, + "plan": None, + "sync_port": None, + "sync_model_ids": None, + "delete_unused": False, + "unused_entries": [], + "model_entries": [], + "entry_ids": [], + "install_guidance": [], + "output_path": Path("/x/server.json"), + "host": "127.0.0.1", + "port": 8080, + "lazy_load": True, + } + settings.update(overrides) + return settings + + def test_two_lanes_when_building(self): + args = make_server.build_parser().parse_args([]) + lanes = make_server._execute_lanes(self._settings(), args) + self.assertEqual([lane.title for lane in lanes], + ["Build", "Configure & download"]) + self.assertEqual([s.title for s in lanes[0].steps], + ["Build audiocpp_server (cuda)"]) + self.assertEqual([s.title for s in lanes[1].steps], + ["Transcribe reference voices", + "Write server.json & sync config", + "Download models"]) + + def test_single_lane_when_not_building(self): + args = make_server.build_parser().parse_args([]) + lanes = make_server._execute_lanes( + self._settings(build=False), args) + self.assertEqual([lane.title for lane in lanes], + ["Configure & download"]) + + def test_flattened_console_steps_keep_the_build_first(self): + args = make_server.build_parser().parse_args([]) + steps = make_server._execute_steps(self._settings(), args) + self.assertEqual([s.title for s in steps], + ["Build audiocpp_server (cuda)", + "Transcribe reference voices", + "Write server.json & sync config", + "Download models"]) + + def test_download_step_prints_the_parallel_launch_hint(self): + args = make_server.build_parser().parse_args([]) + lanes = make_server._execute_lanes(self._settings(), args, + parallel=True) + install_step = lanes[1].steps[2] + with patch.object(make_server, "_install_models") as mk_install, \ + patch.object(make_server, "_print_launch_hint") as mk_hint: + install_step.work(lambda line: None, threading.Event()) + mk_hint.assert_called_once() + self.assertTrue(mk_hint.call_args[1]["pending_build"]) + + def test_download_step_console_hint_is_not_pending(self): + args = make_server.build_parser().parse_args([]) + lanes = make_server._execute_lanes(self._settings(), args) + install_step = lanes[1].steps[2] + with patch.object(make_server, "_install_models") as mk_install, \ + patch.object(make_server, "_print_launch_hint") as mk_hint: + install_step.work(lambda line: None, threading.Event()) + mk_hint.assert_called_once() + self.assertFalse(mk_hint.call_args[1]["pending_build"]) + + +class LaunchHintTests(unittest.TestCase): + """_print_launch_hint: exact command vs. the pending-build message.""" + + def _capture(self, audiocpp_dir, output_path, pending_build=False): + buf = io.StringIO() + with redirect_stdout(buf), \ + patch.object(make_server, "find_audiocpp_server_bin", + return_value=None): + make_server._print_launch_hint(audiocpp_dir, output_path, + pending_build=pending_build) + return buf.getvalue() + + def test_pending_build_names_the_post_build_command(self): + out = self._capture(Path("/tmp/acpp"), Path("/tmp/acpp/server.json"), + pending_build=True) + self.assertIn("still building", out) + self.assertNotIn("Build it first", out) + self.assertIn("audiocpp_server --config /tmp/acpp/server.json", out) + + def test_missing_binary_gives_build_remediation(self): + out = self._capture(Path("/tmp/acpp"), Path("/tmp/acpp/server.json")) + self.assertIn("Build it first", out) + self.assertNotIn("still building", out) |
