From ba12a80fbfb7db930dd429c34bd2844245845091 Mon Sep 17 00:00:00 2001 From: Connor Quagliana Date: Mon, 19 Dec 2016 14:01:03 -0800 Subject: [PATCH] Add fix for SendEvent causing test to fail (#195) Add flag in ServiceHost to ignore SendEvent errors --- .../Hosting/Protocol/ProtocolEndpoint.cs | 78 ++++++++++++------- .../LanguageServer/LanguageServiceTests.cs | 11 ++- 2 files changed, 58 insertions(+), 31 deletions(-) diff --git a/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/ProtocolEndpoint.cs b/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/ProtocolEndpoint.cs index 5a18f85b..aaa4b7db 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/ProtocolEndpoint.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/ProtocolEndpoint.cs @@ -9,6 +9,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Channel; using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; +using Microsoft.SqlTools.ServiceLayer.Utility; namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol { @@ -28,6 +29,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol private Dictionary> pendingRequests = new Dictionary>(); + /// + /// When true, SendEvent will ignore exceptions and write them + /// to the log instead. Intended to be used for test scenarios + /// where SendEvent throws exceptions unrelated to what is + /// being tested. + /// + internal static bool SendEventIgnoreExceptions = false; + /// /// Gets the MessageDispatcher which allows registration of /// handlers for requests, responses, and events that are @@ -194,37 +203,52 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol EventType eventType, TParams eventParams) { - if (!this.protocolChannel.IsConnected) + try { - throw new InvalidOperationException("SendEvent called when ProtocolChannel was not yet connected"); + if (!this.protocolChannel.IsConnected) + { + throw new InvalidOperationException("SendEvent called when ProtocolChannel was not yet connected"); + } + + // Some events could be raised from a different thread. + // To ensure that messages are written serially, dispatch + // dispatch the SendEvent call to the message loop thread. + + if (!this.MessageDispatcher.InMessageLoopThread) + { + TaskCompletionSource writeTask = new TaskCompletionSource(); + + this.MessageDispatcher.SynchronizationContext.Post( + async (obj) => + { + await this.protocolChannel.MessageWriter.WriteEvent( + eventType, + eventParams); + + writeTask.SetResult(true); + }, null); + + return writeTask.Task; + } + else + { + return this.protocolChannel.MessageWriter.WriteEvent( + eventType, + eventParams); + } } - - // Some events could be raised from a different thread. - // To ensure that messages are written serially, dispatch - // dispatch the SendEvent call to the message loop thread. - - if (!this.MessageDispatcher.InMessageLoopThread) + catch (Exception ex) { - TaskCompletionSource writeTask = new TaskCompletionSource(); - - this.MessageDispatcher.SynchronizationContext.Post( - async (obj) => - { - await this.protocolChannel.MessageWriter.WriteEvent( - eventType, - eventParams); - - writeTask.SetResult(true); - }, null); - - return writeTask.Task; - } - else - { - return this.protocolChannel.MessageWriter.WriteEvent( - eventType, - eventParams); + if (SendEventIgnoreExceptions) + { + Logger.Write(LogLevel.Verbose, "Exception in SendEvent " + ex.ToString()); + } + else + { + throw; + } } + return Task.FromResult(false); } #endregion diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/LanguageServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/LanguageServiceTests.cs index 0c1629de..fcf73a99 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/LanguageServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/LanguageServiceTests.cs @@ -3,7 +3,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // -using Microsoft.SqlServer.Management.SqlParser.Parser; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.LanguageServices; using Microsoft.SqlTools.ServiceLayer.LanguageServices.Completion; @@ -290,6 +289,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServer { // When we make a connection to a live database ScriptFile scriptFile; + Hosting.ServiceHost.SendEventIgnoreExceptions = true; ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfo(out scriptFile); // And we place the cursor after a function that should prompt for signature help @@ -308,12 +308,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServer } }; - // If we have a valid ScriptParseInfo and the SQL has already been parsed + // If the SQL has already been parsed var service = LanguageService.Instance; - ScriptParseInfo parseInfo = service.GetScriptParseInfo(scriptFile.ClientFilePath); await service.UpdateLanguageServiceOnConnection(connInfo); - // We should get back a non-null SignatureHelp + // We should get back a non-null ScriptParseInfo + ScriptParseInfo parseInfo = service.GetScriptParseInfo(scriptFile.ClientFilePath); + Assert.NotNull(parseInfo); + + // And we should get back a non-null SignatureHelp SignatureHelp signatureHelp = service.GetSignatureHelp(textDocument, scriptFile); Assert.NotNull(signatureHelp); }