/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework.UnitTests/RequestExecutionQueueTests.cs
170 строк
8 KB
David Barbet
Refactor LSP server logging to remove singleton lsp instance (#84001)
16 июн 2026, 05:04
Не верифицирован
16 июн 2026, 05:04
82e81e5
Код
Авторство
О чём код?
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.LanguageServer; using Microsoft.CommonLanguageServerProtocol.Framework.Example; using Microsoft.Extensions.DependencyInjection; using Nerdbank.Streams; using StreamJsonRpc; using Xunit; namespace Microsoft.CommonLanguageServerProtocol.Framework.UnitTests; public sealed class RequestExecutionQueueTests { private sealed class MockServer : SystemTextJsonLanguageServer<TestRequestContext> { private static readonly JsonSerializerOptions s_jsonSerializerOptions = new SystemTextJsonFormatter().JsonSerializerOptions.AddLspSerializerOptions(); public MockServer() : base(new JsonRpc(new HeaderDelimitedMessageHandler(FullDuplexStream.CreatePair().Item1)), s_jsonSerializerOptions) { } protected override ILspServices ConstructLspServices() => RequestExecutionQueueTests.GetLspServices(); } private static RequestExecutionQueue<TestRequestContext> GetRequestExecutionQueue( bool cancelInProgressWorkUponMutatingRequest, params (RequestHandlerMetadata metadata, IMethodHandler handler)[] handlers) { var provider = new TestHandlerProvider(handlers); var executionQueue = new TestRequestExecutionQueue(new MockServer(), provider, cancelInProgressWorkUponMutatingRequest); executionQueue.Start(); return executionQueue; } private static ILspServices GetLspServices() => TestLspServices.Create( services: [ (typeof(AbstractRequestContextFactory<TestRequestContext>), (object)TestRequestContext.Factory.Instance), (typeof(ILspLogger), NoOpLspLogger.Instance) ], supportsMethodHandlerProvider: false); [Fact] public async Task ExecuteAsync_ThrowCompletes() { // Arrange var requestExecutionQueue = GetRequestExecutionQueue(false, (ThrowingHandler.Metadata, ThrowingHandler.Instance)); var lspServices = GetLspServices(); // Act & Assert await Assert.ThrowsAsync<NotImplementedException>(() => requestExecutionQueue.ExecuteAsync(JsonSerializer.SerializeToElement(new MockRequest(1)), ThrowingHandler.Name, lspServices, CancellationToken.None)); } [Fact] public async Task ExecuteAsync_WithCancelInProgressWork_CancelsInProgressWorkWhenMutatingRequestArrives() { // Let's try it a bunch of times to try to find timing issues. for (var i = 0; i < 20; i++) { // Arrange var requestExecutionQueue = GetRequestExecutionQueue(cancelInProgressWorkUponMutatingRequest: true, handlers: [ (CancellingHandler.Metadata, CancellingHandler.Instance), (CompletingHandler.Metadata, CompletingHandler.Instance), (MutatingHandler.Metadata, MutatingHandler.Instance), ]); var lspServices = GetLspServices(); var cancellingRequestCancellationToken = new CancellationToken(); var completingRequestCancellationToken = new CancellationToken(); var _ = requestExecutionQueue.ExecuteAsync(JsonSerializer.SerializeToElement(new MockRequest(1)), CancellingHandler.Name, lspServices, cancellingRequestCancellationToken); var _1 = requestExecutionQueue.ExecuteAsync(JsonSerializer.SerializeToElement(new MockRequest(1)), CompletingHandler.Name, lspServices, completingRequestCancellationToken); // Act & Assert // A Debug.Assert would throw if the tasks hadn't completed when the mutating request is called. await requestExecutionQueue.ExecuteAsync(JsonSerializer.SerializeToElement(new MockRequest(1)), MutatingHandler.Name, lspServices, CancellationToken.None); } } [Fact] public async Task Dispose_MultipleTimes_Succeeds() { // Arrange var requestExecutionQueue = GetRequestExecutionQueue(false, (TestMethodHandler.Metadata, TestMethodHandler.Instance)); // Act await requestExecutionQueue.DisposeAsync(); await requestExecutionQueue.DisposeAsync(); // Assert, it didn't fail } [Fact] public async Task ExecuteAsync_CompletesTask() { var requestExecutionQueue = GetRequestExecutionQueue(false, (TestMethodHandler.Metadata, TestMethodHandler.Instance)); var lspServices = GetLspServices(); var response = (MockResponse?)await requestExecutionQueue.ExecuteAsync(JsonSerializer.SerializeToElement(new MockRequest(1)), TestMethodHandler.Name, lspServices, CancellationToken.None); Assert.Equal("stuff", response?.Response); } [Fact] public async Task ExecuteAsync_CompletesTask_Parameterless() { var requestExecutionQueue = GetRequestExecutionQueue(false, (TestParameterlessMethodHandler.Metadata, TestParameterlessMethodHandler.Instance)); var lspServices = GetLspServices(); var response = (MockResponse?)await requestExecutionQueue.ExecuteAsync(serializedRequest: null, TestParameterlessMethodHandler.Name, lspServices, CancellationToken.None); Assert.Equal("true", response?.Response); } [Fact] public async Task ExecuteAsync_CompletesTask_Notification() { var requestExecutionQueue = GetRequestExecutionQueue(false, (TestNotificationHandler.Metadata, TestNotificationHandler.Instance)); var lspServices = GetLspServices(); var response = await requestExecutionQueue.ExecuteAsync(JsonSerializer.SerializeToElement(new MockRequest(1)), TestNotificationHandler.Name, lspServices, CancellationToken.None); Assert.Same(NoValue.Instance, response); } [Fact] public async Task ExecuteAsync_CompletesTask_Notification_Parameterless() { var requestExecutionQueue = GetRequestExecutionQueue(false, (TestParameterlessNotificationHandler.Metadata, TestParameterlessNotificationHandler.Instance)); var lspServices = GetLspServices(); var response = await requestExecutionQueue.ExecuteAsync(serializedRequest: null, TestParameterlessNotificationHandler.Name, lspServices, CancellationToken.None); Assert.Same(NoValue.Instance, response); } [Fact] public async Task Queue_DrainsOnShutdown() { var requestExecutionQueue = GetRequestExecutionQueue(false, (TestMethodHandler.Metadata, TestMethodHandler.Instance)); var request = JsonSerializer.SerializeToElement(new MockRequest(1)); var lspServices = GetLspServices(); var task1 = requestExecutionQueue.ExecuteAsync(request, TestMethodHandler.Name, lspServices, CancellationToken.None); var task2 = requestExecutionQueue.ExecuteAsync(request, TestMethodHandler.Name, lspServices, CancellationToken.None); await requestExecutionQueue.DisposeAsync(); Assert.True(task1.IsCompleted); Assert.True(task2.IsCompleted); } private sealed class TestRequestExecutionQueue : RequestExecutionQueue<TestRequestContext> { private readonly bool _cancelInProgressWorkUponMutatingRequest; public TestRequestExecutionQueue(AbstractLanguageServer<TestRequestContext> languageServer, AbstractHandlerProvider handlerProvider, bool cancelInProgressWorkUponMutatingRequest) : base(languageServer, handlerProvider) { _cancelInProgressWorkUponMutatingRequest = cancelInProgressWorkUponMutatingRequest; } protected override bool CancelInProgressWorkUponMutatingRequest => _cancelInProgressWorkUponMutatingRequest; } }