diff --git a/compute_endpoint/tests/conftest.py b/compute_endpoint/tests/conftest.py index c14c19227..8677ca6b4 100644 --- a/compute_endpoint/tests/conftest.py +++ b/compute_endpoint/tests/conftest.py @@ -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 diff --git a/compute_endpoint/tests/integration/endpoint/endpoint/test_endpoint_manager.py b/compute_endpoint/tests/integration/endpoint/endpoint/test_endpoint_manager.py index 179063a21..cb8bfc7cd 100644 --- a/compute_endpoint/tests/integration/endpoint/endpoint/test_endpoint_manager.py +++ b/compute_endpoint/tests/integration/endpoint/endpoint/test_endpoint_manager.py @@ -2,7 +2,6 @@ import os import pathlib import shutil -import uuid from importlib.machinery import SourceFileLoader from unittest.mock import ANY, patch @@ -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") @@ -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" @@ -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 diff --git a/compute_endpoint/tests/integration/endpoint/endpoint/test_interchange_with_rabbit.py b/compute_endpoint/tests/integration/endpoint/endpoint/test_interchange_with_rabbit.py index bda6f4037..669f4ac9d 100644 --- a/compute_endpoint/tests/integration/endpoint/endpoint/test_interchange_with_rabbit.py +++ b/compute_endpoint/tests/integration/endpoint/endpoint/test_interchange_with_rabbit.py @@ -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. @@ -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() @@ -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) @@ -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()) @@ -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()) @@ -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 @@ -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()) @@ -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()) diff --git a/compute_endpoint/tests/unit/test_cli_behavior.py b/compute_endpoint/tests/unit/test_cli_behavior.py index 66af1dee0..76510a6de 100644 --- a/compute_endpoint/tests/unit/test_cli_behavior.py +++ b/compute_endpoint/tests/unit/test_cli_behavior.py @@ -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) @@ -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: diff --git a/compute_endpoint/tests/unit/test_endpoint_unit.py b/compute_endpoint/tests/unit/test_endpoint_unit.py index ce9166cda..577c3f8f2 100644 --- a/compute_endpoint/tests/unit/test_endpoint_unit.py +++ b/compute_endpoint/tests/unit/test_endpoint_unit.py @@ -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( @@ -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 @@ -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={}, ) @@ -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?" @@ -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 @@ -843,9 +842,9 @@ 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") @@ -853,29 +852,27 @@ def test_handles_provided_endpoint_id_no_json( 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") @@ -883,7 +880,7 @@ def test_handles_provided_endpoint_id_with_json( 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 @@ -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 @@ -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} diff --git a/compute_endpoint/tests/unit/test_endpointmanager_unit.py b/compute_endpoint/tests/unit/test_endpointmanager_unit.py index 8edafe0bc..db91f6e9d 100644 --- a/compute_endpoint/tests/unit/test_endpointmanager_unit.py +++ b/compute_endpoint/tests/unit/test_endpointmanager_unit.py @@ -139,14 +139,9 @@ def mock_setproctitle(mocker, randomstring): @pytest.fixture -def mock_ep_uuid() -> str: - yield str(uuid.uuid4()) - - -@pytest.fixture -def mock_reg_info(mock_ep_uuid) -> str: +def mock_reg_info(ep_uuid) -> str: yield { - "endpoint_id": mock_ep_uuid, + "endpoint_id": ep_uuid, "command_queue_info": {"connection_url": "", "queue": ""}, "result_queue_info": { "connection_url": "", @@ -157,11 +152,11 @@ def mock_reg_info(mock_ep_uuid) -> str: @pytest.fixture -def mock_client(mocker, mock_ep_uuid, mock_reg_info): +def mock_client(mocker, ep_uuid, mock_reg_info): mock_gcc = mock.Mock() mock_gcc.register_endpoint.return_value = mock_reg_info mocker.patch("globus_compute_sdk.Client", return_value=mock_gcc) - yield mock_ep_uuid, mock_gcc + yield ep_uuid, mock_gcc @pytest.fixture(autouse=True) @@ -950,28 +945,24 @@ def test_iterates_even_if_no_commands(mocker, epmanager_as_root): @pytest.mark.parametrize("hb", (-100, -5, 0, 0.1, 4, 7, 11, None)) -def test_heartbeat_period_minimum(conf_dir, mock_conf, hb, mock_ep_uuid, mock_reg_info): +def test_heartbeat_period_minimum(conf_dir, mock_conf, hb, ep_uuid, mock_reg_info): if hb is not None: mock_conf._heartbeat_period = hb # assert mock_conf.heartbeat_period == hb, "Avoid config setter" - em = EndpointManager(conf_dir, mock_ep_uuid, mock_conf, mock_reg_info) + em = EndpointManager(conf_dir, ep_uuid, mock_conf, mock_reg_info) exp_hb = 30.0 if hb is None else max(MINIMUM_HEARTBEAT, hb) assert exp_hb == em._heartbeat_period, "Expected a reasonable minimum heartbeat" -def test_send_heartbeat_verifies_thread( - mock_conf, conf_dir, mock_ep_uuid, mock_reg_info -): - em = EndpointManager(conf_dir, mock_ep_uuid, mock_conf, mock_reg_info) +def test_send_heartbeat_verifies_thread(mock_conf, conf_dir, ep_uuid, mock_reg_info): + em = EndpointManager(conf_dir, ep_uuid, mock_conf, mock_reg_info) f = em.send_heartbeat() exc = f.exception() assert "publisher is not running" in str(exc) -def test_send_heartbeat_honors_shutdown( - mock_conf, conf_dir, mock_ep_uuid, mock_reg_info -): - em = EndpointManager(conf_dir, mock_ep_uuid, mock_conf, mock_reg_info) +def test_send_heartbeat_honors_shutdown(mock_conf, conf_dir, ep_uuid, mock_reg_info): + em = EndpointManager(conf_dir, ep_uuid, mock_conf, mock_reg_info) em._heartbeat_period = random.randint(1, 10000) em._heartbeat_publisher = mock.Mock(spec=ResultPublisher) @@ -987,10 +978,10 @@ def test_send_heartbeat_honors_shutdown( def test_send_heartbeat_shares_exception( - mock_log, mock_conf, conf_dir, mock_ep_uuid, mock_reg_info, randomstring + mock_log, mock_conf, conf_dir, ep_uuid, mock_reg_info, randomstring ): exc_text = randomstring() - em = EndpointManager(conf_dir, mock_ep_uuid, mock_conf, mock_reg_info) + em = EndpointManager(conf_dir, ep_uuid, mock_conf, mock_reg_info) em._heartbeat_publisher = mock.Mock(spec=ResultPublisher) em._heartbeat_publisher.publish.return_value = Future() f = em.send_heartbeat()