Download tests/test_deploy_droplet.py from PYTHAI/mindXtrain: direct link, hf CLI and curl.
- Browser
- Download file 5.78 kB
-
https://huggingface.co/PYTHAI/mindXtrain/resolve/main/tests/test_deploy_droplet.py
- Command line
-
hf download hf://PYTHAI/mindXtrain/tests/test_deploy_droplet.py
-
curl -L -o test_deploy_droplet.py https://huggingface.co/PYTHAI/mindXtrain/resolve/main/tests/test_deploy_droplet.py
5.78 kB
| """Droplet sync builder tests — argv shape, no-shell contract, ssh hardening.""" | |
| from __future__ import annotations | |
| from pathlib import Path | |
| import pytest | |
| from mindxtrain.deploy.droplet import ( | |
| DropletConfig, | |
| build_bench_ssh, | |
| build_provision_ssh, | |
| build_rsync, | |
| build_scp_plan_back, | |
| build_ssh_probe, | |
| build_tail_cloud_init, | |
| from_env, | |
| missing_env, | |
| status_missing, | |
| status_target, | |
| sync_steps, | |
| ) | |
| def _cfg() -> DropletConfig: | |
| return DropletConfig(host="mi300x.example.com", user="ubuntu") | |
| def test_missing_env_keys() -> None: | |
| assert "DROPLET_HOST" in missing_env({}) | |
| assert missing_env({"DROPLET_HOST": "h", "DROPLET_USER": "u"}) == [] | |
| def test_status_target_formats_user_at_host_path() -> None: | |
| target = status_target({ | |
| "DROPLET_HOST": "mi300x.example.com", | |
| "DROPLET_USER": "root", | |
| "DROPLET_REMOTE_PATH": "/workspace/mindxtrain", | |
| }) | |
| assert target == "root@mi300x.example.com:/workspace/mindxtrain" | |
| def test_status_target_blank_when_unconfigured() -> None: | |
| assert status_target({"DROPLET_HOST": "h"}) == "" # no user | |
| assert status_target({"DROPLET_USER": "u"}) == "" # no host | |
| def test_from_env_raises_when_missing() -> None: | |
| with pytest.raises(RuntimeError, match="DROPLET_HOST"): | |
| from_env({}) | |
| def test_from_env_picks_defaults() -> None: | |
| cfg = from_env({"DROPLET_HOST": "h", "DROPLET_USER": "u"}) | |
| assert cfg.host == "h" | |
| assert cfg.user == "u" | |
| assert cfg.container == "rocm/primus:v26.2" | |
| assert cfg.remote_path == "/workspace/mindxtrain" | |
| def test_rsync_argv_has_excludes_and_trailing_slashes(tmp_path: Path) -> None: | |
| cmd = build_rsync(_cfg(), tmp_path) | |
| assert cmd[0] == "rsync" | |
| # Must exclude .git or the cloud-init clone path is the source of truth. | |
| assert "--exclude" in cmd | |
| assert ".git" in cmd | |
| # Source ends with `/`, dest ends with `/` — rsync semantics for "copy contents". | |
| src = cmd[-2] | |
| dst = cmd[-1] | |
| assert src.endswith("/") | |
| assert dst.endswith("/") | |
| assert dst == "ubuntu@mi300x.example.com:/workspace/mindxtrain/" | |
| def test_ssh_options_set_batchmode_everywhere() -> None: | |
| """BatchMode=yes prevents an interactive prompt from silently hanging | |
| the spawn thread. Pin it for every ssh-flavored command.""" | |
| for cmd in ( | |
| build_provision_ssh(_cfg()), | |
| build_bench_ssh(_cfg()), | |
| build_ssh_probe(_cfg()), | |
| build_tail_cloud_init(_cfg()), | |
| build_scp_plan_back(_cfg(), Path("/tmp/x")), | |
| ): | |
| joined = " ".join(cmd) | |
| assert "BatchMode=yes" in joined, f"missing BatchMode in {cmd!r}" | |
| def test_bench_ssh_uses_force_pty() -> None: | |
| """`-tt` is what propagates SIGINT through ssh to the remote podman. | |
| Without it, registry.cancel() leaves the GPU spinning.""" | |
| cmd = build_bench_ssh(_cfg()) | |
| assert "-tt" in cmd, f"missing -tt: {cmd!r}" | |
| def test_provision_ssh_is_idempotent_shell_body() -> None: | |
| cmd = build_provision_ssh(_cfg()) | |
| body = cmd[-1] | |
| assert "command -v podman" in body | |
| assert "podman image exists" in body | |
| def test_bench_ssh_runs_inside_container() -> None: | |
| cmd = build_bench_ssh(_cfg()) | |
| body = cmd[-1] | |
| assert "podman run" in body | |
| assert "--device /dev/kfd" in body | |
| assert "--device /dev/dri" in body | |
| assert "mindxtrain bench --gpu 0 --out plan.json" in body | |
| def test_no_shell_true_contract_via_argv_form() -> None: | |
| """Hostile-looking host string lands as a single argv element rather | |
| than getting split by a shell. `subprocess.Popen(cmd_list)` is called | |
| with `shell=False` (default), so this is a smoke check that the | |
| builder doesn't accidentally interpolate into a string.""" | |
| evil = "evil; rm -rf /" | |
| cfg = DropletConfig(host=evil, user="u") | |
| for cmd in (build_provision_ssh(cfg), build_bench_ssh(cfg), build_ssh_probe(cfg)): | |
| # The host has to land in one and only one argv element (the user@host bit | |
| # or in the bench ssh body). Any case where ssh-options leak into shell | |
| # parsing would split this string across multiple args. | |
| joined_args = [a for a in cmd if evil in a] | |
| assert joined_args, f"host string vanished from cmd: {cmd!r}" | |
| # And no element is bash-looking ("rm -rf" as a standalone arg means | |
| # the shell already ran it locally — bug). | |
| for arg in cmd: | |
| assert arg != "rm", f"shell injection: rm leaked as standalone arg in {cmd!r}" | |
| def test_scp_plan_back_targets_local_path(tmp_path: Path) -> None: | |
| dest = tmp_path / "plan.remote.json" | |
| cmd = build_scp_plan_back(_cfg(), dest) | |
| assert cmd[0] == "scp" | |
| assert str(dest) in cmd | |
| src = [a for a in cmd if "@" in a and "plan.json" in a] | |
| assert src, f"no remote source in {cmd!r}" | |
| def test_sync_steps_with_bench_includes_scp(tmp_path: Path) -> None: | |
| steps = sync_steps(_cfg(), tmp_path, run_bench=True, fetch_plan=True) | |
| labels = [s.label for s in steps] | |
| assert labels == ["rsync", "provision", "bench", "scp-plan"] | |
| def test_sync_steps_without_bench_skips_bench_and_scp(tmp_path: Path) -> None: | |
| steps = sync_steps(_cfg(), tmp_path, run_bench=False, fetch_plan=True) | |
| labels = [s.label for s in steps] | |
| assert labels == ["rsync", "provision"] | |
| def test_status_missing_surfaces_missing_binaries(monkeypatch: pytest.MonkeyPatch) -> None: | |
| monkeypatch.setattr("shutil.which", lambda _b: None) | |
| miss = status_missing({"DROPLET_HOST": "h", "DROPLET_USER": "u"}) | |
| assert "rsync" in miss | |
| assert "ssh" in miss | |
| assert "scp" in miss | |
| def test_tail_cloud_init_waits_for_sentinel() -> None: | |
| cmd = build_tail_cloud_init(_cfg()) | |
| body = cmd[-1] | |
| assert "/workspace/mindxtrain/.bootstrap-done" in body | |
| assert "tail" in body | |