Skip to content

Commit d24f464

Browse files
committed
Add request-level tests for LspConnection.
1 parent fe0a81a commit d24f464

File tree

2 files changed

+178
-3
lines changed

2 files changed

+178
-3
lines changed

src/Client/Protocol/LspConnection.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ public sealed class LspConnection
8484
/// </summary>
8585
int _nextRequestId = 0;
8686

87+
/// <summary>
88+
/// Has the connection been disposed?
89+
/// </summary>
90+
bool _disposed;
91+
8792
/// <summary>
8893
/// The cancellation source for the read and write loops.
8994
/// </summary>
@@ -158,9 +163,19 @@ public LspConnection(ILoggerFactory loggerFactory, Stream input, Stream output)
158163
/// </summary>
159164
public void Dispose()
160165
{
161-
Disconnect();
166+
if (_disposed)
167+
return;
162168

163-
_cancellationSource?.Dispose();
169+
try
170+
{
171+
Disconnect();
172+
173+
_cancellationSource?.Dispose();
174+
}
175+
finally
176+
{
177+
_disposed = true;
178+
}
164179
}
165180

166181
/// <summary>

test/Client.Tests/ConnectionTests.cs

Lines changed: 161 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ public async Task Client_HandleEmptyNotification_Success()
3232
{
3333
var testCompletion = new TaskCompletionSource<object>();
3434

35-
LspConnection serverConnection = await CreateServerConnection();
3635
LspConnection clientConnection = await CreateClientConnection();
36+
LspConnection serverConnection = await CreateServerConnection();
3737

3838
var serverDispatcher = new LspDispatcher();
3939
serverDispatcher.HandleEmptyNotification("test", () =>
@@ -85,5 +85,165 @@ public async Task Server_HandleEmptyNotification_Success()
8585

8686
await Task.WhenAll(clientConnection.HasHasDisconnected, serverConnection.HasHasDisconnected);
8787
}
88+
89+
/// <summary>
90+
/// Verify that a client <see cref="LspConnection"/> can handle a request from a server <see cref="LspConnection"/>.
91+
/// </summary>
92+
[Fact(DisplayName = "Client connection can handle request from server")]
93+
public async Task Server_HandleRequest_Success()
94+
{
95+
LspConnection clientConnection = await CreateClientConnection();
96+
LspConnection serverConnection = await CreateServerConnection();
97+
98+
var clientDispatcher = new LspDispatcher();
99+
clientDispatcher.HandleRequest<TestRequest, TestResponse>("test", (request, cancellationToken) =>
100+
{
101+
Log.LogInformation("Got request: {@Request}", request);
102+
103+
return Task.FromResult(new TestResponse
104+
{
105+
Value = request.Value.ToString()
106+
});
107+
});
108+
clientConnection.Connect(clientDispatcher);
109+
110+
serverConnection.Connect(new LspDispatcher());
111+
TestResponse response = await serverConnection.SendRequest<TestResponse>("test", new TestRequest
112+
{
113+
Value = 1234
114+
});
115+
116+
Assert.Equal("1234", response.Value);
117+
118+
Log.LogInformation("Got response: {@Response}", response);
119+
120+
serverConnection.Disconnect(flushOutgoing: true);
121+
clientConnection.Disconnect();
122+
123+
await Task.WhenAll(clientConnection.HasHasDisconnected, serverConnection.HasHasDisconnected);
124+
}
125+
126+
/// <summary>
127+
/// Verify that a server <see cref="LspConnection"/> can handle a request from a client <see cref="LspConnection"/>.
128+
/// </summary>
129+
[Fact(DisplayName = "Server connection can handle request from client")]
130+
public async Task Client_HandleRequest_Success()
131+
{
132+
LspConnection clientConnection = await CreateClientConnection();
133+
LspConnection serverConnection = await CreateServerConnection();
134+
135+
var serverDispatcher = new LspDispatcher();
136+
serverDispatcher.HandleRequest<TestRequest, TestResponse>("test", (request, cancellationToken) =>
137+
{
138+
Log.LogInformation("Got request: {@Request}", request);
139+
140+
return Task.FromResult(new TestResponse
141+
{
142+
Value = request.Value.ToString()
143+
});
144+
});
145+
serverConnection.Connect(serverDispatcher);
146+
147+
clientConnection.Connect(new LspDispatcher());
148+
TestResponse response = await clientConnection.SendRequest<TestResponse>("test", new TestRequest
149+
{
150+
Value = 1234
151+
});
152+
153+
Assert.Equal("1234", response.Value);
154+
155+
Log.LogInformation("Got response: {@Response}", response);
156+
157+
clientConnection.Disconnect(flushOutgoing: true);
158+
serverConnection.Disconnect();
159+
160+
await Task.WhenAll(clientConnection.HasHasDisconnected, serverConnection.HasHasDisconnected);
161+
}
162+
163+
/// <summary>
164+
/// Verify that a client <see cref="LspConnection"/> can handle a command-style request (i.e. no response body) from a server <see cref="LspConnection"/>.
165+
/// </summary>
166+
[Fact(DisplayName = "Client connection can handle command request from server")]
167+
public async Task Server_HandleCommandRequest_Success()
168+
{
169+
LspConnection clientConnection = await CreateClientConnection();
170+
LspConnection serverConnection = await CreateServerConnection();
171+
172+
var clientDispatcher = new LspDispatcher();
173+
clientDispatcher.HandleRequest<TestRequest>("test", (request, cancellationToken) =>
174+
{
175+
Log.LogInformation("Got request: {@Request}", request);
176+
177+
Assert.Equal(1234, request.Value);
178+
179+
return Task.CompletedTask;
180+
});
181+
clientConnection.Connect(clientDispatcher);
182+
183+
serverConnection.Connect(new LspDispatcher());
184+
await serverConnection.SendRequest("test", new TestRequest
185+
{
186+
Value = 1234
187+
});
188+
189+
serverConnection.Disconnect(flushOutgoing: true);
190+
clientConnection.Disconnect();
191+
192+
await Task.WhenAll(clientConnection.HasHasDisconnected, serverConnection.HasHasDisconnected);
193+
}
194+
195+
/// <summary>
196+
/// Verify that a server <see cref="LspConnection"/> can handle a command-style request (i.e. no response body) from a client <see cref="LspConnection"/>.
197+
/// </summary>
198+
[Fact(DisplayName = "Server connection can handle command request from client")]
199+
public async Task Client_HandleCommandRequest_Success()
200+
{
201+
LspConnection clientConnection = await CreateClientConnection();
202+
LspConnection serverConnection = await CreateServerConnection();
203+
204+
var serverDispatcher = new LspDispatcher();
205+
serverDispatcher.HandleRequest<TestRequest>("test", (request, cancellationToken) =>
206+
{
207+
Log.LogInformation("Got request: {@Request}", request);
208+
209+
Assert.Equal(1234, request.Value);
210+
211+
return Task.CompletedTask;
212+
});
213+
serverConnection.Connect(serverDispatcher);
214+
215+
clientConnection.Connect(new LspDispatcher());
216+
await clientConnection.SendRequest("test", new TestRequest
217+
{
218+
Value = 1234
219+
});
220+
221+
clientConnection.Disconnect(flushOutgoing: true);
222+
serverConnection.Disconnect();
223+
224+
await Task.WhenAll(clientConnection.HasHasDisconnected, serverConnection.HasHasDisconnected);
225+
}
226+
}
227+
228+
/// <summary>
229+
/// A test request.
230+
/// </summary>
231+
class TestRequest
232+
{
233+
/// <summary>
234+
/// A test value for the request.
235+
/// </summary>
236+
public int Value { get; set; }
237+
}
238+
239+
/// <summary>
240+
/// A test response.
241+
/// </summary>
242+
class TestResponse
243+
{
244+
/// <summary>
245+
/// A test value for the response.
246+
/// </summary>
247+
public string Value { get; set; }
88248
}
89249
}

0 commit comments

Comments
 (0)