From 82a007d0a13df350d3b94d68e62be3853afc8043 Mon Sep 17 00:00:00 2001 From: Lester Hedges Date: Mon, 20 Jan 2025 17:03:57 +0000 Subject: [PATCH] Fix server handling in tests. --- tests/conftest.py | 44 +++++++++++++++++++----------------- tests/test_delta_learning.py | 22 +++++++++++------- tests/test_external.py | 14 ++++++++++++ tests/test_interpolate.py | 26 +++++++++++++++++++++ tests/test_qm_xyz.py | 8 +++++++ 5 files changed, 85 insertions(+), 29 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index d981781..6fd7d28 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,30 +1,32 @@ -import pytest -import psutil +import subprocess -@pytest.fixture(autouse=True) -def wrapper(): - """ - A wrapper function to stop the EMLE server after each test. +def start_server(cwd, env=None): """ + Start the EMLE server using the environment variables. - yield + Parameters + ---------- - # Kill the EMLE server. - kill_server() + cwd : str + The current working directory. + env : dict + The environment variables. -def kill_server(): - """ - Helper function to kill the EMLE server. + Returns + ------- + + process : subprocess.Popen + The EMLE server process object. """ - # Kill the EMLE server. We do this manually rather than using emle-stop - # because there is sometimes a delay in the termination of the server, - # which causes the next test to fail. This only seems to happen when - # testing during CI. - for conn in psutil.net_connections(kind="inet"): - if conn.laddr.port == 10000: - process = psutil.Process(conn.pid) - process.terminate() - break + process = subprocess.Popen( + ["emle-server"], + cwd=cwd, + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + + return process diff --git a/tests/test_delta_learning.py b/tests/test_delta_learning.py index 209a605..4a42702 100644 --- a/tests/test_delta_learning.py +++ b/tests/test_delta_learning.py @@ -4,19 +4,18 @@ import shutil import subprocess import tempfile -import time import yaml +from conftest import start_server -def test_delta_learning(backend="torchani,xtb"): + +def test_delta_learning(): """ Make sure that the server can run using two backends for the in vacuo vacuo calculation. The first is the "reference" backend, the second applies delta learning corrections. """ - from conftest import kill_server - with tempfile.TemporaryDirectory() as tmpdir: # Copy files to temporary directory. shutil.copyfile("tests/input/adp.parm7", tmpdir + "/adp.parm7") @@ -30,6 +29,9 @@ def test_delta_learning(backend="torchani,xtb"): env["EMLE_BACKEND"] = "torchani,xtb" env["EMLE_ENERGY_FREQUENCY"] = "1" + # Start the server. + server = start_server(tmpdir, env=env) + # Create the sander command. command = "sander -O -i emle_sp.in -p adp.parm7 -c adp.rst7 -o emle.out" @@ -60,10 +62,8 @@ def test_delta_learning(backend="torchani,xtb"): + float(lines[-1].strip()) ) - # Kill the server. (Try twice, since there is sometimes a delay.) - kill_server() - time.sleep(1) - kill_server() + # Stop the server. + server.terminate() # Now swap the order of the backends. @@ -80,6 +80,9 @@ def test_delta_learning(backend="torchani,xtb"): env["EMLE_BACKEND"] = "xtb,torchani" env["EMLE_ENERGY_FREQUENCY"] = "1" + # Start the server. + server = start_server(tmpdir, env=env) + # Create the sander command. command = "sander -O -i emle_sp.in -p adp.parm7 -c adp.rst7 -o emle.out" @@ -109,5 +112,8 @@ def test_delta_learning(backend="torchani,xtb"): + float(lines[-1].strip()) ) + # Stop the server. + server.terminate() + # Make sure that the results are the same. assert math.isclose(result_ab, result_ba, rel_tol=1e-6) diff --git a/tests/test_external.py b/tests/test_external.py index ebd165e..c8aac90 100644 --- a/tests/test_external.py +++ b/tests/test_external.py @@ -4,6 +4,8 @@ import subprocess import tempfile +from conftest import start_server + def test_external_local_directory(): """ @@ -25,6 +27,9 @@ def test_external_local_directory(): env["EMLE_EXTERNAL_BACKEND"] = "external.run_external" env["EMLE_ENERGY_FREQUENCY"] = "1" + # Start the server. + server = start_server(tmpdir, env=env) + # Create the sander command. command = "sander -O -i emle_sp.in -p adp.parm7 -c adp.rst7 -o emle.out" @@ -42,6 +47,9 @@ def test_external_local_directory(): # Make sure that an energy file is written. assert os.path.isfile(tmpdir + "/emle_energy.txt") + # Stop the server. + server.terminate() + def test_external_plugin_directory(): """ @@ -63,6 +71,9 @@ def test_external_plugin_directory(): env["EMLE_PLUGIN_PATH"] = os.getcwd() + "/tests/input" env["EMLE_ENERGY_FREQUENCY"] = "1" + # Start the server. + server = start_server(tmpdir, env=env) + # Create the sander command. command = "sander -O -i emle_sp.in -p adp.parm7 -c adp.rst7 -o emle.out" @@ -79,3 +90,6 @@ def test_external_plugin_directory(): # Make sure that an energy file is written. assert os.path.isfile(tmpdir + "/emle_energy.txt") + + # Stop the server. + server.terminate() diff --git a/tests/test_interpolate.py b/tests/test_interpolate.py index 2b4d1b0..c0f0db7 100644 --- a/tests/test_interpolate.py +++ b/tests/test_interpolate.py @@ -5,6 +5,8 @@ import subprocess import tempfile +from conftest import start_server + def parse_mdinfo(mdinfo_file): """ @@ -30,6 +32,9 @@ def test_interpolate(): shutil.copyfile("tests/input/adp.rst7", tmpdir + "/adp.rst7") shutil.copyfile("tests/input/mm_sp.in", tmpdir + "/mm_sp.in") + # Start the server. + server = start_server(tmpdir) + # Create the sander command. command = "sander -O -i mm_sp.in -p adp.parm7 -c adp.rst7" @@ -50,6 +55,9 @@ def test_interpolate(): assert math.isclose(nrg_ref, nrg_mm, rel_tol=1e-5) + # Stop the server. + server.terminate() + # Now perform and interpolated EMLE simulation at lambda=0. with tempfile.TemporaryDirectory() as tmpdir: # Copy files to temporary directory. @@ -74,6 +82,9 @@ def test_interpolate(): env["EMLE_QM_INDICES"] = "adp_qm_indices.txt" env["EMLE_ENERGY_FREQUENCY"] = "1" + # Start the server. + server = start_server(tmpdir, env=env) + # Create the sander command. command = "sander -O -i emle_sp.in -p adp.parm7 -c adp.rst7 -o emle.out" @@ -92,6 +103,9 @@ def test_interpolate(): assert math.isclose(nrg_ref, nrg_emle, rel_tol=1e-4) + # Stop the server. + server.terminate() + def test_interpolate_steps(): """ @@ -123,6 +137,9 @@ def test_interpolate_steps(): env["EMLE_QM_INDICES"] = "adp_qm_indices.txt" env["EMLE_ENERGY_FREQUENCY"] = "1" + # Start the server. + server = start_server(tmpdir, env=env) + # Create the sander command. command = "sander -O -i emle_prod.in -p adp.parm7 -c adp.rst7 -o emle.out" @@ -147,6 +164,9 @@ def test_interpolate_steps(): nrg_interp = lam * data[4] + (1 - lam) * data[3] assert math.isclose(nrg_lambda, nrg_interp, rel_tol=1e-5) + # Stop the server. + server.terminate() + def test_interpolate_steps_config(): """ @@ -168,6 +188,9 @@ def test_interpolate_steps_config(): # Set environment variables. env["EMLE_CONFIG"] = "config.yaml" + # Start the server. + server = start_server(tmpdir, env=env) + # Create the sander command. command = "sander -O -i emle_prod.in -p adp.parm7 -c adp.rst7 -o emle.out" @@ -191,3 +214,6 @@ def test_interpolate_steps_config(): nrg_lambda = data[2] nrg_interp = lam * data[4] + (1 - lam) * data[3] assert math.isclose(nrg_lambda, nrg_interp, rel_tol=1e-5) + + # Stop the server. + server.terminate() diff --git a/tests/test_qm_xyz.py b/tests/test_qm_xyz.py index 59728a5..073086d 100644 --- a/tests/test_qm_xyz.py +++ b/tests/test_qm_xyz.py @@ -4,6 +4,8 @@ import subprocess import tempfile +from conftest import start_server + def test_qm_xyz(): """ @@ -22,6 +24,9 @@ def test_qm_xyz(): # Set environment variables. env["EMLE_QM_XYZ_FREQUENCY"] = "2" + # Start the server. + server = start_server(tmpdir, env=env) + # Create the sander command. command = "sander -O -i emle_prod.in -p adp.parm7 -c adp.rst7 -o emle.out" @@ -46,3 +51,6 @@ def test_qm_xyz(): if line.startswith("22"): num_frames += 1 assert num_frames == 11 + + # Stop the server. + server.terminate()