matlab-proxy 0.26.0__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.

Files changed (54) hide show
  1. matlab_proxy/app.py +13 -15
  2. matlab_proxy/app_state.py +8 -2
  3. matlab_proxy/default_configuration.py +2 -2
  4. matlab_proxy/gui/index.html +1 -1
  5. matlab_proxy/gui/static/js/{index.CZgGkMCD.js → index.BcDShXfH.js} +16 -16
  6. matlab_proxy/settings.py +3 -2
  7. matlab_proxy/util/list_servers.py +2 -2
  8. matlab_proxy/util/mwi/environment_variables.py +5 -0
  9. matlab_proxy/util/mwi/session_name.py +28 -0
  10. matlab_proxy/util/mwi/validators.py +2 -4
  11. {matlab_proxy-0.26.0.dist-info → matlab_proxy-0.27.0.dist-info}/METADATA +37 -25
  12. {matlab_proxy-0.26.0.dist-info → matlab_proxy-0.27.0.dist-info}/RECORD +19 -49
  13. {matlab_proxy-0.26.0.dist-info → matlab_proxy-0.27.0.dist-info}/WHEEL +1 -2
  14. matlab_proxy_manager/README.md +85 -0
  15. matlab_proxy_manager/lib/README.md +53 -0
  16. matlab_proxy_manager/storage/README.md +54 -0
  17. matlab_proxy_manager/web/README.md +37 -0
  18. matlab_proxy-0.26.0.dist-info/top_level.txt +0 -3
  19. tests/integration/__init__.py +0 -1
  20. tests/integration/integration_tests_with_license/__init__.py +0 -1
  21. tests/integration/integration_tests_with_license/conftest.py +0 -47
  22. tests/integration/integration_tests_with_license/test_http_end_points.py +0 -397
  23. tests/integration/integration_tests_without_license/__init__.py +0 -1
  24. tests/integration/integration_tests_without_license/conftest.py +0 -116
  25. tests/integration/integration_tests_without_license/test_matlab_is_down_if_unlicensed.py +0 -49
  26. tests/integration/utils/__init__.py +0 -1
  27. tests/integration/utils/integration_tests_utils.py +0 -352
  28. tests/integration/utils/licensing.py +0 -152
  29. tests/unit/__init__.py +0 -1
  30. tests/unit/conftest.py +0 -66
  31. tests/unit/test_app.py +0 -1299
  32. tests/unit/test_app_state.py +0 -1094
  33. tests/unit/test_constants.py +0 -7
  34. tests/unit/test_ddux.py +0 -22
  35. tests/unit/test_devel.py +0 -246
  36. tests/unit/test_non_dev_mode.py +0 -169
  37. tests/unit/test_settings.py +0 -679
  38. tests/unit/util/__init__.py +0 -3
  39. tests/unit/util/mwi/__init__.py +0 -1
  40. tests/unit/util/mwi/embedded_connector/__init__.py +0 -1
  41. tests/unit/util/mwi/embedded_connector/test_helpers.py +0 -29
  42. tests/unit/util/mwi/embedded_connector/test_request.py +0 -64
  43. tests/unit/util/mwi/test_custom_http_headers.py +0 -281
  44. tests/unit/util/mwi/test_download.py +0 -152
  45. tests/unit/util/mwi/test_logger.py +0 -82
  46. tests/unit/util/mwi/test_token_auth.py +0 -303
  47. tests/unit/util/mwi/test_validators.py +0 -364
  48. tests/unit/util/test_cookie_jar.py +0 -252
  49. tests/unit/util/test_mw.py +0 -550
  50. tests/unit/util/test_util.py +0 -221
  51. tests/utils/__init__.py +0 -1
  52. tests/utils/logging_util.py +0 -81
  53. {matlab_proxy-0.26.0.dist-info → matlab_proxy-0.27.0.dist-info}/entry_points.txt +0 -0
  54. {matlab_proxy-0.26.0.dist-info → matlab_proxy-0.27.0.dist-info/licenses}/LICENSE.md +0 -0
