Skip to content

Commit

Permalink
Remove a fixture duplication
Browse files Browse the repository at this point in the history
  • Loading branch information
khk-globus committed Nov 19, 2024
1 parent 94ae4d2 commit b12192f
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 79 deletions.
5 changes: 5 additions & 0 deletions compute_endpoint/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ def other_endpoint_id():
return str(uuid.UUID(int=2))


@pytest.fixture
def ep_uuid() -> str:
return str(uuid.uuid4())


@pytest.fixture(scope="session")
def tod_session_num():
yield round(time.time()) % 86400
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import os
import pathlib
import shutil
import uuid
from importlib.machinery import SourceFileLoader
from unittest.mock import ANY, patch

Expand Down Expand Up @@ -437,10 +436,9 @@ def test_with_funcx_config(self, mocker):

@pytest.mark.parametrize("web_svc_ok", (True, False))
@pytest.mark.parametrize("force", (True, False))
def test_delete_endpoint(self, mocker, web_svc_ok, force):
def test_delete_endpoint(self, mocker, web_svc_ok, force, ep_uuid):
manager = Endpoint()
config_dir = pathlib.Path("/some/path/mock_endpoint")
ep_uuid_str = str(uuid.uuid4())

mock_stop_endpoint = mocker.patch.object(Endpoint, "stop_endpoint")
mock_rmtree = mocker.patch.object(shutil, "rmtree")
Expand All @@ -458,9 +456,7 @@ def test_delete_endpoint(self, mocker, web_svc_ok, force):

if not force:
with pytest.raises(SystemExit), patch(f"{_MOCK_BASE}log") as mock_log:
manager.delete_endpoint(
config_dir, force=force, ep_uuid=ep_uuid_str
)
manager.delete_endpoint(config_dir, force=force, ep_uuid=ep_uuid)
a, _k = mock_log.critical.call_args
assert "without deleting the local endpoint" in a[0], "expected notice"

Expand All @@ -475,16 +471,13 @@ def test_delete_endpoint(self, mocker, web_svc_ok, force):

try:
manager.delete_endpoint(
config_dir,
ep_config=None,
force=force,
ep_uuid=ep_uuid_str,
config_dir, ep_config=None, force=force, ep_uuid=ep_uuid
)

if web_svc_ok:
mock_stop_endpoint.assert_called_with(config_dir, None, remote=False)
assert mock_gcc.delete_endpoint.called
assert mock_gcc.delete_endpoint.call_args[0][0] == ep_uuid_str
assert mock_gcc.delete_endpoint.call_args[0][0] == ep_uuid
mock_rmtree.assert_called_with(config_dir)
except SystemExit as e:
# If currently running, error out if force is not specified
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def run_interchange_process(
setup_register_endpoint_response,
tmp_path,
request, # Allows a custom config to be passed in if needed
ep_uuid,
):
"""
Start and stop a subprocess that executes the EndpointInterchange class.
Expand Down Expand Up @@ -53,22 +54,21 @@ def run_it(reg_info: dict, endpoint_uuid, endpoint_dir):

ix.start()

endpoint_uuid = str(uuid.uuid4())
endpoint_name = "endpoint_foo"
gcc = get_standard_compute_client()
setup_register_endpoint_response(endpoint_uuid)
reg_info = gcc.register_endpoint(endpoint_name, endpoint_uuid)
setup_register_endpoint_response(ep_uuid)
reg_info = gcc.register_endpoint(endpoint_name, ep_uuid)
assert isinstance(reg_info, dict), "Test setup verification"
assert reg_info["endpoint_id"] == endpoint_uuid, "Test setup verification"
assert reg_info["endpoint_id"] == ep_uuid, "Test setup verification"
assert "task_queue_info" in reg_info
assert "result_queue_info" in reg_info

ix_proc = multiprocessing.Process(
target=run_it, args=(reg_info, endpoint_uuid), kwargs={"endpoint_dir": tmp_path}
target=run_it, args=(reg_info, ep_uuid), kwargs={"endpoint_dir": tmp_path}
)
ix_proc.start()

yield ix_proc, tmp_path, endpoint_uuid, reg_info
yield ix_proc, tmp_path, ep_uuid, reg_info

if ix_proc.is_alive():
ix_proc.terminate()
Expand All @@ -84,14 +84,14 @@ def run_it(reg_info: dict, endpoint_uuid, endpoint_dir):


def test_epi_graceful_shutdown(run_interchange_process):
ix_proc, tmp_path, endpoint_uuid, _reg_info = run_interchange_process
ix_proc, tmp_path, ep_uuid, _reg_info = run_interchange_process
time.sleep(2) # simple test approach for now: assume it's up after 2s
ix_proc.terminate()
assert try_for_timeout(lambda: ix_proc.exitcode is not None), "Failed to shutdown"


def test_epi_stored_results_processed(run_interchange_process):
ix_proc, tmp_path, endpoint_uuid, _reg_info = run_interchange_process
ix_proc, tmp_path, ep_uuid, _reg_info = run_interchange_process

unacked_results_dir = tmp_path / "unacked_results"
unacked_results_dir.mkdir(exist_ok=True)
Expand All @@ -113,7 +113,7 @@ def test_epi_forwards_tasks_and_results(
appropriate queue, and results are put into appropriate queue with the correct
routing_key.
"""
ix_proc, tmp_path, endpoint_uuid, reg_info = run_interchange_process
ix_proc, tmp_path, ep_uuid, reg_info = run_interchange_process

