matlab-proxy 0.15.0__py3-none-any.whl → 0.16.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 (41) hide show
  1. matlab_proxy/app.py +13 -7
  2. matlab_proxy/app_state.py +9 -6
  3. matlab_proxy/constants.py +1 -0
  4. matlab_proxy/gui/asset-manifest.json +3 -3
  5. matlab_proxy/gui/index.html +1 -1
  6. matlab_proxy/gui/static/js/{main.14aa7840.js → main.522d83ba.js} +3 -3
  7. matlab_proxy/gui/static/js/main.522d83ba.js.map +1 -0
  8. matlab_proxy/settings.py +7 -4
  9. matlab_proxy/util/__init__.py +8 -1
  10. matlab_proxy/util/mwi/token_auth.py +19 -5
  11. {matlab_proxy-0.15.0.dist-info → matlab_proxy-0.16.0.dist-info}/METADATA +1 -1
  12. {matlab_proxy-0.15.0.dist-info → matlab_proxy-0.16.0.dist-info}/RECORD +40 -20
  13. tests/integration/integration_tests_with_license/test_http_end_points.py +4 -4
  14. tests/integration/integration_tests_without_license/conftest.py +4 -3
  15. tests/integration/integration_tests_without_license/test_matlab_is_down_if_unlicensed.py +3 -0
  16. tests/unit/__init__.py +1 -0
  17. tests/unit/conftest.py +67 -0
  18. tests/unit/test_app.py +1113 -0
  19. tests/unit/test_app_state.py +586 -0
  20. tests/unit/test_constants.py +6 -0
  21. tests/unit/test_ddux.py +22 -0
  22. tests/unit/test_devel.py +246 -0
  23. tests/unit/test_non_dev_mode.py +169 -0
  24. tests/unit/test_settings.py +460 -0
  25. tests/unit/util/__init__.py +3 -0
  26. tests/unit/util/mwi/__init__.py +1 -0
  27. tests/unit/util/mwi/embedded_connector/__init__.py +1 -0
  28. tests/unit/util/mwi/embedded_connector/test_helpers.py +29 -0
  29. tests/unit/util/mwi/embedded_connector/test_request.py +64 -0
  30. tests/unit/util/mwi/test_custom_http_headers.py +281 -0
  31. tests/unit/util/mwi/test_logger.py +49 -0
  32. tests/unit/util/mwi/test_token_auth.py +303 -0
  33. tests/unit/util/mwi/test_validators.py +331 -0
  34. tests/unit/util/test_mw.py +550 -0
  35. tests/unit/util/test_util.py +135 -0
  36. matlab_proxy/gui/static/js/main.14aa7840.js.map +0 -1
  37. /matlab_proxy/gui/static/js/{main.14aa7840.js.LICENSE.txt → main.522d83ba.js.LICENSE.txt} +0 -0
  38. {matlab_proxy-0.15.0.dist-info → matlab_proxy-0.16.0.dist-info}/LICENSE.md +0 -0
  39. {matlab_proxy-0.15.0.dist-info → matlab_proxy-0.16.0.dist-info}/WHEEL +0 -0
  40. {matlab_proxy-0.15.0.dist-info → matlab_proxy-0.16.0.dist-info}/entry_points.txt +0 -0
  41. {matlab_proxy-0.15.0.dist-info → matlab_proxy-0.16.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,586 @@
1
+ # Copyright 2023-2024 The MathWorks, Inc.
2
+
3
+ import json
4
+ import os
5
+ from dataclasses import dataclass
6
+ from pathlib import Path
7
+ from typing import Optional
8
+
9
+ import pytest
10
+
11
+ from matlab_proxy import settings
12
+ from matlab_proxy.app_state import AppState
13
+ from matlab_proxy.constants import MWI_AUTH_TOKEN_NAME_FOR_HTTP
14
+ from matlab_proxy.util.mwi.exceptions import LicensingError, MatlabError
15
+ from tests.unit.util import MockResponse
16
+
17
+
18
+ @pytest.fixture
19
+ def sample_settings_fixture(tmp_path):
20
+ """A pytest fixture which returns a dict containing sample settings for the AppState class.
21
+
22
+ Args:
23
+ tmp_path : Builtin pytest fixture
24
+
25
+ Returns:
26
+ dict: A dictionary of sample settings
27
+ """
28
+ tmp_file = tmp_path / "parent_1" / "parent_2" / "tmp_file.json"
29
+ return {
30
+ "error": None,
31
+ "warnings": [],
32
+ "matlab_config_file": tmp_file,
33
+ "is_xvfb_available": True,
34
+ "mwi_server_url": "dummy",
35
+ "mwi_logs_root_dir": Path(settings.get_mwi_config_folder(dev=True)),
36
+ "app_port": 12345,
37
+ "mwapikey": "asdf",
38
+ }
39
+
40
+
41
+ @pytest.fixture
42
+ def app_state_fixture(sample_settings_fixture):
43
+ """A pytest fixture which returns an instance of AppState class with no errors.
44
+
45
+ Args:
46
+ sample_settings_fixture (dict): A dictionary of sample settings to be used by
47
+
48
+ Returns:
49
+ AppState: An object of the AppState class
50
+ """
51
+ app_state = AppState(settings=sample_settings_fixture)
52
+ app_state.processes = {"matlab": None, "xvfb": None}
53
+ app_state.licensing = {"type": "existing_license"}
54
+ return app_state
55
+
56
+
57
+ @pytest.fixture
58
+ def sample_token_headers_fixture():
59
+ return {MWI_AUTH_TOKEN_NAME_FOR_HTTP: "asdf"}
60
+
61
+
62
+ @pytest.fixture
63
+ def app_state_with_token_auth_fixture(
64
+ app_state_fixture, sample_token_headers_fixture, tmp_path
65
+ ):
66
+ """Pytest fixture which returns AppState instance with token authentication enabled.
67
+
68
+ Args:
69
+ app_state_fixture (AppState): Pytest fixture
70
+ tmp_path (str): Built-in pytest fixture
71
+
72
+ Returns:
73
+ (AppState, dict): Instance of the AppState class with token authentication enabled and token headers
74
+ """
75
+ tmp_matlab_ready_file = Path(tmp_path) / "tmp_file.txt"
76
+ tmp_matlab_ready_file.touch()
77
+ ((mwi_auth_token_name, mwi_auth_token_hash),) = sample_token_headers_fixture.items()
78
+ app_state_fixture.matlab_session_files["matlab_ready_file"] = tmp_matlab_ready_file
79
+ app_state_fixture.settings["mwi_is_token_auth_enabled"] = True
80
+ app_state_fixture.settings["mwi_auth_token_name_for_env"] = mwi_auth_token_name
81
+ app_state_fixture.settings["mwi_auth_token_name_for_http"] = (
82
+ MWI_AUTH_TOKEN_NAME_FOR_HTTP
83
+ )
84
+ app_state_fixture.settings["mwi_auth_token_hash"] = mwi_auth_token_hash
85
+ app_state_fixture.settings["mwi_server_url"] = "http://localhost:8888"
86
+
87
+ return app_state_fixture
88
+
89
+
90
+ @pytest.fixture
91
+ def mocker_os_patching_fixture(mocker, platform):
92
+ """A pytest fixture which patches the is_* functions in system.py module
93
+
94
+ Args:
95
+ mocker : Built in pytest fixture
96
+ platform (str): A string representing "windows", "linux" or "mac"
97
+
98
+ Returns:
99
+ mocker: Built in pytest fixture with patched calls to system.py module.
100
+ """
101
+ mocker.patch("matlab_proxy.app_state.system.is_linux", return_value=False)
102
+ mocker.patch("matlab_proxy.app_state.system.is_windows", return_value=False)
103
+ mocker.patch("matlab_proxy.app_state.system.is_mac", return_value=False)
104
+ mocker.patch("matlab_proxy.app_state.system.is_posix", return_value=False)
105
+
106
+ if platform == "linux":
107
+ mocker.patch("matlab_proxy.app_state.system.is_linux", return_value=True)
108
+ mocker.patch("matlab_proxy.app_state.system.is_posix", return_value=True)
109
+
110
+ elif platform == "windows":
111
+ mocker.patch("matlab_proxy.app_state.system.is_windows", return_value=True)
112
+ mocker.patch("matlab_proxy.app_state.system.is_posix", return_value=False)
113
+
114
+ else:
115
+ mocker.patch("matlab_proxy.app_state.system.is_mac", return_value=True)
116
+ mocker.patch("matlab_proxy.app_state.system.is_posix", return_value=True)
117
+
118
+ return mocker
119
+
120
+
121
+ @dataclass(frozen=True)
122
+ class Mock_xvfb:
123
+ """An immutable dataclass representing a mocked Xvfb process"""
124
+
125
+ returncode: Optional[int]
126
+ pid: Optional[int]
127
+
128
+
129
+ @dataclass(frozen=True)
130
+ class Mock_matlab:
131
+ """An immutable dataclass representing a mocked MATLAB process"""
132
+
133
+ returncode: Optional[int]
134
+ pid: Optional[int]
135
+
136
+
137
+ @pytest.mark.parametrize(
138
+ "licensing, expected",
139
+ [
140
+ (None, False),
141
+ ({"type": "nlm", "conn_str": "123@host"}, True),
142
+ ({"type": "nlm"}, False),
143
+ ({"type": "mhlm", "identity_token": "random_token"}, False),
144
+ (
145
+ {
146
+ "type": "mhlm",
147
+ "identity_token": "random_token",
148
+ "source_id": "dummy_id",
149
+ "expiry": "Jan 1, 1970",
150
+ "entitlement_id": "123456",
151
+ },
152
+ True,
153
+ ),
154
+ ({"type": "existing_license"}, True),
155
+ ({"type": "invalid_type"}, False),
156
+ ],
157
+ ids=[
158
+ "None licensing",
159
+ "happy path-nlm",
160
+ "incomplete nlm data",
161
+ "incomplete mhlm data",
162
+ "happy path-mhlm",
163
+ "happy path-existing license",
164
+ "invalid license",
165
+ ],
166
+ )
167
+ def test_is_licensed(app_state_fixture, licensing, expected):
168
+ """Test to check is_licensed()
169
+
170
+ Args:
171
+ app_state_fixture (AppState): Object of AppState class with defaults set
172
+ licensing (dict): Represents licensing information
173
+ expected (bool): Expected return value.
174
+ """
175
+ # Arrange
176
+ # Nothing to arrange
177
+
178
+ # Act
179
+ app_state_fixture.licensing = licensing
180
+
181
+ # Assert
182
+ assert app_state_fixture.is_licensed() == expected
183
+
184
+
185
+ @pytest.mark.parametrize(
186
+ "err, expected_err",
187
+ [
188
+ (MatlabError(message="dummy error"), MatlabError(message="dummy")),
189
+ (LicensingError(message="license issue"), None),
190
+ ],
191
+ ids=["Any error except licensing error", "licensing error"],
192
+ )
193
+ def test_unset_licensing(err, app_state_fixture, expected_err):
194
+ """Test to check unset_liecnsing removes licensing from the AppState object
195
+
196
+ Args:
197
+ err (Exception): Custom exceptions defined in exceptions.py
198
+ licensing (bool): Whether licensing info is removed
199
+ expected_err (Exception): Expected exception
200
+ """
201
+ # Arrange
202
+ app_state_fixture.error = err
203
+
204
+ # Act
205
+ app_state_fixture.unset_licensing()
206
+
207
+ # Assert
208
+ assert app_state_fixture.licensing == None
209
+ assert type(app_state_fixture.error) is type(expected_err)
210
+
211
+
212
+ # config file is deleted when licensing info is not set i.e. set to None
213
+ def test_persist_licensing_when_licensing_info_is_not_set(app_state_fixture):
214
+ """Test to check if data is not persisted to a file if licensing info is not present
215
+
216
+ Args:
217
+ tmp_path (Path): Built in pytest fixture
218
+ """
219
+ # Arrange
220
+ # Nothing to arrange
221
+ app_state_fixture.licensing = None
222
+
223
+ # Act
224
+ app_state_fixture.persist_config_data()
225
+
226
+ # Assert
227
+ assert os.path.exists(app_state_fixture.settings["matlab_config_file"]) is False
228
+
229
+
230
+ @pytest.mark.parametrize(
231
+ "licensing_data",
232
+ [
233
+ ({"type": "nlm", "conn_str": "123@host"}),
234
+ (
235
+ {
236
+ "type": "mhlm",
237
+ "identity_token": "random_token",
238
+ "source_id": "dummy_id",
239
+ "expiry": "Jan 1, 1970",
240
+ "entitlement_id": "123456",
241
+ }
242
+ ),
243
+ ({"type": "existing_license"}),
244
+ ],
245
+ ids=["nlm type", "mhlm type", "existing license type"],
246
+ )
247
+ def test_persist_config_data(licensing_data: dict, tmp_path):
248
+ """Test to check if persist_licensing() writes data to the file system
249
+
250
+ Args:
251
+ data (dict): Represents matlab-proxy licensing data
252
+ tmp_path : Built-in pytest fixture.
253
+ """
254
+ # Arrange
255
+ tmp_file = tmp_path / "parent_1" / "parent_2" / "tmp_file.json"
256
+ settings = {
257
+ "matlab_config_file": tmp_file,
258
+ "error": None,
259
+ "matlab_version": None,
260
+ "warnings": [],
261
+ }
262
+ app_state = AppState(settings=settings)
263
+ app_state.licensing = licensing_data
264
+
265
+ cached_data = {"licensing": licensing_data, "matlab": {"version": None}}
266
+
267
+ # Act
268
+ app_state.persist_config_data()
269
+ with open(tmp_file, "r") as file:
270
+ got = file.read()
271
+
272
+ # Assert
273
+ assert json.loads(got) == cached_data
274
+
275
+
276
+ validate_required_processes_test_data = [
277
+ (None, None, "linux", False), # xvfb is None == True
278
+ (None, Mock_xvfb(None, 1), "linux", False), # matlab is None == True
279
+ (
280
+ Mock_matlab(None, 1),
281
+ Mock_xvfb(None, 1),
282
+ "linux",
283
+ True,
284
+ ), # All branches are skipped and nothing returned
285
+ (
286
+ Mock_matlab(None, 1),
287
+ Mock_xvfb(123, 2),
288
+ "linux",
289
+ False,
290
+ ), # xvfb.returncode is not None == True
291
+ (
292
+ Mock_matlab(123, 1),
293
+ Mock_xvfb(None, 2),
294
+ "linux",
295
+ False,
296
+ ), # matlab.returncode is not None == True
297
+ (
298
+ Mock_matlab(None, 1),
299
+ None,
300
+ "linux",
301
+ True,
302
+ ), # Xvfb not found on path
303
+ ]
304
+
305
+
306
+ @pytest.mark.parametrize(
307
+ "matlab, xvfb, platform, expected",
308
+ validate_required_processes_test_data,
309
+ ids=[
310
+ "processes_not_running",
311
+ "matlab_not_running",
312
+ "All_required_processes_running",
313
+ "All_processes_running_with_xvfb_returning_non_zero_code",
314
+ "All_processes_running_with_matlab_returning_non_zero_code",
315
+ "xvfb_is_optional_matlab_starts_without_it",
316
+ ],
317
+ )
318
+ def test_are_required_processes_ready(
319
+ app_state_fixture, mocker_os_patching_fixture, matlab, xvfb, expected
320
+ ):
321
+ """Test to check if required processes are ready
322
+
323
+ Args:
324
+ app_state_fixture (AppState): Object of AppState class with defaults set
325
+ mocker_os_patching_fixture (mocker): Custom pytest fixture for mocking
326
+ matlab (Mock_matlab): Represents a mocked MATLAB process
327
+ xvfb (Mock_xvfb): Represents a mocked Xvfb process
328
+ expected (bool): Expected return value based on process return code
329
+ """
330
+ # Arrange
331
+ app_state_fixture.processes = {"matlab": matlab, "xvfb": xvfb}
332
+ if not xvfb:
333
+ app_state_fixture.settings["is_xvfb_available"] = False
334
+
335
+ # Act
336
+ actual = app_state_fixture._are_required_processes_ready()
337
+
338
+ # Assert
339
+ assert actual == expected
340
+
341
+
342
+ get_matlab_status_based_on_connector_status_test_data = [
343
+ ("up", True, "up"),
344
+ ("down", True, "starting"),
345
+ ("up", False, "starting"),
346
+ ]
347
+
348
+
349
+ @pytest.mark.parametrize(
350
+ "connector_status, ready_file_present, matlab_status",
351
+ get_matlab_status_based_on_connector_status_test_data,
352
+ ids=["connector_up", "connector_down", "connector_up_ready_file_not_present"],
353
+ )
354
+ async def test_get_matlab_status_based_on_connector_status(
355
+ mocker, app_state_fixture, connector_status, ready_file_present, matlab_status
356
+ ):
357
+ """Test to check matlab status based on connector status
358
+
359
+ Args:
360
+ mocker : Built in pytest fixture.
361
+ connector_status (str): Status of Embedded Connector.
362
+ ready_file_present (bool): Represents if the ready file has been created or not.
363
+ matlab_status (str): Represents the status of MATLAB process.
364
+ """
365
+ # Arrange
366
+ mocker.patch(
367
+ "matlab_proxy.app_state.mwi.embedded_connector.request.get_state",
368
+ return_value=connector_status,
369
+ )
370
+ mocker.patch.object(Path, "exists", return_value=ready_file_present)
371
+ app_state_fixture.settings["mwi_is_token_auth_enabled"] = False
372
+ app_state_fixture.matlab_session_files["matlab_ready_file"] = Path("dummy")
373
+
374
+ # Act
375
+ actual_matlab_status = await app_state_fixture._get_matlab_connector_status()
376
+
377
+ # Assert
378
+ assert actual_matlab_status == matlab_status
379
+
380
+
381
+ @pytest.mark.parametrize(
382
+ "valid_processes, connector_status, expected",
383
+ [
384
+ (True, "up", "up"),
385
+ (False, "up", "down"),
386
+ (True, "down", "down"),
387
+ ],
388
+ ids=[
389
+ "valid_processes_connector_up",
390
+ "invalid_processes_connector_up",
391
+ "valid_processes_connector_down",
392
+ ],
393
+ )
394
+ async def test_get_matlab_state(
395
+ app_state_fixture, mocker, valid_processes, connector_status, expected
396
+ ):
397
+ """Test to check get_matlab_state returns the correct MATLAB state based on the connector status
398
+
399
+ Args:
400
+ app_state_fixture (AppState): Object of AppState class with defaults set
401
+ mocker : Built in pytest fixture
402
+ valid_processes (bool): Represents if the processes are valid or not
403
+ connector_status (str): Status of Embedded Connector.
404
+ expected (str): Expected status of MATLAB process.
405
+ """
406
+ # Arrange
407
+ mocker.patch.object(
408
+ AppState,
409
+ "_are_required_processes_ready",
410
+ return_value=valid_processes,
411
+ )
412
+ mocker.patch.object(
413
+ AppState,
414
+ "_get_matlab_connector_status",
415
+ return_value=connector_status,
416
+ )
417
+
418
+ # Act
419
+ actual_state = await app_state_fixture.get_matlab_state()
420
+
421
+ # Assert
422
+ assert actual_state == expected
423
+
424
+
425
+ @pytest.mark.parametrize("platform", [("linux"), ("windows"), ("mac")])
426
+ async def test_track_embedded_connector(mocker_os_patching_fixture, app_state_fixture):
427
+ """Test to check track_embedded_connector task
428
+
429
+ Args:
430
+ mocker_os_patching_fixture (mocker): Custom pytest fixture for mocking
431
+ app_state_fixture (AppState): Object of AppState class with defaults set
432
+ """
433
+
434
+ # Arrange
435
+ # patching embedded_connector_start_time to EPOCH+1 seconds and state to be "down"
436
+ mocker_os_patching_fixture.patch.object(
437
+ app_state_fixture, "embedded_connector_start_time", new=float(1.0)
438
+ )
439
+ mocker_os_patching_fixture.patch.object(
440
+ app_state_fixture, "embedded_connector_state", return_value="down"
441
+ )
442
+
443
+ # verify that stop_matlab() is called once
444
+ spy = mocker_os_patching_fixture.spy(app_state_fixture, "stop_matlab")
445
+
446
+ # Act
447
+ await app_state_fixture._AppState__track_embedded_connector_state()
448
+
449
+ # Assert
450
+ spy.assert_called_once()
451
+
452
+
453
+ @pytest.mark.parametrize(
454
+ "env_var_name, filter_prefix, is_filtered",
455
+ [("MWI_AUTH_TOKEN", "MWI_", None), ("MWIFOO_AUTH_TOKEN", "MWI_", "foo")],
456
+ ids=["env_var_is_filtered", "env_var_is_not_filtered"],
457
+ )
458
+ def test_env_variables_filtration_for_xvfb_process(
459
+ monkeypatch, env_var_name, filter_prefix, is_filtered
460
+ ):
461
+ """Test to check if __filter_env_variables filters environment variables with a certain prefix correctly.
462
+
463
+ Args:
464
+ monkeypatch (Object): Built-in pytest fixture for monkeypatching
465
+ env_var_name (str): Name of the environment variable
466
+ filter_prefix (str): Prefix to check for filtering
467
+ is_filtered (bool): To check if the env variable with specified prefix is filtered.
468
+ """
469
+ # Arrange
470
+ env_var = env_var_name
471
+ monkeypatch.setenv(env_var, "foo")
472
+
473
+ # Act
474
+ filtered_env_vars: dict = AppState._AppState__filter_env_variables(
475
+ os.environ, filter_prefix
476
+ )
477
+
478
+ # Assert
479
+ assert filtered_env_vars.get(env_var) == is_filtered
480
+
481
+
482
+ @pytest.mark.parametrize(
483
+ "platform, expected_output",
484
+ [("linux", "stdout"), ("windows", "file"), ("mac", "stdout")],
485
+ )
486
+ async def test_setup_env_for_matlab(
487
+ mocker_os_patching_fixture, platform, expected_output, app_state_fixture, tmp_path
488
+ ):
489
+ """Test to check MW_DIAGNOSTIC_DEST is set appropriately for posix and non-posix systems
490
+
491
+ Args:
492
+ mocker_os_patching_fixture (mocker): Custom pytest fixture for mocking
493
+ platform (str): string describing a platform
494
+ app_state_fixture (AppState): Object of AppState class with defaults set
495
+ tmp_path (Path): Built-in pytest fixture for temporary paths
496
+ """
497
+
498
+ # Arrange
499
+ app_state_fixture.licensing = {"type": "existing_license"}
500
+ app_state_fixture.settings = {"mwapikey": None, "matlab_display": ":1"}
501
+ app_state_fixture.mwi_logs_dir = tmp_path
502
+ mocker_os_patching_fixture.patch(
503
+ "matlab_proxy.app_state.logger.isEnabledFor", return_value=True
504
+ )
505
+
506
+ # Act
507
+ matlab_env = await app_state_fixture._AppState__setup_env_for_matlab()
508
+
509
+ # Assert
510
+ assert expected_output in matlab_env["MW_DIAGNOSTIC_DEST"]
511
+
512
+
513
+ @pytest.mark.parametrize(
514
+ "function_to_call ,mock_response",
515
+ [
516
+ ("_get_matlab_connector_status", MockResponse(ok=True)),
517
+ (
518
+ "_AppState__send_stop_request_to_matlab",
519
+ MockResponse(
520
+ ok=True, payload={"messages": {"EvalResponse": [{"isError": None}]}}
521
+ ),
522
+ ),
523
+ ],
524
+ ids=["request matlab connector status", "send request to stop matlab"],
525
+ )
526
+ async def test_requests_sent_by_matlab_proxy_have_headers(
527
+ app_state_with_token_auth_fixture,
528
+ function_to_call,
529
+ mock_response,
530
+ mocker,
531
+ sample_token_headers_fixture,
532
+ ):
533
+ """Test to check if token headers are included in requests sent by matlab-proxy when authentication is enabled
534
+
535
+ Args:
536
+ app_state_fixture_with_token_auth (AppState): Instance of AppState class with token authentication enabled
537
+ mocker : Built-in pytest fixture
538
+ """
539
+ # Arrange
540
+ mocked_request = mocker.patch(
541
+ "aiohttp.ClientSession.request", return_value=mock_response
542
+ )
543
+
544
+ # Act
545
+ # Call the function passed as a string
546
+ method = getattr(app_state_with_token_auth_fixture, function_to_call)
547
+ _ = await method()
548
+
549
+ # Assert
550
+ connector_status_request_headers = list(mocked_request.call_args_list)[0].kwargs[
551
+ "headers"
552
+ ]
553
+ assert sample_token_headers_fixture == connector_status_request_headers
554
+
555
+
556
+ async def test_start_matlab_without_xvfb(app_state_fixture, mocker):
557
+ """Test to check if Matlab process starts without throwing errors when Xvfb is not present
558
+
559
+ Args:
560
+ app_state_fixture (AppState): Object of AppState class with defaults set
561
+ mocker : Built-in pytest fixture
562
+ """
563
+ # Arrange
564
+ app_state_fixture.settings["is_xvfb_available"] = False
565
+ mock_matlab = Mock_matlab(None, 1)
566
+
567
+ # Starting asyncio tasks related to matlab is not required here as only Xvfb check is required.
568
+ mocker.patch.object(
569
+ AppState, "_AppState__start_matlab_process", return_value=mock_matlab
570
+ )
571
+ mocker.patch.object(
572
+ AppState, "_AppState__matlab_stderr_reader_posix", return_value=None
573
+ )
574
+ mocker.patch.object(
575
+ AppState, "_AppState__track_embedded_connector_state", return_value=None
576
+ )
577
+ mocker.patch.object(AppState, "_AppState__update_matlab_port", return_value=None)
578
+
579
+ # Act
580
+ await app_state_fixture.start_matlab()
581
+
582
+ # Assert
583
+ # Check if Xvfb has not started
584
+ assert app_state_fixture.processes["xvfb"] is None
585
+ # Check if Matlab started
586
+ assert app_state_fixture.processes["matlab"] is mock_matlab
@@ -0,0 +1,6 @@
1
+ # Copyright 2023-2024 The MathWorks, Inc.
2
+
3
+ TWO_MAX_TRIES = 2
4
+ FIVE_MAX_TRIES = 5
5
+ HALF_SECOND_DELAY = 0.5
6
+ ONE_SECOND_DELAY = 1
@@ -0,0 +1,22 @@
1
+ # Copyright 2020-2022 The MathWorks, Inc.
2
+
3
+ import matlab_proxy
4
+ from matlab_proxy import util
5
+
6
+
7
+ def test_get_mwi_ddux_value():
8
+ """Tests ddux value for matlab-proxy with different extension names"""
9
+ expected_result = matlab_proxy.__get_matlab_proxy_base_ddux_value()
10
+ actual_result = matlab_proxy.get_mwi_ddux_value(
11
+ matlab_proxy.get_default_config_name()
12
+ )
13
+
14
+ assert expected_result == actual_result
15
+
16
+ expected_result = f"MATLAB_PROXY:HELLO_WORLD:V1"
17
+ actual_result = matlab_proxy.get_mwi_ddux_value("hello world")
18
+
19
+ assert expected_result == actual_result
20
+
21
+ actual_result = matlab_proxy.get_mwi_ddux_value(" \n \t hello-world \n")
22
+ assert expected_result == actual_result