|
| 1 | +import json |
1 | 2 | import os
|
2 | 3 | import threading
|
3 | 4 | import time
|
4 | 5 | from unittest.mock import patch
|
5 | 6 |
|
6 | 7 | import pytest
|
| 8 | +from jupyter_core.paths import secure_write |
| 9 | +from traitlets.config.loader import Config |
7 | 10 |
|
8 | 11 | from ipykernel.kernelapp import IPKernelApp
|
9 | 12 |
|
10 | 13 | from .conftest import MockKernel
|
| 14 | +from .utils import TemporaryWorkingDirectory |
11 | 15 |
|
12 | 16 | try:
|
13 | 17 | import trio
|
@@ -47,6 +51,73 @@ def trigger_stop():
|
47 | 51 | app.close()
|
48 | 52 |
|
49 | 53 |
|
| 54 | +@pytest.mark.skipif(os.name == "nt", reason="permission errors on windows") |
| 55 | +def test_merge_connection_file(): |
| 56 | + cfg = Config() |
| 57 | + with TemporaryWorkingDirectory() as d: |
| 58 | + cfg.ProfileDir.location = d |
| 59 | + cf = os.path.join(d, "kernel.json") |
| 60 | + initial_connection_info = { |
| 61 | + "ip": "*", |
| 62 | + "transport": "tcp", |
| 63 | + "shell_port": 0, |
| 64 | + "hb_port": 0, |
| 65 | + "iopub_port": 0, |
| 66 | + "stdin_port": 0, |
| 67 | + "control_port": 53555, |
| 68 | + "key": "abc123", |
| 69 | + "signature_scheme": "hmac-sha256", |
| 70 | + "kernel_name": "My Kernel", |
| 71 | + } |
| 72 | + # We cannot use connect.write_connection_file since |
| 73 | + # it replaces port number 0 with a random port |
| 74 | + # and we want IPKernelApp to do that replacement. |
| 75 | + with secure_write(cf) as f: |
| 76 | + json.dump(initial_connection_info, f) |
| 77 | + assert os.path.exists(cf) |
| 78 | + |
| 79 | + app = IPKernelApp(config=cfg, connection_file=cf) |
| 80 | + |
| 81 | + # Calling app.initialize() does not work in the test, so we call the relevant functions that initialize() calls |
| 82 | + # We must pass in an empty argv, otherwise the default is to try to parse the test runner's argv |
| 83 | + super(IPKernelApp, app).initialize(argv=[""]) |
| 84 | + app.init_connection_file() |
| 85 | + app.init_sockets() |
| 86 | + app.init_heartbeat() |
| 87 | + app.write_connection_file() |
| 88 | + |
| 89 | + # Initialize should have merged the actual connection info |
| 90 | + # with the connection info in the file |
| 91 | + assert cf == app.abs_connection_file |
| 92 | + assert os.path.exists(cf) |
| 93 | + |
| 94 | + with open(cf) as f: |
| 95 | + new_connection_info = json.load(f) |
| 96 | + |
| 97 | + # ports originally set as 0 have been replaced |
| 98 | + for port in ("shell", "hb", "iopub", "stdin"): |
| 99 | + key = f"{port}_port" |
| 100 | + # We initially had the port as 0 |
| 101 | + assert initial_connection_info[key] == 0 |
| 102 | + # the port is not 0 now |
| 103 | + assert new_connection_info[key] > 0 |
| 104 | + # the port matches the port the kernel actually used |
| 105 | + assert new_connection_info[key] == getattr(app, key), f"{key}" |
| 106 | + del new_connection_info[key] |
| 107 | + del initial_connection_info[key] |
| 108 | + |
| 109 | + # The wildcard ip address was also replaced |
| 110 | + assert new_connection_info["ip"] != "*" |
| 111 | + del new_connection_info["ip"] |
| 112 | + del initial_connection_info["ip"] |
| 113 | + |
| 114 | + # everything else in the connection file is the same |
| 115 | + assert initial_connection_info == new_connection_info |
| 116 | + |
| 117 | + app.close() |
| 118 | + os.remove(cf) |
| 119 | + |
| 120 | + |
50 | 121 | @pytest.mark.skipif(trio is None, reason="requires trio")
|
51 | 122 | def test_trio_loop():
|
52 | 123 | app = IPKernelApp(trio_loop=True)
|
|
0 commit comments