Skip to content

Commit e342aa4

Browse files
committed
tests(unit): update tests to use explicit Dask scheduler interface
1 parent 7baaaff commit e342aa4

1 file changed

Lines changed: 106 additions & 4 deletions

File tree

tests/unit/CodeEntropy/core/dask_clusters/test_dask_clusters.py

Lines changed: 106 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import sys
77
from unittest import mock
88

9+
import pytest
10+
911
from CodeEntropy.core.dask_clusters import HPCDaskManager
1012

1113

@@ -22,6 +24,8 @@ def args_helper(args_list):
2224
parser.add_argument("--hpc-nodes", type=int, default=4)
2325
parser.add_argument("--hpc-processes", type=int, default=20)
2426
parser.add_argument("--hpc-walltime", type=str, default="24:00:00")
27+
parser.add_argument("--hpc-interface", type=str, default=None)
28+
parser.add_argument("--hpc-modules", nargs="+", default=None)
2529

2630
parser.add_argument("--conda-env", type=str, default="codeentropy")
2731
parser.add_argument("--conda-exec", type=str, default="conda")
@@ -138,6 +142,33 @@ def test_slurm_prologues_mamba():
138142
]
139143

140144

145+
def test_slurm_prologues_includes_hpc_modules():
146+
args = args_helper(
147+
[
148+
"--hpc-modules",
149+
"apps/binapps/conda/miniforge3/25.9.1",
150+
"gcc/12.2.0",
151+
"--conda-env",
152+
"codeentropy",
153+
"--conda-exec",
154+
"conda",
155+
"--conda-path",
156+
"/path/to/conda",
157+
]
158+
)
159+
manager = HPCDaskManager(args)
160+
161+
prologue = manager.slurm_prologues()
162+
163+
assert prologue == [
164+
"module load apps/binapps/conda/miniforge3/25.9.1",
165+
"module load gcc/12.2.0",
166+
'eval "$(/path/to/conda shell.bash hook)"',
167+
"conda activate codeentropy",
168+
"export SLURM_CPU_FREQ_REQ=2250000",
169+
]
170+
171+
141172
@mock.patch("psutil.net_if_addrs")
142173
def test_system_network_interface_prefers_ib0(net_if_addrs):
143174
net_if_addrs.return_value = {"ib0": [], "eth0": []}
@@ -149,13 +180,34 @@ def test_system_network_interface_prefers_ib0(net_if_addrs):
149180

150181

151182
@mock.patch("psutil.net_if_addrs")
152-
def test_system_network_interface_fallback(net_if_addrs):
153-
net_if_addrs.return_value = {"lo": [], "docker0": []}
183+
def test_system_network_interface_uses_configured_interface(net_if_addrs):
184+
net_if_addrs.return_value = {"lo": [], "ib0": []}
185+
186+
args = args_helper(["--hpc-interface", "custom0"])
187+
manager = HPCDaskManager(args)
188+
189+
assert manager.system_network_interface() == "custom0"
190+
191+
192+
@mock.patch("psutil.net_if_addrs")
193+
def test_system_network_interface_falls_back_to_non_loopback_interface(net_if_addrs):
194+
net_if_addrs.return_value = {"lo": [], "ens5": [], "docker0": []}
154195

155196
args = args_helper([])
156197
manager = HPCDaskManager(args)
157198

158-
assert manager.system_network_interface() == "lo"
199+
assert manager.system_network_interface() == "ens5"
200+
201+
202+
@mock.patch("psutil.net_if_addrs")
203+
def test_system_network_interface_raises_without_non_loopback_interface(net_if_addrs):
204+
net_if_addrs.return_value = {"lo": [], "docker0": [], "veth123": []}
205+
206+
args = args_helper([])
207+
manager = HPCDaskManager(args)
208+
209+
with pytest.raises(RuntimeError, match="Could not find a non-loopback"):
210+
manager.system_network_interface()
159211

160212

161213
@mock.patch("subprocess.check_output")
@@ -219,7 +271,6 @@ def test_submit_master_writes_expected_script_conda(check_output):
219271
assert "conda activate codeentropy" in script
220272
assert "srun CodeEntropy" in script
221273
assert "--submit" not in script
222-
assert "srun CodeEntropy" in script
223274
assert " --submit " not in script
224275
assert not script.rstrip().endswith(" true")
225276

@@ -274,6 +325,53 @@ def test_submit_master_writes_expected_script_mamba(check_output):
274325
os.remove("CodeEntropy-master-submit.sh")
275326

276327

328+
@mock.patch("subprocess.check_output")
329+
def test_submit_master_writes_hpc_modules(check_output):
330+
check_output.return_value = b"Submitted batch job 12345\n"
331+
332+
args = args_helper(
333+
[
334+
"--hpc-modules",
335+
"apps/binapps/conda/miniforge3/25.9.1",
336+
"--conda-env",
337+
"codeentropy",
338+
"--conda-exec",
339+
"conda",
340+
"--conda-path",
341+
"/path/to/conda",
342+
"--hpc-queue",
343+
"standard",
344+
]
345+
)
346+
manager = HPCDaskManager(args)
347+
348+
cli = [
349+
"CodeEntropy",
350+
"--top_traj_file",
351+
"topology.tpr",
352+
"trajectory.trr",
353+
"--hpc",
354+
"true",
355+
"--submit",
356+
"true",
357+
]
358+
359+
try:
360+
with mock.patch.object(sys, "argv", cli):
361+
manager.submit_master()
362+
363+
with open("CodeEntropy-master-submit.sh", encoding="utf-8") as file:
364+
script = file.read()
365+
366+
assert "module load apps/binapps/conda/miniforge3/25.9.1" in script
367+
assert 'eval "$(/path/to/conda shell.bash hook)"' in script
368+
assert "conda activate codeentropy" in script
369+
370+
finally:
371+
if os.path.exists("CodeEntropy-master-submit.sh"):
372+
os.remove("CodeEntropy-master-submit.sh")
373+
374+
277375
@mock.patch("CodeEntropy.core.dask_clusters.Client")
278376
@mock.patch("CodeEntropy.core.dask_clusters.SLURMCluster")
279377
@mock.patch.object(HPCDaskManager, "system_network_interface")
@@ -324,6 +422,10 @@ def test_configure_cluster_writes_job_script(
324422
assert returned_client is client_instance
325423

326424
slurm_cluster.assert_called_once()
425+
_, kwargs = slurm_cluster.call_args
426+
assert kwargs["interface"] == "ib0"
427+
assert kwargs["scheduler_options"] == {"interface": "ib0"}
428+
327429
cluster_instance.scale.assert_called_once_with(jobs=4)
328430
client.assert_called_once_with(cluster_instance)
329431

0 commit comments

Comments
 (0)