matlab-proxy 0.25.1__py3-none-any.whl → 0.27.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 +68 -16
- matlab_proxy/app_state.py +8 -2
- matlab_proxy/constants.py +1 -0
- matlab_proxy/default_configuration.py +2 -2
- matlab_proxy/gui/index.html +1 -1
- matlab_proxy/gui/static/js/{index.CZgGkMCD.js → index.BcDShXfH.js} +16 -16
- matlab_proxy/settings.py +24 -2
- matlab_proxy/util/cookie_jar.py +72 -0
- matlab_proxy/util/list_servers.py +2 -2
- matlab_proxy/util/mwi/environment_variables.py +15 -0
- matlab_proxy/util/mwi/session_name.py +28 -0
- matlab_proxy/util/mwi/validators.py +2 -4
- {matlab_proxy-0.25.1.dist-info → matlab_proxy-0.27.0.dist-info}/METADATA +37 -23
- {matlab_proxy-0.25.1.dist-info → matlab_proxy-0.27.0.dist-info}/RECORD +29 -56
- {matlab_proxy-0.25.1.dist-info → matlab_proxy-0.27.0.dist-info}/WHEEL +1 -2
- matlab_proxy_manager/README.md +85 -0
- matlab_proxy_manager/lib/README.md +53 -0
- matlab_proxy_manager/lib/api.py +156 -114
- matlab_proxy_manager/storage/README.md +54 -0
- matlab_proxy_manager/storage/server.py +5 -2
- matlab_proxy_manager/utils/constants.py +2 -1
- matlab_proxy_manager/utils/environment_variables.py +6 -1
- matlab_proxy_manager/utils/exceptions.py +45 -0
- matlab_proxy_manager/utils/helpers.py +2 -2
- matlab_proxy_manager/utils/logger.py +4 -1
- matlab_proxy_manager/web/README.md +37 -0
- matlab_proxy_manager/web/app.py +71 -19
- matlab_proxy-0.25.1.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 -1200
- 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 -659
- 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_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.25.1.dist-info → matlab_proxy-0.27.0.dist-info}/entry_points.txt +0 -0
- {matlab_proxy-0.25.1.dist-info → matlab_proxy-0.27.0.dist-info/licenses}/LICENSE.md +0 -0
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
# Copyright 2023-2024 The MathWorks, Inc.
|
|
2
|
-
|
|
3
|
-
import pytest
|
|
4
|
-
from tests.integration.utils import integration_tests_utils as utils
|
|
5
|
-
import requests
|
|
6
|
-
from tests.utils.logging_util import create_integ_test_logger
|
|
7
|
-
import os
|
|
8
|
-
from urllib.parse import urlparse, parse_qs
|
|
9
|
-
from matlab_proxy.constants import MWI_AUTH_TOKEN_NAME_FOR_HTTP
|
|
10
|
-
|
|
11
|
-
_logger = create_integ_test_logger(__name__)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@pytest.fixture(scope="module", name="module_monkeypatch")
|
|
15
|
-
def monkeypatch_module_scope_fixture():
|
|
16
|
-
"""
|
|
17
|
-
Pytest fixture for creating a monkeypatch object in 'module' scope.
|
|
18
|
-
The default monkeypatch fixture returns monkeypatch object in
|
|
19
|
-
'function' scope but a 'module' scope object is needed with matlab-proxy
|
|
20
|
-
'module' scope fixture.
|
|
21
|
-
|
|
22
|
-
Yields:
|
|
23
|
-
class object: Object of class MonkeyPatch
|
|
24
|
-
"""
|
|
25
|
-
with pytest.MonkeyPatch.context() as mp:
|
|
26
|
-
yield mp
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@pytest.fixture
|
|
30
|
-
def parse_matlab_proxy_url():
|
|
31
|
-
# Get the base URL from a utility function or environment variable
|
|
32
|
-
mwi_app_port = os.environ["MWI_APP_PORT"]
|
|
33
|
-
|
|
34
|
-
# Construct the parameters dictionary
|
|
35
|
-
parsed_url = urlparse(utils.get_connection_string(mwi_app_port))
|
|
36
|
-
|
|
37
|
-
headers = {
|
|
38
|
-
MWI_AUTH_TOKEN_NAME_FOR_HTTP: (
|
|
39
|
-
parse_qs(parsed_url.query)[MWI_AUTH_TOKEN_NAME_FOR_HTTP][0]
|
|
40
|
-
if MWI_AUTH_TOKEN_NAME_FOR_HTTP in parse_qs(parsed_url.query)
|
|
41
|
-
else ""
|
|
42
|
-
)
|
|
43
|
-
}
|
|
44
|
-
connection_scheme = parsed_url.scheme
|
|
45
|
-
|
|
46
|
-
# Return the base URL and parameters as a tuple
|
|
47
|
-
return parsed_url, headers, connection_scheme
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
@pytest.fixture(scope="module", autouse=True)
|
|
51
|
-
def start_matlab_proxy_fixture(module_monkeypatch):
|
|
52
|
-
"""Starts the matlab proxy process"""
|
|
53
|
-
utils.perform_basic_checks()
|
|
54
|
-
|
|
55
|
-
# Start matlab-proxy-app for testing
|
|
56
|
-
|
|
57
|
-
mwi_app_port = utils.get_random_free_port()
|
|
58
|
-
mwi_base_url = "/matlab-test"
|
|
59
|
-
|
|
60
|
-
input_env = {
|
|
61
|
-
"MWI_APP_PORT": mwi_app_port,
|
|
62
|
-
"MWI_BASE_URL": mwi_base_url,
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
import shutil
|
|
66
|
-
import matlab_proxy
|
|
67
|
-
|
|
68
|
-
matlab_config_file = str(
|
|
69
|
-
utils.get_matlab_config_file()
|
|
70
|
-
) # ~/.matlab/MWI/hosts/hostname/proxy_app_config.json
|
|
71
|
-
|
|
72
|
-
_logger.info(f"matlab_config_file {matlab_config_file}")
|
|
73
|
-
|
|
74
|
-
dotmatlab_dir_path = os.path.dirname(os.path.dirname(matlab_config_file))
|
|
75
|
-
|
|
76
|
-
# Create a temporary location in .matlab directory
|
|
77
|
-
temp_dir_path = os.path.join(dotmatlab_dir_path, "temp_dir")
|
|
78
|
-
os.mkdir(temp_dir_path) # delete this folder after the test execution
|
|
79
|
-
shutil.move(matlab_config_file, temp_dir_path)
|
|
80
|
-
|
|
81
|
-
loop = matlab_proxy.util.get_event_loop()
|
|
82
|
-
|
|
83
|
-
# Run matlab-proxy in the background in an event loop
|
|
84
|
-
proc = loop.run_until_complete(utils.start_matlab_proxy_app(input_env=input_env))
|
|
85
|
-
_logger.info("Started MATLAB Proxy process")
|
|
86
|
-
|
|
87
|
-
# Wait for mwi_server.info file to be ready
|
|
88
|
-
utils.wait_server_info_ready(mwi_app_port)
|
|
89
|
-
|
|
90
|
-
# Get the scheme on which MATLAB Proxy connection string
|
|
91
|
-
matlab_proxy_url = utils.get_connection_string(mwi_app_port)
|
|
92
|
-
|
|
93
|
-
utils.poll_web_service(
|
|
94
|
-
matlab_proxy_url,
|
|
95
|
-
step=5,
|
|
96
|
-
timeout=120,
|
|
97
|
-
ignore_exceptions=(
|
|
98
|
-
requests.exceptions.ConnectionError,
|
|
99
|
-
requests.exceptions.SSLError,
|
|
100
|
-
),
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
for key, value in input_env.items():
|
|
104
|
-
module_monkeypatch.setenv(key, value)
|
|
105
|
-
|
|
106
|
-
yield
|
|
107
|
-
from pathlib import Path
|
|
108
|
-
|
|
109
|
-
shutil.move(
|
|
110
|
-
str(temp_dir_path / Path("proxy_app_config.json")),
|
|
111
|
-
str(os.path.dirname(matlab_config_file)),
|
|
112
|
-
)
|
|
113
|
-
shutil.rmtree(temp_dir_path)
|
|
114
|
-
|
|
115
|
-
proc.terminate()
|
|
116
|
-
loop.run_until_complete(proc.wait())
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# Copyright 2023-2024 The MathWorks, Inc.
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
import json
|
|
5
|
-
import requests
|
|
6
|
-
from requests.adapters import HTTPAdapter, Retry
|
|
7
|
-
from tests.integration.utils import integration_tests_utils as utils
|
|
8
|
-
from urllib.parse import urlparse
|
|
9
|
-
from tests.utils.logging_util import create_integ_test_logger
|
|
10
|
-
|
|
11
|
-
_logger = create_integ_test_logger(log_name=__name__)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def test_matlab_down(parse_matlab_proxy_url):
|
|
15
|
-
"""Test that matlab is down and no license is picked up"""
|
|
16
|
-
|
|
17
|
-
parsed_url, headers, connection_scheme = parse_matlab_proxy_url
|
|
18
|
-
http_endpoint = "/get_status"
|
|
19
|
-
uri = (
|
|
20
|
-
connection_scheme + "://" + parsed_url.netloc + parsed_url.path + http_endpoint
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
json_response = None
|
|
24
|
-
|
|
25
|
-
with requests.Session() as s:
|
|
26
|
-
retries = Retry(total=10, backoff_factor=0.1)
|
|
27
|
-
s.mount(f"{connection_scheme}://", HTTPAdapter(max_retries=retries))
|
|
28
|
-
response = s.get(uri, headers=headers, verify=False)
|
|
29
|
-
json_response = json.loads(response.text)
|
|
30
|
-
|
|
31
|
-
matlab_status = json_response["matlab"]["status"]
|
|
32
|
-
assert matlab_status == "down"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def test_matlab_proxy_app_installed():
|
|
36
|
-
import shutil
|
|
37
|
-
|
|
38
|
-
"""Test that the executable matlab_proxy_app is located on PATH and executable"""
|
|
39
|
-
|
|
40
|
-
which_matlabproxyapp = shutil.which("matlab-proxy-app")
|
|
41
|
-
assert (
|
|
42
|
-
which_matlabproxyapp is not None
|
|
43
|
-
), "matlab-proxy-app does not exist in system path"
|
|
44
|
-
assert (
|
|
45
|
-
os.access(which_matlabproxyapp, os.R_OK) == True
|
|
46
|
-
), """matlab-proxy-app does not have the read permissions"""
|
|
47
|
-
assert (
|
|
48
|
-
os.access(which_matlabproxyapp, os.X_OK) == True
|
|
49
|
-
), """matlab-proxy-app does not have the execute permissions"""
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# Copyright 2023-2024 The MathWorks, Inc.
|
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
# Copyright 2023-2024 The MathWorks, Inc.
|
|
2
|
-
# Utility functions for integration testing of matlab-proxy
|
|
3
|
-
|
|
4
|
-
import asyncio
|
|
5
|
-
import os
|
|
6
|
-
import socket
|
|
7
|
-
import time
|
|
8
|
-
import urllib3
|
|
9
|
-
import requests
|
|
10
|
-
import json
|
|
11
|
-
from tests.utils.logging_util import create_integ_test_logger
|
|
12
|
-
|
|
13
|
-
_logger = create_integ_test_logger(__name__)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def perform_basic_checks():
|
|
17
|
-
"""
|
|
18
|
-
Perform basic checks for the prerequisites for starting
|
|
19
|
-
matlab-proxy
|
|
20
|
-
"""
|
|
21
|
-
import matlab_proxy.settings
|
|
22
|
-
|
|
23
|
-
_logger.info("Performing basic checks for matlab-proxy")
|
|
24
|
-
|
|
25
|
-
# Validate MATLAB before testing
|
|
26
|
-
_, matlab_path = matlab_proxy.settings.get_matlab_executable_and_root_path()
|
|
27
|
-
|
|
28
|
-
# Check if MATLAB is in the system path
|
|
29
|
-
assert matlab_path is not None, "MATLAB is not in system path"
|
|
30
|
-
|
|
31
|
-
# Check if MATLAB verison is >= R2020b
|
|
32
|
-
assert (
|
|
33
|
-
matlab_proxy.settings.get_matlab_version(matlab_path) >= "R2020b"
|
|
34
|
-
), "MATLAB version should be R2020b or later"
|
|
35
|
-
_logger.debug("Exiting perform_basic_checks")
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def matlab_proxy_cmd_for_testing():
|
|
39
|
-
"""
|
|
40
|
-
Get command for starting matlab-proxy process
|
|
41
|
-
|
|
42
|
-
Returns:
|
|
43
|
-
list(string): Command for starting matlab-proxy process
|
|
44
|
-
"""
|
|
45
|
-
|
|
46
|
-
import matlab_proxy
|
|
47
|
-
|
|
48
|
-
matlab_cmd = [matlab_proxy.get_executable_name()]
|
|
49
|
-
|
|
50
|
-
return matlab_cmd
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
async def start_matlab_proxy_app(out=asyncio.subprocess.PIPE, input_env={}):
|
|
54
|
-
"""
|
|
55
|
-
Starts matlab-proxy as a subprocess. The subprocess runs forever unless
|
|
56
|
-
there is any error
|
|
57
|
-
|
|
58
|
-
Args:
|
|
59
|
-
input_env (dict, optional): Environment variables to be
|
|
60
|
-
initialized for the subprocess. Defaults to {}.
|
|
61
|
-
|
|
62
|
-
Returns:
|
|
63
|
-
Process: subprocess object
|
|
64
|
-
"""
|
|
65
|
-
from matlab_proxy.util import system
|
|
66
|
-
|
|
67
|
-
_logger.info("Starting MATLAB Proxy app")
|
|
68
|
-
cmd = matlab_proxy_cmd_for_testing()
|
|
69
|
-
matlab_proxy_env = os.environ.copy()
|
|
70
|
-
matlab_proxy_env.update(input_env)
|
|
71
|
-
|
|
72
|
-
proc = await asyncio.create_subprocess_exec(
|
|
73
|
-
*cmd,
|
|
74
|
-
env=matlab_proxy_env,
|
|
75
|
-
stdout=out,
|
|
76
|
-
stderr=out,
|
|
77
|
-
)
|
|
78
|
-
_logger.debug("MATLAB Proxy App started")
|
|
79
|
-
return proc
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def send_http_request(
|
|
83
|
-
connection_scheme,
|
|
84
|
-
mwi_app_port,
|
|
85
|
-
mwi_base_url="",
|
|
86
|
-
http_endpoint="",
|
|
87
|
-
method="GET",
|
|
88
|
-
headers={},
|
|
89
|
-
):
|
|
90
|
-
"""Send HTTP request to matlab-proxy server.
|
|
91
|
-
Returns HTTP response JSON"""
|
|
92
|
-
|
|
93
|
-
uri = (
|
|
94
|
-
f"{connection_scheme}://localhost:{mwi_app_port}{mwi_base_url}/{http_endpoint}"
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
with urllib3.PoolManager(
|
|
98
|
-
retries=urllib3.Retry(backoff_factor=0.1, backoff_max=300)
|
|
99
|
-
) as http:
|
|
100
|
-
res = http.request(method, uri, fields=headers)
|
|
101
|
-
return json.loads(res.data.decode("utf-8"))
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def wait_matlab_proxy_ready(matlab_proxy_url):
|
|
105
|
-
"""
|
|
106
|
-
Wait for matlab-proxy to be up and running
|
|
107
|
-
|
|
108
|
-
Args:
|
|
109
|
-
matlab_proxy_url (string): URL to access matlab-proxy
|
|
110
|
-
"""
|
|
111
|
-
|
|
112
|
-
from matlab_proxy.util import system
|
|
113
|
-
import matlab_proxy.settings as settings
|
|
114
|
-
|
|
115
|
-
_logger.info("Wait for MATLAB Proxy to start")
|
|
116
|
-
# Wait until the matlab config file is created
|
|
117
|
-
MAX_TIMEOUT = settings.get_process_startup_timeout()
|
|
118
|
-
start_time = time.time()
|
|
119
|
-
|
|
120
|
-
while not os.path.exists(str(get_matlab_config_file())) and (
|
|
121
|
-
time.time() - start_time < MAX_TIMEOUT
|
|
122
|
-
):
|
|
123
|
-
time.sleep(1)
|
|
124
|
-
|
|
125
|
-
try:
|
|
126
|
-
if not os.path.exists(str(get_matlab_config_file())):
|
|
127
|
-
raise FileNotFoundError("Config file is not present on the path")
|
|
128
|
-
|
|
129
|
-
except FileNotFoundError as e:
|
|
130
|
-
_logger.exception("Config file does not exist")
|
|
131
|
-
_logger.exception(e)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def get_random_free_port() -> str:
|
|
135
|
-
"""
|
|
136
|
-
Get a random free port
|
|
137
|
-
|
|
138
|
-
Returns:
|
|
139
|
-
string: A random free port
|
|
140
|
-
"""
|
|
141
|
-
|
|
142
|
-
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
143
|
-
s.bind(("", 0))
|
|
144
|
-
port = str(s.getsockname()[1])
|
|
145
|
-
s.close()
|
|
146
|
-
return port
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
def wait_server_info_ready(port_number):
|
|
150
|
-
"""
|
|
151
|
-
Waits for server file to be available on the disk
|
|
152
|
-
"""
|
|
153
|
-
|
|
154
|
-
import matlab_proxy.settings as settings
|
|
155
|
-
|
|
156
|
-
# timeout_value is in seconds
|
|
157
|
-
timeout_value = 60
|
|
158
|
-
start_time = time.time()
|
|
159
|
-
config_folder = settings.get_mwi_config_folder()
|
|
160
|
-
_path = config_folder / "ports" / port_number / "mwi_server.info"
|
|
161
|
-
|
|
162
|
-
while time.time() - start_time < timeout_value:
|
|
163
|
-
if _path.exists():
|
|
164
|
-
return True
|
|
165
|
-
|
|
166
|
-
time.sleep(1)
|
|
167
|
-
|
|
168
|
-
raise FileNotFoundError("mwi_server.info file does not exist")
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
def license_matlab_proxy(matlab_proxy_url):
|
|
172
|
-
"""
|
|
173
|
-
Use Playwright UI automation to license matlab-proxy.
|
|
174
|
-
Uses TEST_USERNAME and TEST_PASSWORD from environment variables.
|
|
175
|
-
|
|
176
|
-
Args:
|
|
177
|
-
matlab_proxy_url (string): URL to access matlab-proxy
|
|
178
|
-
"""
|
|
179
|
-
from playwright.sync_api import sync_playwright, expect
|
|
180
|
-
|
|
181
|
-
_logger.info("Licensing MATLAB using matlab-proxy")
|
|
182
|
-
# These are MathWorks Account credentials to license MATLAB
|
|
183
|
-
# Throws 'KeyError' if the following environment variables are not set
|
|
184
|
-
TEST_USERNAME = os.environ["TEST_USERNAME"]
|
|
185
|
-
TEST_PASSWORD = os.environ["TEST_PASSWORD"]
|
|
186
|
-
|
|
187
|
-
with sync_playwright() as playwright:
|
|
188
|
-
browser = playwright.chromium.launch(headless=True)
|
|
189
|
-
context = browser.new_context(ignore_https_errors=True)
|
|
190
|
-
|
|
191
|
-
page = context.new_page()
|
|
192
|
-
|
|
193
|
-
page.goto(matlab_proxy_url)
|
|
194
|
-
|
|
195
|
-
# Find the MHLM licensing windows in matlab-proxy
|
|
196
|
-
mhlm_div = page.locator("#MHLM")
|
|
197
|
-
expect(
|
|
198
|
-
mhlm_div,
|
|
199
|
-
"Wait for MHLM licensing window to appear. This might fail if the MATLAB is already licensed",
|
|
200
|
-
).to_be_visible(timeout=60000)
|
|
201
|
-
|
|
202
|
-
# The login iframe is present within the MHLM Div
|
|
203
|
-
login_iframe = mhlm_div.frame_locator("#loginframe")
|
|
204
|
-
|
|
205
|
-
# Fills in the username textbox
|
|
206
|
-
email_text_box = login_iframe.locator("#userId")
|
|
207
|
-
expect(
|
|
208
|
-
email_text_box,
|
|
209
|
-
"Wait for email ID textbox to appear",
|
|
210
|
-
).to_be_visible(timeout=20000)
|
|
211
|
-
email_text_box.fill(TEST_USERNAME)
|
|
212
|
-
email_text_box.press("Enter")
|
|
213
|
-
|
|
214
|
-
# Fills in the password textbox
|
|
215
|
-
password_text_box = login_iframe.locator("#password")
|
|
216
|
-
expect(password_text_box, "Wait for password textbox to appear").to_be_visible(
|
|
217
|
-
timeout=20000
|
|
218
|
-
)
|
|
219
|
-
password_text_box.fill(TEST_PASSWORD)
|
|
220
|
-
password_text_box.press("Enter")
|
|
221
|
-
|
|
222
|
-
# Verifies if licensing is successful by checking the status information
|
|
223
|
-
status_info = page.get_by_text("Status Information")
|
|
224
|
-
expect(
|
|
225
|
-
status_info,
|
|
226
|
-
"Verify if Licensing is successful. This might fail if incorrect credentials are provided",
|
|
227
|
-
).to_be_visible(timeout=60000)
|
|
228
|
-
_logger.debug("Succeeded in licensing MATLAB using matlab-proxy")
|
|
229
|
-
browser.close()
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
def unlicense_matlab_proxy(matlab_proxy_url):
|
|
233
|
-
"""
|
|
234
|
-
Unlicense matlab-proxy that is licensed using online licensing
|
|
235
|
-
|
|
236
|
-
Args:
|
|
237
|
-
matlab_proxy_url (string): URL to access matlab-proxy
|
|
238
|
-
"""
|
|
239
|
-
import warnings
|
|
240
|
-
|
|
241
|
-
_logger.info("Unlicensing matlab-proxy")
|
|
242
|
-
max_retries = 3 # Max retries for unlicensing matlab-proxy
|
|
243
|
-
retries = 0
|
|
244
|
-
|
|
245
|
-
while retries < max_retries:
|
|
246
|
-
error = None
|
|
247
|
-
try:
|
|
248
|
-
resp = requests.delete(
|
|
249
|
-
matlab_proxy_url + "/set_licensing_info", headers={}, verify=False
|
|
250
|
-
)
|
|
251
|
-
|
|
252
|
-
if resp.status_code == requests.codes.OK:
|
|
253
|
-
data = resp.json()
|
|
254
|
-
assert data["licensing"] == None, "matlab-proxy licensing is not unset"
|
|
255
|
-
assert (
|
|
256
|
-
data["matlab"]["status"] == "down"
|
|
257
|
-
), "matlab-proxy is not in 'stopped' state"
|
|
258
|
-
|
|
259
|
-
# Throw warning if matlab-proxy is unlicensed but with some error
|
|
260
|
-
if data["error"] != None:
|
|
261
|
-
warnings.warn(
|
|
262
|
-
f"matlab-proxy is unlicensed but with error: {data['error']}",
|
|
263
|
-
UserWarning,
|
|
264
|
-
)
|
|
265
|
-
_logger.debug("Succeeded in unlicensing matlab-proxy")
|
|
266
|
-
break
|
|
267
|
-
else:
|
|
268
|
-
resp.raise_for_status()
|
|
269
|
-
except Exception as e:
|
|
270
|
-
error = e
|
|
271
|
-
finally:
|
|
272
|
-
retries += 1
|
|
273
|
-
|
|
274
|
-
# If the above code threw error even after maximum retries, then raise error
|
|
275
|
-
if error:
|
|
276
|
-
raise error
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
def get_connection_string(port_number):
|
|
280
|
-
"""Returns the scheme on which matlab proxy starts (http or https)
|
|
281
|
-
|
|
282
|
-
Args:
|
|
283
|
-
port_number (string): Port on which MATLAB proxy starts
|
|
284
|
-
|
|
285
|
-
Returns:
|
|
286
|
-
scheme: String representing the scheme
|
|
287
|
-
"""
|
|
288
|
-
import matlab_proxy.settings as settings
|
|
289
|
-
|
|
290
|
-
config_folder = settings.get_mwi_config_folder()
|
|
291
|
-
_path = config_folder / "ports" / port_number / "mwi_server.info"
|
|
292
|
-
conn_string = None
|
|
293
|
-
|
|
294
|
-
try:
|
|
295
|
-
with open(_path, "r") as _file:
|
|
296
|
-
conn_string = _file.readline().rstrip()
|
|
297
|
-
|
|
298
|
-
except FileNotFoundError:
|
|
299
|
-
_logger.exception(f"{_path} does not exist")
|
|
300
|
-
|
|
301
|
-
return conn_string
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
def poll_web_service(url, step=1, timeout=60, ignore_exceptions=None):
|
|
305
|
-
"""Poll a web service for a 200 response
|
|
306
|
-
|
|
307
|
-
Args:
|
|
308
|
-
url (string): URL of the web service
|
|
309
|
-
step (int, optional): Poll Interval. Defaults to 1 second.
|
|
310
|
-
timeout (int, optional): Polling timout. Defaults to 60 seconds.
|
|
311
|
-
ignore_exceptions (tuple, optional): The exceptions that need to be ignored
|
|
312
|
-
within the polling timout. Defaults to None.
|
|
313
|
-
|
|
314
|
-
Raises:
|
|
315
|
-
TimeoutError: Error if polling timeout is exceeded
|
|
316
|
-
|
|
317
|
-
Returns:
|
|
318
|
-
dict: response dictionary object
|
|
319
|
-
"""
|
|
320
|
-
start_time = time.time()
|
|
321
|
-
end_time = start_time + timeout
|
|
322
|
-
|
|
323
|
-
import matlab_proxy.settings as settings
|
|
324
|
-
|
|
325
|
-
config_folder = settings.get_mwi_config_folder()
|
|
326
|
-
|
|
327
|
-
while time.time() < end_time:
|
|
328
|
-
try:
|
|
329
|
-
response = requests.get(url, verify=False)
|
|
330
|
-
if response.status_code == 200:
|
|
331
|
-
return response
|
|
332
|
-
|
|
333
|
-
except Exception as e:
|
|
334
|
-
if ignore_exceptions and isinstance(e, ignore_exceptions):
|
|
335
|
-
continue # Ignore specified exceptions
|
|
336
|
-
time.sleep(step)
|
|
337
|
-
|
|
338
|
-
raise TimeoutError(
|
|
339
|
-
f"{url} did not return a 200 response within the timeout period {timeout} seconds."
|
|
340
|
-
)
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
def get_matlab_config_file():
|
|
344
|
-
"""
|
|
345
|
-
Gets the path to MATLAB config file generated by matlab-proxy
|
|
346
|
-
|
|
347
|
-
Returns:
|
|
348
|
-
string: MATLAB config file path
|
|
349
|
-
"""
|
|
350
|
-
from matlab_proxy import settings
|
|
351
|
-
|
|
352
|
-
return settings.get()["matlab_config_file"]
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
# Copyright 2024 The MathWorks, Inc.
|
|
2
|
-
import os
|
|
3
|
-
import logging
|
|
4
|
-
from playwright.sync_api import Page, Error, sync_playwright, expect
|
|
5
|
-
from tests.integration.utils import integration_tests_utils as utils
|
|
6
|
-
from tests.utils.logging_util import create_integ_test_logger
|
|
7
|
-
|
|
8
|
-
# Configure logging
|
|
9
|
-
_logger = create_integ_test_logger(__name__)
|
|
10
|
-
|
|
11
|
-
TIMEOUTS = {
|
|
12
|
-
# Time in milliseconds
|
|
13
|
-
"MHLM_VISIBLE": 60 * 1000,
|
|
14
|
-
"TEXTBOX_VISIBLE": 5 * 1000,
|
|
15
|
-
"MATLAB_STARTS": 3 * 60 * 1000,
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
POLL_INTERVAL = 1000
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def _get_matlab_proxy_url():
|
|
23
|
-
# import integration_tests_utils as utils
|
|
24
|
-
import matlab_proxy.util
|
|
25
|
-
|
|
26
|
-
mwi_app_port = utils.get_random_free_port()
|
|
27
|
-
mwi_base_url = "/matlab-test"
|
|
28
|
-
|
|
29
|
-
input_env = {
|
|
30
|
-
"MWI_APP_PORT": mwi_app_port,
|
|
31
|
-
"MWI_BASE_URL": mwi_base_url,
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
loop = matlab_proxy.util.get_event_loop()
|
|
35
|
-
# Run matlab-proxy in the background in an event loop
|
|
36
|
-
proc = loop.run_until_complete(utils.start_matlab_proxy_app(input_env=input_env))
|
|
37
|
-
|
|
38
|
-
utils.wait_server_info_ready(mwi_app_port)
|
|
39
|
-
matlab_proxy_url = utils.get_connection_string(mwi_app_port)
|
|
40
|
-
return matlab_proxy_url, proc, loop
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def license_matlab_proxy():
|
|
44
|
-
import requests
|
|
45
|
-
|
|
46
|
-
matlab_proxy_url, proc, loop = _get_matlab_proxy_url()
|
|
47
|
-
|
|
48
|
-
utils.poll_web_service(
|
|
49
|
-
matlab_proxy_url,
|
|
50
|
-
step=5,
|
|
51
|
-
timeout=120,
|
|
52
|
-
ignore_exceptions=(
|
|
53
|
-
requests.exceptions.ConnectionError,
|
|
54
|
-
requests.exceptions.SSLError,
|
|
55
|
-
),
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
licensing_with_online_licensing(matlab_proxy_url)
|
|
59
|
-
utils.wait_matlab_proxy_ready(matlab_proxy_url)
|
|
60
|
-
proc.terminate()
|
|
61
|
-
loop.run_until_complete(proc.wait())
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def licensing_with_online_licensing(matlab_proxy_url):
|
|
65
|
-
"""
|
|
66
|
-
Use Playwright UI automation to license matlab-proxy.
|
|
67
|
-
Uses TEST_USERNAME and TEST_PASSWORD from environment variables.
|
|
68
|
-
|
|
69
|
-
Args:
|
|
70
|
-
matlab_proxy_url (string): URL to access matlab-proxy
|
|
71
|
-
"""
|
|
72
|
-
from playwright.sync_api import sync_playwright, expect
|
|
73
|
-
|
|
74
|
-
# These are MathWorks Account credentials to license MATLAB
|
|
75
|
-
# Throws 'KeyError' if the following environment variables are not set
|
|
76
|
-
TEST_USERNAME = os.environ["TEST_USERNAME"]
|
|
77
|
-
TEST_PASSWORD = os.environ["TEST_PASSWORD"]
|
|
78
|
-
|
|
79
|
-
playwright, browser, page = _launch_browser()
|
|
80
|
-
page.goto(matlab_proxy_url)
|
|
81
|
-
|
|
82
|
-
# Find the MHLM licensing window in matlab-proxy
|
|
83
|
-
login_iframe = _wait_for_login_iframe(page)
|
|
84
|
-
|
|
85
|
-
# Fills in the username textbox
|
|
86
|
-
email_text_box = _fill_in_username(TEST_USERNAME, login_iframe)
|
|
87
|
-
email_text_box.press("Enter")
|
|
88
|
-
|
|
89
|
-
# Fills in the password textbox
|
|
90
|
-
password_text_box = _fill_in_password(TEST_PASSWORD, login_iframe)
|
|
91
|
-
password_text_box.press("Enter")
|
|
92
|
-
|
|
93
|
-
# Verifies if licensing is successful by checking the status information
|
|
94
|
-
_verify_licensing(page)
|
|
95
|
-
_close_resources(playwright, browser)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
def _verify_licensing(page):
|
|
99
|
-
status_info = page.get_by_text("Status Information")
|
|
100
|
-
expect(
|
|
101
|
-
status_info,
|
|
102
|
-
"Verify if Licensing is successful. This might fail if incorrect credentials are provided",
|
|
103
|
-
).to_be_visible(timeout=TIMEOUTS["MHLM_VISIBLE"])
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def _wait_for_login_iframe(matlab_proxy_page):
|
|
107
|
-
"""Waits for the MHLM/Online Licensing form to appear."""
|
|
108
|
-
mhlm_div = matlab_proxy_page.locator("#MHLM")
|
|
109
|
-
expect(
|
|
110
|
-
mhlm_div,
|
|
111
|
-
"Wait for MHLM licensing window to appear. This might fail if the MATLAB is already licensed",
|
|
112
|
-
).to_be_visible(timeout=TIMEOUTS["MHLM_VISIBLE"])
|
|
113
|
-
|
|
114
|
-
# The login iframe is present within the MHLM Div
|
|
115
|
-
login_iframe = mhlm_div.frame_locator("#loginframe")
|
|
116
|
-
return login_iframe
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def _launch_browser(headless: bool = True) -> tuple:
|
|
120
|
-
"""Launches the browser and returns the browser and page objects."""
|
|
121
|
-
playwright = sync_playwright().start()
|
|
122
|
-
browser = playwright.chromium.launch(headless=headless)
|
|
123
|
-
context = browser.new_context(ignore_https_errors=True)
|
|
124
|
-
page = context.new_page()
|
|
125
|
-
return playwright, browser, page
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
def _close_resources(playwright, browser):
|
|
129
|
-
"""Closes the browser and playwright resources properly."""
|
|
130
|
-
browser.close()
|
|
131
|
-
playwright.stop()
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def _fill_in_username(username, login_iframe):
|
|
135
|
-
"""Inputs the provided username string into the MHLM login form."""
|
|
136
|
-
email_text_box = login_iframe.locator("#userId")
|
|
137
|
-
expect(
|
|
138
|
-
email_text_box,
|
|
139
|
-
"Wait for email ID textbox to appear",
|
|
140
|
-
).to_be_visible(timeout=TIMEOUTS["TEXTBOX_VISIBLE"])
|
|
141
|
-
email_text_box.fill(username)
|
|
142
|
-
return email_text_box
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
def _fill_in_password(password, login_iframe):
|
|
146
|
-
"""Inputs the provided password string into the MHLM login form."""
|
|
147
|
-
password_text_box = login_iframe.locator("#password")
|
|
148
|
-
expect(password_text_box, "Wait for password textbox to appear").to_be_visible(
|
|
149
|
-
timeout=TIMEOUTS["TEXTBOX_VISIBLE"]
|
|
150
|
-
)
|
|
151
|
-
password_text_box.fill(password)
|
|
152
|
-
return password_text_box
|
tests/unit/__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
# Copyright 2024 The MathWorks, Inc.
|