|
| 1 | +from concore_cli.commands.build import _write_docker_compose |
| 2 | +from rich.console import Console |
| 3 | +from pathlib import Path |
| 4 | + |
| 5 | + |
| 6 | +def _fake_run_script(output_dir, services): |
| 7 | + lines = [ |
| 8 | + f"docker run --name {s['name']} -v /study:/study {s['image']} &" |
| 9 | + for s in services |
| 10 | + ] |
| 11 | + (Path(output_dir) / "run").write_text("\n".join(lines)) |
| 12 | + |
| 13 | + |
| 14 | +def test_compose_has_restart_policy(tmp_path): |
| 15 | + _fake_run_script(tmp_path, [{"name": "node1", "image": "concore/py"}]) |
| 16 | + path = _write_docker_compose(tmp_path, Console(quiet=True)) |
| 17 | + assert path is not None |
| 18 | + content = path.read_text() |
| 19 | + assert "restart: on-failure" in content |
| 20 | + |
| 21 | + |
| 22 | +def test_compose_has_network_section(tmp_path): |
| 23 | + _fake_run_script(tmp_path, [{"name": "node1", "image": "concore/py"}]) |
| 24 | + path = _write_docker_compose(tmp_path, Console(quiet=True)) |
| 25 | + content = path.read_text() |
| 26 | + assert "concore_net" in content |
| 27 | + assert "networks:" in content |
| 28 | + |
| 29 | + |
| 30 | +def test_compose_depends_on_second_service(tmp_path): |
| 31 | + _fake_run_script( |
| 32 | + tmp_path, |
| 33 | + [ |
| 34 | + {"name": "controller", "image": "concore/py"}, |
| 35 | + {"name": "plant", "image": "concore/cpp"}, |
| 36 | + ], |
| 37 | + ) |
| 38 | + path = _write_docker_compose(tmp_path, Console(quiet=True)) |
| 39 | + content = path.read_text() |
| 40 | + assert "depends_on" in content |
| 41 | + assert "controller" in content |
| 42 | + |
| 43 | + |
| 44 | +def test_compose_first_service_has_no_depends_on(tmp_path): |
| 45 | + _fake_run_script( |
| 46 | + tmp_path, |
| 47 | + [ |
| 48 | + {"name": "controller", "image": "concore/py"}, |
| 49 | + {"name": "plant", "image": "concore/cpp"}, |
| 50 | + ], |
| 51 | + ) |
| 52 | + path = _write_docker_compose(tmp_path, Console(quiet=True)) |
| 53 | + lines = path.read_text().splitlines() |
| 54 | + controller_idx = next( |
| 55 | + i for i, line in enumerate(lines) if "controller:" in line |
| 56 | + ) |
| 57 | + plant_idx = next( |
| 58 | + i for i, line in enumerate(lines) if "plant:" in line |
| 59 | + ) |
| 60 | + section = lines[controller_idx:plant_idx] |
| 61 | + assert not any("depends_on" in line for line in section) |
| 62 | + |
| 63 | + |
| 64 | +def test_zmq_mode_adds_env(tmp_path): |
| 65 | + _fake_run_script(tmp_path, [{"name": "node1", "image": "concore/py"}]) |
| 66 | + path = _write_docker_compose( |
| 67 | + tmp_path, Console(quiet=True), zmq_mode=True |
| 68 | + ) |
| 69 | + content = path.read_text() |
| 70 | + assert "CONCORE_TRANSPORT=zmq" in content |
| 71 | + |
| 72 | + |
| 73 | +def test_no_zmq_env_in_default_mode(tmp_path): |
| 74 | + _fake_run_script(tmp_path, [{"name": "node1", "image": "concore/py"}]) |
| 75 | + path = _write_docker_compose( |
| 76 | + tmp_path, Console(quiet=True), zmq_mode=False |
| 77 | + ) |
| 78 | + content = path.read_text() |
| 79 | + assert "CONCORE_TRANSPORT" not in content |
| 80 | + |
| 81 | + |
| 82 | +def test_missing_run_script_returns_none(tmp_path): |
| 83 | + result = _write_docker_compose(tmp_path, Console(quiet=True)) |
| 84 | + assert result is None |
| 85 | + |
| 86 | + |
| 87 | +def test_zmq_without_compose_errors(): |
| 88 | + from click.testing import CliRunner |
| 89 | + from concore_cli.cli import cli |
| 90 | + runner = CliRunner() |
| 91 | + result = runner.invoke(cli, ["build", "wf.graphml", "--zmq"]) |
| 92 | + assert result.exit_code != 0 |
0 commit comments