matlab-proxy 0.26.0__py3-none-any.whl → 0.27.1__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 +50 -39
- matlab_proxy/app_state.py +9 -3
- matlab_proxy/default_configuration.py +2 -2
- matlab_proxy/gui/index.html +2 -2
- matlab_proxy/gui/static/css/{index.BSVLACuY.css → index.BLxKpbak.css} +2 -2
- matlab_proxy/gui/static/js/{index.CZgGkMCD.js → index.CKi3IRxe.js} +16 -16
- matlab_proxy/settings.py +5 -5
- matlab_proxy/util/__init__.py +2 -2
- matlab_proxy/util/list_servers.py +2 -2
- matlab_proxy/util/mwi/environment_variables.py +5 -0
- matlab_proxy/util/mwi/logger.py +1 -2
- matlab_proxy/util/mwi/session_name.py +28 -0
- matlab_proxy/util/mwi/token_auth.py +2 -2
- matlab_proxy/util/mwi/validators.py +3 -5
- {matlab_proxy-0.26.0.dist-info → matlab_proxy-0.27.1.dist-info}/METADATA +37 -25
- {matlab_proxy-0.26.0.dist-info → matlab_proxy-0.27.1.dist-info}/RECORD +23 -53
- {matlab_proxy-0.26.0.dist-info → matlab_proxy-0.27.1.dist-info}/WHEEL +1 -2
- matlab_proxy_manager/README.md +85 -0
- matlab_proxy_manager/lib/README.md +53 -0
- matlab_proxy_manager/storage/README.md +54 -0
- matlab_proxy_manager/web/README.md +37 -0
- matlab_proxy-0.26.0.dist-info/top_level.txt +0 -3
- tests/integration/__init__.py +0 -1
- tests/integration/integration_tests_with_license/__init__.py +0 -1
- tests/integration/integration_tests_with_license/conftest.py +0 -47
- tests/integration/integration_tests_with_license/test_http_end_points.py +0 -397
- tests/integration/integration_tests_without_license/__init__.py +0 -1
- tests/integration/integration_tests_without_license/conftest.py +0 -116
- tests/integration/integration_tests_without_license/test_matlab_is_down_if_unlicensed.py +0 -49
- tests/integration/utils/__init__.py +0 -1
- tests/integration/utils/integration_tests_utils.py +0 -352
- tests/integration/utils/licensing.py +0 -152
- tests/unit/__init__.py +0 -1
- tests/unit/conftest.py +0 -66
- tests/unit/test_app.py +0 -1299
- tests/unit/test_app_state.py +0 -1094
- tests/unit/test_constants.py +0 -7
- tests/unit/test_ddux.py +0 -22
- tests/unit/test_devel.py +0 -246
- tests/unit/test_non_dev_mode.py +0 -169
- tests/unit/test_settings.py +0 -679
- tests/unit/util/__init__.py +0 -3
- tests/unit/util/mwi/__init__.py +0 -1
- tests/unit/util/mwi/embedded_connector/__init__.py +0 -1
- tests/unit/util/mwi/embedded_connector/test_helpers.py +0 -29
- tests/unit/util/mwi/embedded_connector/test_request.py +0 -64
- tests/unit/util/mwi/test_custom_http_headers.py +0 -281
- tests/unit/util/mwi/test_download.py +0 -152
- tests/unit/util/mwi/test_logger.py +0 -82
- tests/unit/util/mwi/test_token_auth.py +0 -303
- tests/unit/util/mwi/test_validators.py +0 -364
- tests/unit/util/test_cookie_jar.py +0 -252
- tests/unit/util/test_mw.py +0 -550
- tests/unit/util/test_util.py +0 -221
- tests/utils/__init__.py +0 -1
- tests/utils/logging_util.py +0 -81
- {matlab_proxy-0.26.0.dist-info → matlab_proxy-0.27.1.dist-info}/entry_points.txt +0 -0
- {matlab_proxy-0.26.0.dist-info → matlab_proxy-0.27.1.dist-info/licenses}/LICENSE.md +0 -0
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
# Copyright 2023-2025 The MathWorks, Inc.
|
|
2
|
-
|
|
3
|
-
import pytest
|
|
4
|
-
from aiohttp import web
|
|
5
|
-
from aiohttp_session import setup as aiohttp_session_setup
|
|
6
|
-
from aiohttp_session.cookie_storage import EncryptedCookieStorage
|
|
7
|
-
from cryptography import fernet
|
|
8
|
-
|
|
9
|
-
from matlab_proxy.constants import MWI_AUTH_TOKEN_NAME_FOR_HTTP
|
|
10
|
-
from matlab_proxy.util.mwi import environment_variables as mwi_env
|
|
11
|
-
from matlab_proxy.util.mwi import token_auth
|
|
12
|
-
|
|
13
|
-
## APIs to test:
|
|
14
|
-
# 1. generate_mwi_auth_token (auth enabled, auth enabled+custom token, custom token, auth disabled)
|
|
15
|
-
# 2. authenticate_access_decorator (headers & url_string, and session storage)
|
|
16
|
-
|
|
17
|
-
## Testing generate_mwi_auth_token :
|
|
18
|
-
|
|
19
|
-
test_data = [
|
|
20
|
-
pytest.param(
|
|
21
|
-
"False",
|
|
22
|
-
"CustomTokenStr123_-Test1",
|
|
23
|
-
None,
|
|
24
|
-
id="token isn't generated when MWI_ENABLE_AUTH_TOKEN is explicitly disabled & has custom token set",
|
|
25
|
-
),
|
|
26
|
-
pytest.param(
|
|
27
|
-
"",
|
|
28
|
-
"CustomTokenStr123_-Test2",
|
|
29
|
-
"CustomTokenStr123_-Test2",
|
|
30
|
-
id="token is generated when MWI_ENABLE_AUTH_TOKEN is not set & has custom token set",
|
|
31
|
-
),
|
|
32
|
-
pytest.param(
|
|
33
|
-
"True",
|
|
34
|
-
"CustomTokenStr123_-Test3",
|
|
35
|
-
"CustomTokenStr123_-Test3",
|
|
36
|
-
id="token is generated when MWI_ENABLE_AUTH_TOKEN is set & has custom token set",
|
|
37
|
-
),
|
|
38
|
-
]
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
@pytest.mark.parametrize(
|
|
42
|
-
"expected_auth_enablement, auth_token, expected_auth_token",
|
|
43
|
-
test_data,
|
|
44
|
-
)
|
|
45
|
-
def test_generate_mwi_auth_token(
|
|
46
|
-
monkeypatch, expected_auth_enablement, auth_token, expected_auth_token
|
|
47
|
-
):
|
|
48
|
-
monkeypatch.setenv(
|
|
49
|
-
mwi_env.get_env_name_enable_mwi_auth_token(), str(expected_auth_enablement)
|
|
50
|
-
)
|
|
51
|
-
monkeypatch.setenv(mwi_env.get_env_name_mwi_auth_token(), str(auth_token))
|
|
52
|
-
|
|
53
|
-
generated_token = token_auth.generate_mwi_auth_token_and_hash()["token"]
|
|
54
|
-
assert generated_token == expected_auth_token
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def test_auto_token_generation_with_enable_flag_set(monkeypatch):
|
|
58
|
-
# Test if token is auto-generated when MWI_ENABLE_AUTH_TOKEN is True
|
|
59
|
-
expected_auth_enablement = "True"
|
|
60
|
-
monkeypatch.setenv(
|
|
61
|
-
mwi_env.get_env_name_enable_mwi_auth_token(), str(expected_auth_enablement)
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
generated_token = token_auth.generate_mwi_auth_token_and_hash()["token"]
|
|
65
|
-
assert generated_token is not None
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
def test_auto_token_generation_with_enable_flag_unset():
|
|
69
|
-
# Test if token is generated by default when MWI_ENABLE_AUTH_TOKEN and MWI_AUTH_TOKEN are not set
|
|
70
|
-
generated_token = token_auth.generate_mwi_auth_token_and_hash()["token"]
|
|
71
|
-
assert generated_token is not None
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
## Testing authenticate_access_decorator :
|
|
75
|
-
# This in turn, also tests authenticate_request
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
@pytest.fixture
|
|
79
|
-
def get_custom_auth_token_str():
|
|
80
|
-
return "CustomTokenStr123_-TestOtherAPIS"
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
@token_auth.authenticate_access_decorator
|
|
84
|
-
async def fake_endpoint(request):
|
|
85
|
-
if request.method == "POST":
|
|
86
|
-
request.app["value"] = (await request.post())["value"]
|
|
87
|
-
return web.Response(body=b"thanks for the data")
|
|
88
|
-
return web.Response(body="value: {}".format(request.app["value"]).encode("utf-8"))
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
@pytest.fixture
|
|
92
|
-
def fake_server_with_auth_enabled(
|
|
93
|
-
event_loop, aiohttp_client, monkeypatch, get_custom_auth_token_str
|
|
94
|
-
):
|
|
95
|
-
auth_token = get_custom_auth_token_str
|
|
96
|
-
auth_enablement = "True"
|
|
97
|
-
monkeypatch.setenv(
|
|
98
|
-
mwi_env.get_env_name_enable_mwi_auth_token(), str(auth_enablement)
|
|
99
|
-
)
|
|
100
|
-
monkeypatch.setenv(mwi_env.get_env_name_mwi_auth_token(), str(auth_token))
|
|
101
|
-
|
|
102
|
-
(
|
|
103
|
-
mwi_auth_token,
|
|
104
|
-
mwi_auth_token_hash,
|
|
105
|
-
) = token_auth.generate_mwi_auth_token_and_hash().values()
|
|
106
|
-
|
|
107
|
-
app = web.Application()
|
|
108
|
-
app["settings"] = {
|
|
109
|
-
"mwi_is_token_auth_enabled": mwi_auth_token is not None,
|
|
110
|
-
"mwi_auth_token": mwi_auth_token,
|
|
111
|
-
"mwi_auth_token_hash": mwi_auth_token_hash,
|
|
112
|
-
"mwi_auth_token_name_for_http": MWI_AUTH_TOKEN_NAME_FOR_HTTP,
|
|
113
|
-
"mwi_auth_token_name_for_env": mwi_env.get_env_name_mwi_auth_token().lower(),
|
|
114
|
-
}
|
|
115
|
-
app.router.add_get("/", fake_endpoint)
|
|
116
|
-
app.router.add_post("/", fake_endpoint)
|
|
117
|
-
# Setup the session storage
|
|
118
|
-
fernet_key = fernet.Fernet.generate_key()
|
|
119
|
-
f = fernet.Fernet(fernet_key)
|
|
120
|
-
aiohttp_session_setup(
|
|
121
|
-
app, EncryptedCookieStorage(f, cookie_name="matlab-proxy-session")
|
|
122
|
-
)
|
|
123
|
-
return event_loop.run_until_complete(aiohttp_client(app))
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
async def test_set_value_with_token(
|
|
127
|
-
fake_server_with_auth_enabled, get_custom_auth_token_str
|
|
128
|
-
):
|
|
129
|
-
resp = await fake_server_with_auth_enabled.post(
|
|
130
|
-
"/",
|
|
131
|
-
data={"value": "foo"},
|
|
132
|
-
headers={MWI_AUTH_TOKEN_NAME_FOR_HTTP: get_custom_auth_token_str},
|
|
133
|
-
)
|
|
134
|
-
assert resp.status == web.HTTPOk.status_code
|
|
135
|
-
assert await resp.text() == "thanks for the data"
|
|
136
|
-
assert fake_server_with_auth_enabled.server.app["value"] == "foo"
|
|
137
|
-
|
|
138
|
-
# Test subsequent requests do not need token authentication
|
|
139
|
-
resp2 = await fake_server_with_auth_enabled.post(
|
|
140
|
-
"/",
|
|
141
|
-
data={"value": "foobar"},
|
|
142
|
-
)
|
|
143
|
-
assert resp2.status == web.HTTPOk.status_code
|
|
144
|
-
assert fake_server_with_auth_enabled.server.app["value"] == "foobar"
|
|
145
|
-
|
|
146
|
-
# Test request which accepts cookies from previous request
|
|
147
|
-
resp3 = await fake_server_with_auth_enabled.post(
|
|
148
|
-
"/",
|
|
149
|
-
data={"value": "foobar1"},
|
|
150
|
-
cookies=resp.cookies,
|
|
151
|
-
)
|
|
152
|
-
assert resp3.status == web.HTTPOk.status_code
|
|
153
|
-
assert fake_server_with_auth_enabled.server.app["value"] == "foobar1"
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
async def test_set_value_with_token_hash(
|
|
157
|
-
fake_server_with_auth_enabled, get_custom_auth_token_str
|
|
158
|
-
):
|
|
159
|
-
resp = await fake_server_with_auth_enabled.post(
|
|
160
|
-
"/",
|
|
161
|
-
data={"value": "foo"},
|
|
162
|
-
headers={
|
|
163
|
-
MWI_AUTH_TOKEN_NAME_FOR_HTTP: token_auth._generate_hash(
|
|
164
|
-
get_custom_auth_token_str
|
|
165
|
-
)
|
|
166
|
-
},
|
|
167
|
-
)
|
|
168
|
-
assert resp.status == web.HTTPOk.status_code
|
|
169
|
-
assert await resp.text() == "thanks for the data"
|
|
170
|
-
assert fake_server_with_auth_enabled.server.app["value"] == "foo"
|
|
171
|
-
|
|
172
|
-
# Test subsequent requests do not need token authentication
|
|
173
|
-
resp2 = await fake_server_with_auth_enabled.post(
|
|
174
|
-
"/",
|
|
175
|
-
data={"value": "foobar"},
|
|
176
|
-
)
|
|
177
|
-
assert resp2.status == web.HTTPOk.status_code
|
|
178
|
-
assert fake_server_with_auth_enabled.server.app["value"] == "foobar"
|
|
179
|
-
|
|
180
|
-
# Test request which accepts cookies from previous request
|
|
181
|
-
resp3 = await fake_server_with_auth_enabled.post(
|
|
182
|
-
"/",
|
|
183
|
-
data={"value": "foobar1"},
|
|
184
|
-
cookies=resp.cookies,
|
|
185
|
-
)
|
|
186
|
-
assert resp3.status == web.HTTPOk.status_code
|
|
187
|
-
assert fake_server_with_auth_enabled.server.app["value"] == "foobar1"
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
async def test_set_value_without_token(fake_server_with_auth_enabled):
|
|
191
|
-
resp2 = await fake_server_with_auth_enabled.post(
|
|
192
|
-
"/",
|
|
193
|
-
data={"value": "foobar"},
|
|
194
|
-
)
|
|
195
|
-
assert resp2.status == web.HTTPForbidden.status_code
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
async def test_set_value_with_invalid_token(fake_server_with_auth_enabled):
|
|
199
|
-
resp2 = await fake_server_with_auth_enabled.post(
|
|
200
|
-
"/",
|
|
201
|
-
data={"value": "foobar"},
|
|
202
|
-
headers={MWI_AUTH_TOKEN_NAME_FOR_HTTP: "invalid-token"},
|
|
203
|
-
)
|
|
204
|
-
assert resp2.status == web.HTTPForbidden.status_code
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
async def test_set_value_with_token_in_params(
|
|
208
|
-
fake_server_with_auth_enabled, get_custom_auth_token_str
|
|
209
|
-
):
|
|
210
|
-
fake_server_with_auth_enabled.server.app["value"] = "foo"
|
|
211
|
-
resp = await fake_server_with_auth_enabled.post(
|
|
212
|
-
"/",
|
|
213
|
-
data={"value": "foofoo"},
|
|
214
|
-
params={
|
|
215
|
-
MWI_AUTH_TOKEN_NAME_FOR_HTTP: token_auth._generate_hash(
|
|
216
|
-
get_custom_auth_token_str
|
|
217
|
-
)
|
|
218
|
-
},
|
|
219
|
-
)
|
|
220
|
-
assert resp.status == web.HTTPOk.status_code
|
|
221
|
-
assert await resp.text() == "thanks for the data"
|
|
222
|
-
assert fake_server_with_auth_enabled.server.app["value"] == "foofoo"
|
|
223
|
-
|
|
224
|
-
# Test subsequent requests do not need token authentication
|
|
225
|
-
resp2 = await fake_server_with_auth_enabled.post(
|
|
226
|
-
"/",
|
|
227
|
-
data={"value": "foobar"},
|
|
228
|
-
)
|
|
229
|
-
assert resp2.status == web.HTTPForbidden.status_code
|
|
230
|
-
# assert server_with_auth_enabled.server.app["value"] == "foobar"
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
async def test_get_value_without_token(fake_server_with_auth_enabled):
|
|
234
|
-
fake_server_with_auth_enabled.server.app["value"] = "bar"
|
|
235
|
-
resp = await fake_server_with_auth_enabled.get("/")
|
|
236
|
-
assert resp.status == web.HTTPForbidden.status_code
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
async def test_get_value_with_token_in_query_params(
|
|
240
|
-
fake_server_with_auth_enabled, get_custom_auth_token_str
|
|
241
|
-
):
|
|
242
|
-
fake_server_with_auth_enabled.server.app["value"] = "bar"
|
|
243
|
-
resp = await fake_server_with_auth_enabled.get(
|
|
244
|
-
"/",
|
|
245
|
-
params={
|
|
246
|
-
MWI_AUTH_TOKEN_NAME_FOR_HTTP: token_auth._generate_hash(
|
|
247
|
-
get_custom_auth_token_str
|
|
248
|
-
)
|
|
249
|
-
},
|
|
250
|
-
)
|
|
251
|
-
assert resp.status == web.HTTPOk.status_code
|
|
252
|
-
assert await resp.text() == "value: bar"
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
## Create a fake_server without authentication enabled, and test that you can access data.
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
@pytest.fixture
|
|
259
|
-
def fake_server_without_auth_enabled(event_loop, aiohttp_client, monkeypatch):
|
|
260
|
-
auth_enablement = "False"
|
|
261
|
-
monkeypatch.setenv(
|
|
262
|
-
mwi_env.get_env_name_enable_mwi_auth_token(), str(auth_enablement)
|
|
263
|
-
)
|
|
264
|
-
(
|
|
265
|
-
mwi_auth_token,
|
|
266
|
-
mwi_auth_token_hash,
|
|
267
|
-
) = token_auth.generate_mwi_auth_token_and_hash().values()
|
|
268
|
-
|
|
269
|
-
app = web.Application()
|
|
270
|
-
app["settings"] = {
|
|
271
|
-
"mwi_is_token_auth_enabled": mwi_auth_token != None,
|
|
272
|
-
"mwi_auth_token": mwi_auth_token,
|
|
273
|
-
"mwi_auth_token_hash": mwi_auth_token_hash,
|
|
274
|
-
"mwi_auth_token_name_for_env": mwi_env.get_env_name_mwi_auth_token().lower(),
|
|
275
|
-
}
|
|
276
|
-
app.router.add_get("/", fake_endpoint)
|
|
277
|
-
app.router.add_post("/", fake_endpoint)
|
|
278
|
-
# Setup the session storage
|
|
279
|
-
fernet_key = fernet.Fernet.generate_key()
|
|
280
|
-
f = fernet.Fernet(fernet_key)
|
|
281
|
-
aiohttp_session_setup(
|
|
282
|
-
app, EncryptedCookieStorage(f, cookie_name="matlab-proxy-session")
|
|
283
|
-
)
|
|
284
|
-
return event_loop.run_until_complete(aiohttp_client(app))
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
async def test_get_value(fake_server_without_auth_enabled):
|
|
288
|
-
fake_server_without_auth_enabled.server.app["value"] = "bar1"
|
|
289
|
-
resp = await fake_server_without_auth_enabled.get("/")
|
|
290
|
-
assert resp.status == web.HTTPOk.status_code
|
|
291
|
-
assert await resp.text() == "value: bar1"
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
async def test_get_value_in_query_params(
|
|
295
|
-
fake_server_without_auth_enabled, get_custom_auth_token_str
|
|
296
|
-
):
|
|
297
|
-
# Server should respond even if token is provided when not needed.
|
|
298
|
-
fake_server_without_auth_enabled.server.app["value"] = "bar2"
|
|
299
|
-
resp = await fake_server_without_auth_enabled.get(
|
|
300
|
-
"/", params={"mwi-auth-token": get_custom_auth_token_str}
|
|
301
|
-
)
|
|
302
|
-
assert resp.status == web.HTTPOk.status_code
|
|
303
|
-
assert await resp.text() == "value: bar2"
|
|
@@ -1,364 +0,0 @@
|
|
|
1
|
-
# Copyright 2020-2025 The MathWorks, Inc.
|
|
2
|
-
|
|
3
|
-
"""Tests for functions in matlab_proxy/util/mwi_validators.py"""
|
|
4
|
-
|
|
5
|
-
import os
|
|
6
|
-
import random
|
|
7
|
-
import socket
|
|
8
|
-
import tempfile
|
|
9
|
-
from matlab_proxy.util.mwi.validators import (
|
|
10
|
-
validate_idle_timeout,
|
|
11
|
-
validate_matlab_root_path,
|
|
12
|
-
)
|
|
13
|
-
from matlab_proxy import constants
|
|
14
|
-
from pathlib import Path
|
|
15
|
-
|
|
16
|
-
import matlab_proxy
|
|
17
|
-
import pytest
|
|
18
|
-
from matlab_proxy.util import system
|
|
19
|
-
from matlab_proxy.util.mwi import environment_variables as mwi_env
|
|
20
|
-
from matlab_proxy.util.mwi import validators
|
|
21
|
-
from matlab_proxy.util.mwi.exceptions import (
|
|
22
|
-
NetworkLicensingError,
|
|
23
|
-
FatalError,
|
|
24
|
-
MatlabInstallError,
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
@pytest.mark.parametrize(
|
|
29
|
-
"MLM_LICENSE_FILE",
|
|
30
|
-
[
|
|
31
|
-
("/path/to/a/non-existent/file"),
|
|
32
|
-
("1234"),
|
|
33
|
-
("hostname"),
|
|
34
|
-
("1234hostname"),
|
|
35
|
-
],
|
|
36
|
-
ids=[
|
|
37
|
-
"Invalid path to a license file",
|
|
38
|
-
"NLM string with just port number",
|
|
39
|
-
"NLM string with just hostname",
|
|
40
|
-
"NLM string with just port number and hostname",
|
|
41
|
-
],
|
|
42
|
-
)
|
|
43
|
-
def test_validate_mlm_license_file_invalid_value(MLM_LICENSE_FILE, monkeypatch):
|
|
44
|
-
"""Check if validator raises expected exception"""
|
|
45
|
-
|
|
46
|
-
env_name = mwi_env.get_env_name_network_license_manager()
|
|
47
|
-
|
|
48
|
-
monkeypatch.setenv(env_name, MLM_LICENSE_FILE)
|
|
49
|
-
nlm_conn_str = os.getenv(env_name)
|
|
50
|
-
|
|
51
|
-
with pytest.raises(NetworkLicensingError) as e_info:
|
|
52
|
-
validators.validate_mlm_license_file(nlm_conn_str)
|
|
53
|
-
assert MLM_LICENSE_FILE in str(e_info.value)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
@pytest.fixture(name="temporary_license_file")
|
|
57
|
-
def temporary_license_file_fixture(tmp_path):
|
|
58
|
-
"""Pytest fixture which returns a valid path to temporary license file."""
|
|
59
|
-
import time
|
|
60
|
-
|
|
61
|
-
temp_license_file_path = tmp_path / f'{str(time.time()).replace(".", "")}.lic'
|
|
62
|
-
temp_license_file_path.touch()
|
|
63
|
-
|
|
64
|
-
return temp_license_file_path
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def test_validate_mlm_license_file_valid_license_file_path(
|
|
68
|
-
temporary_license_file, monkeypatch
|
|
69
|
-
):
|
|
70
|
-
"""Check if a valid license path has been supplied to MLM_LICENSE_FILE env var"""
|
|
71
|
-
env_name = mwi_env.get_env_name_network_license_manager()
|
|
72
|
-
monkeypatch.setenv(env_name, str(temporary_license_file))
|
|
73
|
-
|
|
74
|
-
validated_file_path = validators.validate_mlm_license_file(os.getenv(env_name))
|
|
75
|
-
assert str(temporary_license_file) == validated_file_path
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
@pytest.mark.parametrize(
|
|
79
|
-
"MLM_LICENSE_FILE",
|
|
80
|
-
[
|
|
81
|
-
(["1234@1.2_any-alphanumeric"]),
|
|
82
|
-
(["1234@1.2_any-alphanumeric", "1234@1.2_any-alphanumeric"]),
|
|
83
|
-
(
|
|
84
|
-
[
|
|
85
|
-
"1234@1.2_any-alphanumeric",
|
|
86
|
-
"1234@1.2_any-alphanumeric",
|
|
87
|
-
"1234@1.2_any-alphanumeric",
|
|
88
|
-
]
|
|
89
|
-
),
|
|
90
|
-
[
|
|
91
|
-
"1234@1.2_any-alphanumeric,1234@1.2_any-alphanumeric,1234@1.2_any-alphanumeric"
|
|
92
|
-
],
|
|
93
|
-
(
|
|
94
|
-
[
|
|
95
|
-
"1234@1.2_any-alphanumeric",
|
|
96
|
-
"1234@1.2_any-alphanumeric,1234@1.2_any-alphanumeric,1234@1.2_any-alphanumeric",
|
|
97
|
-
]
|
|
98
|
-
),
|
|
99
|
-
(
|
|
100
|
-
[
|
|
101
|
-
"1234@1.2_any-alphanumeric,1234@1.2_any-alphanumeric,1234@1.2_any-alphanumeric",
|
|
102
|
-
"1234@1.2_any-alphanumeric",
|
|
103
|
-
]
|
|
104
|
-
),
|
|
105
|
-
(
|
|
106
|
-
[
|
|
107
|
-
"1234@1.2_any-alphanumeric",
|
|
108
|
-
"1234@1.2_any-alphanumeric,1234@1.2_any-alphanumeric,1234@1.2_any-alphanumeric",
|
|
109
|
-
"1234@1.2_any-alphanumeric",
|
|
110
|
-
]
|
|
111
|
-
),
|
|
112
|
-
],
|
|
113
|
-
ids=[
|
|
114
|
-
"1 NLM server",
|
|
115
|
-
"2 NLM servers",
|
|
116
|
-
"3 NLM servers",
|
|
117
|
-
"Just a server triad",
|
|
118
|
-
"1 NLM server prefixed to a server triad",
|
|
119
|
-
"1 NLM server suffixed to a server triad",
|
|
120
|
-
"1 NLM server prefixed and another suffixed to a server triad",
|
|
121
|
-
],
|
|
122
|
-
)
|
|
123
|
-
def test_validate_mlm_license_file_for_valid_nlm_string(MLM_LICENSE_FILE, monkeypatch):
|
|
124
|
-
"""Check if port@hostname passes validation"""
|
|
125
|
-
|
|
126
|
-
seperator = system.get_mlm_license_file_seperator()
|
|
127
|
-
MLM_LICENSE_FILE = seperator.join(MLM_LICENSE_FILE)
|
|
128
|
-
env_name = mwi_env.get_env_name_network_license_manager()
|
|
129
|
-
monkeypatch.setenv(env_name, MLM_LICENSE_FILE)
|
|
130
|
-
conn_str = validators.validate_mlm_license_file(os.getenv(env_name))
|
|
131
|
-
assert conn_str == MLM_LICENSE_FILE
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def test_validate_mlm_license_file_None():
|
|
135
|
-
"""Test to check if validate_mlm_license_file() returns None when nlm_conn_str is None."""
|
|
136
|
-
assert validators.validate_mlm_license_file(None) is None
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
def test_get_with_environment_variables(monkeypatch):
|
|
140
|
-
"""Check if path to license file passes validation"""
|
|
141
|
-
env_name = mwi_env.get_env_name_network_license_manager()
|
|
142
|
-
fd, path = tempfile.mkstemp()
|
|
143
|
-
monkeypatch.setenv(env_name, path)
|
|
144
|
-
try:
|
|
145
|
-
conn_str = validators.validate_mlm_license_file(os.getenv(env_name))
|
|
146
|
-
assert conn_str == str(path)
|
|
147
|
-
finally:
|
|
148
|
-
os.close(fd)
|
|
149
|
-
os.remove(path)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
def test_validate_app_port_is_free_false():
|
|
153
|
-
"""Test to validate if supplied app port is free"""
|
|
154
|
-
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
155
|
-
s.bind(("", 0))
|
|
156
|
-
port = s.getsockname()[1]
|
|
157
|
-
with pytest.raises(FatalError) as e:
|
|
158
|
-
validators.validate_app_port_is_free(port)
|
|
159
|
-
s.close()
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
def test_validate_app_port_is_free_true():
|
|
163
|
-
"""Test to validate if supplied app port is free"""
|
|
164
|
-
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
165
|
-
s.bind(("", 0))
|
|
166
|
-
port = s.getsockname()[1]
|
|
167
|
-
s.close()
|
|
168
|
-
assert validators.validate_app_port_is_free(port) == port
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
def test_validate_app_port_None():
|
|
172
|
-
"""Tests if validated app port is None when MWI_APP_PORT env variable is not set.
|
|
173
|
-
If validated app port is None implies a random free port will be used at launch.
|
|
174
|
-
"""
|
|
175
|
-
assert validators.validate_app_port_is_free(None) is None
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
def test_validate_env_config_true():
|
|
179
|
-
"""Validate the default config which is used in this package."""
|
|
180
|
-
config = validators.validate_env_config(matlab_proxy.get_default_config_name())
|
|
181
|
-
assert isinstance(config, dict)
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
def test_validate_env_config_false():
|
|
185
|
-
"""Passing a non existent config should raise FatalError exception"""
|
|
186
|
-
|
|
187
|
-
with pytest.raises(FatalError):
|
|
188
|
-
validators.validate_env_config(str(random.randint(10, 100)))
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
def test_get_configs():
|
|
192
|
-
"""Test to check if atleast 1 env config is discovered.
|
|
193
|
-
When this package is installed, we will have a default config.
|
|
194
|
-
"""
|
|
195
|
-
configs = validators.__get_configs()
|
|
196
|
-
|
|
197
|
-
assert len(configs.keys()) >= 1
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
@pytest.mark.parametrize(
|
|
201
|
-
"mwi_base_url, validated_base_url",
|
|
202
|
-
[
|
|
203
|
-
("", ""),
|
|
204
|
-
("/bla", "/bla"),
|
|
205
|
-
("/bla/", "/bla"),
|
|
206
|
-
],
|
|
207
|
-
ids=[
|
|
208
|
-
"Launch integration at root",
|
|
209
|
-
"Launch at custom path",
|
|
210
|
-
"Launch at custom with suffix: /",
|
|
211
|
-
],
|
|
212
|
-
)
|
|
213
|
-
def test_validate_base_url(mwi_base_url, validated_base_url):
|
|
214
|
-
"""Tests multiple base_urls which will beparsed and validated successfully.
|
|
215
|
-
|
|
216
|
-
Args:
|
|
217
|
-
base_url (str): base_url
|
|
218
|
-
validated_base_url (str): validated base_url
|
|
219
|
-
"""
|
|
220
|
-
assert validators.validate_base_url(mwi_base_url) == validated_base_url
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
def test_validate_base_url_no_prefix_error():
|
|
224
|
-
"""Test to check base_url will throw error when a prefix / is not present in it.[summary]"""
|
|
225
|
-
with pytest.raises(FatalError) as e:
|
|
226
|
-
validators.validate_base_url("matlab/")
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
def test_validate_mwi_ssl_key_and_cert_file(monkeypatch):
|
|
230
|
-
"""Check if port@hostname passes validation"""
|
|
231
|
-
ssl_cert_file_env_name = mwi_env.get_env_name_ssl_cert_file()
|
|
232
|
-
ssl_key_file_env_name = mwi_env.get_env_name_ssl_key_file()
|
|
233
|
-
fd, path = tempfile.mkstemp()
|
|
234
|
-
|
|
235
|
-
monkeypatch.setenv(ssl_cert_file_env_name, path)
|
|
236
|
-
monkeypatch.setenv(ssl_key_file_env_name, path)
|
|
237
|
-
try:
|
|
238
|
-
# Verify that if KEY and CERT are provided
|
|
239
|
-
key_file, cert_file = validators.validate_ssl_key_and_cert_file(
|
|
240
|
-
os.getenv(ssl_key_file_env_name), os.getenv(ssl_cert_file_env_name)
|
|
241
|
-
)
|
|
242
|
-
assert key_file == str(path)
|
|
243
|
-
assert cert_file == str(path)
|
|
244
|
-
|
|
245
|
-
# Verify that KEY can be None
|
|
246
|
-
key_file, cert_file = validators.validate_ssl_key_and_cert_file(
|
|
247
|
-
None, os.getenv(ssl_cert_file_env_name)
|
|
248
|
-
)
|
|
249
|
-
assert key_file == None
|
|
250
|
-
assert cert_file == str(path)
|
|
251
|
-
|
|
252
|
-
# Verify that if KEY is provided, CERT must also be provided
|
|
253
|
-
with pytest.raises(FatalError) as e:
|
|
254
|
-
validators.validate_ssl_key_and_cert_file(
|
|
255
|
-
os.getenv(ssl_key_file_env_name), None
|
|
256
|
-
)
|
|
257
|
-
|
|
258
|
-
# Verify that KEY is valid file location
|
|
259
|
-
with pytest.raises(FatalError) as e:
|
|
260
|
-
validators.validate_ssl_key_and_cert_file(
|
|
261
|
-
"/file/does/not/exist", os.getenv(ssl_cert_file_env_name)
|
|
262
|
-
)
|
|
263
|
-
|
|
264
|
-
# Verify that KEY is valid file location
|
|
265
|
-
with pytest.raises(FatalError) as e:
|
|
266
|
-
validators.validate_ssl_key_and_cert_file(
|
|
267
|
-
os.getenv(ssl_key_file_env_name), "/file/does/not/exist"
|
|
268
|
-
)
|
|
269
|
-
finally:
|
|
270
|
-
# Need to close the file descriptor in Windows
|
|
271
|
-
# Or else PermissionError is raised.
|
|
272
|
-
os.close(fd)
|
|
273
|
-
os.remove(path)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
def test_validate_matlab_root_path(tmp_path):
|
|
277
|
-
"""Checks if matlab root is validated without raising exceptions"""
|
|
278
|
-
|
|
279
|
-
# Arrange
|
|
280
|
-
matlab_root = Path(tmp_path) / "MATLAB"
|
|
281
|
-
os.mkdir(matlab_root)
|
|
282
|
-
version_info_file = Path(matlab_root) / constants.VERSION_INFO_FILE_NAME
|
|
283
|
-
version_info_file.touch()
|
|
284
|
-
|
|
285
|
-
# Act
|
|
286
|
-
actual_matlab_root = validate_matlab_root_path(
|
|
287
|
-
matlab_root, is_custom_matlab_root=False
|
|
288
|
-
)
|
|
289
|
-
actual_matlab_root_custom = validate_matlab_root_path(
|
|
290
|
-
matlab_root, is_custom_matlab_root=True
|
|
291
|
-
)
|
|
292
|
-
|
|
293
|
-
# Assert
|
|
294
|
-
assert actual_matlab_root == matlab_root
|
|
295
|
-
assert actual_matlab_root_custom == matlab_root
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
def test_validate_matlab_root_path_non_existent_root_path(tmp_path):
|
|
299
|
-
"""Checks if validate_matlab_root_path raises MatlabInstallError when non-existent path is supplied"""
|
|
300
|
-
# Arrange
|
|
301
|
-
matlab_root = Path(tmp_path) / "MATLAB"
|
|
302
|
-
|
|
303
|
-
# Act
|
|
304
|
-
with pytest.raises(MatlabInstallError):
|
|
305
|
-
actual_matlab_root = validate_matlab_root_path(
|
|
306
|
-
matlab_root, is_custom_matlab_root=False
|
|
307
|
-
)
|
|
308
|
-
actual_matlab_root_custom = validate_matlab_root_path(
|
|
309
|
-
matlab_root, is_custom_matlab_root=True
|
|
310
|
-
)
|
|
311
|
-
|
|
312
|
-
# Assert
|
|
313
|
-
assert actual_matlab_root is None
|
|
314
|
-
assert actual_matlab_root_custom is None
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
def test_validate_matlab_root_path_non_existent_versioninfo_file(tmp_path):
|
|
318
|
-
"""Checks if validate_matlab_root_path does not raise any exceptions even if VersionInfo.xml file does not exist
|
|
319
|
-
when matlab wrapper is used and raises an exception when custom matlab root is used.
|
|
320
|
-
"""
|
|
321
|
-
# Arrange
|
|
322
|
-
matlab_root = Path(tmp_path) / "MATLAB"
|
|
323
|
-
os.mkdir(matlab_root)
|
|
324
|
-
|
|
325
|
-
# Act
|
|
326
|
-
# Location of VersionInfo.xml can't be determined with matlab wrapper script
|
|
327
|
-
# and error should not be raised
|
|
328
|
-
actual_matlab_root = validate_matlab_root_path(
|
|
329
|
-
matlab_root, is_custom_matlab_root=False
|
|
330
|
-
)
|
|
331
|
-
|
|
332
|
-
# Location of VersionInfo.xml must be determinable when custom MATLAB root is supplied.
|
|
333
|
-
# If not, an exception must be raised
|
|
334
|
-
with pytest.raises(MatlabInstallError):
|
|
335
|
-
validate_matlab_root_path(matlab_root, is_custom_matlab_root=True)
|
|
336
|
-
|
|
337
|
-
# Assert
|
|
338
|
-
assert actual_matlab_root is None
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
@pytest.mark.parametrize(
|
|
342
|
-
"timeout, validated_timeout",
|
|
343
|
-
[
|
|
344
|
-
(None, None),
|
|
345
|
-
("abc", None),
|
|
346
|
-
(-10, None),
|
|
347
|
-
(123, 60 * 123),
|
|
348
|
-
],
|
|
349
|
-
ids=[
|
|
350
|
-
"No IDLE timeout specified",
|
|
351
|
-
"Invalid IDLE timeout specified",
|
|
352
|
-
"Negative number supplied as IDLE timeout",
|
|
353
|
-
"Valid IDLE timeout specified",
|
|
354
|
-
],
|
|
355
|
-
)
|
|
356
|
-
def test_validate_idle_timeout(timeout, validated_timeout):
|
|
357
|
-
# Arrange
|
|
358
|
-
# Nothing to arrange
|
|
359
|
-
|
|
360
|
-
# Act
|
|
361
|
-
actual_timeout = validate_idle_timeout(timeout)
|
|
362
|
-
|
|
363
|
-
# Assert
|
|
364
|
-
assert actual_timeout == validated_timeout
|