matlab-proxy 0.18.0__py3-none-any.whl → 0.18.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of matlab-proxy might be problematic. Click here for more details.
- matlab_proxy/app.py +3 -1
- matlab_proxy/settings.py +12 -2
- matlab_proxy/util/mwi/environment_variables.py +1 -1
- {matlab_proxy-0.18.0.dist-info → matlab_proxy-0.18.2.dist-info}/METADATA +1 -1
- {matlab_proxy-0.18.0.dist-info → matlab_proxy-0.18.2.dist-info}/RECORD +11 -10
- tests/integration/integration_tests_with_license/test_http_end_points.py +217 -42
- tests/unit/util/mwi/test_download.py +152 -0
- {matlab_proxy-0.18.0.dist-info → matlab_proxy-0.18.2.dist-info}/LICENSE.md +0 -0
- {matlab_proxy-0.18.0.dist-info → matlab_proxy-0.18.2.dist-info}/WHEEL +0 -0
- {matlab_proxy-0.18.0.dist-info → matlab_proxy-0.18.2.dist-info}/entry_points.txt +0 -0
- {matlab_proxy-0.18.0.dist-info → matlab_proxy-0.18.2.dist-info}/top_level.txt +0 -0
matlab_proxy/app.py
CHANGED
|
@@ -624,10 +624,12 @@ async def matlab_view(req):
|
|
|
624
624
|
|
|
625
625
|
# Standard HTTP Request
|
|
626
626
|
else:
|
|
627
|
-
# Proxy, injecting request header
|
|
627
|
+
# Proxy, injecting request header, disabling request timeouts
|
|
628
|
+
timeout = aiohttp.ClientTimeout(total=None)
|
|
628
629
|
async with aiohttp.ClientSession(
|
|
629
630
|
trust_env=True,
|
|
630
631
|
connector=aiohttp.TCPConnector(verify_ssl=False),
|
|
632
|
+
timeout=timeout,
|
|
631
633
|
) as client_session:
|
|
632
634
|
try:
|
|
633
635
|
req_body = await transform_body(req)
|
matlab_proxy/settings.py
CHANGED
|
@@ -395,8 +395,10 @@ def get_matlab_settings():
|
|
|
395
395
|
has_custom_code_to_execute = (
|
|
396
396
|
len(os.getenv(mwi_env.get_env_name_custom_matlab_code(), "").strip()) > 0
|
|
397
397
|
)
|
|
398
|
-
|
|
399
|
-
|
|
398
|
+
|
|
399
|
+
# Sanitize file paths to avoid MATLAB not running the script due to early breakup of character array.
|
|
400
|
+
mp_code_to_execute = f"try; run('{_sanitize_file_path_for_matlab(matlab_startup_file)}'); catch MATLABProxyInitializationError; disp(MATLABProxyInitializationError.message); end;"
|
|
401
|
+
custom_code_to_execute = f"try; run('{_sanitize_file_path_for_matlab(matlab_code_file)}'); catch MATLABCustomStartupCodeError; disp(MATLABCustomStartupCodeError.message); end;"
|
|
400
402
|
code_to_execute = (
|
|
401
403
|
mp_code_to_execute + custom_code_to_execute
|
|
402
404
|
if has_custom_code_to_execute
|
|
@@ -621,3 +623,11 @@ def generate_new_self_signed_certs(mwi_certs_dir):
|
|
|
621
623
|
cert_file = priv_key_file = None
|
|
622
624
|
|
|
623
625
|
return cert_file, priv_key_file
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
def _sanitize_file_path_for_matlab(filepath: str) -> str:
|
|
629
|
+
"""
|
|
630
|
+
Replace single quotes in the filepath with double single quotes to preserve the quote when used in MATLAB code.
|
|
631
|
+
"""
|
|
632
|
+
filepath_with_single_quotes_escaped = filepath.replace("'", "''")
|
|
633
|
+
return filepath_with_single_quotes_escaped
|
|
@@ -187,7 +187,7 @@ class Experimental:
|
|
|
187
187
|
@staticmethod
|
|
188
188
|
def should_use_mos_html():
|
|
189
189
|
"""Returns true if matlab-proxy should use MOS htmls to load MATLAB"""
|
|
190
|
-
return _is_env_set_to_true("MWI_USE_MOS")
|
|
190
|
+
return _is_env_set_to_true("MWI_USE_MOS")
|
|
191
191
|
|
|
192
192
|
@staticmethod
|
|
193
193
|
def should_use_mre_html():
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
matlab_proxy/__init__.py,sha256=6cwi8buKCMtw9OeWaOYUHEoqwl5MyJ_s6GxgNuqPuNg,1673
|
|
2
|
-
matlab_proxy/app.py,sha256=
|
|
2
|
+
matlab_proxy/app.py,sha256=ri2Dm3G3uVmIhoEV01awazsO4t3Z92LEwin657bq8bw,34538
|
|
3
3
|
matlab_proxy/app_state.py,sha256=i5AVaNroFSld4Y36BNil5lwS0PNrHnceYq7swXY5AI4,60502
|
|
4
4
|
matlab_proxy/constants.py,sha256=CrbIA098b5LMsqxY7nbap0_tqA2tIrIckGAffTgIkrA,1039
|
|
5
5
|
matlab_proxy/default_configuration.py,sha256=DxQaHzAivzstiPl_nDfxs8SOyP9oaK9v3RP4LtroJl4,843
|
|
6
6
|
matlab_proxy/devel.py,sha256=nR6XPVBUEdQ-RZGtYvX1YHTp8gj9cuw5Hp8ahasMBc8,14310
|
|
7
|
-
matlab_proxy/settings.py,sha256=
|
|
7
|
+
matlab_proxy/settings.py,sha256=6KHKg96WjTz5xboBQllB6nDDTHhT9NBkWNGcWjwkJ6s,26096
|
|
8
8
|
matlab_proxy/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
matlab_proxy/gui/asset-manifest.json,sha256=XqmLvi3DDOGSbBxNZwjuaNJXoYjZiG2HasxvZnEzPEo,3516
|
|
10
10
|
matlab_proxy/gui/favicon.ico,sha256=7w7Ki1uQP2Rgwc64dOV4-NrTu97I3WsZw8OvRSoY1A0,130876
|
|
@@ -63,7 +63,7 @@ matlab_proxy/util/windows.py,sha256=J5O-wihOxEex43_AzwvFylNlN4hcZdO6KD5cpLv1FX8,
|
|
|
63
63
|
matlab_proxy/util/mwi/__init__.py,sha256=zI-X1lafr8H3j17PyA0oSZ0q5nINfK-WDA7VmJKmSAQ,158
|
|
64
64
|
matlab_proxy/util/mwi/custom_http_headers.py,sha256=kfDjSnEXEVzoF2pZuEn76LKayeD2WKoQEDu2Y9EMOAo,7154
|
|
65
65
|
matlab_proxy/util/mwi/download.py,sha256=-GJj3yOsL4vF_9baqRXkgBI-vu_OwjZMQVkJXFS8GMc,4965
|
|
66
|
-
matlab_proxy/util/mwi/environment_variables.py,sha256=
|
|
66
|
+
matlab_proxy/util/mwi/environment_variables.py,sha256=0B6rW1sMXGHmSTw6oPgOKz-QM40URIleO6d_zCTkkK8,7271
|
|
67
67
|
matlab_proxy/util/mwi/exceptions.py,sha256=93HrHbOq24KI4Md2el23XN01wIqVShEK29Pbt2V0Jr8,4628
|
|
68
68
|
matlab_proxy/util/mwi/logger.py,sha256=e7wTPclrtJ-aX5mPk_pUJMX7-1QD_snGBW1P2ks-ETE,3311
|
|
69
69
|
matlab_proxy/util/mwi/token_auth.py,sha256=UbIWqo7qADaZdijFvorLYsZbxzaB8TycGP8nk305ru0,9997
|
|
@@ -74,7 +74,7 @@ matlab_proxy/util/mwi/embedded_connector/request.py,sha256=-6DL9K8JWjX5u5XVOEGaq
|
|
|
74
74
|
tests/integration/__init__.py,sha256=ttzJ8xKWGxOJZz56qOiWOn6sp5LGomkZMn_w4KJLRMU,42
|
|
75
75
|
tests/integration/integration_tests_with_license/__init__.py,sha256=vVYZCur-QhmIGCxUmn-WZjIywtDQidaLDmlmrRHRlgY,37
|
|
76
76
|
tests/integration/integration_tests_with_license/conftest.py,sha256=sCaIXB8d4vf05C7JWSVA7g5gnPjbpRq3dftuBpWyp1s,1599
|
|
77
|
-
tests/integration/integration_tests_with_license/test_http_end_points.py,sha256=
|
|
77
|
+
tests/integration/integration_tests_with_license/test_http_end_points.py,sha256=51r3foIshg80NLgvsxaQUxlnnZiKs0O6gLvdF3Y7sWk,14448
|
|
78
78
|
tests/integration/integration_tests_without_license/__init__.py,sha256=vVYZCur-QhmIGCxUmn-WZjIywtDQidaLDmlmrRHRlgY,37
|
|
79
79
|
tests/integration/integration_tests_without_license/conftest.py,sha256=n-oppKWxavyy1O0J6DywO3DnOHuYc7yUZRXm3Bt4szU,3526
|
|
80
80
|
tests/integration/integration_tests_without_license/test_matlab_is_down_if_unlicensed.py,sha256=tkdyhfZBpfJpbnEzjURyV-GE0p43YxOa9xooJf-JoM4,1653
|
|
@@ -95,6 +95,7 @@ tests/unit/util/test_mw.py,sha256=YC4mjn6G6_XuHELt8uW9F6g2K0_fWtQl1R0kWFvWbAo,18
|
|
|
95
95
|
tests/unit/util/test_util.py,sha256=vqTPgmaKDWhVBRnCKtCNg-OtyR5bP8jeH9DnpcbfVTk,5141
|
|
96
96
|
tests/unit/util/mwi/__init__.py,sha256=pl5jqyCHEwZEviiL8OC-SHulb1rBecstQCFF6qVjL9Y,37
|
|
97
97
|
tests/unit/util/mwi/test_custom_http_headers.py,sha256=UfrhclS0j6WhShtg1ki2oF1kK8JqRC29uevH4tuDqF4,11182
|
|
98
|
+
tests/unit/util/mwi/test_download.py,sha256=jYwPJFYGrPKqnkIJW42XYSe1fowmzChAkOx0k0xVldo,4779
|
|
98
99
|
tests/unit/util/mwi/test_logger.py,sha256=zWImNitMYKPJunXWJjEDEtCEKwBz615PC844ZLwoxIg,1845
|
|
99
100
|
tests/unit/util/mwi/test_token_auth.py,sha256=-eBsaQ5JC7pyd9PXt48Rqs4cWjg6I-eOkp_gFVEwYhk,10538
|
|
100
101
|
tests/unit/util/mwi/test_validators.py,sha256=YeOP0-T7SFNeiC7JIQj7cV4ja3d6PhswsTz27IEgJHQ,10852
|
|
@@ -103,9 +104,9 @@ tests/unit/util/mwi/embedded_connector/test_helpers.py,sha256=vYTWNUTuDeaygo16JG
|
|
|
103
104
|
tests/unit/util/mwi/embedded_connector/test_request.py,sha256=PR-jddnXDEiip-lD7A_QSvRwEkwo3eQ8owZlk-r9vnk,1867
|
|
104
105
|
tests/utils/__init__.py,sha256=ttzJ8xKWGxOJZz56qOiWOn6sp5LGomkZMn_w4KJLRMU,42
|
|
105
106
|
tests/utils/logging_util.py,sha256=VBy_NRvwau3C_CVTBjK5RMROrQimnJYHO2U0aKSZiRw,2234
|
|
106
|
-
matlab_proxy-0.18.
|
|
107
|
-
matlab_proxy-0.18.
|
|
108
|
-
matlab_proxy-0.18.
|
|
109
|
-
matlab_proxy-0.18.
|
|
110
|
-
matlab_proxy-0.18.
|
|
111
|
-
matlab_proxy-0.18.
|
|
107
|
+
matlab_proxy-0.18.2.dist-info/LICENSE.md,sha256=oF0h3UdSF-rlUiMGYwi086ZHqelzz7yOOk9HFDv9ELo,2344
|
|
108
|
+
matlab_proxy-0.18.2.dist-info/METADATA,sha256=Jnbri3j-_H13v1Ly8LTT2vqwrm8SXPDpPkoQ9lZUvkE,10177
|
|
109
|
+
matlab_proxy-0.18.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
110
|
+
matlab_proxy-0.18.2.dist-info/entry_points.txt,sha256=DbBLYgnRt8UGiOpd0zHigRTyyMdZYhMdvCvSYP7wPN0,244
|
|
111
|
+
matlab_proxy-0.18.2.dist-info/top_level.txt,sha256=9uVTjsUCAS4TwsxueTBxrBg3PdBiTSsYowAkHPv9VY0,19
|
|
112
|
+
matlab_proxy-0.18.2.dist-info/RECORD,,
|
|
@@ -1,27 +1,167 @@
|
|
|
1
1
|
# Copyright 2023-2024 The MathWorks, Inc.
|
|
2
2
|
|
|
3
|
+
"""
|
|
4
|
+
Contains integration tests which exercise HTTP endpoints of interest exposed by matlab-proxy-app
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# Imports
|
|
8
|
+
from enum import Enum
|
|
3
9
|
import json
|
|
4
10
|
import os
|
|
5
|
-
import time
|
|
6
|
-
import matlab_proxy.settings as settings
|
|
7
|
-
from tests.integration.utils import integration_tests_utils as utils
|
|
8
11
|
import pytest
|
|
9
|
-
from matlab_proxy.util import system
|
|
10
|
-
import requests
|
|
11
12
|
import re
|
|
13
|
+
import requests
|
|
14
|
+
import time
|
|
12
15
|
from requests.adapters import HTTPAdapter, Retry
|
|
13
16
|
from urllib.parse import urlparse, parse_qs
|
|
14
|
-
|
|
17
|
+
|
|
18
|
+
# Local module imports
|
|
19
|
+
import matlab_proxy.settings as settings
|
|
15
20
|
from matlab_proxy.constants import MWI_AUTH_TOKEN_NAME_FOR_HTTP
|
|
21
|
+
from matlab_proxy.util import system
|
|
22
|
+
from tests.integration.utils import integration_tests_utils as utils
|
|
23
|
+
from tests.utils.logging_util import create_integ_test_logger
|
|
16
24
|
|
|
25
|
+
# Logger Setup
|
|
17
26
|
_logger = create_integ_test_logger(__name__)
|
|
18
27
|
|
|
28
|
+
# Constants
|
|
29
|
+
|
|
19
30
|
# Timeout for polling the matlab-proxy http endpoints
|
|
20
31
|
# matlab proxy in Mac machines takes more time to be 'up'
|
|
21
|
-
|
|
22
32
|
MAX_TIMEOUT = settings.get_process_startup_timeout()
|
|
23
33
|
|
|
24
34
|
|
|
35
|
+
class Format(Enum):
|
|
36
|
+
"""
|
|
37
|
+
An enumeration to specify different format types.
|
|
38
|
+
|
|
39
|
+
Attributes:
|
|
40
|
+
JSON (int): Represents the JSON format type.
|
|
41
|
+
TEXT (int): Represents the plain text format type.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
JSON = 1
|
|
45
|
+
TEXT = 2
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# Utility Functions
|
|
49
|
+
def _http_get_request(
|
|
50
|
+
uri, connection_scheme, headers, http_endpoint="", outputFormat=Format.TEXT
|
|
51
|
+
):
|
|
52
|
+
"""
|
|
53
|
+
Sends an HTTP GET request to a specified URI, optionally appending an endpoint to the URI.
|
|
54
|
+
|
|
55
|
+
This function uses a session with retries configured for transient network errors. It can return
|
|
56
|
+
the response in either text or JSON format, based on the outputFormat parameter.
|
|
57
|
+
|
|
58
|
+
Parameters:
|
|
59
|
+
- uri (str): The base URI for the HTTP request.
|
|
60
|
+
- connection_scheme (str): The scheme to use for the connection (e.g., 'http' or 'https').
|
|
61
|
+
- headers (dict): A dictionary of HTTP headers to include in the request.
|
|
62
|
+
- http_endpoint (str, optional): An additional endpoint to append to the base URI. Defaults to an empty string.
|
|
63
|
+
- outputFormat (format, optional): The desired format for the response content. This should be an attribute
|
|
64
|
+
of a format enumeration, supporting at least 'TEXT' and 'JSON' options. Defaults to Format.TEXT.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
- str or dict: The response content as a string if outputFormat is Format.TEXT, or as a dictionary
|
|
68
|
+
if outputFormat is Format.JSON.
|
|
69
|
+
|
|
70
|
+
Raises:
|
|
71
|
+
- Exception: If an invalid output format is specified.
|
|
72
|
+
|
|
73
|
+
Note:
|
|
74
|
+
- The function disables SSL certificate verification (`verify=False`). This may introduce security risks,
|
|
75
|
+
such as vulnerability to man-in-the-middle attacks. Use with caution in a production environment.
|
|
76
|
+
"""
|
|
77
|
+
request_uri = uri + http_endpoint
|
|
78
|
+
with requests.Session() as s:
|
|
79
|
+
retries = Retry(total=10, backoff_factor=0.1)
|
|
80
|
+
s.mount(f"{connection_scheme}://", HTTPAdapter(max_retries=retries))
|
|
81
|
+
response = s.get(request_uri, headers=headers, verify=False)
|
|
82
|
+
|
|
83
|
+
if outputFormat == Format.TEXT:
|
|
84
|
+
return response.text
|
|
85
|
+
elif outputFormat == Format.JSON:
|
|
86
|
+
return json.loads(response.text)
|
|
87
|
+
|
|
88
|
+
raise Exception("Invalid output format specified.")
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _check_matlab_status(matlab_proxy_app_fixture, status):
|
|
92
|
+
"""
|
|
93
|
+
Check the status of a MATLAB session until a specified status is reached or a timeout occurs.
|
|
94
|
+
|
|
95
|
+
This function repeatedly sends HTTP GET requests to a MATLAB proxy application to check the current
|
|
96
|
+
status of MATLAB. It continues checking until MATLAB's status matches the specified target status or
|
|
97
|
+
until a maximum timeout is reached.
|
|
98
|
+
|
|
99
|
+
Parameters:
|
|
100
|
+
- matlab_proxy_app_fixture: An object containing configuration for connecting to the MATLAB proxy application.
|
|
101
|
+
This object must have the following attributes:
|
|
102
|
+
- url (str): The base URL of the MATLAB proxy application.
|
|
103
|
+
- connection_scheme (str): The scheme used for the connection (e.g., 'http' or 'https').
|
|
104
|
+
- headers (dict): A dictionary of HTTP headers to be sent with each request.
|
|
105
|
+
- status (str): The target status to wait for MATLAB to reach.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
- str: The status of MATLAB at the end of the function execution. This could be the target status if
|
|
109
|
+
it was reached within the timeout period, or the last known status of MATLAB if the timeout was reached
|
|
110
|
+
first.
|
|
111
|
+
|
|
112
|
+
Notes:
|
|
113
|
+
- The function waits for a maximum of MAX_TIMEOUT seconds, defined elsewhere, before exiting.
|
|
114
|
+
- It checks the MATLAB status every 1 second.
|
|
115
|
+
- The MATLAB status is obtained by sending a GET request to the '/get_status' endpoint of the proxy application.
|
|
116
|
+
- The response from the proxy application is expected to be in JSON format, with MATLAB's status accessible
|
|
117
|
+
via `res["matlab"]["status"]`.
|
|
118
|
+
|
|
119
|
+
Exceptions:
|
|
120
|
+
- This function may raise exceptions related to network issues or JSON parsing errors, which are not
|
|
121
|
+
explicitly handled within the function.
|
|
122
|
+
"""
|
|
123
|
+
uri = matlab_proxy_app_fixture.url
|
|
124
|
+
connection_scheme = matlab_proxy_app_fixture.connection_scheme
|
|
125
|
+
headers = matlab_proxy_app_fixture.headers
|
|
126
|
+
|
|
127
|
+
matlab_status = None
|
|
128
|
+
|
|
129
|
+
start_time = time.time()
|
|
130
|
+
while matlab_status != status and (time.time() - start_time < MAX_TIMEOUT):
|
|
131
|
+
time.sleep(1)
|
|
132
|
+
res = _http_get_request(
|
|
133
|
+
uri,
|
|
134
|
+
connection_scheme,
|
|
135
|
+
headers,
|
|
136
|
+
http_endpoint="/get_status",
|
|
137
|
+
outputFormat=Format.JSON,
|
|
138
|
+
)
|
|
139
|
+
matlab_status = res["matlab"]["status"]
|
|
140
|
+
|
|
141
|
+
return matlab_status
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _download_test_file(matlab_proxy_app_fixture, test_file):
|
|
145
|
+
"""Returns result of hitting the /download endpoint for test_file.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
str: The contents of the test_file being downloaded through matlab-proxy.
|
|
149
|
+
"""
|
|
150
|
+
uri = matlab_proxy_app_fixture.url
|
|
151
|
+
connection_scheme = matlab_proxy_app_fixture.connection_scheme
|
|
152
|
+
headers = matlab_proxy_app_fixture.headers
|
|
153
|
+
|
|
154
|
+
res = _http_get_request(
|
|
155
|
+
uri,
|
|
156
|
+
connection_scheme,
|
|
157
|
+
headers,
|
|
158
|
+
http_endpoint="/download/" + test_file,
|
|
159
|
+
outputFormat=Format.TEXT,
|
|
160
|
+
)
|
|
161
|
+
return res
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
# Main Classes
|
|
25
165
|
class RealMATLABServer:
|
|
26
166
|
"""
|
|
27
167
|
Context Manager class which returns matlab proxy web server serving real MATLAB
|
|
@@ -103,40 +243,7 @@ class RealMATLABServer:
|
|
|
103
243
|
_logger.debug("Terminated the MATLAB process.")
|
|
104
244
|
|
|
105
245
|
|
|
106
|
-
|
|
107
|
-
"""Send HTTP request to matlab-proxy server.
|
|
108
|
-
Returns HTTP response JSON"""
|
|
109
|
-
|
|
110
|
-
request_uri = uri + http_endpoint
|
|
111
|
-
|
|
112
|
-
json_response = None
|
|
113
|
-
with requests.Session() as s:
|
|
114
|
-
retries = Retry(total=10, backoff_factor=0.1)
|
|
115
|
-
s.mount(f"{connection_scheme}://", HTTPAdapter(max_retries=retries))
|
|
116
|
-
response = s.get(request_uri, headers=headers, verify=False)
|
|
117
|
-
json_response = json.loads(response.text)
|
|
118
|
-
|
|
119
|
-
return json_response
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def _check_matlab_status(matlab_proxy_app_fixture, status):
|
|
123
|
-
uri = matlab_proxy_app_fixture.url
|
|
124
|
-
connection_scheme = matlab_proxy_app_fixture.connection_scheme
|
|
125
|
-
headers = matlab_proxy_app_fixture.headers
|
|
126
|
-
|
|
127
|
-
matlab_status = None
|
|
128
|
-
|
|
129
|
-
start_time = time.time()
|
|
130
|
-
while matlab_status != status and (time.time() - start_time < MAX_TIMEOUT):
|
|
131
|
-
time.sleep(1)
|
|
132
|
-
res = _send_http_get_request(
|
|
133
|
-
uri, connection_scheme, headers, http_endpoint="/get_status"
|
|
134
|
-
)
|
|
135
|
-
matlab_status = res["matlab"]["status"]
|
|
136
|
-
|
|
137
|
-
return matlab_status
|
|
138
|
-
|
|
139
|
-
|
|
246
|
+
# Fixtures
|
|
140
247
|
@pytest.fixture
|
|
141
248
|
def matlab_proxy_app_fixture(
|
|
142
249
|
loop,
|
|
@@ -159,6 +266,44 @@ def matlab_proxy_app_fixture(
|
|
|
159
266
|
pass
|
|
160
267
|
|
|
161
268
|
|
|
269
|
+
@pytest.fixture
|
|
270
|
+
def test_file_contents():
|
|
271
|
+
"""
|
|
272
|
+
A pytest fixture that provides a string for testing purposes.
|
|
273
|
+
|
|
274
|
+
This fixture returns a predefined string that can be used in tests to simulate
|
|
275
|
+
the contents of a file or any scenario where a constant string value is needed.
|
|
276
|
+
|
|
277
|
+
Returns:
|
|
278
|
+
str: A string containing the text "I LOVE MATLAB."
|
|
279
|
+
"""
|
|
280
|
+
return "I LOVE MATLAB."
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
@pytest.fixture
|
|
284
|
+
def test_file(tmp_path, test_file_contents):
|
|
285
|
+
"""
|
|
286
|
+
A pytest fixture that creates a temporary test file with given contents.
|
|
287
|
+
|
|
288
|
+
This fixture utilizes pytest's `tmp_path` fixture to generate a temporary directory,
|
|
289
|
+
then creates a file named "temporary_test_file.txt" within this directory,
|
|
290
|
+
and writes the provided contents to this file. It is useful for tests that require
|
|
291
|
+
reading from or writing to files without affecting the actual file system.
|
|
292
|
+
|
|
293
|
+
Parameters:
|
|
294
|
+
- tmp_path (Path): A pytest fixture that provides a temporary directory unique to the test function.
|
|
295
|
+
- test_file_contents (str): The content to be written into the temporary test file.
|
|
296
|
+
|
|
297
|
+
Returns:
|
|
298
|
+
- str: The path to the created temporary test file as a string.
|
|
299
|
+
"""
|
|
300
|
+
test_file = os.path.join(tmp_path, "temporary_test_file.txt")
|
|
301
|
+
with open(test_file, "w+") as f:
|
|
302
|
+
f.write(test_file_contents)
|
|
303
|
+
return test_file
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
# Test Functions
|
|
162
307
|
def test_matlab_is_up(matlab_proxy_app_fixture):
|
|
163
308
|
"""Test that the status switches from 'starting' to 'up' within a timeout.
|
|
164
309
|
|
|
@@ -195,13 +340,13 @@ def test_stop_matlab(matlab_proxy_app_fixture):
|
|
|
195
340
|
assert status == "down"
|
|
196
341
|
|
|
197
342
|
|
|
198
|
-
# FIXME: If output has logging or extra debug info, 600 bytes might not be enough.
|
|
199
343
|
async def test_print_message(matlab_proxy_app_fixture):
|
|
200
344
|
"""Test if the right logs are printed
|
|
201
345
|
|
|
202
346
|
Args:
|
|
203
347
|
matlab_proxy_app_fixture: A pytest fixture which yields a real matlab server to be used by tests.
|
|
204
348
|
|
|
349
|
+
FIXME: If output has logging or extra debug info, 600 bytes might not be enough.
|
|
205
350
|
"""
|
|
206
351
|
# Checks if matlab proxy is in "up" state or not
|
|
207
352
|
status = _check_matlab_status(matlab_proxy_app_fixture, "up")
|
|
@@ -221,3 +366,33 @@ async def test_print_message(matlab_proxy_app_fixture):
|
|
|
221
366
|
# Close the read and write descriptors.
|
|
222
367
|
os.close(read_descriptor)
|
|
223
368
|
os.close(write_descriptor)
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def test_download_file_from_matlab(
|
|
372
|
+
matlab_proxy_app_fixture, test_file, test_file_contents
|
|
373
|
+
):
|
|
374
|
+
"""
|
|
375
|
+
Test the downloading of a file from a MATLAB proxy application.
|
|
376
|
+
|
|
377
|
+
This test function checks if the MATLAB proxy application is up and running, and then attempts to download
|
|
378
|
+
a specific test file from it. It validates both the status of the MATLAB proxy and the contents of the downloaded file.
|
|
379
|
+
|
|
380
|
+
Parameters:
|
|
381
|
+
- matlab_proxy_app_fixture (fixture): A test fixture representing the MATLAB proxy application environment.
|
|
382
|
+
- test_file (str): The name or path of the test file to be downloaded from the MATLAB proxy application.
|
|
383
|
+
- test_file_contents (str): The expected contents of the test file to validate the download operation.
|
|
384
|
+
|
|
385
|
+
Assertions:
|
|
386
|
+
- Asserts that the MATLAB proxy application is "up".
|
|
387
|
+
- Asserts that the content of the downloaded file matches the expected `test_file_contents`.
|
|
388
|
+
|
|
389
|
+
Raises:
|
|
390
|
+
- AssertionError: If any of the assertions fail, indicating either the MATLAB proxy application is not running
|
|
391
|
+
as expected or there is a mismatch in the file content.
|
|
392
|
+
"""
|
|
393
|
+
status = _check_matlab_status(matlab_proxy_app_fixture, "up")
|
|
394
|
+
assert status == "up"
|
|
395
|
+
|
|
396
|
+
# Once MATLAB is up, we can then attempt to download
|
|
397
|
+
result = _download_test_file(matlab_proxy_app_fixture, test_file)
|
|
398
|
+
assert result == test_file_contents
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Copyright 2024 The MathWorks, Inc.
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from matlab_proxy.util.mwi.download import (
|
|
5
|
+
_get_download_payload_path,
|
|
6
|
+
get_download_url,
|
|
7
|
+
is_download_request,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# Mock the request object
|
|
12
|
+
@pytest.fixture
|
|
13
|
+
def mock_request_fixture(mocker):
|
|
14
|
+
mock_req = mocker.MagicMock()
|
|
15
|
+
mock_req.app = {
|
|
16
|
+
"settings": {"base_url": ""},
|
|
17
|
+
"state": mocker.MagicMock(),
|
|
18
|
+
}
|
|
19
|
+
mock_req.rel_url = mocker.MagicMock()
|
|
20
|
+
return mock_req
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _get_expected_output_based_on_os_type(paths: list) -> str:
|
|
24
|
+
import matlab_proxy.util.system as system
|
|
25
|
+
|
|
26
|
+
return "\\".join(paths) if system.is_windows() else "/".join(paths)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# Test for is_download_request function
|
|
30
|
+
@pytest.mark.parametrize(
|
|
31
|
+
"test_base_url, path, expected",
|
|
32
|
+
[
|
|
33
|
+
("/", "/download/something", True),
|
|
34
|
+
("", "/download/something", True),
|
|
35
|
+
("/base", "/base/download/something", True),
|
|
36
|
+
("/base", "/download/something", False),
|
|
37
|
+
],
|
|
38
|
+
ids=[
|
|
39
|
+
"/ base url and path starting with /download",
|
|
40
|
+
"empty base url and path starting with /download",
|
|
41
|
+
"non-empty base url and path starting with that base url",
|
|
42
|
+
"non-empty base url and path not starting with that base url",
|
|
43
|
+
],
|
|
44
|
+
)
|
|
45
|
+
def test_is_download_request(mock_request_fixture, test_base_url, path, expected):
|
|
46
|
+
mock_request_fixture.app["settings"]["base_url"] = test_base_url
|
|
47
|
+
mock_request_fixture.rel_url.path = path
|
|
48
|
+
assert is_download_request(mock_request_fixture) == expected
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
# Test for _get_download_payload_path function
|
|
52
|
+
# This test is a bit tricky since it involves file system operations and OS checks.
|
|
53
|
+
# We will mock system.is_windows() and test for both Windows and Posix systems.
|
|
54
|
+
@pytest.mark.parametrize(
|
|
55
|
+
"is_windows, test_base_url, path, expected",
|
|
56
|
+
[
|
|
57
|
+
(
|
|
58
|
+
True,
|
|
59
|
+
"",
|
|
60
|
+
"/downloadC:\\some\\path\\to\\file.txt",
|
|
61
|
+
"C:\\some\\path\\to\\file.txt",
|
|
62
|
+
),
|
|
63
|
+
(
|
|
64
|
+
True,
|
|
65
|
+
"/base",
|
|
66
|
+
"/base/downloadC:\\some\\path\\to\\file.txt",
|
|
67
|
+
"C:\\some\\path\\to\\file.txt",
|
|
68
|
+
),
|
|
69
|
+
(
|
|
70
|
+
False,
|
|
71
|
+
"",
|
|
72
|
+
"/download/some/path/to/file.txt",
|
|
73
|
+
_get_expected_output_based_on_os_type(["/some", "path", "to", "file.txt"]),
|
|
74
|
+
),
|
|
75
|
+
(
|
|
76
|
+
False,
|
|
77
|
+
"/base",
|
|
78
|
+
"/base/download/some/path/to/file.txt",
|
|
79
|
+
_get_expected_output_based_on_os_type(["/some", "path", "to", "file.txt"]),
|
|
80
|
+
),
|
|
81
|
+
],
|
|
82
|
+
ids=[
|
|
83
|
+
"Windows with null base url",
|
|
84
|
+
"Windows with non-null base url",
|
|
85
|
+
"Linux with null base url",
|
|
86
|
+
"Linux with non-null base url",
|
|
87
|
+
],
|
|
88
|
+
)
|
|
89
|
+
def test_get_download_payload_path(
|
|
90
|
+
mock_request_fixture, mocker, is_windows, test_base_url, path, expected
|
|
91
|
+
):
|
|
92
|
+
mocker.patch("matlab_proxy.util.system.is_windows", return_value=is_windows)
|
|
93
|
+
mock_request_fixture.app["settings"]["base_url"] = test_base_url
|
|
94
|
+
mock_request_fixture.rel_url.path = path
|
|
95
|
+
assert _get_download_payload_path(mock_request_fixture) == expected
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_get_download_payload_path_invalid_request(mock_request_fixture):
|
|
99
|
+
test_base_url = "/base"
|
|
100
|
+
path = "/download/something"
|
|
101
|
+
|
|
102
|
+
mock_request_fixture.app["settings"]["base_url"] = test_base_url
|
|
103
|
+
mock_request_fixture.rel_url.path = path
|
|
104
|
+
|
|
105
|
+
assert _get_download_payload_path(mock_request_fixture) is None
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@pytest.mark.parametrize(
|
|
109
|
+
"response_json, expected_url",
|
|
110
|
+
[
|
|
111
|
+
(
|
|
112
|
+
{
|
|
113
|
+
"messages": {
|
|
114
|
+
"FEvalResponse": [
|
|
115
|
+
{"isError": False, "results": ["http://download-url.com"]}
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"http://download-url.com",
|
|
120
|
+
),
|
|
121
|
+
({"messages": {"FEvalResponse": [{"isError": True}]}}, None),
|
|
122
|
+
],
|
|
123
|
+
ids=["connector returning correct download url", "connector returning an error"],
|
|
124
|
+
)
|
|
125
|
+
async def test_get_download_url(
|
|
126
|
+
mock_request_fixture, mocker, response_json, expected_url
|
|
127
|
+
):
|
|
128
|
+
test_base_url = "/"
|
|
129
|
+
path = "/download/some/path/to/file.txt"
|
|
130
|
+
|
|
131
|
+
mock_request_fixture.app["state"].settings = {
|
|
132
|
+
"mwi_server_url": "http://mwi-server.com"
|
|
133
|
+
}
|
|
134
|
+
mock_request_fixture.app["settings"]["base_url"] = test_base_url
|
|
135
|
+
mock_request_fixture.rel_url.path = path
|
|
136
|
+
|
|
137
|
+
mocker.patch(
|
|
138
|
+
"matlab_proxy.util.mwi.embedded_connector.helpers.get_data_to_feval_mcode",
|
|
139
|
+
return_value={},
|
|
140
|
+
)
|
|
141
|
+
mocker.patch(
|
|
142
|
+
"matlab_proxy.util.mwi.embedded_connector.helpers.get_mvm_endpoint",
|
|
143
|
+
return_value="http://mwi-server.com",
|
|
144
|
+
)
|
|
145
|
+
mocker.patch(
|
|
146
|
+
"matlab_proxy.util.mwi.embedded_connector.send_request",
|
|
147
|
+
return_value=response_json,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
download_url = await get_download_url(mock_request_fixture)
|
|
151
|
+
|
|
152
|
+
assert download_url == expected_url
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|