3
3
4
4
import os
5
5
import time
6
- import multiprocessing
7
6
import sys
8
- from threading import Thread
7
+
8
+ from test .test_utils import ClientServerPair
9
9
10
10
from flaky import flaky
11
11
from pylsp_jsonrpc .exceptions import JsonRpcMethodNotFound
12
12
import pytest
13
13
14
- from pylsp .python_lsp import start_io_lang_server , PythonLSPServer
15
14
16
- CALL_TIMEOUT = 10
17
15
RUNNING_IN_CI = bool (os .environ .get ("CI" ))
18
16
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
74
18
75
19
76
20
@pytest .fixture
77
21
def client_exited_server ():
78
22
"""A fixture that sets up a client/server pair that support checking parent process aliveness
79
23
and assert the server has already exited
80
24
"""
81
- client_server_pair = _ClientServer ( True )
25
+ client_server_pair_obj = ClientServerPair ( True , True )
82
26
83
- # yield client_server_pair.client
84
- yield client_server_pair
27
+ yield client_server_pair_obj
85
28
86
- assert client_server_pair . process .is_alive () is False
29
+ assert client_server_pair_obj . server_process .is_alive () is False
87
30
88
31
89
32
@flaky (max_runs = 10 , min_passes = 1 )
90
33
@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 (
93
37
"initialize" ,
94
38
{"rootPath" : os .path .dirname (__file__ ), "initializationOptions" : {}},
95
- ).result (timeout = CALL_TIMEOUT )
39
+ ).result (timeout = CALL_TIMEOUT_IN_SECONDS )
96
40
assert "capabilities" in response
97
41
98
42
@@ -104,7 +48,10 @@ def test_exit_with_parent_process_died(
104
48
client_exited_server ,
105
49
): # pylint: disable=redefined-outer-name
106
50
# 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
+ )
108
55
# with pytest.raises(Exception):
109
56
lsp_server ._endpoint .request
E377
span>(
110
57
"initialize" ,
@@ -113,31 +60,35 @@ def test_exit_with_parent_process_died(
113
60
"rootPath" : os .path .dirname (__file__ ),
114
61
"initializationOptions" : {},
115
62
},
116
- ).result (timeout = CALL_TIMEOUT )
63
+ ).result (timeout = CALL_TIMEOUT_IN_SECONDS )
117
64
118
65
mock_process .terminate ()
119
- time .sleep (CALL_TIMEOUT )
66
+ time .sleep (CALL_TIMEOUT_IN_SECONDS )
120
67
assert not client_exited_server .client_thread .is_alive ()
121
68
122
69
123
70
@flaky (max_runs = 10 , min_passes = 1 )
124
71
@pytest .mark .skipif (sys .platform .startswith ("linux" ), reason = "Fails on linux" )
125
72
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 (
129
77
"initialize" ,
130
78
{
131
79
"processId" : 1234 ,
132
80
"rootPath" : os .path .dirname (__file__ ),
133
81
"initializationOptions" : {},
134
82
},
135
- ).result (timeout = CALL_TIMEOUT )
83
+ ).result (timeout = CALL_TIMEOUT_IN_SECONDS )
136
84
assert "capabilities" in response
137
85
138
86
139
87
@flaky (max_runs = 10 , min_passes = 1 )
140
88
@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
142
91
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
+ )
0 commit comments