10000 Converge unit tests for test_language_server and test_notebook_docume… · python-lsp/python-lsp-server@ceb8af2 · GitHub
[go: up one dir, main page]

Skip to content

Commit ceb8af2

Browse files
authored
Converge unit tests for test_language_server and test_notebook_document (#418)
1 parent d47dc3c commit ceb8af2

File tree

4 files changed

+104
-119
lines changed

4 files changed

+104
-119
lines changed

test/fixtures.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
from io import StringIO
66
from unittest.mock import MagicMock
77

8+
from test.test_utils import ClientServerPair
9+
810
import pytest
911
from pylsp_jsonrpc.dispatchers import MethodDispatcher
1012
from pylsp_jsonrpc.endpoint import Endpoint
@@ -22,6 +24,7 @@
2224
def main():
2325
print sys.stdin.read()
2426
"""
27+
CALL_TIMEOUT_IN_SECONDS = 30
2528

2629

2730
class FakeEditorMethodsMixin:
@@ -163,3 +166,17 @@ def create_file(name, content):
163166
return workspace
164167

165168
return fn
169+
170+
171+
@pytest.fixture
172+
def client_server_pair():
173+
"""A fixture that sets up a client/server pair and shuts down the server"""
174+
client_server_pair_obj = ClientServerPair()
175+
176+
yield (client_server_pair_obj.client, client_server_pair_obj.server)
177+
178+
shutdown_response = client_server_pair_obj.client._endpoint.request(
179+
"shutdown"
180+
).result(timeout=CALL_TIMEOUT_IN_SECONDS)
181+
assert shutdown_response is None
182+
client_server_pair_obj.client._endpoint.notify("exit")

test/test_language_server.py

Lines changed: 26 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -3,96 +3,40 @@
33

44
import os
55
import time
6-
import multiprocessing
76
import sys
8-
from threading import Thread
7+
8+
from test.test_utils import ClientServerPair
99

1010
from flaky import flaky
1111
from pylsp_jsonrpc.exceptions import JsonRpcMethodNotFound
1212
import pytest
1313

14-
from pylsp.python_lsp import start_io_lang_server, PythonLSPServer
1514

16-
CALL_TIMEOUT = 10
1715
RUNNING_IN_CI = bool(os.environ.get("CI"))
1816

19-
20-
def start_client(client):
21-
client.start()
22-
23-
24-
class _ClientServer:
25-
"""A class to setup a client/server pair"""
26-
27-
def __init__(self, check_parent_process=False):
28-
# Client to Server pipe
29-
csr, csw = os.pipe()
30-
# Server to client pipe
31-
scr, scw = os.pipe()
32-
33-
if os.name == "nt":
34-
ParallelKind = Thread
35-
else:
36-
if sys.version_info[:2] >= (3, 8):
37-
ParallelKind = multiprocessing.get_context("fork").Process
38-
else:
39-
ParallelKind = multiprocessing.Process
40-
41-
self.process = ParallelKind(
42-
target=start_io_lang_server,
43-
args=(
44-
os.fdopen(csr, "rb"),
45-
os.fdopen(scw, "wb"),
46-
check_parent_process,
47-
PythonLSPServer,
48-
),
49-
)
50-
self.process.start()
51-
52-
self.client = PythonLSPServer(
53-
os.fdopen(scr, "rb"), os.fdopen(csw, "wb"), start_io_lang_server
54-
)
55-
self.client_thread = Thread(target=start_client, args=[self.client])
56-
self.client_thread.daemon = True
57-
self.client_thread.start()
58-
59-
60-
@pytest.fixture
61-
def client_server():
62-
"""A fixture that sets up a client/server pair and shuts down the server
63-
This client/server pair does not support checking parent process aliveness
64-
"""
65-
client_server_pair = _ClientServer()
66-
67-
yield client_server_pair.client
68-
69-
shutdown_response = client_server_pair.client._endpoint.request("shutdown").result(
70-
timeout=CALL_TIMEOUT
71-
)
72-
assert shutdown_response is None
73-
client_server_pair.client._endpoint.notify("exit")
17+
CALL_TIMEOUT_IN_SECONDS = 10
7418

7519

7620
@pytest.fixture
7721
def client_exited_server():
7822
"""A fixture that sets up a client/server pair that support checking parent process aliveness
7923
and assert the server has already exited
8024
"""
81-
client_server_pair = _ClientServer(True)
25+
client_server_pair_obj = ClientServerPair(True, True)
8226

83-
# yield client_server_pair.client
84-
yield client_server_pair
27+
yield client_server_pair_obj
8528

86-
assert client_server_pair.process.is_alive() is False
29+
assert client_server_pair_obj.server_process.is_alive() is False
8730

8831

8932
@flaky(max_runs=10, min_passes=1)
9033
@pytest.mark.skipif(sys.platform == "darwin", reason="Too flaky on Mac")
91-
def test_initialize(client_server): # pylint: disable=redefined-outer-name
92-
response = client_server._endpoint.request(
34+
def test_initialize(client_server_pair):
35+
client, _ = client_server_pair
36+
response = client._endpoint.request(
9337
"initialize",
9438
{"rootPath": os.path.dirname(__file__), "initializationOptions": {}},
95-
).result(timeout=CALL_TIMEOUT)
39+
).result(timeout=CALL_TIMEOUT_IN_SECONDS)
9640
assert "capabilities" in response
9741

9842

@@ -104,7 +48,10 @@ def test_exit_with_parent_process_died(
10448
client_exited_server,
10549
): # pylint: disable=redefined-outer-name
10650
# language server should have already exited before responding
107-
lsp_server, mock_process = client_exited_server.client, client_exited_server.process
51+
lsp_server, mock_process = (
52+
client_exited_server.client,
53+
client_exited_server.server_process,
54+
)
10855
# with pytest.raises(Exception):
10956
lsp_server._endpoint.request(
11057
"initialize",
@@ -113,31 +60,35 @@ def test_exit_with_parent_process_died(
11360
"rootPath": os.path.dirname(__file__),
11461
"initializationOptions": {},
11562
},
116-
).result(timeout=CALL_TIMEOUT)
63+
).result(timeout=CALL_TIMEOUT_IN_SECONDS)
11764

11865
mock_process.terminate()
119-
time.sleep(CALL_TIMEOUT)
66+
time.sleep(CALL_TIMEOUT_IN_SECONDS)
12067
assert not client_exited_server.client_thread.is_alive()
12168

12269

12370
@flaky(max_runs=10, min_passes=1)
12471
@pytest.mark.skipif(sys.platform.startswith("linux"), reason="Fails on linux")
12572
def test_not_exit_without_check_parent_process_flag(
126-
client_server,
127-
): # pylint: disable=redefined-outer-name
128-
response = client_server._endpoint.request(
73+
client_server_pair,
74+
):
75+
client, _ = client_server_pair
76+
response = client._endpoint.request(
12977
"initialize",
13078
{
13179
"processId": 1234,
13280
"rootPath": os.path.dirname(__file__),
13381
"initializationOptions": {},
13482
},
135-
).result(timeout=CALL_TIMEOUT)
83+
).result(timeout=CALL_TIMEOUT_IN_SECONDS)
13684
assert "capabilities" in response
13785

13886

13987
@flaky(max_runs=10, min_passes=1)
14088
@pytest.mark.skipif(RUNNING_IN_CI, reason="This test is hanging on CI")
141-
def test_missing_message(client_server): # pylint: disable=redefined-outer-name
89+
def test_missing_message(client_server_pair):
90+
client, _ = client_server_pair
14291
with pytest.raises(JsonRpcMethodNotFound):
143-
client_server._endpoint.request("unknown_method").result(timeout=CALL_TIMEOUT)
92+
client._endpoint.request("unknown_method").result(
93+
timeout=CALL_TIMEOUT_IN_SECONDS
94+
)

test/test_notebook_document.py

Lines changed: 6 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,15 @@
22

33
import os
44
import time
5-
from threading import Thread
65
from unittest.mock import patch, call
76

7+
from test.fixtures import CALL_TIMEOUT_IN_SECONDS
8+
89
import pytest
910

1011
from pylsp import IS_WIN
11-
from pylsp.python_lsp import PythonLSPServer
1212
from pylsp.lsp import NotebookCellKind
1313

14-
CALL_TIMEOUT_IN_SECONDS = 30
15-
1614

1715
def wait_for_condition(condition, timeout=CALL_TIMEOUT_IN_SECONDS):
1816
"""Wait for a condition to be true, or timeout."""
@@ -23,44 +21,8 @@ def wait_for_condition(condition, timeout=CALL_TIMEOUT_IN_SECONDS):
2321
raise TimeoutError("Timeout waiting for condition")
2422

2523

26-
def start(obj):
27-
obj.start()
28-
29-
30-
class ClientServerPair:
31-
"""A class to setup a client/server pair"""
32-
33-
def __init__(self):
34-
# Client to Server pipe
35-
csr, csw = os.pipe()
36-
# Server to client pipe
37-
scr, scw = os.pipe()
38-
39-
self.server = PythonLSPServer(os.fdopen(csr, "rb"), os.fdopen(scw, "wb"))
40-
self.server_thread = Thread(target=start, args=[self.server])
41-
self.server_thread.start()
42-
43-
self.client = PythonLSPServer(os.fdopen(scr, "rb"), os.fdopen(csw, "wb"))
44-
self.client_thread = Thread(target=start, args=[self.client])
45-
self.client_thread.start()
46-
47-
48-
@pytest.fixture
49-
def client_server_pair():
50-
"""A fixture that sets up a client/server pair and shuts down the server"""
51-
client_server_pair_obj = ClientServerPair()
52-
53-
yield (client_server_pair_obj.client, client_server_pair_obj.server)
54-
55-
shutdown_response = client_server_pair_obj.client._endpoint.request(
56-
"shutdown"
57-
).result(timeout=CALL_TIMEOUT_IN_SECONDS)
58-
assert shutdown_response is None
59-
client_server_pair_obj.client._endpoint.notify("exit")
60-
61-
6224
@pytest.mark.skipif(IS_WIN, reason="Flaky on Windows")
63-
def test_initialize(client_server_pair): # pylint: disable=redefined-outer-name
25+
def test_initialize(client_server_pair):
6426
client, server = client_server_pair
6527
response = client._endpoint.request(
6628
"initialize",
@@ -77,7 +39,7 @@ def test_initialize(client_server_pair): # pylint: disable=redefined-outer-name
7739
@pytest.mark.skipif(IS_WIN, reason="Flaky on Windows")
7840
def test_notebook_document__did_open(
7941
client_server_pair,
80-
): # pylint: disable=redefined-outer-name
42+
):
8143
client, server = client_server_pair
8244
client._endpoint.request(
8345
"initialize",
@@ -241,7 +203,7 @@ def test_notebook_document__did_open(
241203
@pytest.mark.skipif(IS_WIN, reason="Flaky on Windows")
242204
def test_notebook_document__did_change(
243205
client_server_pair,
244-
): # pylint: disable=redefined-outer-name
206+
):
245207
client, server = client_server_pair
246208
client._endpoint.request(
247209
"initialize",
@@ -513,7 +475,7 @@ def test_notebook_document__did_change(
513475
@pytest.mark.skipif(IS_WIN, reason="Flaky on Windows")
514476
def test_notebook__did_close(
515477
client_server_pair,
516-
): # pylint: disable=redefined-outer-name
478+
):
517479
client, server = client_server_pair
518480
client._endpoint.request(
519481
"initialize",

test/test_utils.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,67 @@
11
# Copyright 2017-2020 Palantir Technologies, Inc.
22
# Copyright 2021- Python Language Server Contributors.
33

4+
import multiprocessing
5+
import os
6+
import sys
7+
from threading import Thread
48
import time
59
from unittest import mock
610

711
from flaky import flaky
812

913
from pylsp import _utils
14+
from pylsp.python_lsp import PythonLSPServer, start_io_lang_server
15+
16+
17+
def start(obj):
18+
obj.start()
19+
20+
21+
class ClientServerPair:
22+
"""
23+
A class to setup a client/server pair.
24+
25+
args:
26+
start_server_in_process: if True, the server will be started in a process.
27+
check_parent_process: if True, the server_process will check if the parent process is alive.
28+
"""
29+
30+
def __init__(self, start_server_in_process=False, check_parent_process=False):
31+
# Client to Server pipe
32+
csr, csw = os.pipe()
33+
# Server to client pipe
34+
scr, scw = os.pipe()
35+
36+
if start_server_in_process:
37+
ParallelKind = self._get_parallel_kind()
38+
self.server_process = ParallelKind(
39+
target=start_io_lang_server,
40+
args=(
41+
os.fdopen(csr, "rb"),
42+
os.fdopen(scw, "wb"),
43+
check_parent_process,
44+
PythonLSPServer,
45+
),
46+
)
47+
self.server_process.start()
48+
else:
49+
self.server = PythonLSPServer(os.fdopen(csr, "rb"), os.fdopen(scw, "wb"))
50+
self.server_thread = Thread(target=start, args=[self.server])
51+
self.server_thread.start()
52+
53+
self.client = PythonLSPServer(os.fdopen(scr, "rb"), os.fdopen(csw, "wb"))
54+
self.client_thread = Thread(target=start, args=[self.client])
55+
self.client_thread.start()
56+
57+
def _get_parallel_kind(self):
58+
if os.name == "nt":
59+
return Thread
60+
61+
if sys.version_info[:2] >= (3, 8):
62+
return multiprocessing.get_context("fork").Process
63+
64+
return multiprocessing.Process
1065

1166

1267
@flaky(max_runs=6, min_passes=1)

0 commit comments

Comments
 (0)
0