diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/AmbientSettings.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/AmbientSettings.cs index fc8e7302..f1022ecb 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/AmbientSettings.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/AmbientSettings.cs @@ -48,12 +48,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection internal const string DoNotSerializeQueryStoreSettingsIndex = "DoNotSerializeQueryStoreSettings"; internal const string AlwaysEncryptedWizardMigrationIndex = "AlwaysEncryptedWizardMigration"; - private static readonly AmbientData _defaultSettings; + internal static AmbientData _defaultSettings; static AmbientSettings() { _defaultSettings = new AmbientData(); - } + } /// /// Access to the default ambient settings. Access to these settings is made available diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs index 4f31fcf3..3ce8c9e8 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableConnectionHelper.cs @@ -801,7 +801,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection public string DatabaseName; } - private static bool TryGetConnectionStringBuilder(string connectionString, out SqlConnectionStringBuilder builder) + internal static bool TryGetConnectionStringBuilder(string connectionString, out SqlConnectionStringBuilder builder) { builder = null; diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlCommand.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlCommand.cs index 4f051688..eaacdfb0 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlCommand.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/ReliableSqlCommand.cs @@ -235,7 +235,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection return _command; } - private void ValidateConnectionIsSet() + internal void ValidateConnectionIsSet() { if (_connection == null) { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryLimitExceededException.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryLimitExceededException.cs index 0ae8b4e7..c4f99e59 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryLimitExceededException.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryLimitExceededException.cs @@ -34,5 +34,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection [Serializable] internal sealed class RetryLimitExceededException : Exception { + internal RetryLimitExceededException() : base() + { + } + + internal RetryLimitExceededException(string m, Exception e) : base(m, e) + { + } } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.cs b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.cs index 23159d3e..37be0b15 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Connection/ReliableConnection/RetryPolicy.cs @@ -292,7 +292,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection } */ - private static int? GetErrorNumber(Exception ex) + internal static int? GetErrorNumber(Exception ex) { SqlException sqlEx = ex as SqlException; if (sqlEx == null) diff --git a/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageDispatcher.cs b/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageDispatcher.cs index 3b3d11c8..4c711cdb 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageDispatcher.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/MessageDispatcher.cs @@ -23,10 +23,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol private AsyncContextThread messageLoopThread; - private Dictionary> requestHandlers = + internal Dictionary> requestHandlers = new Dictionary>(); - private Dictionary> eventHandlers = + internal Dictionary> eventHandlers = new Dictionary>(); private Action responseHandler; @@ -218,10 +218,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol { string message = string.Format("Exception occurred while parsing message: {0}", e.Message); Logger.Write(LogLevel.Error, message); - await MessageWriter.WriteEvent(HostingErrorEvent.Type, new HostingErrorParams - { - Message = message - }); + await MessageWriter.WriteEvent(HostingErrorEvent.Type, new HostingErrorParams { Message = message }); // Continue the loop continue; @@ -236,10 +233,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol // Log the error and send an error event to the client string message = string.Format("Exception occurred while receiving message: {0}", e.Message); Logger.Write(LogLevel.Error, message); - await MessageWriter.WriteEvent(HostingErrorEvent.Type, new HostingErrorParams - { - Message = message - }); + await MessageWriter.WriteEvent(HostingErrorEvent.Type, new HostingErrorParams { Message = message }); // Continue the loop continue; @@ -273,10 +267,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol { handlerToAwait = requestHandler(messageToDispatch, messageWriter); } - else - { - // TODO: Message not supported error - } + // else + // { + // // TODO: Message not supported error + // } } else if (messageToDispatch.MessageType == MessageType.Response) { @@ -297,10 +291,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol // TODO: Message not supported error } } - else - { - // TODO: Return message not supported - } + // else + // { + // // TODO: Return message not supported + // } if (handlerToAwait != null) { @@ -325,7 +319,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol } } - private void OnListenTaskCompleted(Task listenTask) + internal void OnListenTaskCompleted(Task listenTask) { if (listenTask.IsFaulted) { diff --git a/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/Serializers/V8MessageSerializer.cs b/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/Serializers/V8MessageSerializer.cs index f1385e00..f0e144e6 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/Serializers/V8MessageSerializer.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Hosting/Protocol/Serializers/V8MessageSerializer.cs @@ -89,10 +89,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Serializers messageJson.GetValue("message")); } } - else - { - // TODO: Parse error - } + // else + // { + // // TODO: Parse error + // } } else if (string.Equals("event", messageType, StringComparison.CurrentCultureIgnoreCase)) diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs index 7fb4bc69..ff5b1178 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/LanguageService.cs @@ -282,7 +282,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices /// /// /// - private static async Task HandleCompletionResolveRequest( + internal static async Task HandleCompletionResolveRequest( CompletionItem completionItem, RequestContext requestContext) { @@ -344,7 +344,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } #endif - private static async Task HandleSignatureHelpRequest( + internal static async Task HandleSignatureHelpRequest( TextDocumentPosition textDocumentPosition, RequestContext requestContext) { @@ -1041,11 +1041,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } catch (Exception e) { - Logger.Write( - LogLevel.Error, - string.Format( - "Exception while cancelling analysis task:\n\n{0}", - e.ToString())); + Logger.Write(LogLevel.Error, string.Format("Exception while cancelling analysis task:\n\n{0}", e.ToString())); TaskCompletionSource cancelTask = new TaskCompletionSource(); cancelTask.SetCanceled(); @@ -1169,7 +1165,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices } } - private bool RemoveScriptParseInfo(string uri) + internal bool RemoveScriptParseInfo(string uri) { lock (this.parseMapLock) { @@ -1188,7 +1184,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices /// Returns a flag indicating if the ScriptFile refers to the output window. /// /// - private bool IsPreviewWindow(ScriptFile scriptFile) + internal bool IsPreviewWindow(ScriptFile scriptFile) { if (scriptFile != null && !string.IsNullOrWhiteSpace(scriptFile.ClientFilePath)) { diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ScriptDocumentInfo.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ScriptDocumentInfo.cs index fd15ad82..2735abea 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ScriptDocumentInfo.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageServices/ScriptDocumentInfo.cs @@ -92,7 +92,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Completion /// /// The token text in the file content used for completion list /// - public string TokenText + public virtual string TokenText { get { diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs index 7336cec2..c7c379c9 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Batch.cs @@ -48,7 +48,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution /// /// Internal representation of the messages so we can modify internally /// - private readonly List resultMessages; + internal readonly List resultMessages; /// /// Internal representation of the result sets so we can modify internally @@ -379,7 +379,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution /// /// Sender of the event /// Arguments for the event - private void StatementCompletedHandler(object sender, StatementCompletedEventArgs args) + internal void StatementCompletedHandler(object sender, StatementCompletedEventArgs args) { // Add a message for the number of rows the query returned string message; @@ -414,7 +414,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution /// cannot be converted to SqlException, the message is written to the messages list. /// /// The exception to unwrap - private void UnwrapDbException(DbException dbe) + internal void UnwrapDbException(DbException dbe) { SqlException se = dbe as SqlException; if (se != null) diff --git a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/DbColumnWrapper.cs b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/DbColumnWrapper.cs index 09beae29..3ab13705 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/DbColumnWrapper.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/QueryExecution/Contracts/DbColumnWrapper.cs @@ -19,7 +19,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts /// /// All types supported by the server, stored as a hash set to provide O(1) lookup /// - private static readonly HashSet AllServerDataTypes = new HashSet + internal static readonly HashSet AllServerDataTypes = new HashSet { "bigint", "binary", diff --git a/src/Microsoft.SqlTools.ServiceLayer/Utility/LongList.cs b/src/Microsoft.SqlTools.ServiceLayer/Utility/LongList.cs index afacc98f..306019df 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Utility/LongList.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Utility/LongList.cs @@ -20,15 +20,16 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility /// /// Type of the values to store public class LongList : IEnumerable - { + { #region Member Variables - + + private int expandListSize = int.MaxValue; private List> expandedList; private readonly List shortList; #endregion - /// + /// /// Creates a new long list /// public LongList() @@ -46,7 +47,22 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility public T this[long index] { - get { return GetItem(index); } + get + { + return GetItem(index); + } + } + + public int ExpandListSize + { + get + { + return this.expandListSize; + } + internal set + { + this.expandListSize = value; + } } #endregion @@ -60,7 +76,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility /// Index of the item that was just added public long Add(T val) { - if (Count <= int.MaxValue) + if (Count <= this.ExpandListSize) { shortList.Add(val); } @@ -73,7 +89,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility expandedList = new List> {shortList}; } - int arrayIndex = (int)(Count/int.MaxValue); // 0 based + int arrayIndex = (int)(Count / this.ExpandListSize); // 0 based List arr; if (expandedList.Count <= arrayIndex) // need to make a new array @@ -99,19 +115,19 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility { T val = default(T); - if (Count <= int.MaxValue) + if (Count <= this.ExpandListSize) { int i32Index = Convert.ToInt32(index); val = shortList[i32Index]; } else { - int iArray32Index = (int) (Count/int.MaxValue); + int iArray32Index = (int) (Count / this.ExpandListSize); if (expandedList.Count > iArray32Index) { List arr = expandedList[iArray32Index]; - int i32Index = (int) (Count%int.MaxValue); + int i32Index = (int) (Count % this.ExpandListSize); if (arr.Count > i32Index) { val = arr[i32Index]; @@ -128,7 +144,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility /// The index to remove from the list public void RemoveAt(long index) { - if (Count <= int.MaxValue) + if (Count <= this.ExpandListSize) { int iArray32MemberIndex = Convert.ToInt32(index); // 0 based shortList.RemoveAt(iArray32MemberIndex); @@ -136,21 +152,21 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility else // handle the case of multiple arrays { // find out which array it is in - int arrayIndex = (int) (index/int.MaxValue); + int arrayIndex = (int) (index / this.ExpandListSize); List arr = expandedList[arrayIndex]; // find out index into this array - int iArray32MemberIndex = (int) (index%int.MaxValue); + int iArray32MemberIndex = (int) (index % this.ExpandListSize); arr.RemoveAt(iArray32MemberIndex); // now shift members of the array back one - int iArray32TotalIndex = (int) (Count/Int32.MaxValue); + int iArray32TotalIndex = (int) (Count / this.ExpandListSize); for (int i = arrayIndex + 1; i < iArray32TotalIndex; i++) { List arr1 = expandedList[i - 1]; List arr2 = expandedList[i]; - arr1.Add(arr2[int.MaxValue - 1]); + arr1.Add(arr2[this.ExpandListSize - 1]); arr2.RemoveAt(0); } } diff --git a/src/Microsoft.SqlTools.ServiceLayer/Workspace/Workspace.cs b/src/Microsoft.SqlTools.ServiceLayer/Workspace/Workspace.cs index 1c798a5d..e3954d39 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Workspace/Workspace.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Workspace/Workspace.cs @@ -194,7 +194,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace this.workspaceFiles.Remove(scriptFile.Id); } - private string GetBaseFilePath(string filePath) + internal string GetBaseFilePath(string filePath) { if (IsPathInMemory(filePath)) { @@ -215,7 +215,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace return Path.GetDirectoryName(filePath); } - private string ResolveRelativeScriptPath(string baseFilePath, string relativePath) + internal string ResolveRelativeScriptPath(string baseFilePath, string relativePath) { if (Path.IsPathRooted(relativePath)) { diff --git a/src/Microsoft.SqlTools.ServiceLayer/sr.cs b/src/Microsoft.SqlTools.ServiceLayer/sr.cs index c8abeed3..b5d188d5 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/sr.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/sr.cs @@ -13,7 +13,7 @@ namespace Microsoft.SqlTools.ServiceLayer [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class SR { - protected SR() + internal SR() { } public static CultureInfo Culture @@ -549,7 +549,7 @@ namespace Microsoft.SqlTools.ServiceLayer public const string WorkspaceServiceBufferPositionOutOfOrder = "WorkspaceServiceBufferPositionOutOfOrder"; - private Keys() + internal Keys() { } public static CultureInfo Culture diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/Connection/ConnectionServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/Connection/ConnectionServiceTests.cs index 3bc7b14c..9ead2576 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/Connection/ConnectionServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/Connection/ConnectionServiceTests.cs @@ -536,6 +536,17 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection Assert.True(connectionString.Contains(connectionStringMarker)); } + /// + /// Build connection string with an invalid auth type + /// + [Fact] + public void BuildConnectionStringWithInvalidAuthType() + { + ConnectionDetails details = TestObjects.GetTestConnectionDetails(); + details.AuthenticationType = "NotAValidAuthType"; + Assert.Throws(() => ConnectionService.BuildConnectionString(details)); + } + /// /// Verify that a connection changed event is fired when the database context changes. /// @@ -892,6 +903,29 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection }); } + // + /// Test that cancel connection with a null connection parameter + /// + [Fact] + public void TestCancelConnectionNullParam() + { + var service = TestObjects.GetTestConnectionService(); + Assert.False(service.CancelConnect(null)); + } + + // + /// Test that cancel connection with a null connection parameter + /// + [Fact] + public void TestListDatabasesInvalidParams() + { + var service = TestObjects.GetTestConnectionService(); + var listParams = new ListDatabasesParams(); + Assert.Throws(() => service.ListDatabases(listParams)); + listParams.OwnerUri = "file://notmyfile.sql"; + Assert.Throws(() => service.ListDatabases(listParams)); + } + /// /// Test that the connection complete notification type can be created. /// diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/Connection/ReliableConnectionTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/Connection/ReliableConnectionTests.cs index 95194a55..65ff5eaf 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/Connection/ReliableConnectionTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/Connection/ReliableConnectionTests.cs @@ -10,8 +10,11 @@ using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Data.SqlClient; +using System.Threading; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection; +using Microsoft.SqlTools.ServiceLayer.QueryExecution; +using Microsoft.SqlTools.ServiceLayer.Test.QueryExecution; using Microsoft.SqlTools.ServiceLayer.Test.Utility; using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; using Microsoft.SqlTools.Test.Utility; @@ -70,6 +73,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection { return ShouldRetryImpl(retryStateObj); } + + public void DoOnIgnoreErrorOccurred(RetryState retryState) + { + OnIgnoreErrorOccurred(retryState); + } } internal class TestProgressiveRetryPolicy : ProgressiveRetryPolicy @@ -126,10 +134,46 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection strategy: new NetworkConnectivityErrorDetectionStrategy(), maxRetryCount: 3, intervalBetweenRetries: TimeSpan.FromMilliseconds(100)); - bool shouldRety = policy.InvokeShouldRetryImpl(new RetryStateEx()); + var retryState = new RetryStateEx(); + bool shouldRety = policy.InvokeShouldRetryImpl(retryState); + policy.DoOnIgnoreErrorOccurred(retryState); Assert.True(shouldRety); } + [Fact] + public void FixedDelayPolicyExecuteActionTest() + { + TestFixedDelayPolicy policy = new TestFixedDelayPolicy( + strategy: new NetworkConnectivityErrorDetectionStrategy(), + maxRetryCount: 3, + intervalBetweenRetries: TimeSpan.FromMilliseconds(20)); + + // execute an action that throws a retry limit exception + CancellationToken token = new CancellationToken(); + Assert.Equal(policy.ExecuteAction((s) => { throw new RetryLimitExceededException(); }, token), default(int)); + + // execute an action that throws a retry limit exeception with an inner exception + Assert.Throws(() => + { + policy.ExecuteAction((s) => + { + var e = new RetryLimitExceededException("retry", new Exception()); + throw e; + }); + }); + } + + [Fact] + public void IsRetryableExceptionTest() + { + TestFixedDelayPolicy policy = new TestFixedDelayPolicy( + strategy: new NetworkConnectivityErrorDetectionStrategy(), + maxRetryCount: 3, + intervalBetweenRetries: TimeSpan.FromMilliseconds(20)); + + Assert.False(policy.IsRetryableException(new Exception())); + } + [Fact] public void ProgressiveRetryPolicyTest() { @@ -140,6 +184,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection increment: TimeSpan.FromMilliseconds(100)); bool shouldRety = policy.InvokeShouldRetryImpl(new RetryStateEx()); Assert.True(shouldRety); + Assert.NotNull(policy.CommandTimeoutInSeconds); + policy.ShouldIgnoreOnFirstTry = false; + Assert.False(policy.ShouldIgnoreOnFirstTry); } [Fact] @@ -157,6 +204,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection Assert.True(shouldRety); } + + [Fact] + public void GetErrorNumberWithNullExceptionTest() + { + Assert.Null(RetryPolicy.GetErrorNumber(null)); + } + /// /// Environment variable that stores the name of the test server hosting the SQL Server instance. /// @@ -260,6 +314,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection Assert.True(serverInfo.ServerEdition == serverInfo2.ServerEdition); Assert.True(serverInfo.IsCloud == serverInfo2.IsCloud); Assert.True(serverInfo.AzureVersion == serverInfo2.AzureVersion); + Assert.True(serverInfo.IsAzureV1 == serverInfo2.IsAzureV1); } }); } @@ -290,6 +345,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection Assert.False(isReadOnly); } + /// + /// /// Tests ReliableConnectionHelper.IsDatabaseReadonly() with null builder parameter + /// + [Fact] + public void TestIsDatabaseReadonlyWithNullBuilder() + { + Assert.Throws(() => ReliableConnectionHelper.IsDatabaseReadonly(null)); + } + /// /// Verify ANSI_NULL and QUOTED_IDENTIFIER settings can be set and retrieved for a session /// @@ -475,6 +539,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection }); } + /// + /// Test that TryGetServerVersion() fails with invalid connection string + /// + [Fact] + public void TestTryGetServerVersionInvalidConnectionString() + { + TestUtils.RunIfWindows(() => + { + ReliableConnectionHelper.ServerInfo info = null; + Assert.False(ReliableConnectionHelper.TryGetServerVersion("this is not a valid connstr", out info)); + }); + } /// /// Validate ambient static settings @@ -561,6 +637,28 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection data.TraceSettings(); } + [Fact] + public void RaiseAmbientRetryMessageTest() + { + bool handlerCalled = false; + var data = new AmbientSettings.AmbientData(); + data.ConnectionRetryMessageHandler = (a) => handlerCalled = true; + AmbientSettings._defaultSettings = data; + RetryPolicyUtils.RaiseAmbientRetryMessage(new RetryStateEx() { LastError = new Exception() }, 100); + Assert.True(handlerCalled); + } + + [Fact] + public void RaiseAmbientIgnoreMessageTest() + { + bool handlerCalled = false; + var data = new AmbientSettings.AmbientData(); + data.ConnectionRetryMessageHandler = (a) => handlerCalled = true; + AmbientSettings._defaultSettings = data; + RetryPolicyUtils.RaiseAmbientIgnoreMessage(new RetryStateEx() { LastError = new Exception() }, 100); + Assert.True(handlerCalled); + } + [Fact] public void RetryPolicyFactoryTest() { @@ -681,6 +779,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection var detectionStrategy2 = new TestSqlAzureTemporaryAndIgnorableErrorDetectionStrategy(); Assert.NotNull(detectionStrategy2.InvokeCanRetrySqlException(sqlException)); Assert.NotNull(detectionStrategy2.InvokeShouldIgnoreSqlException(sqlException)); + + Batch batch = new Batch(Common.StandardQuery, Common.SubsectionDocument, Common.Ordinal, Common.GetFileStreamFactory(null)); + batch.UnwrapDbException(sqlException); } var unknownCodeReason = RetryPolicy.ThrottlingReason.FromReasonCode(-1); @@ -736,6 +837,119 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection Assert.Equal(exception, args.Exception); Assert.Equal(timespan, args.Delay); } + + [Fact] + public void CheckStaticVariables() + { + Assert.NotNull(ReliableConnectionHelper.BuilderWithDefaultApplicationName); + } + + [Fact] + public void SetLockAndCommandTimeoutThrowsOnNull() + { + Assert.Throws(typeof(ArgumentNullException), () => ReliableConnectionHelper.SetLockAndCommandTimeout(null)); + } + + [Fact] + public void StandardExceptionHandlerTests() + { + Assert.True(ReliableConnectionHelper.StandardExceptionHandler(new InvalidCastException())); + Assert.False(ReliableConnectionHelper.StandardExceptionHandler(new Exception())); + } + + [Fact] + public void GetConnectionStringBuilderNullConnectionString() + { + SqlConnectionStringBuilder builder; + Assert.False(ReliableConnectionHelper.TryGetConnectionStringBuilder(null, out builder)); + } + + [Fact] + public void GetConnectionStringBuilderExceptionTests() + { + SqlConnectionStringBuilder builder; + + // throws ArgumentException + Assert.False(ReliableConnectionHelper.TryGetConnectionStringBuilder("IntegratedGoldFish=True", out builder)); + + // throws FormatException + Assert.False(ReliableConnectionHelper.TryGetConnectionStringBuilder("rabbits**frogs**lizards", out builder)); + } + + [Fact] + public void GetCompleteServerNameTests() + { + Assert.Null(ReliableConnectionHelper.GetCompleteServerName(null)); + + Assert.NotNull(ReliableConnectionHelper.GetCompleteServerName("localhost")); + + Assert.NotNull(ReliableConnectionHelper.GetCompleteServerName("mytestservername")); + } + + [Fact] + public void ReliableSqlCommandConstructorTests() + { + // verify default constructor doesn't throw + Assert.NotNull(new ReliableSqlConnection.ReliableSqlCommand()); + + // verify constructor with null connection doesn't throw + Assert.NotNull(new ReliableSqlConnection.ReliableSqlCommand(null)); + } + + [Fact] + public void ReliableSqlCommandProperties() + { + var command = new ReliableSqlConnection.ReliableSqlCommand(); + command.CommandText = "SELECT 1"; + Assert.Equal(command.CommandText, "SELECT 1"); + Assert.NotNull(command.CommandTimeout); + Assert.NotNull(command.CommandType); + command.DesignTimeVisible = true; + Assert.True(command.DesignTimeVisible); + command.UpdatedRowSource = UpdateRowSource.None; + Assert.Equal(command.UpdatedRowSource, UpdateRowSource.None); + Assert.NotNull(command.GetUnderlyingCommand()); + Assert.Throws(() => command.ValidateConnectionIsSet()); + command.Prepare(); + Assert.NotNull(command.CreateParameter()); + command.Cancel(); + } + + [Fact] + public void ReliableConnectionResourcesTests() + { + Assert.NotNull(Resources.ConnectionPassedToIsCloudShouldBeOpen); + Assert.NotNull(Resources.ExceptionCannotBeRetried); + Assert.NotNull(Resources.FailedToCacheIsCloud); + Assert.NotNull(Resources.FailedToParseConnectionString); + Assert.NotNull(Resources.InvalidCommandType); + Assert.NotNull(Resources.InvalidConnectionType); + Assert.NotNull(Resources.OnlyReliableConnectionSupported); + Assert.NotNull(Resources.UnableToAssignValue); + Assert.NotNull(Resources.UnableToRetrieveAzureSessionId); + } + + [Fact] + public void CalcExponentialRetryDelayWithSchemaDefaultsTest() + { + Assert.NotNull(RetryPolicyUtils.CalcExponentialRetryDelayWithSchemaDefaults(1)); + } + + [Fact] + public void IsSupportedCommandNullCommandTest() + { + Assert.False(DbCommandWrapper.IsSupportedCommand(null)); + } + + [Fact] + public void StatementCompletedTests() + { + bool handlerCalled = false; + StatementCompletedEventHandler handler = (s, e) => handlerCalled = true; + var command = new DbCommandWrapper(new SqlCommand()); + command.StatementCompleted += handler; + command.StatementCompleted -= handler; + } } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/AutocompleteTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/AutocompleteTests.cs index a9e346cd..b034609a 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/AutocompleteTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/AutocompleteTests.cs @@ -39,8 +39,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices private Mock> requestContext; + private Mock scriptFile; + private Mock binder; + private ScriptParseInfo scriptParseInfo; + private TextDocumentPosition textDocument; private void InitializeTestObjects() @@ -60,14 +64,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices WorkspaceService.Instance.CurrentSettings = new SqlToolsSettings(); // set up file for returning the query - var fileMock = new Mock(); - fileMock.SetupGet(file => file.Contents).Returns(Common.StandardQuery); - fileMock.SetupGet(file => file.ClientFilePath).Returns(this.testScriptUri); + scriptFile = new Mock(); + scriptFile.SetupGet(file => file.Contents).Returns(Common.StandardQuery); + scriptFile.SetupGet(file => file.ClientFilePath).Returns(this.testScriptUri); // set up workspace mock workspaceService = new Mock>(); workspaceService.Setup(service => service.Workspace.GetFile(It.IsAny())) - .Returns(fileMock.Object); + .Returns(scriptFile.Object); // setup binding queue mock bindingQueue = new Mock(); @@ -93,16 +97,113 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices It.IsAny(), It.IsAny())); - var testScriptParseInfo = new ScriptParseInfo(); - LanguageService.Instance.AddOrUpdateScriptParseInfo(this.testScriptUri, testScriptParseInfo); - testScriptParseInfo.IsConnected = true; - testScriptParseInfo.ConnectionKey = LanguageService.Instance.BindingQueue.AddConnectionContext(connectionInfo); + scriptParseInfo = new ScriptParseInfo(); + LanguageService.Instance.AddOrUpdateScriptParseInfo(this.testScriptUri, scriptParseInfo); + scriptParseInfo.IsConnected = true; + scriptParseInfo.ConnectionKey = LanguageService.Instance.BindingQueue.AddConnectionContext(connectionInfo); // setup the binding context object ConnectedBindingContext bindingContext = new ConnectedBindingContext(); bindingContext.Binder = binder.Object; bindingContext.MetadataDisplayInfoProvider = new MetadataDisplayInfoProvider(); - LanguageService.Instance.BindingQueue.BindingContextMap.Add(testScriptParseInfo.ConnectionKey, bindingContext); + LanguageService.Instance.BindingQueue.BindingContextMap.Add(scriptParseInfo.ConnectionKey, bindingContext); + } + + [Fact] + public void HandleCompletionRequestDisabled() + { + InitializeTestObjects(); + WorkspaceService.Instance.CurrentSettings.SqlTools.IntelliSense.EnableIntellisense = false; + Assert.NotNull(LanguageService.HandleCompletionRequest(null, null)); + } + + [Fact] + public void HandleCompletionResolveRequestDisabled() + { + InitializeTestObjects(); + WorkspaceService.Instance.CurrentSettings.SqlTools.IntelliSense.EnableIntellisense = false; + Assert.NotNull(LanguageService.HandleCompletionResolveRequest(null, null)); + } + + [Fact] + public void HandleSignatureHelpRequestDisabled() + { + InitializeTestObjects(); + WorkspaceService.Instance.CurrentSettings.SqlTools.IntelliSense.EnableIntellisense = false; + Assert.NotNull(LanguageService.HandleSignatureHelpRequest(null, null)); + } + + [Fact] + public void AddOrUpdateScriptParseInfoNullUri() + { + InitializeTestObjects(); + LanguageService.Instance.AddOrUpdateScriptParseInfo("abracadabra", scriptParseInfo); + Assert.True(LanguageService.Instance.ScriptParseInfoMap.ContainsKey("abracadabra")); + } + + [Fact] + public void GetDefinitionInvalidTextDocument() + { + InitializeTestObjects(); + textDocument.TextDocument.Uri = "invaliduri"; + Assert.Null(LanguageService.Instance.GetDefinition(textDocument, null, null)); + } + + [Fact] + public void RemoveScriptParseInfoNullUri() + { + InitializeTestObjects(); + Assert.False(LanguageService.Instance.RemoveScriptParseInfo("abc123")); + } + + [Fact] + public void IsPreviewWindowNullScriptFileTest() + { + InitializeTestObjects(); + Assert.False(LanguageService.Instance.IsPreviewWindow(null)); + } + + [Fact] + public void GetCompletionItemsInvalidTextDocument() + { + InitializeTestObjects(); + textDocument.TextDocument.Uri = "somethinggoeshere"; + Assert.True(LanguageService.Instance.GetCompletionItems(textDocument, scriptFile.Object, null).Length > 0); + } + + [Fact] + public void GetDiagnosticFromMarkerTest() + { + var scriptFileMarker = new ScriptFileMarker() + { + Message = "Message", + Level = ScriptFileMarkerLevel.Error, + ScriptRegion = new ScriptRegion() + { + File = "file://nofile.sql", + StartLineNumber = 1, + StartColumnNumber = 1, + StartOffset = 0, + EndLineNumber = 1, + EndColumnNumber = 1, + EndOffset = 0 + } + }; + var diagnostic = DiagnosticsHelper.GetDiagnosticFromMarker(scriptFileMarker); + Assert.Equal(diagnostic.Message, scriptFileMarker.Message); + } + + [Fact] + public void MapDiagnosticSeverityTest() + { + var level = ScriptFileMarkerLevel.Error; + Assert.Equal(DiagnosticsHelper.MapDiagnosticSeverity(level), DiagnosticSeverity.Error); + level = ScriptFileMarkerLevel.Warning; + Assert.Equal(DiagnosticsHelper.MapDiagnosticSeverity(level), DiagnosticSeverity.Warning); + level = ScriptFileMarkerLevel.Information; + Assert.Equal(DiagnosticsHelper.MapDiagnosticSeverity(level), DiagnosticSeverity.Information); + level = (ScriptFileMarkerLevel)100; + Assert.Equal(DiagnosticsHelper.MapDiagnosticSeverity(level), DiagnosticSeverity.Error); } /// diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/LanguageServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/LanguageServiceTests.cs index a445fb49..4979c507 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/LanguageServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/LanguageServiceTests.cs @@ -3,8 +3,10 @@ // 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; using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts; using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; using Microsoft.SqlTools.Test.Utility; @@ -143,6 +145,56 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServer Assert.Null(signatureHelp); } + [Fact] + public void EmptyCompletionListTest() + { + Assert.Equal(AutoCompleteHelper.EmptyCompletionList.Length, 0); + } + + [Fact] + public void SetWorkspaceServiceInstanceTest() + { + AutoCompleteHelper.WorkspaceServiceInstance = null; + // workspace will be recreated if it's set to null + Assert.NotNull(AutoCompleteHelper.WorkspaceServiceInstance); + } + + internal class TestScriptDocumentInfo : ScriptDocumentInfo + { + public TestScriptDocumentInfo(TextDocumentPosition textDocumentPosition, ScriptFile scriptFile, ScriptParseInfo scriptParseInfo) + :base(textDocumentPosition, scriptFile, scriptParseInfo) + { + + } + + public override string TokenText + { + get + { + return "doesntmatchanythingintheintellisensedefaultlist"; + } + } + } + + [Fact] + public void GetDefaultCompletionListWithNoMatchesTest() + { + var scriptFile = new ScriptFile(); + scriptFile.SetFileContents("koko wants a bananas"); + + ScriptParseInfo scriptInfo = new ScriptParseInfo { IsConnected = false }; + + var scriptDocumentInfo = new TestScriptDocumentInfo( + new TextDocumentPosition() + { + TextDocument = new TextDocumentIdentifier() { Uri = TestObjects.ScriptUri }, + Position = new Position() { Line = 0, Character = 0 } + }, scriptFile, scriptInfo); + + AutoCompleteHelper.GetDefaultCompletionItems(scriptDocumentInfo, false); + + } + private TextDocumentPosition CreateDummyDocPosition() { return new TextDocumentPosition @@ -180,11 +232,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServer connInfo = TestObjects.InitLiveConnectionInfo(out scriptFile); } - + /// /// Test the service initialization code path and verify nothing throws /// - // Test is causing failures in build lab..investigating to reenable [Fact] public void ServiceInitialization() { @@ -200,12 +251,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServer Assert.True(LanguageService.ConnectionServiceInstance != null); Assert.True(LanguageService.Instance.CurrentSettings != null); Assert.True(LanguageService.Instance.CurrentWorkspace != null); - } + } /// /// Test the service initialization code path and verify nothing throws /// - // Test is causing failures in build lab..investigating to reenable [Fact] public void PrepopulateCommonMetadata() { diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/PeekDefinitionTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/PeekDefinitionTests.cs index 9bb871b1..522703fc 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/PeekDefinitionTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/PeekDefinitionTests.cs @@ -197,9 +197,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices public void GetValidTableDefinitionTest() { // Get live connectionInfo - ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition(); - PeekDefinition peekDefinition = new PeekDefinition(connInfo); - string objectName = "test_table"; + PeekDefinition peekDefinition = new PeekDefinition(TestObjects.InitLiveConnectionInfoForDefinition()); + string objectName = "spt_monitor"; string schemaName = null; string objectType = "TABLE"; @@ -216,8 +215,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices public void GetTableDefinitionInvalidObjectTest() { // Get live connectionInfo - ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition(); - PeekDefinition peekDefinition = new PeekDefinition(connInfo); + PeekDefinition peekDefinition = new PeekDefinition(TestObjects.InitLiveConnectionInfoForDefinition()); string objectName = "test_invalid"; string schemaName = null; string objectType = "TABLE"; @@ -234,9 +232,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices public void GetTableDefinitionWithSchemaTest() { // Get live connectionInfo - ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition(); - PeekDefinition peekDefinition = new PeekDefinition(connInfo); - string objectName = "test_table"; + PeekDefinition peekDefinition = new PeekDefinition(TestObjects.InitLiveConnectionInfoForDefinition()); + string objectName = "spt_monitor"; string schemaName = "dbo"; string objectType = "TABLE"; @@ -279,9 +276,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices /// [Fact] public void GetValidViewDefinitionTest() - { - ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition(); - PeekDefinition peekDefinition = new PeekDefinition(connInfo); + { + PeekDefinition peekDefinition = new PeekDefinition(TestObjects.InitLiveConnectionInfoForDefinition()); string objectName = "objects"; string schemaName = "sys"; string objectType = "VIEW"; @@ -297,8 +293,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices [Fact] public void GetViewDefinitionInvalidObjectTest() { - ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition(); - PeekDefinition peekDefinition = new PeekDefinition(connInfo); + PeekDefinition peekDefinition = new PeekDefinition(TestObjects.InitLiveConnectionInfoForDefinition()); string objectName = "objects"; string schemaName = null; string objectType = "VIEW"; @@ -313,9 +308,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices [Fact] public void GetStoredProcedureDefinitionTest() { - ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition(); - PeekDefinition peekDefinition = new PeekDefinition(connInfo); - string objectName = "SP1"; + PeekDefinition peekDefinition = new PeekDefinition(TestObjects.InitLiveConnectionInfoForDefinition()); + string objectName = "sp_MSrepl_startup"; string schemaName = "dbo"; string objectType = "PROCEDURE"; @@ -330,8 +324,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices [Fact] public void GetStoredProcedureDefinitionFailureTest() { - ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition(); - PeekDefinition peekDefinition = new PeekDefinition(connInfo); + PeekDefinition peekDefinition = new PeekDefinition(TestObjects.InitLiveConnectionInfoForDefinition()); string objectName = "SP2"; string schemaName = "dbo"; string objectType = "PROCEDURE"; @@ -346,9 +339,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices [Fact] public void GetStoredProcedureDefinitionWithoutSchemaTest() { - ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition(); - PeekDefinition peekDefinition = new PeekDefinition(connInfo); - string objectName = "SP1"; + PeekDefinition peekDefinition = new PeekDefinition(TestObjects.InitLiveConnectionInfoForDefinition()); + string objectName = "sp_MSrepl_startup"; string schemaName = null; string objectType = "PROCEDURE"; diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/Messaging/MessageDispatcherTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/Messaging/MessageDispatcherTests.cs new file mode 100644 index 00000000..673b0884 --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/Messaging/MessageDispatcherTests.cs @@ -0,0 +1,88 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Threading.Tasks; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Channel; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; +using Moq; +using Xunit; + +namespace Microsoft.SqlTools.ServiceLayer.Test.Messaging +{ + public class MessageDispatcherTests + { + [Fact] + public void SetRequestHandlerWithOverrideTest() + { + RequestType requestType = RequestType.Create("test/requestType"); + var dispatcher = new MessageDispatcher(new Mock().Object); + dispatcher.SetRequestHandler( + requestType, + (i, j) => + { + return Task.FromResult(0); + }, + true); + Assert.True(dispatcher.requestHandlers.Count > 0); + } + + [Fact] + public void SetEventHandlerTest() + { + EventType eventType = EventType.Create("test/eventType"); + var dispatcher = new MessageDispatcher(new Mock().Object); + dispatcher.SetEventHandler( + eventType, + (i, j) => + { + return Task.FromResult(0); + }); + Assert.True(dispatcher.eventHandlers.Count > 0); + } + + [Fact] + public void SetEventHandlerWithOverrideTest() + { + EventType eventType = EventType.Create("test/eventType"); + var dispatcher = new MessageDispatcher(new Mock().Object); + dispatcher.SetEventHandler( + eventType, + (i, j) => + { + return Task.FromResult(0); + }, + true); + Assert.True(dispatcher.eventHandlers.Count > 0); + } + + [Fact] + public void OnListenTaskCompletedFaultedTaskTest() + { + Task t = null; + + try + { + t = Task.Run(() => + { + throw new Exception(); + }); + t.Wait(); + } + catch + { + } + finally + { + bool handlerCalled = false; + var dispatcher = new MessageDispatcher(new Mock().Object); + dispatcher.UnhandledException += (s, e) => handlerCalled = true; + dispatcher.OnListenTaskCompleted(t); + Assert.True(handlerCalled); + } + } + } +} \ No newline at end of file diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/Messaging/MessageWriterTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/Messaging/MessageWriterTests.cs index 3c007a85..4cc99592 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/Messaging/MessageWriterTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/Messaging/MessageWriterTests.cs @@ -7,7 +7,9 @@ using System.IO; using System.Text; using System.Threading.Tasks; using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts; using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Serializers; +using Newtonsoft.Json.Linq; using Xunit; namespace Microsoft.SqlTools.ServiceLayer.Test.Messaging @@ -21,6 +23,40 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Messaging this.messageSerializer = new V8MessageSerializer(); } + [Fact] + public void SerializeMessageTest() + { + // serialize\deserialize a request + var message = new Message(); + message.MessageType = MessageType.Request; + message.Id = "id"; + message.Method = "method"; + message.Contents = null; + var serializedMessage = this.messageSerializer.SerializeMessage(message); + Assert.NotNull(serializedMessage); + var deserializedMessage = this.messageSerializer.DeserializeMessage(serializedMessage); + Assert.Equal(message.Id, deserializedMessage.Id); + + // serialize\deserialize a response + message.MessageType = MessageType.Response; + serializedMessage = this.messageSerializer.SerializeMessage(message); + Assert.NotNull(serializedMessage); + deserializedMessage = this.messageSerializer.DeserializeMessage(serializedMessage); + Assert.Equal(message.Id, deserializedMessage.Id); + + // serialize\deserialize a response with an error + message.Error = JToken.FromObject("error"); + serializedMessage = this.messageSerializer.SerializeMessage(message); + Assert.NotNull(serializedMessage); + deserializedMessage = this.messageSerializer.DeserializeMessage(serializedMessage); + Assert.Equal(message.Error, deserializedMessage.Error); + + // serialize\deserialize an unknown response type + serializedMessage.Remove("type"); + serializedMessage.Add("type", JToken.FromObject("dontknowthisone")); + Assert.Equal(this.messageSerializer.DeserializeMessage(serializedMessage).MessageType, MessageType.Unknown); + } + [Fact] public async Task WritesMessage() { diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/DataStorage/StorageDataReaderTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/DataStorage/StorageDataReaderTests.cs index e29c8394..567e1a7a 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/DataStorage/StorageDataReaderTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/DataStorage/StorageDataReaderTests.cs @@ -5,6 +5,7 @@ #if LIVE_CONNECTION_TESTS +using System; using System.Data.Common; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage; @@ -60,8 +61,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage reader.Read(); Assert.False(storageReader.IsDBNull(0)); + Assert.NotNull(storageReader.GetValue(0)); + string shortName = storageReader.GetCharsWithMaxCapacity(0, 2); Assert.True(shortName.Length == 2); + + Assert.Throws(() => storageReader.GetBytesWithMaxCapacity(0, 0)); + Assert.Throws(() => storageReader.GetCharsWithMaxCapacity(0, 0)); } /// @@ -88,10 +94,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.DataStorage [Fact] public void StringWriterWithMaxCapacityTest() { - var writer = new StorageDataReader.StringWriterWithMaxCapacity(null, 100); + var writer = new StorageDataReader.StringWriterWithMaxCapacity(null, 4); string output = "..."; writer.Write(output); Assert.True(writer.ToString().Equals(output)); + writer.Write('.'); + Assert.True(writer.ToString().Equals(output + '.')); + writer.Write(output); + writer.Write('.'); + Assert.True(writer.ToString().Equals(output + '.')); } } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/Execution/BatchTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/Execution/BatchTests.cs index 12b99a3b..9ac1f6c2 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/Execution/BatchTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/Execution/BatchTests.cs @@ -5,7 +5,9 @@ using System; using System.Collections.Generic; +using System.Data; using System.Data.Common; +using System.Data.SqlClient; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -388,8 +390,22 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.Execution // Then: // ... It should throw an exception Assert.Throws(() => new Batch("stuff", Common.SubsectionDocument, -1, Common.GetFileStreamFactory(null))); - } + } + [Fact] + public void StatementCompletedHandlerTest() + { + // If: + // ... I call the StatementCompletedHandler + // Then: + // ... a ResultMaessage should be logged in the resultsMessages collection + Batch batch = new Batch(Common.StandardQuery, Common.SubsectionDocument, Common.Ordinal, Common.GetFileStreamFactory(null)); + batch.StatementCompletedHandler(null, new StatementCompletedEventArgs(1)); + Assert.True(batch.ResultMessages.Count() == 1); + batch.StatementCompletedHandler(null, new StatementCompletedEventArgs(2)); + Assert.True(batch.ResultMessages.Count() == 2); + } + private static DbConnection GetConnection(ConnectionInfo info) { return info.Factory.CreateSqlConnection(ConnectionService.BuildConnectionString(info.ConnectionDetails)); diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/Execution/DbColumnWrapperTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/Execution/DbColumnWrapperTests.cs new file mode 100644 index 00000000..ca88699b --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/QueryExecution/Execution/DbColumnWrapperTests.cs @@ -0,0 +1,114 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Data.Common; +using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts; +using Xunit; + +namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution.Execution +{ + /// + /// DbColumnWrapper tests + /// + public class DbColumnWrapperTests + { + /// + /// Test DbColumn derived class + /// + class TestColumn : DbColumn + { + public TestColumn( + string dataTypeName = null, + int? columnSize = null, + string columnName = null, + string udtAssemblyQualifiedName = null) + { + if (!string.IsNullOrEmpty(dataTypeName)) + { + this.DataTypeName = dataTypeName; + } + + if (columnSize.HasValue) + { + this.ColumnSize = columnSize; + } + + if (!string.IsNullOrEmpty(columnName)) + { + this.ColumnName = columnName; + } + + if (!string.IsNullOrEmpty(udtAssemblyQualifiedName)) + { + this.UdtAssemblyQualifiedName = udtAssemblyQualifiedName; + } + } + } + + /// + /// Basic data type and properites test + /// + [Fact] + public void DataTypeAndPropertiesTest() + { + // check that data types array contains items + var serverDataTypes = DbColumnWrapper.AllServerDataTypes; + Assert.True(serverDataTypes.Count > 0); + + // check default constructor doesn't throw + Assert.NotNull(new DbColumnWrapper()); + + // check various properties are either null or not null + var column = new TestColumn(); + var wrapper = new DbColumnWrapper(column); + Assert.NotNull(wrapper.DataType); + Assert.Null(wrapper.AllowDBNull); + Assert.Null(wrapper.BaseCatalogName); + Assert.Null(wrapper.BaseColumnName); + Assert.Null(wrapper.BaseServerName); + Assert.Null(wrapper.BaseTableName); + Assert.Null(wrapper.ColumnOrdinal); + Assert.Null(wrapper.ColumnSize); + Assert.Null(wrapper.IsAliased); + Assert.Null(wrapper.IsAutoIncrement); + Assert.Null(wrapper.IsExpression); + Assert.Null(wrapper.IsHidden); + Assert.Null(wrapper.IsIdentity); + Assert.Null(wrapper.IsKey); + Assert.Null(wrapper. IsReadOnly); + Assert.Null(wrapper.IsUnique); + Assert.Null(wrapper.NumericPrecision); + Assert.Null(wrapper.NumericScale); + Assert.Null(wrapper.UdtAssemblyQualifiedName); + Assert.Null(wrapper.DataTypeName); + } + + /// + /// constructor test + /// + [Fact] + public void DbColumnConstructorTests() + { + // check that various constructor parameters initial the wrapper correctly + var w1 = new DbColumnWrapper(new TestColumn("varchar", int.MaxValue, "Microsoft SQL Server 2005 XML Showplan")); + Assert.True(w1.IsXml); + + var w2 = new DbColumnWrapper(new TestColumn("binary")); + Assert.True(w2.IsBytes); + + var w3 = new DbColumnWrapper(new TestColumn("varbinary", int.MaxValue)); + Assert.True(w3.IsBytes); + + var w4 = new DbColumnWrapper(new TestColumn("sql_variant")); + Assert.True(w4.IsSqlVariant); + + var w5 = new DbColumnWrapper(new TestColumn("my_udt")); + Assert.True(w5.IsUdt); + + var w6 = new DbColumnWrapper(new TestColumn("my_hieracrchy", null, null, "MICROSOFT.SQLSERVER.TYPES.SQLHIERARCHYID")); + Assert.True(w6.IsUdt); + } + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/Utility/LongListTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/Utility/LongListTests.cs index a28714bc..330214ca 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/Utility/LongListTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/Utility/LongListTests.cs @@ -25,5 +25,34 @@ namespace Microsoft.SqlTools.Test.Utility longList.RemoveAt(0); Assert.True(longList.Count == 0); } + + /// + /// Add and remove and item in a LongList causing an expansion + /// + [Fact] + public void LongListExpandTest() + { + var longList = new LongList(); + longList.ExpandListSize = 3; + for (int i = 0; i < 6; ++i) + { + longList.Add(i); + } + Assert.Equal(longList.Count, 6); + Assert.NotNull(longList.GetItem(4)); + + bool didEnum = false; + foreach (var j in longList) + { + didEnum = true; + break; + } + + Assert.True(didEnum); + + longList.RemoveAt(4); + Assert.Equal(longList.Count, 5); + } } } + diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/Utility/SrTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/Utility/SrTests.cs new file mode 100644 index 00000000..8b3b7041 --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/Utility/SrTests.cs @@ -0,0 +1,27 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.ServiceLayer; +using Xunit; + +namespace Microsoft.SqlTools.Test.Utility +{ + public class SrTests + { + /// + /// Add and remove and item in a LongList + /// + [Fact] + public void SrPropertiesTest() + { + Assert.NotNull(new SR()); + Assert.NotNull(SR.QueryServiceSubsetBatchNotCompleted); + Assert.NotNull(SR.QueryServiceFileWrapperWriteOnly); + Assert.NotNull(SR.QueryServiceFileWrapperNotInitialized); + Assert.NotNull(SR.QueryServiceColumnNull); + Assert.NotNull(new SR.Keys()); + } + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/Utility/TestObjects.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/Utility/TestObjects.cs index 0f861433..56753010 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/Utility/TestObjects.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/Utility/TestObjects.cs @@ -7,8 +7,10 @@ using System; using System.Collections.Generic; using System.Data; using System.Data.Common; +using System.Data.SqlClient; using System.IO; using System.Reflection; +using Microsoft.SqlServer.Management.Common; using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; using Microsoft.SqlTools.ServiceLayer.Credentials; @@ -192,7 +194,7 @@ namespace Microsoft.SqlTools.Test.Utility return connInfo; } - public static ConnectionInfo InitLiveConnectionInfoForDefinition() + public static ServerConnection InitLiveConnectionInfoForDefinition() { TestObjects.InitializeTestServices(); @@ -210,7 +212,9 @@ namespace Microsoft.SqlTools.Test.Utility ConnectionInfo connInfo = null; connectionService.TryFindConnection(ownerUri, out connInfo); - return connInfo; + + SqlConnection sqlConn = new SqlConnection(ConnectionService.BuildConnectionString(connInfo.ConnectionDetails)); + return new ServerConnection(sqlConn); } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/Utility/ValidateTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/Utility/ValidateTests.cs new file mode 100644 index 00000000..8f4f790d --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/Utility/ValidateTests.cs @@ -0,0 +1,38 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using Microsoft.SqlTools.ServiceLayer.Utility; +using Xunit; + +namespace Microsoft.SqlTools.Test.Utility +{ + public class ValidateTests + { + [Fact] + public void IsWithinRangeTest() + { + Assert.Throws(() => Validate.IsWithinRange("parameterName", 1, 2, 3)); + } + + [Fact] + public void IsLessThanTest() + { + Assert.Throws(() => Validate.IsLessThan("parameterName", 2, 1)); + } + + [Fact] + public void IsNotEqualTest() + { + Assert.Throws(() => Validate.IsNotEqual("parameterName", 1, 1)); + } + + [Fact] + public void IsNullOrWhiteSpaceTest() + { + Assert.Throws(() => Validate.IsNotNullOrWhitespaceString("parameterName", null)); + } + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.Test/Workspace/WorkspaceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.Test/Workspace/WorkspaceTests.cs index ad5c3b3d..df63e816 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.Test/Workspace/WorkspaceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.Test/Workspace/WorkspaceTests.cs @@ -3,10 +3,12 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. // +using System; using System.IO; using System.Threading.Tasks; using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol; using Microsoft.SqlTools.ServiceLayer.SqlContext; +using Microsoft.SqlTools.ServiceLayer.Test.Utility; using Microsoft.SqlTools.ServiceLayer.Workspace; using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; using Microsoft.SqlTools.Test.Utility; @@ -90,5 +92,58 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Workspace Assert.Empty(workspace.GetOpenedFiles()); Assert.False(callbackCalled); } + + [Fact] + public void BufferRangeNoneNotNull() + { + Assert.NotNull(BufferRange.None); + } + + [Fact] + public void BufferRangeStartGreaterThanEnd() + { + Assert.Throws(() => + new BufferRange(new BufferPosition(2, 2), new BufferPosition(1, 1))); + } + + [Fact] + public void BufferRangeEquals() + { + var range = new BufferRange(new BufferPosition(1, 1), new BufferPosition(2, 2)); + Assert.False(range.Equals(null)); + Assert.True(range.Equals(range)); + Assert.NotNull(range.GetHashCode()); + } + + [Fact] + public void UnescapePath() + { + Assert.NotNull(Microsoft.SqlTools.ServiceLayer.Workspace.Workspace.UnescapePath("`/path/`")); + } + + [Fact] + public void GetBaseFilePath() + { + TestUtils.RunIfWindows(() => + { + using (var workspace = new ServiceLayer.Workspace.Workspace()) + { + Assert.Throws(() => workspace.GetBaseFilePath("path")); + Assert.NotNull(workspace.GetBaseFilePath(@"c:\path\file.sql")); + Assert.Equal(workspace.GetBaseFilePath("tsqloutput://c:/path/file.sql"), workspace.WorkspacePath); + } + }); + } + + [Fact] + public void ResolveRelativeScriptPath() + { + TestUtils.RunIfWindows(() => + { + var workspace = new ServiceLayer.Workspace.Workspace(); + Assert.NotNull(workspace.ResolveRelativeScriptPath(null, @"c:\path\file.sql")); + Assert.NotNull(workspace.ResolveRelativeScriptPath(@"c:\path\", "file.sql")); + }); + } } }