-
Notifications
You must be signed in to change notification settings - Fork 1
Further instrument server fixes + improving test coverage #570
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 23 commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
67cc036
Captured post request when registering tomography preprocessing param…
tieneupin aa690ff
Fixed logic when parsing MachineConfig for rsync URL
tieneupin 360a345
Allow 'None' in 'dose_per_frame' key in 'Base' sub-class
tieneupin 245ee6a
Added unit test for 'upload_gain_reference()' API endpoint
tieneupin ed38844
Adjusted location of comments
tieneupin a3cfb85
Fixed which function/module layer to mock
tieneupin 898efd3
Tried fixing the 'requests.get' mock
tieneupin a5a30a0
Typo in URL path to endpoint to test
tieneupin 914e997
Commented out 'mock_request' to see if test function actually runs
tieneupin f242cd1
Adjusted assertion logic for urlparse result
tieneupin fb62ccc
Adjusted assertion logic for urlparse return value
tieneupin 2a489e7
Check if endpoint is being poked correctly first
tieneupin 73beba4
Try testing the function by itself, and not as a FastAPI call
tieneupin 4a1548e
Forgot remove extra variables after changing length of parameter tupl…
tieneupin cfc48cb
Check contents of request.get() call
tieneupin 25725e3
Try using unittest.mock.ANY to skip token authentication check
tieneupin 26b0b17
Added fixture to simulate a pre-loaded client-side configuration Conf…
tieneupin a4a274b
Added test for '_get_murfey_url' function
tieneupin 7d08e2e
Parametrised the '_get_murfey_url' test
tieneupin c196e6b
Code block shouldn't have to be indented
tieneupin bd8883f
Added 'http://' to URL test cases with no schemes when performing com…
tieneupin b27585c
'tokens' variable should not require mocking anymore
tieneupin 75c8e41
Turns out the token still needs to be mocked, oops
tieneupin 87e91f6
Removed residual comment
tieneupin 6bcb2b5
Does 'stderr' need to be set if that branch of logic is not tested here?
tieneupin 6cc5c53
Test for 'port' and 'hostname' attributes as well
tieneupin cc6477e
Rearranged code in blocks according to purpose
tieneupin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,144 @@ | ||
| from pathlib import Path | ||
| from typing import Optional | ||
| from unittest.mock import ANY, Mock, patch | ||
| from urllib.parse import urlparse | ||
|
|
||
| from pytest import mark | ||
|
|
||
| from murfey.instrument_server.api import ( | ||
| GainReference, | ||
| _get_murfey_url, | ||
| upload_gain_reference, | ||
| ) | ||
| from murfey.util import posix_path | ||
|
|
||
| test_get_murfey_url_params_matrix = ( | ||
| # Server URL to use | ||
| ("default",), | ||
| ("0.0.0.0:8000",), | ||
| ("murfey_server",), | ||
| ("http://murfey_server:8000",), | ||
| ("http://murfey_server:8080/api",), | ||
| ) | ||
|
|
||
|
|
||
| @mark.parametrize("test_params", test_get_murfey_url_params_matrix) | ||
| def test_get_murfey_url( | ||
| test_params: tuple[str], | ||
| mock_client_configuration, # From conftest.py | ||
| ): | ||
| # Unpack test_params | ||
| (server_url_to_test,) = test_params | ||
|
|
||
| # Replace the server URL from the fixture with other ones for testing | ||
| if server_url_to_test != "default": | ||
| mock_client_configuration["Murfey"]["server"] = server_url_to_test | ||
|
|
||
| # Mock the module-wide config variable with the fixture value | ||
| # The fixture is only loaded within the test function, so this patch | ||
| # has to happen inside the function instead of as a decorator | ||
| with patch("murfey.instrument_server.api.config", mock_client_configuration): | ||
| known_server = _get_murfey_url() | ||
|
|
||
| # Check that the components of the result match those in the config | ||
| parsed_server = urlparse(known_server) | ||
| original_url = str(mock_client_configuration["Murfey"].get("server")) | ||
| if not original_url.startswith(("http://", "https://")): | ||
| original_url = f"http://{original_url}" | ||
| parsed_original = urlparse(original_url) | ||
| assert parsed_server.scheme in ("http", "https") | ||
| assert parsed_server.netloc == parsed_original.netloc | ||
| assert parsed_server.path == parsed_original.path | ||
|
|
||
|
|
||
| test_upload_gain_reference_params_matrix = ( | ||
| # Rsync URL settings | ||
| ("http://1.1.1.1",), # When rsync_url is provided | ||
| ("",), # When rsync_url is blank | ||
| (None,), # When rsync_url not provided | ||
| ) | ||
|
|
||
|
|
||
| @mark.parametrize("test_params", test_upload_gain_reference_params_matrix) | ||
| @patch("murfey.instrument_server.api.subprocess") | ||
| @patch("murfey.instrument_server.api.tokens") | ||
| @patch("murfey.instrument_server.api._get_murfey_url") | ||
| @patch("murfey.instrument_server.api.requests") | ||
| def test_upload_gain_reference( | ||
| mock_request, | ||
| mock_get_server_url, | ||
| mock_tokens, | ||
| mock_subprocess, | ||
| test_params: tuple[Optional[str]], | ||
| ): | ||
|
|
||
| # Unpack test parameters and define other ones | ||
| (rsync_url_setting,) = test_params | ||
| server_url = "http://0.0.0.0:8000" | ||
| instrument_name = "murfey" | ||
| session_id = 1 | ||
|
|
||
| # Create a mock machine config base on the test params | ||
| rsync_module = "data" | ||
| gain_ref_dir = "C:/ProgramData/Gatan/Gain Reference" | ||
| mock_machine_config = { | ||
| "rsync_module": rsync_module, | ||
| "gain_reference_directory": gain_ref_dir, | ||
| } | ||
| if rsync_url_setting is not None: | ||
| mock_machine_config["rsync_url"] = rsync_url_setting | ||
|
|
||
| # Assign expected values to the mock objects | ||
| mock_response = Mock() | ||
| mock_response.status_code = 200 | ||
| mock_response.json.return_value = mock_machine_config | ||
| mock_request.get.return_value = mock_response | ||
| mock_get_server_url.return_value = server_url | ||
| mock_subprocess.run.return_value = Mock( | ||
| returncode=0, stderr="An error has occurred." | ||
tieneupin marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ) | ||
|
|
||
| # Construct payload and pass request to function | ||
| gain_ref_file = f"{gain_ref_dir}/gain.mrc" | ||
| visit_path = "2025/aa00000-0" | ||
| gain_dest_dir = "processing" | ||
| payload = { | ||
| "gain_path": gain_ref_file, | ||
| "visit_path": visit_path, | ||
| "gain_destination_dir": gain_dest_dir, | ||
| } | ||
| result = upload_gain_reference( | ||
| instrument_name=instrument_name, | ||
| session_id=session_id, | ||
| gain_reference=GainReference( | ||
| **payload, | ||
| ), | ||
| ) | ||
|
|
||
| # Check that the machine config request was called | ||
| machine_config_url = f"{server_url}/instruments/{instrument_name}/machine" | ||
| mock_request.get.assert_called_once_with( | ||
| machine_config_url, | ||
| headers={"Authorization": ANY}, | ||
| ) | ||
|
|
||
| # Check that the subprocess was run with the expected arguments | ||
| # If no rsync_url key is provided, or rsync_url key is empty, | ||
| # It should default to the server URL | ||
| expected_rsync_url = ( | ||
| urlparse(server_url) if not rsync_url_setting else urlparse(rsync_url_setting) | ||
| ) | ||
| expected_rsync_path = f"{expected_rsync_url.hostname}::{rsync_module}/{visit_path}/{gain_dest_dir}/gain.mrc" | ||
| expected_rsync_cmd = [ | ||
| "rsync", | ||
| posix_path(Path(gain_ref_file)), | ||
| expected_rsync_path, | ||
| ] | ||
| mock_subprocess.run.assert_called_once_with( | ||
| expected_rsync_cmd, | ||
| capture_output=True, | ||
| text=True, | ||
| ) | ||
|
|
||
| # Check that the function ran through to completion successfully | ||
| assert result == {"success": True} | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.