tests/unit/test_app.py DELETED
@@ -1,1299 +0,0 @@
1
- # Copyright 2020-2025 The MathWorks, Inc.
2
-
3
- import asyncio
4
- import datetime
5
- import json
6
- import platform
7
- import random
8
- import time
9
- from datetime import timedelta, timezone
10
- from http import HTTPStatus, cookies
11
-
12
- import pytest
13
- from aiohttp import WSMsgType
14
- from aiohttp.web import WebSocketResponse
15
- from multidict import CIMultiDict
16
-
17
- import tests.unit.test_constants as test_constants
18
- from matlab_proxy import app, util
19
- from matlab_proxy.app import matlab_view
20
- from matlab_proxy.util.mwi import environment_variables as mwi_env
21
- from matlab_proxy.util.mwi.exceptions import EntitlementError, MatlabInstallError
22
- from tests.unit.fixtures.fixture_auth import (
23
- patch_authenticate_access_decorator, # noqa: F401
24
- )
25
- from tests.unit.mocks.mock_client import MockWebSocketClient
26
-
27
-
28
- @pytest.mark.parametrize(
29
- "no_proxy_user_configuration",
30
- [
31
- "",
32
- "1234.1234.1234, localhost , 0.0.0.0,1.2.3.4",
33
- "0.0.0.0",
34
- "1234.1234.1234",
35
- " 1234.1234.1234 ",
36
- ],
37
- )
38
- def test_configure_no_proxy_in_env(monkeypatch, no_proxy_user_configuration):
39
- """Tests the behavior of the configure_no_proxy_in_env function
40
-
41
- Args:
42
- monkeypatch (environment): MonkeyPatches the environment to mimic possible user environment settings
43
- """
44
- no_proxy_user_configuration_set = set(
45
- [val.lstrip().rstrip() for val in no_proxy_user_configuration.split(",")]
46
- )
47
- # Update the environment to simulate user environment
48
- monkeypatch.setenv("no_proxy", no_proxy_user_configuration)
49
-
50
- # This function will modify the environment variables to include 0.0.0.0, localhost & 127.0.0.1
51
- app.configure_no_proxy_in_env()
52
-
53
- import os
54
-
55
- modified_no_proxy_env = os.environ.get("no_proxy")
56
-
57
- # Convert to set to compare, as list generated need not be ordered
58
- modified_no_proxy_env_set = set(
59
- [val.lstrip().rstrip() for val in modified_no_proxy_env.split(",")]
60
- )
61
-
62
- expected_no_proxy_configuration_set = {"0.0.0.0", "localhost", "127.0.0.1"}
63
-
64
- # We expect the modified set of values to include the localhost configurations
65
- # along with whatever else the user had set with no duplicates.
66
- assert modified_no_proxy_env_set == no_proxy_user_configuration_set.union(
67
- expected_no_proxy_configuration_set
68
- )
69
-
70
-
71
- def test_create_app(event_loop):
72
- """Test if aiohttp server is being created successfully.
73
-
74
- Checks if the aiohttp server is created successfully, routes, startup and cleanup
75
- tasks are added.
76
- """
77
- test_server = app.create_app()
78
-
79
- # Verify router is configured with some routes
80
- assert test_server.router._resources is not None
81
-
82
- # Verify app server has a cleanup task
83
- # By default there is 1 for clean up task
84
- assert len(test_server.on_cleanup) > 1
85
- event_loop.run_until_complete(test_server["state"].stop_server_tasks())
86
-
87
-
88
- def get_email():
89
- """Returns a placeholder email
90
-
91
- Returns:
92
- String: A placeholder email as a string.
93
- """
94
- return "abc@mathworks.com"
95
-
96
-
97
- def get_connection_string():
98
- """Returns a placeholder nlm connection string
99
-
100
- Returns:
101
- String : A placeholder nlm connection string
102
- """
103
- return "nlm@localhost.com"
104
-
105
-
106
- async def wait_for_matlab_to_be_up(test_server, sleep_seconds):
107
- """Checks at max five times for the MATLAB status to be up and throws ConnectionError
108
- if MATLAB status is not up.
109
-
110
- This function mitigates the scenario where the tests may try to send the request
111
- to the test server and the MATLAB status is not up yet which may cause the test to fail
112
- unexpectedly.
113
-
114
- Use this function if the test intends to wait for the matlab status to be up before
115
- sending any requests.
116
-
117
- Args:
118
- test_server (aiohttp_client) : A aiohttp_client server to send HTTP GET request.
119
- sleep_seconds : Seconds to be sent to the asyncio.sleep method
120
- """
121
-
122
- count = 0
123
- while True:
124
- resp = await test_server.get("/get_status")
125
- assert resp.status == HTTPStatus.OK
126
-
127
- resp_json = json.loads(await resp.text())
128
-
129
- if resp_json["matlab"]["status"] == "up":
130
- break
131
- else:
132
- count += 1
133
- await asyncio.sleep(sleep_seconds)
134
- if count > test_constants.FIVE_MAX_TRIES:
135
- raise ConnectionError
136
-
137
-
138
- @pytest.fixture(
139
- name="licensing_data",
140
- params=[
141
- {"input": None, "expected": None},
142
- {
143
- "input": {"type": "mhlm", "email_addr": get_email()},
144
- "expected": {
145
- "type": "mhlm",
146
- "emailAddress": get_email(),
147
- "entitlements": [],
148
- "entitlementId": None,
149
- },
150
- },
151
- {
152
- "input": {"type": "nlm", "conn_str": get_connection_string()},
153
- "expected": {"type": "nlm", "connectionString": get_connection_string()},
154
- },
155
- {
156
- "input": {"type": "existing_license"},
157
- "expected": {"type": "existing_license"},
158
- },
159
- ],
160
- ids=[
161
- "No Licensing info supplied",
162
- "Licensing type is mhlm",
163
- "Licensing type is nlm",
164
- "Licensing type is existing_license",
165
- ],
166
- )
167
- def licensing_info_fixture(request):
168
- """A pytest fixture which returns licensing_data
169
-
170
- A parameterized pytest fixture which returns a licensing_data dict.
171
- licensing_data of three types:
172
- None : No licensing
173
- MHLM : Matlab Hosted License Manager
174
- NLM : Network License Manager.
175
-
176
-
177
- Args:
178
- request : A built-in pytest fixture
179
-
180
- Returns:
181
- Array : Containing expected and actual licensing data.
182
- """
183
- return request.param
184
-
185
-
186
- def test_marshal_licensing_info(licensing_data):
187
- """Test app.marshal_licensing_info method works correctly
188
-
189
- This test checks if app.marshal_licensing_info returns correct licensing data.
190
- Test checks for 3 cases:
191
- 1) No Licensing Provided
192
- 2) MHLM type Licensing
193
- 3) NLM type licensing
194
-
195
- Args:
196
- licensing_data (Array): An array containing actual and expected licensing data to assert.
197
- """
198
-
199
- actual_licensing_info = licensing_data["input"]
200
- expected_licensing_info = licensing_data["expected"]
201
-
202
- assert app.marshal_licensing_info(actual_licensing_info) == expected_licensing_info
203
-
204
-
205
- @pytest.mark.parametrize(
206
- "actual_error, expected_error",
207
- [
208
- (None, None),
209
- (
210
- MatlabInstallError("'matlab' executable not found in PATH"),
211
- {
212
- "message": "'matlab' executable not found in PATH",
213
- "logs": None,
214
- "type": MatlabInstallError.__name__,
215
- },
216
- ),
217
- ],
218
- ids=["No error", "Raise Matlab Install Error"],
219
- )
220
- def test_marshal_error(actual_error, expected_error):
221
- """Test if marshal_error returns an expected Dict when an error is raised
222
-
223
- Upon raising MatlabInstallError, checks if the the relevant information is returned as a
224
- Dict.
225
-
226
- Args:
227
- actual_error (Exception): An instance of Exception class
228
- expected_error (Dict): A python Dict containing information on the type of Exception
229
- """
230
- assert app.marshal_error(actual_error) == expected_error
231
-
232
-
233
- class FakeServer:
234
- """Context Manager class which returns a web server wrapped in aiohttp_client pytest fixture
235
- for testing.
236
-
237
- The server setup and startup does not need to mimic the way it is being done in main() method in app.py.
238
- Setting up the server in the context of Pytest.
239
- """
240
-
241
- def __init__(self, event_loop, aiohttp_client):
242
- self.loop = event_loop
243
- self.aiohttp_client = aiohttp_client
244
-
245
- def __enter__(self):
246
- server = app.create_app()
247
- self.server = app.configure_and_start(server)
248
- return self.loop.run_until_complete(self.aiohttp_client(self.server))
249
-
250
- def __exit__(self, exc_type, exc_value, exc_traceback):
251
- self.loop.run_until_complete(self.server.shutdown())
252
- self.loop.run_until_complete(self.server.cleanup())
253
-
254
-
255
- @pytest.fixture
256
- def mock_request(mocker):
257
- """Creates a mock request with required attributes"""
258
- req = mocker.MagicMock()
259
- req.app = {
260
- "state": mocker.MagicMock(matlab_port=8000),
261
- "settings": {
262
- "matlab_protocol": "http",
263
- "mwapikey": "test-key",
264
- "cookie_jar": None,
265
- },
266
- }
267
- req.headers = CIMultiDict()
268
- req.cookies = {}
269
- return req
270
-
271
-
272
- @pytest.fixture(name="mock_websocket_messages")
273
- def mock_messages(mocker):
274
- # Mock WebSocket messages
275
- return [
276
- mocker.MagicMock(type=WSMsgType.TEXT, data="test message"),
277
- mocker.MagicMock(type=WSMsgType.BINARY, data=b"test binary"),
278
- mocker.MagicMock(type=WSMsgType.PING),
279
- mocker.MagicMock(type=WSMsgType.PONG),
280
- ]
281
-
282
-
283
- @pytest.fixture(name="test_server")
284
- def test_server_fixture(event_loop, aiohttp_client, monkeypatch, request):
285
- """A pytest fixture which yields a test server to be used by tests.
286
-
287
- Args:
288
- loop (Event loop): The built-in event loop provided by pytest.
289
- aiohttp_client (aiohttp_client): Built-in pytest fixture used as a wrapper to the aiohttp web server.
290
-
291
- Yields:
292
- aiohttp_client : A aiohttp_client server used by tests.
293
- """
294
- # Default set of environment variables for testing convenience
295
- default_env_vars_for_testing = [
296
- (mwi_env.get_env_name_enable_mwi_auth_token(), "False")
297
- ]
298
- custom_env_vars = getattr(request, "param", None)
299
-
300
- if custom_env_vars:
301
- default_env_vars_for_testing.extend(custom_env_vars)
302
-
303
- for env_var_name, env_var_value in default_env_vars_for_testing:
304
- monkeypatch.setenv(env_var_name, env_var_value)
305
-
306
- try:
307
- with FakeServer(event_loop, aiohttp_client) as test_server:
308
- yield test_server
309
-
310
- except ProcessLookupError:
311
- pass
312
-
313
- finally:
314
- # Cleaning up the environment variables set for testing
315
- for env_var_name, _ in default_env_vars_for_testing:
316
- monkeypatch.delenv(env_var_name, raising="False")
317
-
318
-
319
- async def test_get_status_route(test_server):
320
- """Test to check endpoint : "/get_status"
321
-
322
- Args:
323
- test_server (aiohttp_client): A aiohttp_client server for sending GET request.
324
- """
325
-
326
- resp = await test_server.get("/get_status")
327
- assert resp.status == HTTPStatus.OK
328
-
329
-
330
- async def test_clear_client_id_route(test_server):
331
- """Test to check endpoint: "/clear_client_id"
332
-
333
- Args:
334
- test_server (aiohttp_client): A aiohttp_client server for sending POST request.
335
- """
336
-
337
- state = test_server.server.app["state"]
338
- state.active_client = "mock_client_id"
339
- resp = await test_server.post("/clear_client_id")
340
- assert resp.status == HTTPStatus.OK
341
- assert state.active_client is None
342
-
343
-
344
- async def test_get_env_config(test_server):
345
- """Test to check endpoint : "/get_env_config"
346
-
347
- Args:
348
- test_server (aiohttp_client): A aiohttp_client server for sending GET request.
349
- """
350
- expected_json_structure = {
351
- "authentication": {"enabled": False, "status": False},
352
- "matlab": {
353
- "status": "up",
354
- "version": "R2023a",
355
- "supportedVersions": ["R2020b", "R2023a"],
356
- },
357
- "doc_url": "foo",
358
- "extension_name": "bar",
359
- "extension_name_short_description": "foobar",
360
- "should_show_shutdown_button": True,
361
- "isConcurrencyEnabled": "foobar",
362
- "idleTimeoutDuration": 100,
363
- }
364
- resp = await test_server.get("/get_env_config")
365
- assert resp.status == HTTPStatus.OK
366
-
367
- text = await resp.json()
368
- assert text is not None
369
- assert set(expected_json_structure.keys()) == set(text.keys())
370
-
371
-
372
- async def test_start_matlab_route(test_server):
373
- """Test to check endpoint : "/start_matlab"
374
-
375
- Test waits for matlab status to be "up" before sending the GET request to start matlab
376
- Checks whether matlab restarts.
377
-
378
- Args:
379
- test_server (aiohttp_client): A aiohttp_client server to send GET request to.
380
- """
381
- # Waiting for the matlab process to start up.
382
- await wait_for_matlab_to_be_up(
383
- test_server, test_constants.CHECK_MATLAB_STATUS_INTERVAL
384
- )
385
-
386
- # Send get request to end point
387
- await test_server.put("/start_matlab")
388
-
389
- # Check if Matlab restarted successfully
390
- await __check_for_matlab_status(test_server, "starting")
391
-
392
-
393
- async def __check_for_matlab_status(test_server, status, sleep_interval=0.5):
394
- """Helper function to check if the status of MATLAB returned by the server is either of the values mentioned in statuses
395
-
396
- Args:
397
- test_server (aiohttp_client): A aiohttp_client server to send HTTP DELETE request.
398
- statuses ([str]): Possible MATLAB statuses.
399
-
400
- Raises:
401
- ConnectionError: Exception raised if the test_server is not reachable.
402
- """
403
- count = 0
404
- while True:
405
- resp = await test_server.get("/get_status")
406
- assert resp.status == HTTPStatus.OK
407
- resp_json = json.loads(await resp.text())
408
- if resp_json["matlab"]["status"] == status:
409
- break
410
- else:
411
- count += 1
412
- await asyncio.sleep(sleep_interval)
413
- if count > test_constants.FIVE_MAX_TRIES:
414
- raise ConnectionError
415
-
416
-
417
- async def test_stop_matlab_route(test_server):
418
- """Test to check endpoint : "/stop_matlab"
419
-
420
- Sends HTTP DELETE request to stop matlab and checks if matlab status is down.
421
-
422
- Args:
423
- test_server (aiohttp_client): A aiohttp_client server to send HTTP DELETE request.
424
- """
425
- # Arrange
426
- # Nothing to arrange
427
-
428
- # Act
429
- resp = await test_server.delete("/stop_matlab")
430
- assert resp.status == HTTPStatus.OK
431
-
432
- # Assert
433
- # Check if Matlab restarted successfully
434
- await __check_for_matlab_status(test_server, "stopping")
435
-
436
-
437
- async def test_root_redirect(test_server):
438
- """Test to check endpoint : "/"
439
-
440
- Should throw a 404 error. This will look for index.html in root directory of the project
441
- (In non-dev mode, root directory is the package)
442
- This file will not be available in the expected location in dev mode.
443
-
444
- Args:
445
- test_server (aiohttp_client): A aiohttp_client server to send HTTP GET request.
446
-
447
- """
448
- count = 0
449
- while True:
450
- resp = await test_server.get("/")
451
- if resp.status == HTTPStatus.SERVICE_UNAVAILABLE:
452
- time.sleep(test_constants.ONE_SECOND_DELAY)
453
- count += 1
454
- else:
455
- assert resp.status == HTTPStatus.NOT_FOUND
456
- break
457
-
458
- if count > test_constants.FIVE_MAX_TRIES:
459
- raise ConnectionError
460
-
461
-
462
- @pytest.fixture(name="proxy_payload")
463
- def proxy_payload_fixture():
464
- """Pytest fixture which returns a Dict representing the payload.
465
-
466
- Returns:
467
- Dict: A Dict representing the payload for HTTP request.
468
- """
469
- payload = {"messages": {"ClientType": [{"properties": {"TYPE": "jsd"}}]}}
470
-
471
- return payload
472
-
473
-
474
- async def test_matlab_proxy_404(proxy_payload, test_server):
475
- """Test to check if test_server is able to proxy HTTP request to fake matlab server
476
- for a non-existing file. Should return 404 status code in response
477
-
478
- Args:
479
- proxy_payload (Dict): Pytest fixture which returns a Dict.
480
- test_server (aiohttp_client): Test server to send HTTP requests.
481
- """
482
-
483
- headers = {"content-type": "application/json"}
484
-
485
- # Request a non-existing html file.
486
- # Request gets proxied to app.matlab_view() which should raise HTTPNotFound() exception ie. return HTTP status code 404
487
-
488
- count = 0
489
- while True:
490
- resp = await test_server.post(
491
- "/1234.html", data=json.dumps(proxy_payload), headers=headers
492
- )
493
- if resp.status == HTTPStatus.SERVICE_UNAVAILABLE:
494
- time.sleep(test_constants.ONE_SECOND_DELAY)
495
- count += 1
496
- else:
497
- assert resp.status == HTTPStatus.NOT_FOUND
498
- break
499
-
500
- if count > test_constants.FIVE_MAX_TRIES:
501
- raise ConnectionError
502
-
503
-
504
- async def test_matlab_proxy_http_get_request(proxy_payload, test_server):
505
- """Test to check if test_server proxies a HTTP request to fake matlab server and returns
506
- the response back
507
-
508
- Args:
509
- proxy_payload (Dict): Pytest fixture which returns a Dict representing payload for the HTTP request
510
- test_server (aiohttp_client): Test server to send HTTP requests.
511
-
512
- Raises:
513
- ConnectionError: If fake matlab server is not reachable from the test server, raises ConnectionError
514
- """
515
-
516
- max_tries = 5
517
- count = 0
518
-
519
- while True:
520
- resp = await test_server.get(
521
- "/http_get_request.html", data=json.dumps(proxy_payload)
522
- )
523
-
524
- if resp.status in (HTTPStatus.NOT_FOUND, HTTPStatus.SERVICE_UNAVAILABLE):
525
- time.sleep(1)
526
- count += 1
527
-
528
- else:
529
- resp_body = await resp.text()
530
- assert json.dumps(proxy_payload) == resp_body
531
- break
532
-
533
- if count > max_tries:
534
- raise ConnectionError
535
-
536
-
537
- async def test_matlab_proxy_http_put_request(proxy_payload, test_server):
538
- """Test to check if test_server proxies a HTTP request to fake matlab server and returns
539
- the response back
540
-
541
- Args:
542
- proxy_payload (Dict): Pytest fixture which returns a Dict representing payload for the HTTP request
543
- test_server (aiohttp_client): Test server to send HTTP requests.
544
-
545
- Raises:
546
- ConnectionError: If fake matlab server is not reachable from the test server, raises ConnectionError
547
- """
548
-
549
- max_tries = 5
550
- count = 0
551
-
552
- while True:
553
- resp = await test_server.put(
554
- "/http_put_request.html", data=json.dumps(proxy_payload)
555
- )
556
-
557
- if resp.status in (HTTPStatus.NOT_FOUND, HTTPStatus.SERVICE_UNAVAILABLE):
558
- time.sleep(1)
559
- count += 1
560
-
561
- else:
562
- resp_body = await resp.text()
563
- assert json.dumps(proxy_payload) == resp_body
564
- break
565
-
566
- if count > max_tries:
567
- raise ConnectionError
568
-
569
-
570
- async def test_matlab_proxy_http_delete_request(proxy_payload, test_server):
571
- """Test to check if test_server proxies a HTTP request to fake matlab server and returns
572
- the response back
573
-
574
- Args:
575
- proxy_payload (Dict): Pytest fixture which returns a Dict representing payload for the HTTP request
576
- test_server (aiohttp_client): Test server to send HTTP requests.
577
-
578
- Raises:
579
- ConnectionError: If fake matlab server is not reachable from the test server, raises ConnectionError
580
- """
581
-
582
- max_tries = 5
583
- count = 0
584
-
585
- while True:
586
- resp = await test_server.delete(
587
- "/http_delete_request.html", data=json.dumps(proxy_payload)
588
- )
589
-
590
- if resp.status in (HTTPStatus.NOT_FOUND, HTTPStatus.SERVICE_UNAVAILABLE):
591
- time.sleep(1)
592
- count += 1
593
-
594
- else:
595
- resp_body = await resp.text()
596
- assert json.dumps(proxy_payload) == resp_body
597
- break
598
-
599
- if count > max_tries:
600
- raise ConnectionError
601
-
602
-
603
- async def test_matlab_proxy_http_post_request(proxy_payload, test_server):
604
- """Test to check if test_server proxies http post request to fake matlab server.
605
- Checks if payload is being modified before proxying.
606
- Args:
607
- proxy_payload (Dict): Pytest fixture which returns a Dict representing payload for the HTTP Request
608
- test_server (aiohttp_client): Test server to send HTTP requests
609
-
610
- Raises:
611
- ConnectionError: If unable to proxy to fake matlab server raise Connection error
612
- """
613
- max_tries = 5
614
- count = 0
615
-
616
- while True:
617
- resp = await test_server.post(
618
- "/messageservice/json/secure",
619
- data=json.dumps(proxy_payload),
620
- )
621
-
622
- if resp.status in (HTTPStatus.NOT_FOUND, HTTPStatus.SERVICE_UNAVAILABLE):
623
- time.sleep(1)
624
- count += 1
625
-
626
- else:
627
- resp_json = await resp.json()
628
- assert set(resp_json.keys()).issubset(proxy_payload.keys())
629
- break
630
-
631
- if count > max_tries:
632
- raise ConnectionError
633
-
634
-
635
- async def test_set_licensing_info_put_nlm(test_server):
636
- """Test to check endpoint : "/set_licensing_info"
637
-
638
- Test which sends HTTP PUT request with NLM licensing information.
639
- Args:
640
- test_server (aiohttp_client): A aiohttp_client server to send HTTP GET request.
641
- """
642
-
643
- data = {
644
- "type": "nlm",
645
- "status": "starting",
646
- "version": "R2020b",
647
- "connectionString": "123@nlm",
648
- }
649
- resp = await test_server.put("/set_licensing_info", data=json.dumps(data))
650
- assert resp.status == HTTPStatus.OK
651
-
652
-
653
- async def test_set_licensing_info_put_invalid_license(test_server):
654
- """Test to check endpoint : "/set_licensing_info"
655
-
656
- Test which sends HTTP PUT request with INVALID licensing information type.
657
- Args:
658
- test_server (aiohttp_client): A aiohttp_client server to send HTTP GET request.
659
- """
660
-
661
- data = {
662
- "type": "INVALID_TYPE",
663
- "status": "starting",
664
- "version": "R2020b",
665
- "connectionString": "123@nlm",
666
- }
667
- resp = await test_server.put("/set_licensing_info", data=json.dumps(data))
668
- assert resp.status == HTTPStatus.BAD_REQUEST
669
-
670
-
671
- # While acceessing matlab-proxy directly, the web socket request looks like
672
- # {
673
- # "connection": "Upgrade",
674
- # "Upgrade": "websocket",
675
- # }
676
- # whereas while accessing matlab-proxy with nginx as the reverse proxy, the nginx server
677
- # modifies the web socket request to
678
- # {
679
- # "connection": "upgrade",
680
- # "upgrade": "websocket",
681
- # }
682
- @pytest.mark.parametrize(
683
- "headers",
684
- [
685
- CIMultiDict(
686
- {
687
- "connection": "Upgrade",
688
- "Upgrade": "websocket",
689
- }
690
- ),
691
- CIMultiDict(
692
- {
693
- "connection": "upgrade",
694
- "upgrade": "websocket",
695
- }
696
- ),
697
- ],
698
- ids=["Uppercase header", "Lowercase header"],
699
- )
700
- async def test_matlab_view_websocket_success(
701
- mocker,
702
- mock_request,
703
- mock_websocket_messages,
704
- headers,
705
- patch_authenticate_access_decorator, # noqa: F401
706
- ):
707
- """Test successful websocket connection and message forwarding"""
708
-
709
- # Configure request for WebSocket
710
- mock_request.headers = headers
711
- mock_request.method = "GET"
712
- mock_request.path_qs = "/test"
713
-
714
- # Mock WebSocket setup
715
- mock_ws_server = mocker.MagicMock(spec=WebSocketResponse)
716
- mocker.patch(
717
- "matlab_proxy.app.aiohttp.web.WebSocketResponse", return_value=mock_ws_server
718
- )
719
-
720
- # Mock WebSocket client
721
- mock_ws_client = MockWebSocketClient(messages=mock_websocket_messages)
722
- mocker.patch(
723
- "matlab_proxy.app.aiohttp.ClientSession.ws_connect", return_value=mock_ws_client
724
- )
725
-
726
- # Execute
727
- result = await matlab_view(mock_request)
728
-
729
- # Assertions
730
- assert result == mock_ws_server
731
- assert mock_ws_server.send_str.call_count == 1
732
- assert mock_ws_server.send_bytes.call_count == 1
733
- assert mock_ws_server.ping.call_count == 1
734
- assert mock_ws_server.pong.call_count == 1
735
-
736
-
737
- async def test_set_licensing_info_put_mhlm(test_server):
738
- """Test to check endpoint : "/set_licensing_info"
739
-
740
- Test which sends HTTP PUT request with MHLM licensing information.
741
- Args:
742
- test_server (aiohttp_client): A aiohttp_client server to send HTTP GET request.
743
- """
744
- # FIXME: This test is talking to production loginws endpoint and is resulting in an exception.
745
- # TODO: Use mocks to test the mhlm workflows is working as expected
746
- data = {
747
- "type": "mhlm",
748
- "status": "starting",
749
- "version": "R2020b",
750
- "token": "123@nlm",
751
- "emailaddress": "123@nlm",
752
- "sourceId": "123@nlm",
753
- }
754
- resp = await test_server.put("/set_licensing_info", data=json.dumps(data))
755
- assert resp.status == HTTPStatus.OK
756
-
757
-
758
- async def test_set_licensing_info_put_existing_license(test_server):
759
- """Test to check endpoint : "/set_licensing_info"
760
-
761
- Test which sends HTTP PUT request with local licensing information.
762
- Args:
763
- test_server (aiohttp_client): A aiohttp_client server to send HTTP GET request.
764
- """
765
-
766
- data = {"type": "existing_license"}
767
- resp = await test_server.put("/set_licensing_info", data=json.dumps(data))
768
- assert resp.status == HTTPStatus.OK
769
-
770
-
771
- async def test_set_licensing_info_delete(test_server):
772
- """Test to check endpoint : "/set_licensing_info"
773
-
774
- Test which sends HTTP DELETE request to remove licensing. Checks if licensing is set to None
775
- After request is sent.
776
- Args:
777
- test_server (aiohttp_client): A aiohttp_client server to send HTTP GET request.
778
- """
779
-
780
- resp = await test_server.delete("/set_licensing_info")
781
- resp_json = json.loads(await resp.text())
782
- assert resp.status == HTTPStatus.OK and resp_json["licensing"] is None
783
-
784
-
785
- async def test_set_termination_integration_delete(test_server):
786
- """Test to check endpoint : "/shutdown_integration"
787
-
788
- Test which sends HTTP DELETE request to shutdown integration. Checks if integration is shutdown
789
- successfully.
790
- Args:
791
- test_server (aiohttp_client): A aiohttp_client server to send HTTP GET request.
792
- """
793
- # Not awaiting the response here explicitly as the event loop is stopped in the
794
- # handler function.
795
- test_server.delete("/shutdown_integration")
796
-
797
- resp = await test_server.get("/")
798
-
799
- # Assert that the service is unavailable
800
- assert resp.status == 503
801
-
802
-
803
- def test_get_access_url(test_server):
804
- """Should return a url with 127.0.0.1 in test mode
805
-
806
- Args:
807
- test_server (aiohttp.web.Application): Application Server
808
- """
809
-
810
- assert "127.0.0.1" in util.get_access_url(test_server.app)
811
-
812
-
813
- @pytest.fixture(name="non_test_env")
814
- def non_test_env_fixture(monkeypatch):
815
- """Monkeypatches MWI_TEST env var to false
816
-
817
- Args:
818
- monkeypatch (_pytest.monkeypatch.MonkeyPatch): To monkeypatch env vars
819
- """
820
- monkeypatch.setenv(mwi_env.get_env_name_testing(), "false")
821
-
822
-
823
- @pytest.fixture(name="non_default_host_interface")
824
- def non_default_host_interface_fixture(monkeypatch):
825
- """Monkeypatches MWI_TEST env var to false
826
-
827
- Args:
828
- monkeypatch (_pytest.monkeypatch.MonkeyPatch): To monkeypatch env vars
829
- """
830
- monkeypatch.setenv(mwi_env.get_env_name_app_host(), "0.0.0.0")
831
-
832
-
833
- # For pytest fixtures, order of arguments matter.
834
- # First set the default host interface to a non-default value
835
- # Then set MWI_TEST to false and then create an instance of the test_server
836
- # This order will set the test_server with appropriate values.
837
-
838
-
839
- @pytest.mark.skipif(
840
- platform.system() == "Linux" or platform.system() == "Darwin",
841
- reason="Testing the windows access URL",
842
- )
843
- def test_get_access_url_non_dev_windows(
844
- non_default_host_interface, non_test_env, test_server
845
- ):
846
- """Test to check access url to be 127.0.0.1 in non-dev mode on Windows"""
847
- assert "127.0.0.1" in util.get_access_url(test_server.app)
848
-
849
-
850
- @pytest.mark.skipif(
851
- platform.system() == "Windows", reason="Testing the non-Windows access URL"
852
- )
853
- def test_get_access_url_non_dev_posix(
854
- non_default_host_interface, non_test_env, test_server
855
- ):
856
- """Test to check access url to be 0.0.0.0 in non-dev mode on Linux/Darwin"""
857
- assert "0.0.0.0" in util.get_access_url(test_server.app)
858
-
859
-
860
- @pytest.fixture(name="set_licensing_info_mock_fetch_single_entitlement")
861
- def set_licensing_info_mock_fetch_single_entitlement_fixture():
862
- """Fixture that returns a single entitlement
863
-
864
- Returns:
865
- json array: An array consisting of single entitlement information
866
- """
867
- return [
868
- {"id": "Entitlement3", "label": "Label3", "license_number": "License3"},
869
- ]
870
-
871
-
872
- @pytest.fixture(name="set_licensing_info_mock_fetch_multiple_entitlements")
873
- def set_licensing_info_mock_fetch_multiple_entitlements_fixture():
874
- """Fixture that returns multiple entitlements
875
-
876
- Returns:
877
- json array: An array consisting of multiple entitlements
878
- """
879
- return [
880
- {"id": "Entitlement1", "label": "Label1", "license_number": "License1"},
881
- {"id": "Entitlement2", "label": "Label2", "license_number": "License2"},
882
- ]
883
-
884
-
885
- @pytest.fixture(name="set_licensing_info_mock_access_token")
886
- def set_licensing_info_mock_access_token_fixture():
887
- """Pytest fixture that returns a mock token that mimics mw.fetch_access_token() response"""
888
- access_token_string = int("".join([str(random.randint(0, 10)) for _ in range(272)]))
889
- return {
890
- "token": str(access_token_string),
891
- }
892
-
893
-
894
- @pytest.fixture(name="set_licensing_info_mock_expand_token")
895
- def set_licensing_info_mock_expand_token_fixture():
896
- """Pytest fixture which returns a dict
897
-
898
- The return value represents a valid json response when mw.fetch_expand_token function is called.
899
-
900
- Returns:
901
- json data with mimics mw.fetch_expand_token() response
902
- """
903
- now = datetime.datetime.now(timezone.utc)
904
- first_name = "abc"
905
-
906
- json_data = {
907
- "expiry": str((now + timedelta(days=1)).strftime("%Y-%m-%dT%H:%M:%S.%f%z")),
908
- "first_name": first_name,
909
- "last_name": "def",
910
- "display_name": first_name,
911
- "email_addr": "test@test.com",
912
- "user_id": "".join([str(random.randint(0, 10)) for _ in range(13)]),
913
- "profile_id": "".join([str(random.randint(0, 10)) for _ in range(8)]),
914
- }
915
-
916
- return json_data
917
-
918
-
919
- @pytest.fixture(name="set_licensing_info")
920
- async def set_licensing_info_fixture(
921
- mocker,
922
- test_server,
923
- set_licensing_info_mock_expand_token,
924
- set_licensing_info_mock_access_token,
925
- set_licensing_info_mock_fetch_multiple_entitlements,
926
- ):
927
- """Fixture to setup correct licensing state on the server"""
928
- mocker.patch(
929
- "matlab_proxy.app_state.mw.fetch_expand_token",
930
- return_value=set_licensing_info_mock_expand_token,
931
- )
932
-
933
- mocker.patch(
934
- "matlab_proxy.app_state.mw.fetch_access_token",
935
- return_value=set_licensing_info_mock_access_token,
936
- )
937
-
938
- mocker.patch(
939
- "matlab_proxy.app_state.mw.fetch_entitlements",
940
- return_value=set_licensing_info_mock_fetch_multiple_entitlements,
941
- )
942
-
943
- data = {
944
- "type": "mhlm",
945
- "status": "starting",
946
- "version": "R2020b",
947
- "token": "abc@nlm",
948
- "emailAddress": "abc@nlm",
949
- "sourceId": "abc@nlm",
950
- "matlabVersion": "R2023a",
951
- }
952
-
953
- # Waiting for the matlab process to start up.
954
- await wait_for_matlab_to_be_up(test_server, test_constants.ONE_SECOND_DELAY)
955
-
956
- # Set matlab_version to None to check if the version is updated
957
- # after sending a request t o /set_licensing_info endpoint
958
- test_server.server.app["settings"]["matlab_version"] = None
959
-
960
- # Pre-req: stop the matlab that got started during test server startup
961
- resp = await test_server.delete("/stop_matlab")
962
- assert resp.status == HTTPStatus.OK
963
-
964
- resp = await test_server.put("/set_licensing_info", data=json.dumps(data))
965
- assert resp.status == HTTPStatus.OK
966
-
967
- # Assert whether the matlab_version was updated from None when licensing type is mhlm
968
- assert test_server.server.app["settings"]["matlab_version"] == "R2023a"
969
-
970
- return test_server
971
-
972
-
973
- async def test_set_licensing_mhlm_zero_entitlement(
974
- mocker,
975
- set_licensing_info_mock_expand_token,
976
- set_licensing_info_mock_access_token,
977
- test_server,
978
- ):
979
- # Patching the functions where it is used (and not where it is defined)
980
- mocker.patch(
981
- "matlab_proxy.app_state.mw.fetch_expand_token",
982
- return_value=set_licensing_info_mock_expand_token,
983
- )
984
-
985
- mocker.patch(
986
- "matlab_proxy.app_state.mw.fetch_access_token",
987
- return_value=set_licensing_info_mock_access_token,
988
- )
989
-
990
- mocker.patch(
991
- "matlab_proxy.app_state.mw.fetch_entitlements",
992
- side_effect=EntitlementError(
993
- "Your MathWorks account is not linked to a valid license for MATLAB"
994
- ),
995
- )
996
-
997
- data = {
998
- "type": "mhlm",
999
- "status": "starting",
1000
- "version": "R2020b",
1001
- "token": "abc@nlm",
1002
- "emailaddress": "abc@nlm",
1003
- "sourceId": "abc@nlm",
1004
- }
1005
- # Pre-req: stop the matlab that got started as during test server startup
1006
- resp = await test_server.delete("/stop_matlab")
1007
- assert resp.status == HTTPStatus.OK
1008
-
1009
- resp = await test_server.put("/set_licensing_info", data=json.dumps(data))
1010
- assert resp.status == HTTPStatus.OK
1011
- resp_json = await resp.json()
1012
- expectedError = EntitlementError(message="entitlement error")
1013
- assert resp_json["error"]["type"] == type(expectedError).__name__
1014
-
1015
-
1016
- async def test_set_licensing_mhlm_single_entitlement(
1017
- mocker,
1018
- test_server,
1019
- set_licensing_info_mock_expand_token,
1020
- set_licensing_info_mock_access_token,
1021
- set_licensing_info_mock_fetch_single_entitlement,
1022
- ):
1023
- mocker.patch(
1024
- "matlab_proxy.app_state.mw.fetch_expand_token",
1025
- return_value=set_licensing_info_mock_expand_token,
1026
- )
1027
-
1028
- mocker.patch(
1029
- "matlab_proxy.app_state.mw.fetch_access_token",
1030
- return_value=set_licensing_info_mock_access_token,
1031
- )
1032
-
1033
- mocker.patch(
1034
- "matlab_proxy.app_state.mw.fetch_entitlements",
1035
- return_value=set_licensing_info_mock_fetch_single_entitlement,
1036
- )
1037
-
1038
- data = {
1039
- "type": "mhlm",
1040
- "status": "starting",
1041
- "version": "R2020b",
1042
- "token": "abc@nlm",
1043
- "emailAddress": "abc@nlm",
1044
- "sourceId": "abc@nlm",
1045
- }
1046
- # Pre-req: stop the matlab that got started during test server startup
1047
- resp = await test_server.delete("/stop_matlab")
1048
- assert resp.status == HTTPStatus.OK
1049
-
1050
- resp = await test_server.put("/set_licensing_info", data=json.dumps(data))
1051
- assert resp.status == HTTPStatus.OK
1052
- resp_json = await resp.json()
1053
- assert len(resp_json["licensing"]["entitlements"]) == 1
1054
- assert resp_json["licensing"]["entitlementId"] == "Entitlement3"
1055
-
1056
- # validate that MATLAB has started correctly
1057
- await __check_for_matlab_status(test_server, "up", sleep_interval=2)
1058
-
1059
- # test-cleanup: unset licensing
1060
- # without this, we can leave test drool related to cached license file
1061
- # which can impact other non-dev workflows
1062
- resp = await test_server.delete("/set_licensing_info")
1063
- assert resp.status == HTTPStatus.OK
1064
-
1065
-
1066
- async def test_set_licensing_mhlm_multi_entitlements(
1067
- mocker,
1068
- test_server,
1069
- set_licensing_info_mock_expand_token,
1070
- set_licensing_info_mock_access_token,
1071
- set_licensing_info_mock_fetch_multiple_entitlements,
1072
- ):
1073
- mocker.patch(
1074
- "matlab_proxy.app_state.mw.fetch_expand_token",
1075
- return_value=set_licensing_info_mock_expand_token,
1076
- )
1077
-
1078
- mocker.patch(
1079
- "matlab_proxy.app_state.mw.fetch_access_token",
1080
- return_value=set_licensing_info_mock_access_token,
1081
- )
1082
-
1083
- mocker.patch(
1084
- "matlab_proxy.app_state.mw.fetch_entitlements",
1085
- return_value=set_licensing_info_mock_fetch_multiple_entitlements,
1086
- )
1087
-
1088
- data = {
1089
- "type": "mhlm",
1090
- "status": "starting",
1091
- "version": "R2020b",
1092
- "token": "abc@nlm",
1093
- "emailaddress": "abc@nlm",
1094
- "sourceId": "abc@nlm",
1095
- }
1096
- # Pre-req: stop the matlab that got started as during test server startup
1097
- resp = await test_server.delete("/stop_matlab")
1098
- assert resp.status == HTTPStatus.OK
1099
-
1100
- resp = await test_server.put("/set_licensing_info", data=json.dumps(data))
1101
- assert resp.status == HTTPStatus.OK
1102
- resp_json = await resp.json()
1103
- assert len(resp_json["licensing"]["entitlements"]) == 2
1104
- assert resp_json["licensing"]["entitlementId"] == None
1105
-
1106
- # MATLAB should not start if there are multiple entitlements and
1107
- # user hasn't selected the license yet
1108
- resp = await test_server.get("/get_status")
1109
- assert resp.status == HTTPStatus.OK
1110
- __check_for_matlab_status(test_server, "down")
1111
-
1112
- # test-cleanup: unset licensing
1113
- resp = await test_server.delete("/set_licensing_info")
1114
- assert resp.status == HTTPStatus.OK
1115
-
1116
-
1117
- async def test_update_entitlement_with_correct_entitlement(set_licensing_info):
1118
- data = {
1119
- "type": "mhlm",
1120
- "entitlement_id": "Entitlement1",
1121
- }
1122
- # This test_server is pre-configured with multiple entitlements on app state but no entitlmentId
1123
- test_server = set_licensing_info
1124
- resp = await test_server.put("/update_entitlement", data=json.dumps(data))
1125
- assert resp.status == HTTPStatus.OK
1126
- resp_json = await resp.json()
1127
- assert resp_json["matlab"]["status"] != "down"
1128
-
1129
- # test-cleanup: unset licensing
1130
- resp = await test_server.delete("/set_licensing_info")
1131
- assert resp.status == HTTPStatus.OK
1132
-
1133
-
1134
- async def test_get_auth_token_route(test_server):
1135
- """Test to check endpoint : "/get_auth_token"
1136
-
1137
- Args:
1138
- test_server (aiohttp_client): A aiohttp_client server for sending GET request.
1139
- """
1140
- resp = await test_server.get("/get_auth_token")
1141
- res_json = await resp.json()
1142
- # Testing the default dev configuration where the auth is disabled
1143
- assert res_json["token"] == None
1144
- assert resp.status == HTTPStatus.OK
1145
-
1146
-
1147
- async def test_check_for_concurrency(test_server):
1148
- """Test to check the response from endpoint : "/get_status" with different query parameters
1149
-
1150
- Test requests the "/get_status" endpoint with different query parameters to check
1151
- how the server responds.
1152
-
1153
- Args:
1154
- test_server (aiohttp_client): A aiohttp_client server to send GET request to.
1155
- """
1156
- # Request server to check if concurrency check is enabled.
1157
-
1158
- env_resp = await test_server.get("/get_env_config")
1159
- assert env_resp.status == HTTPStatus.OK
1160
- env_resp_json = json.loads(await env_resp.text())
1161
- if env_resp_json["isConcurrencyEnabled"]:
1162
- # A normal request should not repond with client id or active status
1163
- status_resp = await test_server.get("/get_status")
1164
- assert status_resp.status == HTTPStatus.OK
1165
- status_resp_json = json.loads(await status_resp.text())
1166
- assert "clientId" not in status_resp_json
1167
- assert "isActiveClient" not in status_resp_json
1168
-
1169
- # When the request comes from the desktop app the server should respond with client id and active status
1170
- status_resp = await test_server.get('/get_status?IS_DESKTOP="true"')
1171
- assert status_resp.status == HTTPStatus.OK
1172
- status_resp_json = json.loads(await status_resp.text())
1173
- assert "clientId" in status_resp_json
1174
- assert "isActiveClient" in status_resp_json
1175
-
1176
- # When the desktop client requests for a session transfer without client id respond with cliend id and active status should be true
1177
- status_resp = await test_server.get(
1178
- '/get_status?IS_DESKTOP="true"&TRANSFER_SESSION="true"'
1179
- )
1180
- assert status_resp.status == HTTPStatus.OK
1181
- status_resp_json = json.loads(await status_resp.text())
1182
- assert "clientId" in status_resp_json
1183
- assert status_resp_json["isActiveClient"] == True
1184
-
1185
- # When transfering the session is requested by a client whihc is not a desktop client it should be ignored
1186
- status_resp = await test_server.get('/get_status?TRANSFER_SESSION="true"')
1187
- assert status_resp.status == HTTPStatus.OK
1188
- status_resp_json = json.loads(await status_resp.text())
1189
- assert "clientId" not in status_resp_json
1190
- assert "isActiveClient" not in status_resp_json
1191
-
1192
- # When the desktop client requests for a session transfer with a client id then respond only with active status
1193
- status_resp = await test_server.get(
1194
- '/get_status?IS_DESKTOP="true"&MWI_CLIENT_ID="foobar"&TRANSFER_SESSION="true"'
1195
- )
1196
- assert status_resp.status == HTTPStatus.OK
1197
- status_resp_json = json.loads(await status_resp.text())
1198
- assert "clientId" not in status_resp_json
1199
- assert status_resp_json["isActiveClient"] == True
1200
- else:
1201
- # When Concurrency check is disabled the response should not contain client id or active status
1202
- status_resp = await test_server.get("/get_status")
1203
- assert status_resp.status == HTTPStatus.OK
1204
- status_resp_json = json.loads(await status_resp.text())
1205
- assert "clientId" not in status_resp_json
1206
- assert "isActiveClient" not in status_resp_json
1207
- status_resp = await test_server.get(
1208
- '/get_status?IS_DESKTOP="true"&MWI_CLIENT_ID="foobar"&TRANSFER_SESSION="true"'
1209
- )
1210
- assert status_resp.status == HTTPStatus.OK
1211
- status_resp_json = json.loads(await status_resp.text())
1212
- assert "clientId" not in status_resp_json
1213
- assert "isActiveClient" not in status_resp_json
1214
-
1215
-
1216
- # Pytest construct to set the environment variable `MWI_ENABLE_COOKIE_JAR` to `"True"`
1217
- # before initializing the test_server.
1218
- @pytest.mark.parametrize(
1219
- "test_server",
1220
- [
1221
- [(mwi_env.Experimental.get_env_name_use_cookie_cache(), "True")],
1222
- ],
1223
- indirect=True,
1224
- )
1225
- async def test_cookie_jar_http_request(proxy_payload, test_server):
1226
- # Arrange
1227
- actual_custom_cookie = cookies.Morsel()
1228
- actual_custom_cookie.set("custom_cookie", "cookie_value", "cookie_value")
1229
- actual_custom_cookie["domain"] = "example.com"
1230
- actual_custom_cookie["path"] = "/"
1231
- actual_custom_cookie["HttpOnly"] = True
1232
- actual_custom_cookie["expires"] = (
1233
- datetime.datetime.now() + timedelta(days=1)
1234
- ).strftime("%a, %d-%b-%Y %H:%M:%S GMT")
1235
-
1236
- await wait_for_matlab_to_be_up(test_server, test_constants.ONE_SECOND_DELAY)
1237
-
1238
- # Manually update cookie in cookie jar
1239
- test_server.app["settings"]["cookie_jar"]._cookie_jar[
1240
- "custom_cookie"
1241
- ] = actual_custom_cookie
1242
-
1243
- # Act
1244
- async with await test_server.get(
1245
- "/http_get_request.html", data=json.dumps(proxy_payload)
1246
- ) as _:
1247
- expected_custom_cookie = test_server.app["settings"]["cookie_jar"]._cookie_jar[
1248
- "custom_cookie"
1249
- ]
1250
-
1251
- # Assert
1252
- assert actual_custom_cookie == expected_custom_cookie
1253
-
1254
-
1255
- # Pytest construct to set the environment variable `MWI_ENABLE_COOKIE_JAR` to `"True"`
1256
- # before initializing the test_server.
1257
- @pytest.mark.parametrize(
1258
- "test_server",
1259
- [
1260
- [(mwi_env.Experimental.get_env_name_use_cookie_cache(), "True")],
1261
- ],
1262
- indirect=True,
1263
- )
1264
- async def test_cookie_jar_web_socket(proxy_payload, test_server):
1265
- # Arrange
1266
-
1267
- # Createa a custom cookie
1268
- actual_custom_cookie = cookies.Morsel()
1269
- actual_custom_cookie.set("custom_cookie", "cookie_value", "cookie_value")
1270
- actual_custom_cookie["domain"] = "example.com"
1271
- actual_custom_cookie["path"] = "/"
1272
- actual_custom_cookie["expires"] = (
1273
- datetime.datetime.now() + timedelta(days=1)
1274
- ).strftime("%a, %d-%b-%Y %H:%M:%S GMT")
1275
-
1276
- # Update cookie in cookie jar
1277
- test_server.app["settings"]["cookie_jar"]._cookie_jar[
1278
- "custom_cookie"
1279
- ] = actual_custom_cookie
1280
-
1281
- await wait_for_matlab_to_be_up(test_server, test_constants.ONE_SECOND_DELAY)
1282
-
1283
- # Act
1284
- async with test_server.get(
1285
- "/http_ws_request.html/",
1286
- headers={
1287
- # Headers required to initiate a websocket connection
1288
- # First 2 headers are required for the connection upgrade
1289
- "Connection": "upgrade",
1290
- "upgrade": "websocket",
1291
- "Sec-WebSocket-Version": "13", # Required for initiating the websocket handshake with aiohttp server
1292
- "Sec-WebSocket-Key": "dGhlIHNhbXBsZSBub25jZQ==", # Optional unique key for the websocket handshake
1293
- },
1294
- ) as _:
1295
- expected_custom_cookie = test_server.app["settings"]["cookie_jar"]._cookie_jar[
1296
- "custom_cookie"
1297
- ]
1298
- # Assert
1299
- assert actual_custom_cookie == expected_custom_cookie