matlab-proxy 0.24.1__py3-none-any.whl → 0.25.0__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 +1 -3
- matlab_proxy/app_state.py +56 -21
- matlab_proxy/constants.py +2 -1
- matlab_proxy/gui/index.html +1 -1
- matlab_proxy/gui/static/js/index.qK3VCGVb.js +64 -0
- matlab_proxy/matlab/startup.m +1 -4
- matlab_proxy/settings.py +145 -91
- matlab_proxy/util/mwi/environment_variables.py +2 -27
- matlab_proxy/util/mwi/exceptions.py +14 -1
- matlab_proxy/util/mwi/validators.py +19 -11
- {matlab_proxy-0.24.1.dist-info → matlab_proxy-0.25.0.dist-info}/METADATA +32 -20
- {matlab_proxy-0.24.1.dist-info → matlab_proxy-0.25.0.dist-info}/RECORD +25 -25
- {matlab_proxy-0.24.1.dist-info → matlab_proxy-0.25.0.dist-info}/WHEEL +1 -1
- {matlab_proxy-0.24.1.dist-info → matlab_proxy-0.25.0.dist-info}/entry_points.txt +0 -1
- tests/integration/integration_tests_with_license/test_http_end_points.py +4 -5
- tests/unit/test_app.py +94 -45
- tests/unit/test_app_state.py +37 -9
- tests/unit/test_non_dev_mode.py +4 -4
- tests/unit/test_settings.py +175 -11
- tests/unit/util/mwi/test_token_auth.py +5 -5
- tests/unit/util/mwi/test_validators.py +12 -7
- tests/unit/util/test_mw.py +2 -2
- tests/unit/util/test_util.py +7 -7
- matlab_proxy/gui/static/js/index.Cm14Eqsb.js +0 -64
- {matlab_proxy-0.24.1.dist-info → matlab_proxy-0.25.0.dist-info}/LICENSE.md +0 -0
- {matlab_proxy-0.24.1.dist-info → matlab_proxy-0.25.0.dist-info}/top_level.txt +0 -0
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
matlab_proxy/__init__.py,sha256=6cwi8buKCMtw9OeWaOYUHEoqwl5MyJ_s6GxgNuqPuNg,1673
|
|
2
|
-
matlab_proxy/app.py,sha256
|
|
3
|
-
matlab_proxy/app_state.py,sha256=
|
|
4
|
-
matlab_proxy/constants.py,sha256=
|
|
2
|
+
matlab_proxy/app.py,sha256=-lqRLDnDVdz01tPTzE58mRfxxqLKSUptXsI746a6i_k,34566
|
|
3
|
+
matlab_proxy/app_state.py,sha256=jiPSjLZt4UHRElGaYMHf2o6kJXhliwER61mQZeezX0o,73407
|
|
4
|
+
matlab_proxy/constants.py,sha256=So0UJC1QGvP4-nJWhau-xOlzBEdDpdExynzzbvEhtqk,1189
|
|
5
5
|
matlab_proxy/default_configuration.py,sha256=tBHaEq_bYsX2uC9pPA9mi_8M6o94ij-rxq8mbvcYpFc,1874
|
|
6
6
|
matlab_proxy/devel.py,sha256=nR6XPVBUEdQ-RZGtYvX1YHTp8gj9cuw5Hp8ahasMBc8,14310
|
|
7
|
-
matlab_proxy/settings.py,sha256=
|
|
7
|
+
matlab_proxy/settings.py,sha256=31WrxQjqJWpvwU_4dehmkadaj8Vvn-8p8SZljFQDd8s,28540
|
|
8
8
|
matlab_proxy/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
matlab_proxy/gui/favicon.ico,sha256=7w7Ki1uQP2Rgwc64dOV4-NrTu97I3WsZw8OvRSoY1A0,130876
|
|
10
|
-
matlab_proxy/gui/index.html,sha256=
|
|
10
|
+
matlab_proxy/gui/index.html,sha256=MAmmegXIfx13SVifeeQIptqktZuWc8fxzpdljx8QsfM,720
|
|
11
11
|
matlab_proxy/gui/manifest.json,sha256=NwDbrALM5auYyj2bbEf4aGwAUDqNl1FzMFQpPiG2Ty4,286
|
|
12
12
|
matlab_proxy/gui/robots.txt,sha256=kNJLw79pisHhc3OVAimMzKcq3x9WT6sF9IS4xI0crdI,67
|
|
13
13
|
matlab_proxy/gui/static/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
14
|
matlab_proxy/gui/static/css/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
matlab_proxy/gui/static/css/index.BSVLACuY.css,sha256=LzuRvV10Z0pF0ugGSnj5zKJvT4AHwwBbCd-wSH4mHjg,305333
|
|
16
16
|
matlab_proxy/gui/static/js/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
-
matlab_proxy/gui/static/js/index.
|
|
17
|
+
matlab_proxy/gui/static/js/index.qK3VCGVb.js,sha256=v0SfcphW6I8hwDZWViAqDFWp9uHbgKBIeVN9jAP1kd0,279950
|
|
18
18
|
matlab_proxy/gui/static/media/MATLAB-env-blur.NupTbPv_.png,sha256=QpmQTLDvBu2-b7ev83Rvpt0Q72R6wdQGkuJMPPpjv7M,220290
|
|
19
19
|
matlab_proxy/gui/static/media/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
20
|
matlab_proxy/gui/static/media/glyphicons-halflings-regular.BKjkU69z.woff,sha256=omOU9-3hAMoRjv8u2ghZYnWpg5uVnCJuFUOVV6WoB0I,23424
|
|
@@ -38,7 +38,7 @@ matlab_proxy/gui/static/media/trigger-error.QEdsGL-m.svg,sha256=3zzT0uTrl4M_HlAj
|
|
|
38
38
|
matlab_proxy/gui/static/media/trigger-ok.Dzg8OIrk.svg,sha256=mD-7N9cc4ARdMBFcplnogJv6nA4Yh3jQuYbZDUi18LU,4997
|
|
39
39
|
matlab_proxy/icons/matlab.svg,sha256=xh5uYebQd8I-ISvenjU9A-PkClzW_lU9wvm3doXOFKM,13366
|
|
40
40
|
matlab_proxy/matlab/evaluateUserMatlabCode.m,sha256=R8w6nPdGtadR4UUFJaspcrGQL7cJwUItdrfc531w3bM,2420
|
|
41
|
-
matlab_proxy/matlab/startup.m,sha256=
|
|
41
|
+
matlab_proxy/matlab/startup.m,sha256=UcA4i2lAMytwBsO783uPIQoP5Pzw1R0xrUywbBBtTjw,533
|
|
42
42
|
matlab_proxy/util/__init__.py,sha256=JkVIsTOae5giDK0cQ7jcxQSHa8zo1umdq-1C0grDZwk,11712
|
|
43
43
|
matlab_proxy/util/event_loop.py,sha256=sX_0tKlirCY5ImLxkss_XO4Ksj65u6JHtwMj25oGL94,1816
|
|
44
44
|
matlab_proxy/util/list_servers.py,sha256=M93coVZjyQCdIvCCxsNOU_XDWNjBSysOJ5tWXaTjP8Y,1369
|
|
@@ -48,11 +48,11 @@ matlab_proxy/util/windows.py,sha256=_5gl2IyHIfw8-D3_G5uHkycZVGGFVXtjkd6_aP3g2Ts,
|
|
|
48
48
|
matlab_proxy/util/mwi/__init__.py,sha256=zI-X1lafr8H3j17PyA0oSZ0q5nINfK-WDA7VmJKmSAQ,158
|
|
49
49
|
matlab_proxy/util/mwi/custom_http_headers.py,sha256=kfDjSnEXEVzoF2pZuEn76LKayeD2WKoQEDu2Y9EMOAo,7154
|
|
50
50
|
matlab_proxy/util/mwi/download.py,sha256=-GJj3yOsL4vF_9baqRXkgBI-vu_OwjZMQVkJXFS8GMc,4965
|
|
51
|
-
matlab_proxy/util/mwi/environment_variables.py,sha256=
|
|
52
|
-
matlab_proxy/util/mwi/exceptions.py,sha256=
|
|
51
|
+
matlab_proxy/util/mwi/environment_variables.py,sha256=ffKEm56nt18CKYLaTihfAyqhzgYRdtNfHSu3e1Fw1yg,6568
|
|
52
|
+
matlab_proxy/util/mwi/exceptions.py,sha256=8o4PZmira_ZonnOROzu8ERIiSn9y-456JO89gqjCags,5446
|
|
53
53
|
matlab_proxy/util/mwi/logger.py,sha256=GoisSphy3Jyi5-6-X0WRl1YkdrKx2xzjSxBN_w3oTU8,3802
|
|
54
54
|
matlab_proxy/util/mwi/token_auth.py,sha256=UbIWqo7qADaZdijFvorLYsZbxzaB8TycGP8nk305ru0,9997
|
|
55
|
-
matlab_proxy/util/mwi/validators.py,sha256=
|
|
55
|
+
matlab_proxy/util/mwi/validators.py,sha256=dg2OXL686vWie_JoTNpFSje2m_UqdpvpTVHJl5tmxSo,13247
|
|
56
56
|
matlab_proxy/util/mwi/embedded_connector/__init__.py,sha256=Vfl2hNC7V1IwoK9_wrwfENs4BC8P-Mvvqh4BNGi2n48,119
|
|
57
57
|
matlab_proxy/util/mwi/embedded_connector/helpers.py,sha256=kpIgJN0AqYLeX56UylWgB0t07fg8sh0RhIlUH_8JitM,3654
|
|
58
58
|
matlab_proxy/util/mwi/embedded_connector/request.py,sha256=RXoVvrm5fibVb2A6EZnkMWwAQkYX3J5kqDTGQDZo9p0,4316
|
|
@@ -76,7 +76,7 @@ matlab_proxy_manager/web/watcher.py,sha256=89JHjBAQtOrllstaJFxqrjHwckpRmu3qfUqeq
|
|
|
76
76
|
tests/integration/__init__.py,sha256=ttzJ8xKWGxOJZz56qOiWOn6sp5LGomkZMn_w4KJLRMU,42
|
|
77
77
|
tests/integration/integration_tests_with_license/__init__.py,sha256=vVYZCur-QhmIGCxUmn-WZjIywtDQidaLDmlmrRHRlgY,37
|
|
78
78
|
tests/integration/integration_tests_with_license/conftest.py,sha256=sCaIXB8d4vf05C7JWSVA7g5gnPjbpRq3dftuBpWyp1s,1599
|
|
79
|
-
tests/integration/integration_tests_with_license/test_http_end_points.py,sha256=
|
|
79
|
+
tests/integration/integration_tests_with_license/test_http_end_points.py,sha256=SDqYARwZKNXDS8-GzRKZvttCbmjq5ETwduN61ZVgOk8,14441
|
|
80
80
|
tests/integration/integration_tests_without_license/__init__.py,sha256=vVYZCur-QhmIGCxUmn-WZjIywtDQidaLDmlmrRHRlgY,37
|
|
81
81
|
tests/integration/integration_tests_without_license/conftest.py,sha256=n-oppKWxavyy1O0J6DywO3DnOHuYc7yUZRXm3Bt4szU,3526
|
|
82
82
|
tests/integration/integration_tests_without_license/test_matlab_is_down_if_unlicensed.py,sha256=tkdyhfZBpfJpbnEzjURyV-GE0p43YxOa9xooJf-JoM4,1653
|
|
@@ -85,30 +85,30 @@ tests/integration/utils/integration_tests_utils.py,sha256=IbJ9CedFHiz3k85FBY-8Gw
|
|
|
85
85
|
tests/integration/utils/licensing.py,sha256=rEBjvMXO8R3mL6KnePu2lojmOsjD4GXl9frf9N0Wacs,4842
|
|
86
86
|
tests/unit/__init__.py,sha256=KfwQxxM5a1kMRtNbhz8tb7YfHp8e2d0tNLB55wYvDS8,37
|
|
87
87
|
tests/unit/conftest.py,sha256=FIL7bhw2-9B5OEspqt9toZ2ZlN18pOsPEFjeQmVNcSk,1916
|
|
88
|
-
tests/unit/test_app.py,sha256=
|
|
89
|
-
tests/unit/test_app_state.py,sha256=
|
|
88
|
+
tests/unit/test_app.py,sha256=VZt64uhdhsdmZL3Pb9LGtxxgt0H18mzRZRzSyiud6nQ,40028
|
|
89
|
+
tests/unit/test_app_state.py,sha256=ZhywxbZb9HCxLQjgW1QEHccaydCeGKX20YOFFjpKWYM,38047
|
|
90
90
|
tests/unit/test_constants.py,sha256=2nXxTmDP8utr8krsfZ4c_Bh4_mWPcDO5uI8MXeq4Usg,158
|
|
91
91
|
tests/unit/test_ddux.py,sha256=a2J2iM8j_nnfJVuMI38p5AjwrRdoMj3N88gFgS2I4hg,713
|
|
92
92
|
tests/unit/test_devel.py,sha256=A-1iVhSSwmywaW65QIRcUS2Fk7nJxceCcCm7CJtNdEc,7982
|
|
93
|
-
tests/unit/test_non_dev_mode.py,sha256=
|
|
94
|
-
tests/unit/test_settings.py,sha256=
|
|
93
|
+
tests/unit/test_non_dev_mode.py,sha256=Jqs5W-ax6WNM9v5SeTjpmVsojjA95itPC8Lqhs2U3Oc,5533
|
|
94
|
+
tests/unit/test_settings.py,sha256=CZDopczxa7zMC1LIpRckwnG4v2Ag4RBLqPE1TaypNYM,23271
|
|
95
95
|
tests/unit/util/__init__.py,sha256=GInSQBb2SoVD5LZfmSCQa9-UZJT_UP-jNfrojkgCybU,87
|
|
96
|
-
tests/unit/util/test_mw.py,sha256=
|
|
97
|
-
tests/unit/util/test_util.py,sha256=
|
|
96
|
+
tests/unit/util/test_mw.py,sha256=hweBw3ijcdh_2QdECjAWNkmh_7P5Df728cgD51DFkT8,18571
|
|
97
|
+
tests/unit/util/test_util.py,sha256=n-xSkwdqXfq550jWYsmjhGjx6L98URhWeLJLKhGekOw,7476
|
|
98
98
|
tests/unit/util/mwi/__init__.py,sha256=pl5jqyCHEwZEviiL8OC-SHulb1rBecstQCFF6qVjL9Y,37
|
|
99
99
|
tests/unit/util/mwi/test_custom_http_headers.py,sha256=UfrhclS0j6WhShtg1ki2oF1kK8JqRC29uevH4tuDqF4,11182
|
|
100
100
|
tests/unit/util/mwi/test_download.py,sha256=jYwPJFYGrPKqnkIJW42XYSe1fowmzChAkOx0k0xVldo,4779
|
|
101
101
|
tests/unit/util/mwi/test_logger.py,sha256=S0Q5TirFxysrH2YSxRzGY9mWoWB83hG3q3XpGENCpcw,3150
|
|
102
|
-
tests/unit/util/mwi/test_token_auth.py,sha256
|
|
103
|
-
tests/unit/util/mwi/test_validators.py,sha256=
|
|
102
|
+
tests/unit/util/mwi/test_token_auth.py,sha256=0gp41Y7zZFqeFDCA0V3Arv_CqnQKo5RZqijIccvezYM,10562
|
|
103
|
+
tests/unit/util/mwi/test_validators.py,sha256=GvLP3lSvoOQAjoclYunKPfxPIagUsnVGHRskHELResE,11765
|
|
104
104
|
tests/unit/util/mwi/embedded_connector/__init__.py,sha256=pl5jqyCHEwZEviiL8OC-SHulb1rBecstQCFF6qVjL9Y,37
|
|
105
105
|
tests/unit/util/mwi/embedded_connector/test_helpers.py,sha256=vYTWNUTuDeaygo16JGMTvWeI_CLOnvPkwNJmLndvJhE,890
|
|
106
106
|
tests/unit/util/mwi/embedded_connector/test_request.py,sha256=PR-jddnXDEiip-lD7A_QSvRwEkwo3eQ8owZlk-r9vnk,1867
|
|
107
107
|
tests/utils/__init__.py,sha256=ttzJ8xKWGxOJZz56qOiWOn6sp5LGomkZMn_w4KJLRMU,42
|
|
108
108
|
tests/utils/logging_util.py,sha256=VBy_NRvwau3C_CVTBjK5RMROrQimnJYHO2U0aKSZiRw,2234
|
|
109
|
-
matlab_proxy-0.
|
|
110
|
-
matlab_proxy-0.
|
|
111
|
-
matlab_proxy-0.
|
|
112
|
-
matlab_proxy-0.
|
|
113
|
-
matlab_proxy-0.
|
|
114
|
-
matlab_proxy-0.
|
|
109
|
+
matlab_proxy-0.25.0.dist-info/LICENSE.md,sha256=oF0h3UdSF-rlUiMGYwi086ZHqelzz7yOOk9HFDv9ELo,2344
|
|
110
|
+
matlab_proxy-0.25.0.dist-info/METADATA,sha256=8vT3BKQB6VLmlygF55mESkydtp0j3BkvJprloc0MGWM,10505
|
|
111
|
+
matlab_proxy-0.25.0.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
|
|
112
|
+
matlab_proxy-0.25.0.dist-info/entry_points.txt,sha256=3wztwXpt6wdGfTwscc4qHbCeWzi0E2XhyJbMDndyQKc,304
|
|
113
|
+
matlab_proxy-0.25.0.dist-info/top_level.txt,sha256=KF-347aoRGsfHTpiSqfIPUZ95bzK5-oMIu8S_TUcu-w,40
|
|
114
|
+
matlab_proxy-0.25.0.dist-info/RECORD,,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2023-
|
|
1
|
+
# Copyright 2023-2025 The MathWorks, Inc.
|
|
2
2
|
|
|
3
3
|
"""
|
|
4
4
|
Contains integration tests which exercise HTTP endpoints of interest exposed by matlab-proxy-app
|
|
@@ -246,24 +246,23 @@ class RealMATLABServer:
|
|
|
246
246
|
# Fixtures
|
|
247
247
|
@pytest.fixture
|
|
248
248
|
def matlab_proxy_app_fixture(
|
|
249
|
-
|
|
249
|
+
event_loop,
|
|
250
250
|
):
|
|
251
251
|
"""A pytest fixture which yields a real matlab server to be used by tests.
|
|
252
252
|
|
|
253
253
|
Args:
|
|
254
|
-
|
|
254
|
+
event_loop (Event loop): The built-in event loop provided by pytest.
|
|
255
255
|
|
|
256
256
|
Yields:
|
|
257
257
|
real_matlab_server : A real matlab web server used by tests.
|
|
258
258
|
"""
|
|
259
259
|
|
|
260
260
|
try:
|
|
261
|
-
with RealMATLABServer(
|
|
261
|
+
with RealMATLABServer(event_loop) as matlab_proxy_app:
|
|
262
262
|
yield matlab_proxy_app
|
|
263
263
|
except ProcessLookupError as e:
|
|
264
264
|
_logger.debug("ProcessLookupError found in matlab proxy app fixture")
|
|
265
265
|
_logger.debug(e)
|
|
266
|
-
pass
|
|
267
266
|
|
|
268
267
|
|
|
269
268
|
@pytest.fixture
|
tests/unit/test_app.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2020-
|
|
1
|
+
# Copyright 2020-2025 The MathWorks, Inc.
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import datetime
|
|
@@ -9,13 +9,18 @@ import time
|
|
|
9
9
|
from datetime import timedelta, timezone
|
|
10
10
|
from http import HTTPStatus
|
|
11
11
|
|
|
12
|
-
import aiohttp
|
|
13
12
|
import pytest
|
|
14
|
-
|
|
13
|
+
from aiohttp import WSMsgType
|
|
14
|
+
from aiohttp.web import WebSocketResponse
|
|
15
|
+
from multidict import CIMultiDict
|
|
15
16
|
|
|
17
|
+
import tests.unit.test_constants as test_constants
|
|
16
18
|
from matlab_proxy import app, util
|
|
19
|
+
from matlab_proxy.app import matlab_view
|
|
17
20
|
from matlab_proxy.util.mwi import environment_variables as mwi_env
|
|
18
21
|
from matlab_proxy.util.mwi.exceptions import EntitlementError, MatlabInstallError
|
|
22
|
+
from tests.unit.fixtures.fixture_auth import patch_authenticate_access_decorator
|
|
23
|
+
from tests.unit.mocks.mock_client import MockWebSocketClient
|
|
19
24
|
|
|
20
25
|
|
|
21
26
|
@pytest.mark.parametrize(
|
|
@@ -61,7 +66,7 @@ def test_configure_no_proxy_in_env(monkeypatch, no_proxy_user_configuration):
|
|
|
61
66
|
)
|
|
62
67
|
|
|
63
68
|
|
|
64
|
-
def test_create_app(
|
|
69
|
+
def test_create_app(event_loop):
|
|
65
70
|
"""Test if aiohttp server is being created successfully.
|
|
66
71
|
|
|
67
72
|
Checks if the aiohttp server is created successfully, routes, startup and cleanup
|
|
@@ -75,7 +80,7 @@ def test_create_app(loop):
|
|
|
75
80
|
# Verify app server has a cleanup task
|
|
76
81
|
# By default there is 1 for clean up task
|
|
77
82
|
assert len(test_server.on_cleanup) > 1
|
|
78
|
-
|
|
83
|
+
event_loop.run_until_complete(test_server["state"].stop_server_tasks())
|
|
79
84
|
|
|
80
85
|
|
|
81
86
|
def get_email():
|
|
@@ -245,9 +250,33 @@ class FakeServer:
|
|
|
245
250
|
self.loop.run_until_complete(self.server.cleanup())
|
|
246
251
|
|
|
247
252
|
|
|
253
|
+
@pytest.fixture
|
|
254
|
+
def mock_request(mocker):
|
|
255
|
+
"""Creates a mock request with required attributes"""
|
|
256
|
+
req = mocker.MagicMock()
|
|
257
|
+
req.app = {
|
|
258
|
+
"state": mocker.MagicMock(matlab_port=8000),
|
|
259
|
+
"settings": {"matlab_protocol": "http", "mwapikey": "test-key"},
|
|
260
|
+
}
|
|
261
|
+
req.headers = CIMultiDict()
|
|
262
|
+
req.cookies = {}
|
|
263
|
+
return req
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
@pytest.fixture(name="mock_websocket_messages")
|
|
267
|
+
def mock_messages(mocker):
|
|
268
|
+
# Mock WebSocket messages
|
|
269
|
+
return [
|
|
270
|
+
mocker.MagicMock(type=WSMsgType.TEXT, data="test message"),
|
|
271
|
+
mocker.MagicMock(type=WSMsgType.BINARY, data=b"test binary"),
|
|
272
|
+
mocker.MagicMock(type=WSMsgType.PING),
|
|
273
|
+
mocker.MagicMock(type=WSMsgType.PONG),
|
|
274
|
+
]
|
|
275
|
+
|
|
276
|
+
|
|
248
277
|
@pytest.fixture(name="test_server")
|
|
249
278
|
def test_server_fixture(
|
|
250
|
-
|
|
279
|
+
event_loop,
|
|
251
280
|
aiohttp_client,
|
|
252
281
|
monkeypatch,
|
|
253
282
|
):
|
|
@@ -263,7 +292,7 @@ def test_server_fixture(
|
|
|
263
292
|
# Disabling the authentication token mechanism explicitly
|
|
264
293
|
monkeypatch.setenv(mwi_env.get_env_name_enable_mwi_auth_token(), "False")
|
|
265
294
|
try:
|
|
266
|
-
with FakeServer(
|
|
295
|
+
with FakeServer(event_loop, aiohttp_client) as test_server:
|
|
267
296
|
yield test_server
|
|
268
297
|
except ProcessLookupError:
|
|
269
298
|
pass
|
|
@@ -306,8 +335,6 @@ async def test_get_env_config(test_server):
|
|
|
306
335
|
test_server (aiohttp_client): A aiohttp_client server for sending GET request.
|
|
307
336
|
"""
|
|
308
337
|
expected_json_structure = {
|
|
309
|
-
"useMOS": False,
|
|
310
|
-
"useMRE": False,
|
|
311
338
|
"authentication": {"enabled": False, "status": False},
|
|
312
339
|
"matlab": {
|
|
313
340
|
"status": "up",
|
|
@@ -350,7 +377,7 @@ async def test_start_matlab_route(test_server):
|
|
|
350
377
|
await __check_for_matlab_status(test_server, "starting")
|
|
351
378
|
|
|
352
379
|
|
|
353
|
-
async def __check_for_matlab_status(test_server, status):
|
|
380
|
+
async def __check_for_matlab_status(test_server, status, sleep_interval=0.5):
|
|
354
381
|
"""Helper function to check if the status of MATLAB returned by the server is either of the values mentioned in statuses
|
|
355
382
|
|
|
356
383
|
Args:
|
|
@@ -369,7 +396,7 @@ async def __check_for_matlab_status(test_server, status):
|
|
|
369
396
|
break
|
|
370
397
|
else:
|
|
371
398
|
count += 1
|
|
372
|
-
await asyncio.sleep(
|
|
399
|
+
await asyncio.sleep(sleep_interval)
|
|
373
400
|
if count > test_constants.FIVE_MAX_TRIES:
|
|
374
401
|
raise ConnectionError
|
|
375
402
|
|
|
@@ -592,19 +619,6 @@ async def test_matlab_proxy_http_post_request(proxy_payload, test_server):
|
|
|
592
619
|
raise ConnectionError
|
|
593
620
|
|
|
594
621
|
|
|
595
|
-
# While acceessing matlab-proxy directly, the web socket request looks like
|
|
596
|
-
# {
|
|
597
|
-
# "connection": "Upgrade",
|
|
598
|
-
# "Upgrade": "websocket",
|
|
599
|
-
# }
|
|
600
|
-
# whereas while accessing matlab-proxy with nginx as the reverse proxy, the nginx server
|
|
601
|
-
# modifies the web socket request to
|
|
602
|
-
# {
|
|
603
|
-
# "connection": "upgrade",
|
|
604
|
-
# "upgrade": "websocket",
|
|
605
|
-
# }
|
|
606
|
-
|
|
607
|
-
|
|
608
622
|
async def test_set_licensing_info_put_nlm(test_server):
|
|
609
623
|
"""Test to check endpoint : "/set_licensing_info"
|
|
610
624
|
|
|
@@ -641,35 +655,70 @@ async def test_set_licensing_info_put_invalid_license(test_server):
|
|
|
641
655
|
assert resp.status == HTTPStatus.BAD_REQUEST
|
|
642
656
|
|
|
643
657
|
|
|
658
|
+
# While acceessing matlab-proxy directly, the web socket request looks like
|
|
659
|
+
# {
|
|
660
|
+
# "connection": "Upgrade",
|
|
661
|
+
# "Upgrade": "websocket",
|
|
662
|
+
# }
|
|
663
|
+
# whereas while accessing matlab-proxy with nginx as the reverse proxy, the nginx server
|
|
664
|
+
# modifies the web socket request to
|
|
665
|
+
# {
|
|
666
|
+
# "connection": "upgrade",
|
|
667
|
+
# "upgrade": "websocket",
|
|
668
|
+
# }
|
|
644
669
|
@pytest.mark.parametrize(
|
|
645
670
|
"headers",
|
|
646
671
|
[
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
672
|
+
CIMultiDict(
|
|
673
|
+
{
|
|
674
|
+
"connection": "Upgrade",
|
|
675
|
+
"Upgrade": "websocket",
|
|
676
|
+
}
|
|
677
|
+
),
|
|
678
|
+
CIMultiDict(
|
|
679
|
+
{
|
|
680
|
+
"connection": "upgrade",
|
|
681
|
+
"upgrade": "websocket",
|
|
682
|
+
}
|
|
683
|
+
),
|
|
655
684
|
],
|
|
656
685
|
ids=["Uppercase header", "Lowercase header"],
|
|
657
686
|
)
|
|
658
|
-
async def
|
|
659
|
-
|
|
687
|
+
async def test_matlab_view_websocket_success(
|
|
688
|
+
mocker,
|
|
689
|
+
mock_request,
|
|
690
|
+
mock_websocket_messages,
|
|
691
|
+
headers,
|
|
692
|
+
patch_authenticate_access_decorator,
|
|
693
|
+
):
|
|
694
|
+
"""Test successful websocket connection and message forwarding"""
|
|
660
695
|
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
""
|
|
696
|
+
# Configure request for WebSocket
|
|
697
|
+
mock_request.headers = headers
|
|
698
|
+
mock_request.method = "GET"
|
|
699
|
+
mock_request.path_qs = "/test"
|
|
664
700
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
701
|
+
# Mock WebSocket setup
|
|
702
|
+
mock_ws_server = mocker.MagicMock(spec=WebSocketResponse)
|
|
703
|
+
mocker.patch(
|
|
704
|
+
"matlab_proxy.app.aiohttp.web.WebSocketResponse", return_value=mock_ws_server
|
|
705
|
+
)
|
|
706
|
+
|
|
707
|
+
# Mock WebSocket client
|
|
708
|
+
mock_ws_client = MockWebSocketClient(messages=mock_websocket_messages)
|
|
709
|
+
mocker.patch(
|
|
710
|
+
"matlab_proxy.app.aiohttp.ClientSession.ws_connect", return_value=mock_ws_client
|
|
670
711
|
)
|
|
671
|
-
|
|
672
|
-
|
|
712
|
+
|
|
713
|
+
# Execute
|
|
714
|
+
result = await matlab_view(mock_request)
|
|
715
|
+
|
|
716
|
+
# Assertions
|
|
717
|
+
assert result == mock_ws_server
|
|
718
|
+
assert mock_ws_server.send_str.call_count == 1
|
|
719
|
+
assert mock_ws_server.send_bytes.call_count == 1
|
|
720
|
+
assert mock_ws_server.ping.call_count == 1
|
|
721
|
+
assert mock_ws_server.pong.call_count == 1
|
|
673
722
|
|
|
674
723
|
|
|
675
724
|
async def test_set_licensing_info_put_mhlm(test_server):
|
|
@@ -992,7 +1041,7 @@ async def test_set_licensing_mhlm_single_entitlement(
|
|
|
992
1041
|
assert resp_json["licensing"]["entitlementId"] == "Entitlement3"
|
|
993
1042
|
|
|
994
1043
|
# validate that MATLAB has started correctly
|
|
995
|
-
await __check_for_matlab_status(test_server, "up")
|
|
1044
|
+
await __check_for_matlab_status(test_server, "up", sleep_interval=2)
|
|
996
1045
|
|
|
997
1046
|
# test-cleanup: unset licensing
|
|
998
1047
|
# without this, we can leave test drool related to cached license file
|
tests/unit/test_app_state.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2023-
|
|
1
|
+
# Copyright 2023-2025 The MathWorks, Inc.
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import json
|
|
@@ -13,7 +13,11 @@ from matlab_proxy import settings
|
|
|
13
13
|
from matlab_proxy import settings
|
|
14
14
|
from matlab_proxy.app_state import AppState
|
|
15
15
|
from matlab_proxy.constants import MWI_AUTH_TOKEN_NAME_FOR_HTTP
|
|
16
|
-
from matlab_proxy.util.mwi.exceptions import
|
|
16
|
+
from matlab_proxy.util.mwi.exceptions import (
|
|
17
|
+
LicensingError,
|
|
18
|
+
MatlabError,
|
|
19
|
+
MatlabInstallError,
|
|
20
|
+
)
|
|
17
21
|
from matlab_proxy.constants import (
|
|
18
22
|
CONNECTOR_SECUREPORT_FILENAME,
|
|
19
23
|
USER_CODE_OUTPUT_FILE_NAME,
|
|
@@ -39,6 +43,7 @@ def sample_settings_fixture(tmp_path):
|
|
|
39
43
|
"warnings": [],
|
|
40
44
|
"matlab_config_file": tmp_file,
|
|
41
45
|
"is_xvfb_available": True,
|
|
46
|
+
"is_windowmanager_available": True,
|
|
42
47
|
"mwi_server_url": "dummy",
|
|
43
48
|
"mwi_logs_root_dir": Path(settings.get_mwi_config_folder(dev=True)),
|
|
44
49
|
"app_port": 12345,
|
|
@@ -51,12 +56,12 @@ def sample_settings_fixture(tmp_path):
|
|
|
51
56
|
|
|
52
57
|
|
|
53
58
|
@pytest.fixture
|
|
54
|
-
def app_state_fixture(sample_settings_fixture,
|
|
59
|
+
def app_state_fixture(sample_settings_fixture, event_loop):
|
|
55
60
|
"""A pytest fixture which returns an instance of AppState class with no errors.
|
|
56
61
|
|
|
57
62
|
Args:
|
|
58
63
|
sample_settings_fixture (dict): A dictionary of sample settings to be used by
|
|
59
|
-
|
|
64
|
+
event_loop : A pytest builtin fixture
|
|
60
65
|
|
|
61
66
|
Returns:
|
|
62
67
|
AppState: An object of the AppState class
|
|
@@ -67,7 +72,7 @@ def app_state_fixture(sample_settings_fixture, loop):
|
|
|
67
72
|
|
|
68
73
|
yield app_state
|
|
69
74
|
|
|
70
|
-
|
|
75
|
+
event_loop.run_until_complete(app_state.stop_server_tasks())
|
|
71
76
|
|
|
72
77
|
|
|
73
78
|
@pytest.fixture
|
|
@@ -104,13 +109,13 @@ def app_state_with_token_auth_fixture(
|
|
|
104
109
|
|
|
105
110
|
|
|
106
111
|
@pytest.fixture
|
|
107
|
-
def mocker_os_patching_fixture(mocker, platform,
|
|
112
|
+
def mocker_os_patching_fixture(mocker, platform, event_loop):
|
|
108
113
|
"""A pytest fixture which patches the is_* functions in system.py module
|
|
109
114
|
|
|
110
115
|
Args:
|
|
111
116
|
mocker : Built in pytest fixture
|
|
112
117
|
platform (str): A string representing "windows", "linux" or "mac"
|
|
113
|
-
|
|
118
|
+
event_loop : A pytest builtin fixture
|
|
114
119
|
|
|
115
120
|
Returns:
|
|
116
121
|
mocker: Built in pytest fixture with patched calls to system.py module.
|
|
@@ -119,7 +124,7 @@ def mocker_os_patching_fixture(mocker, platform, loop):
|
|
|
119
124
|
mocker.patch("matlab_proxy.app_state.system.is_windows", return_value=False)
|
|
120
125
|
mocker.patch("matlab_proxy.app_state.system.is_mac", return_value=False)
|
|
121
126
|
mocker.patch("matlab_proxy.app_state.system.is_posix", return_value=False)
|
|
122
|
-
mocker.patch("matlab_proxy.app_state.util.get_event_loop", return_value=
|
|
127
|
+
mocker.patch("matlab_proxy.app_state.util.get_event_loop", return_value=event_loop)
|
|
123
128
|
|
|
124
129
|
if platform == "linux":
|
|
125
130
|
mocker.patch("matlab_proxy.app_state.system.is_linux", return_value=True)
|
|
@@ -611,6 +616,29 @@ async def test_start_matlab_without_xvfb(app_state_fixture, mocker):
|
|
|
611
616
|
assert app_state_fixture.processes["matlab"] is mock_matlab
|
|
612
617
|
|
|
613
618
|
|
|
619
|
+
async def test_start_matlab_without_xvfb_and_matlab(app_state_fixture):
|
|
620
|
+
"""Test to check if MATLAB doesn't start and sets the error variable to MatlabInstallError when
|
|
621
|
+
there is not MATLAB on system PATH
|
|
622
|
+
|
|
623
|
+
Args:
|
|
624
|
+
app_state_fixture (AppState): Object of AppState class with defaults set
|
|
625
|
+
"""
|
|
626
|
+
# Arrange
|
|
627
|
+
app_state_fixture.settings["is_xvfb_available"] = False
|
|
628
|
+
app_state_fixture.settings["matlab_cmd"] = None
|
|
629
|
+
|
|
630
|
+
# Act
|
|
631
|
+
await app_state_fixture.start_matlab()
|
|
632
|
+
|
|
633
|
+
# Assert
|
|
634
|
+
# Check if Xvfb has not started
|
|
635
|
+
assert app_state_fixture.processes["xvfb"] is None
|
|
636
|
+
# Check if Matlab has not started
|
|
637
|
+
assert app_state_fixture.processes["matlab"] is None
|
|
638
|
+
# Check if MatlabInstallError is set as the error
|
|
639
|
+
assert isinstance(app_state_fixture.error, MatlabInstallError)
|
|
640
|
+
|
|
641
|
+
|
|
614
642
|
@pytest.mark.parametrize(
|
|
615
643
|
"is_desktop, client_id, is_client_id_present, expected_is_active_client",
|
|
616
644
|
[
|
|
@@ -793,7 +821,7 @@ async def test_decrement_timer_runs_out(sample_settings_fixture, mocker):
|
|
|
793
821
|
app_state.processes = {"matlab": None, "xvfb": None}
|
|
794
822
|
app_state.licensing = {"type": "existing_license"}
|
|
795
823
|
|
|
796
|
-
# mock util.get_event_loop() to return a new
|
|
824
|
+
# mock util.get_event_loop() to return a new event_loop for the test to assert
|
|
797
825
|
mock_loop = asyncio.new_event_loop()
|
|
798
826
|
mocker.patch("matlab_proxy.app_state.util.get_event_loop", return_value=mock_loop)
|
|
799
827
|
|
tests/unit/test_non_dev_mode.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright 2020-
|
|
1
|
+
# Copyright 2020-2025 The MathWorks, Inc.
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
import shutil
|
|
@@ -126,7 +126,7 @@ def mock_settings_get_fixture(mocker):
|
|
|
126
126
|
|
|
127
127
|
@pytest.fixture(name="test_server")
|
|
128
128
|
def test_server_fixture(
|
|
129
|
-
|
|
129
|
+
event_loop,
|
|
130
130
|
aiohttp_client,
|
|
131
131
|
build_frontend,
|
|
132
132
|
matlab_port_setup,
|
|
@@ -140,7 +140,7 @@ def test_server_fixture(
|
|
|
140
140
|
This fixture 'initializes' the test server with different constraints from the test server in test_app.py
|
|
141
141
|
|
|
142
142
|
Args:
|
|
143
|
-
|
|
143
|
+
event_loop : Event loop
|
|
144
144
|
aiohttp_client : A built-in pytest fixture
|
|
145
145
|
build_frontend: Pytest fixture which generates the directory structure of static files with some placeholder content
|
|
146
146
|
matlab_port_setup: Pytest fixture which monkeypatches 'MWI_DEV' env to False. This is required for the test_server to add static content
|
|
@@ -150,7 +150,7 @@ def test_server_fixture(
|
|
|
150
150
|
[aiohttp_client]: A aiohttp_client to send HTTP requests.
|
|
151
151
|
"""
|
|
152
152
|
|
|
153
|
-
with FakeServer(
|
|
153
|
+
with FakeServer(event_loop, aiohttp_client) as test_server:
|
|
154
154
|
yield test_server
|
|
155
155
|
|
|
156
156
|
|