task_uuid = uuid.uuid4()
task_msg = Task(task_id=task_uuid, task_buffer=randomstring())
Expand Down Expand Up @@ -172,7 +172,7 @@ def test_epi_rejects_allowlist_task(
this test also doubles up as checking for not specifying the
resource_specification field.
"""
*_, endpoint_uuid, reg_info = run_interchange_process
*_, ep_uuid, reg_info = run_interchange_process

task_uuid = uuid.uuid4()
task_msg = Task(task_id=task_uuid, task_buffer=randomstring())
Expand Down Expand Up @@ -214,7 +214,7 @@ def test_epi_rejects_allowlist_task(
assert (
f"Function {func_to_run} not permitted" in result.data
), config
assert f"on endpoint {endpoint_uuid}" in result.data, result
assert f"on endpoint {ep_uuid}" in result.data, result
break


Expand All @@ -235,7 +235,7 @@ def test_resource_specification(
appropriate queue, and results are put into appropriate queue with the correct
routing_key.
"""
ix_proc, tmp_path, endpoint_uuid, reg_info = run_interchange_process
ix_proc, tmp_path, ep_uuid, reg_info = run_interchange_process

task_uuid = uuid.uuid4()
task_msg = Task(task_id=task_uuid, task_buffer=randomstring())
Expand Down Expand Up @@ -288,7 +288,7 @@ def test_bad_resource_specification(
a bad resource_spec, in this case we use {"BAD_KEY": ...}
to trigger an exception in the MockExecutor
"""
ix_proc, tmp_path, endpoint_uuid, reg_info = run_interchange_process
ix_proc, tmp_path, ep_uuid, reg_info = run_interchange_process

task_uuid = uuid.uuid4()
task_msg = Task(task_id=task_uuid, task_buffer=randomstring())
Expand Down
15 changes: 5 additions & 10 deletions compute_endpoint/tests/unit/test_cli_behavior.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,6 @@ def ep_name(randomstring):
yield randomstring()


@pytest.fixture
def fake_ep_uuid():
yield str(uuid.uuid4())


@pytest.fixture
def mock_app(mocker: MockFixture):
mock_app = mock.Mock(spec=UserApp)
Expand Down Expand Up @@ -586,17 +581,17 @@ def test_delete_endpoint(
run_line,
mock_cli_state,
ep_name,
fake_ep_uuid,
ep_uuid,
make_endpoint_dir,
use_uuid,
):
get_endpoint_id.return_value = fake_ep_uuid
get_endpoint_id.return_value = ep_uuid

make_endpoint_dir(ep_uuid=fake_ep_uuid)
run_line(f"delete {fake_ep_uuid if use_uuid else ep_name} --yes")
make_endpoint_dir(ep_uuid=ep_uuid)
run_line(f"delete {ep_uuid if use_uuid else ep_name} --yes")
mock_ep, _ = mock_cli_state
mock_ep.delete_endpoint.assert_called_once()
assert mock_ep.delete_endpoint.call_args[1]["ep_uuid"] == fake_ep_uuid
assert mock_ep.delete_endpoint.call_args[1]["ep_uuid"] == ep_uuid
if use_uuid:
get_endpoint_id.assert_not_called()
else:
Expand Down
45 changes: 21 additions & 24 deletions compute_endpoint/tests/unit/test_endpoint_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,12 +207,12 @@ def test_start_endpoint_network_error(
get_standard_compute_client,
register_endpoint_response,
mock_ep_data,
ep_uuid,
):
ep, ep_dir, log_to_console, no_color, ep_conf = mock_ep_data
ep_uuid_str = str(uuid.uuid4())

uname, pword = randomstring(), randomstring()
register_endpoint_response(endpoint_id=ep_uuid_str, username=uname, password=pword)
register_endpoint_response(endpoint_id=ep_uuid, username=uname, password=pword)

mock_gcc = get_standard_compute_client()
mocker.patch.object(
Expand All @@ -226,7 +226,7 @@ def test_start_endpoint_network_error(
with redirect_stdout(f):
with pytest.raises(SystemExit) as pytest_exc:
ep.start_endpoint(
ep_dir, ep_uuid_str, ep_conf, log_to_console, no_color, reg_info={}
ep_dir, ep_uuid, ep_conf, log_to_console, no_color, reg_info={}
)

assert pytest_exc.value.code == os.EX_TEMPFAIL
Expand All @@ -243,15 +243,15 @@ def test_delete_endpoint_network_error(
get_standard_compute_client,
register_endpoint_response,
mock_ep_data,
ep_uuid,
):
ep, ep_dir, _, _, ep_conf = mock_ep_data
ep_uuid_str = str(uuid.uuid4())

uname, pword = randomstring(), randomstring()
register_endpoint_response(endpoint_id=ep_uuid_str, username=uname, password=pword)
register_endpoint_response(endpoint_id=ep_uuid, username=uname, password=pword)
responses.add(
method=responses.GET,
url=f"https://compute.api.globus.org/v2/endpoints/{ep_uuid_str}/status",
url=f"https://compute.api.globus.org/v2/endpoints/{ep_uuid}/status",
headers={"Content-Type": "application/json"},
json={},
)
Expand All @@ -261,13 +261,13 @@ def test_delete_endpoint_network_error(
mock_gcc, "delete_endpoint", side_effect=NetworkError("foo", Exception)
)
mocker.patch(f"{_mock_base}Endpoint.get_funcx_client").return_value = mock_gcc
mocker.patch(f"{_mock_base}Endpoint.get_endpoint_id").return_value = ep_uuid_str
mocker.patch(f"{_mock_base}Endpoint.get_endpoint_id").return_value = ep_uuid
mock_log = mocker.patch(f"{_mock_base}log")

f = io.StringIO()
with redirect_stdout(f):
with pytest.raises(SystemExit) as pytest_exc:
ep.delete_endpoint(ep_dir, ep_conf, ep_uuid=ep_uuid_str)
ep.delete_endpoint(ep_dir, ep_conf, ep_uuid=ep_uuid)

assert pytest_exc.value.code == os.EX_TEMPFAIL
assert mock_delete.called, "Verify test setup; was kernel actually invoked?"
Expand Down Expand Up @@ -825,16 +825,15 @@ def test_get_endpoint_dir_by_uuid(tmp_path, name, uuid, exists):


@pytest.mark.parametrize("json_exists", [True, False])
def test_get_endpoint_id(tmp_path: pathlib.Path, json_exists: bool):
ep_uuid_str = str(uuid.uuid4())
def test_get_endpoint_id(tmp_path: pathlib.Path, json_exists: bool, ep_uuid):
if json_exists:
ep_json = tmp_path / "endpoint.json"
ep_json.write_text(json.dumps({"endpoint_id": ep_uuid_str}))
ep_json.write_text(json.dumps({"endpoint_id": ep_uuid}))

ret = Endpoint.get_endpoint_id(endpoint_dir=tmp_path)

if json_exists:
assert ret == ep_uuid_str
assert ret == ep_uuid
else:
assert ret is None

Expand All @@ -843,47 +842,45 @@ def test_handles_provided_endpoint_id_no_json(
mocker: MockFixture,
mock_ep_data: tuple[Endpoint, pathlib.Path, bool, bool, UserEndpointConfig],
mock_reg_info: dict,
ep_uuid,
):
ep, ep_dir, log_to_console, no_color, ep_conf = mock_ep_data
ep_uuid_str = str(uuid.uuid4())

mocker.patch(f"{_mock_base}daemon")
mocker.patch(f"{_mock_base}EndpointInterchange")

mock_gcc = mocker.Mock()
mock_gcc.register_endpoint.return_value = {
**mock_reg_info,
"endpoint_id": ep_uuid_str,
"endpoint_id": ep_uuid,
}
mocker.patch(f"{_mock_base}Endpoint.get_funcx_client").return_value = mock_gcc

ep.start_endpoint(
ep_dir, ep_uuid_str, ep_conf, log_to_console, no_color, reg_info={}
)
ep.start_endpoint(ep_dir, ep_uuid, ep_conf, log_to_console, no_color, reg_info={})

_a, k = mock_gcc.register_endpoint.call_args
assert k["endpoint_id"] == ep_uuid_str
assert k["endpoint_id"] == ep_uuid


def test_handles_provided_endpoint_id_with_json(
mocker: MockFixture,
mock_ep_data: tuple[Endpoint, pathlib.Path, bool, bool, UserEndpointConfig],
mock_reg_info: dict,
ep_uuid,
):
ep, ep_dir, log_to_console, no_color, ep_conf = mock_ep_data
ep_uuid_str = str(uuid.uuid4())
provided_ep_uuid_str = str(uuid.uuid4())

ep_json = ep_dir / "endpoint.json"
ep_json.write_text(json.dumps({"endpoint_id": ep_uuid_str}))
ep_json.write_text(json.dumps({"endpoint_id": ep_uuid}))

mocker.patch(f"{_mock_base}daemon")
mocker.patch(f"{_mock_base}EndpointInterchange")

mock_gcc = mocker.Mock()
mock_gcc.register_endpoint.return_value = {
**mock_reg_info,
"endpoint_id": ep_uuid_str,
"endpoint_id": ep_uuid,
}
mocker.patch(f"{_mock_base}Endpoint.get_funcx_client").return_value = mock_gcc

Expand All @@ -892,15 +889,15 @@ def test_handles_provided_endpoint_id_with_json(
)

_a, k = mock_gcc.register_endpoint.call_args
assert k["endpoint_id"] == ep_uuid_str
assert k["endpoint_id"] == ep_uuid


def test_delete_remote_endpoint_no_local_offline(
mocker: MockFixture,
mock_ep_data: tuple[Endpoint, pathlib.Path, bool, bool, UserEndpointConfig],
ep_uuid,
):
ep = mock_ep_data[0]
ep_uuid = str(uuid.uuid4())
mock_gcc = mocker.Mock()
mock_gcc.get_endpoint_status.return_value = {"status": "offline"}
mocker.patch(f"{_mock_base}Endpoint.get_funcx_client").return_value = mock_gcc
Expand All @@ -917,9 +914,9 @@ def test_delete_endpoint_with_uuid_happy(
ep_status: str,
mocker: MockFixture,
mock_ep_data: tuple[Endpoint, pathlib.Path, bool, bool, UserEndpointConfig],
ep_uuid,
):
ep, ep_dir, *_, ep_config = mock_ep_data
ep_uuid = str(uuid.uuid4())
mock_log = mocker.patch(f"{_mock_base}log")
mock_gcc = mocker.Mock()
mock_gcc.get_endpoint_status.return_value = {"status": ep_status}
Expand Down
Loading

0 comments on commit b12192f

Please sign in to comment.