mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-24 09:35:39 -05:00
Merge branch 'dev' into bug/addGetSignatureHelpTest
This commit is contained in:
40
.travis.yml
Normal file
40
.travis.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
dotnet: 1.0.0-preview2-003131
|
||||
|
||||
# safelist
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- dev
|
||||
|
||||
language: csharp
|
||||
solution: sqltoolsservice.sln
|
||||
|
||||
before_install:
|
||||
- if [ $TRAVIS_OS_NAME == "linux" ]; then
|
||||
sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotnet-release/ trusty main" > /etc/apt/sources.list.d/dotnetdev.list';
|
||||
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 417A0893;
|
||||
sudo apt-get update;
|
||||
sudo apt-get install dotnet-dev-1.0.0-preview2.1-003177;
|
||||
else
|
||||
brew update;
|
||||
brew install openssl;
|
||||
mkdir -p /usr/local/lib;
|
||||
ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/;
|
||||
ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/;
|
||||
brew cask install dotnet;
|
||||
export PATH="/usr/local/share/dotnet/:$PATH";
|
||||
fi
|
||||
install:
|
||||
- dotnet restore
|
||||
|
||||
script:
|
||||
- dotnet build src/Microsoft.SqlTools.ServiceLayer
|
||||
- dotnet test test/Microsoft.SqlTools.ServiceLayer.Test
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
[](https://travis-ci.org/Microsoft/sqltoolsservice)
|
||||
[](https://ci.appveyor.com/project/kburtram/sqltoolsservice)
|
||||
[](https://coveralls.io/github/Microsoft/sqltoolsservice?branch=dev)
|
||||
|
||||
# Microsoft SQL Tools Service
|
||||
The SQL Tools Service is an application that provides core functionality for various SQL Server tools. These features include the following:
|
||||
* Connection management
|
||||
|
||||
31
appveyor.yml
Normal file
31
appveyor.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
# Note: This file isn't used in current setup. Instead its parts have been
|
||||
# set directly in the AppVeyor project settings - Environment, General, Build, Test sections.
|
||||
# This allows us to get Coveralls to run on PRs, but is more work than just using this file.
|
||||
# Preserving this here so that it's easy to replicate for others
|
||||
environment:
|
||||
COVERALLS_REPO_TOKEN:
|
||||
secure: KjiClJjgj/eB1zo52GBz/CHCmdxj6ut+q6+LD5G3sYhy9Hi4kEF6CWi8vOQPH1oy
|
||||
|
||||
# safelist
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- dev
|
||||
|
||||
before_build:
|
||||
- appveyor-retry dotnet restore -v Minimal
|
||||
|
||||
build_script:
|
||||
- dotnet build src/Microsoft.SqlTools.ServiceLayer
|
||||
|
||||
test_script:
|
||||
- dotnet test test/Microsoft.SqlTools.ServiceLayer.Test
|
||||
|
||||
after_test:
|
||||
- cd test/CodeCoverage
|
||||
- npm install -g gulp-cli
|
||||
- runintegration.bat
|
||||
- cmd: packages\coveralls.io.1.3.4\tools\coveralls.net.exe --opencover coverage.xml
|
||||
|
||||
cache:
|
||||
- '%USERPROFILE%\.nuget\packages'
|
||||
Binary file not shown.
BIN
bin/nuget/Microsoft.SqlServer.Smo.140.1.12.nupkg
Normal file
BIN
bin/nuget/Microsoft.SqlServer.Smo.140.1.12.nupkg
Normal file
Binary file not shown.
@@ -3,7 +3,8 @@
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="Nuget" value="https://www.nuget.org/api/v2" />
|
||||
<add key="Myget" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
|
||||
<add key="Myget" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
|
||||
<add key="dotnet-cli" value="http://myget.org/F/dotnet-cli/api/v3/index.json" />
|
||||
<add key="DataTools Nuget" value="./bin/nuget" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
|
||||
@@ -360,19 +360,26 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
|
||||
|
||||
if (ServiceHost != null)
|
||||
{
|
||||
// Send a telemetry notification for intellisense performance metrics
|
||||
ServiceHost.SendEvent(TelemetryNotification.Type, new TelemetryParams()
|
||||
try
|
||||
{
|
||||
Params = new TelemetryProperties
|
||||
// Send a telemetry notification for intellisense performance metrics
|
||||
ServiceHost.SendEvent(TelemetryNotification.Type, new TelemetryParams()
|
||||
{
|
||||
Properties = new Dictionary<string, string>
|
||||
{
|
||||
{ "IsAzure", info.IsAzure ? "1" : "0" }
|
||||
},
|
||||
EventName = TelemetryEventNames.IntellisenseQuantile,
|
||||
Measures = info.IntellisenseMetrics.Quantile
|
||||
}
|
||||
});
|
||||
Params = new TelemetryProperties
|
||||
{
|
||||
Properties = new Dictionary<string, string>
|
||||
{
|
||||
{ "IsAzure", info.IsAzure ? "1" : "0" }
|
||||
},
|
||||
EventName = TelemetryEventNames.IntellisenseQuantile,
|
||||
Measures = info.IntellisenseMetrics.Quantile
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Write(LogLevel.Verbose, "Could not send Connection telemetry event " + ex.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
// Close the connection
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Access to the default ambient settings. Access to these settings is made available
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -235,7 +235,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection
|
||||
return _command;
|
||||
}
|
||||
|
||||
private void ValidateConnectionIsSet()
|
||||
internal void ValidateConnectionIsSet()
|
||||
{
|
||||
if (_connection == null)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -13,6 +13,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol
|
||||
public const string ContentLengthFormatString = "Content-Length: {0}\r\n\r\n";
|
||||
public static readonly JsonSerializerSettings JsonSerializerSettings;
|
||||
|
||||
public static readonly string SqlLoginAuthenticationType = "SqlLogin";
|
||||
|
||||
static Constants()
|
||||
{
|
||||
JsonSerializerSettings = new JsonSerializerSettings();
|
||||
|
||||
@@ -23,10 +23,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Hosting.Protocol
|
||||
|
||||
private AsyncContextThread messageLoopThread;
|
||||
|
||||
private Dictionary<string, Func<Message, MessageWriter, Task>> requestHandlers =
|
||||
internal Dictionary<string, Func<Message, MessageWriter, Task>> requestHandlers =
|
||||
new Dictionary<string, Func<Message, MessageWriter, Task>>();
|
||||
|
||||
private Dictionary<string, Func<Message, MessageWriter, Task>> eventHandlers =
|
||||
internal Dictionary<string, Func<Message, MessageWriter, Task>> eventHandlers =
|
||||
new Dictionary<string, Func<Message, MessageWriter, Task>>();
|
||||
|
||||
private Action<Message> 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)
|
||||
{
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// <summary>
|
||||
/// Queue a binding request item
|
||||
/// </summary>
|
||||
public QueueItem QueueBindingOperation(
|
||||
public virtual QueueItem QueueBindingOperation(
|
||||
string key,
|
||||
Func<IBindingContext, CancellationToken, object> bindOperation,
|
||||
Func<IBindingContext, object> timeoutOperation = null,
|
||||
|
||||
@@ -14,5 +14,16 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts
|
||||
RequestType<TextDocumentPosition, Location[]> Type =
|
||||
RequestType<TextDocumentPosition, Location[]>.Create("textDocument/definition");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Error object for Definition
|
||||
/// </summary>
|
||||
public class DefinitionError
|
||||
{
|
||||
/// <summary>
|
||||
/// Error message
|
||||
/// </summary>
|
||||
public string message { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// 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.Hosting.Protocol.Contracts;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters sent back with an status change event
|
||||
/// </summary>
|
||||
public class StatusChangeParams
|
||||
{
|
||||
/// <summary>
|
||||
/// URI identifying the text document
|
||||
/// </summary>
|
||||
public string OwnerUri { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The new status for the document
|
||||
/// </summary>
|
||||
public string Status { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event sent for language service status change notification
|
||||
/// </summary>
|
||||
public class StatusChangedNotification
|
||||
{
|
||||
public static readonly
|
||||
EventType<StatusChangeParams> Type =
|
||||
EventType<StatusChangeParams>.Create("textDocument/statusChanged");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.Hosting;
|
||||
using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class to send events to the client
|
||||
/// </summary>
|
||||
public class DocumentStatusHelper
|
||||
{
|
||||
public const string DefinitionRequested = "DefinitionRequested";
|
||||
public const string DefinitionRequestCompleted = "DefinitionRequestCompleted";
|
||||
|
||||
/// <summary>
|
||||
/// Sends an event for specific document using the existing request context
|
||||
/// </summary>
|
||||
public static void SendStatusChange<T>(RequestContext<T> requestContext, TextDocumentPosition textDocumentPosition, string status)
|
||||
{
|
||||
Task.Factory.StartNew(async () =>
|
||||
{
|
||||
if (requestContext != null)
|
||||
{
|
||||
string ownerUri = textDocumentPosition != null && textDocumentPosition.TextDocument != null ? textDocumentPosition.TextDocument.Uri : "";
|
||||
await requestContext.SendEvent(StatusChangedNotification.Type, new StatusChangeParams()
|
||||
{
|
||||
OwnerUri = ownerUri,
|
||||
Status = status
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a telemetry event for specific document using the existing request context
|
||||
/// </summary>
|
||||
public static void SendTelemetryEvent<T>(RequestContext<T> requestContext, string telemetryEvent)
|
||||
{
|
||||
Task.Factory.StartNew(async () =>
|
||||
{
|
||||
await requestContext.SendEvent(TelemetryNotification.Type, new TelemetryParams()
|
||||
{
|
||||
Params = new TelemetryProperties
|
||||
{
|
||||
EventName = telemetryEvent
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -236,6 +236,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
|
||||
// Store the SqlToolsContext for future use
|
||||
Context = context;
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -282,7 +283,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// <param name="completionItem"></param>
|
||||
/// <param name="requestContext"></param>
|
||||
/// <returns></returns>
|
||||
private static async Task HandleCompletionResolveRequest(
|
||||
internal static async Task HandleCompletionResolveRequest(
|
||||
CompletionItem completionItem,
|
||||
RequestContext<CompletionItem> requestContext)
|
||||
{
|
||||
@@ -300,28 +301,37 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
|
||||
internal static async Task HandleDefinitionRequest(TextDocumentPosition textDocumentPosition, RequestContext<Location[]> requestContext)
|
||||
{
|
||||
// Send a notification to signal that definition is sent
|
||||
await requestContext.SendEvent(TelemetryNotification.Type, new TelemetryParams()
|
||||
{
|
||||
Params = new TelemetryProperties
|
||||
{
|
||||
EventName = TelemetryEventNames.PeekDefinitionRequested
|
||||
}
|
||||
});
|
||||
DocumentStatusHelper.SendTelemetryEvent(requestContext, TelemetryEventNames.PeekDefinitionRequested);
|
||||
DocumentStatusHelper.SendStatusChange(requestContext, textDocumentPosition, DocumentStatusHelper.DefinitionRequested);
|
||||
|
||||
if (WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.IsIntelliSenseEnabled)
|
||||
{
|
||||
// Retrieve document and connection
|
||||
ConnectionInfo connInfo;
|
||||
var scriptFile = LanguageService.WorkspaceServiceInstance.Workspace.GetFile(textDocumentPosition.TextDocument.Uri);
|
||||
LanguageService.ConnectionServiceInstance.TryFindConnection(scriptFile.ClientFilePath, out connInfo);
|
||||
|
||||
Location[] locations = LanguageService.Instance.GetDefinition(textDocumentPosition, scriptFile, connInfo);
|
||||
if (locations != null)
|
||||
{
|
||||
await requestContext.SendResult(locations);
|
||||
|
||||
// Send a notification to signal that definition is sent
|
||||
await ServiceHost.Instance.SendEvent(TelemetryNotification.Type, new TelemetryParams()
|
||||
DefinitionResult definitionResult = LanguageService.Instance.GetDefinition(textDocumentPosition, scriptFile, connInfo);
|
||||
if (definitionResult != null)
|
||||
{
|
||||
if (definitionResult.IsErrorResult)
|
||||
{
|
||||
Params = new TelemetryProperties
|
||||
{
|
||||
EventName = TelemetryEventNames.PeekDefinitionRequested
|
||||
}
|
||||
});
|
||||
await requestContext.SendError( new DefinitionError { message = definitionResult.Message });
|
||||
}
|
||||
else
|
||||
{
|
||||
await requestContext.SendResult(definitionResult.Locations);
|
||||
}
|
||||
}
|
||||
}
|
||||
DocumentStatusHelper.SendStatusChange(requestContext, textDocumentPosition, DocumentStatusHelper.DefinitionRequestCompleted);
|
||||
}
|
||||
|
||||
// turn off this code until needed (10/28/2016)
|
||||
@@ -341,7 +351,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
}
|
||||
#endif
|
||||
|
||||
private static async Task HandleSignatureHelpRequest(
|
||||
internal static async Task HandleSignatureHelpRequest(
|
||||
TextDocumentPosition textDocumentPosition,
|
||||
RequestContext<SignatureHelp> requestContext)
|
||||
{
|
||||
@@ -685,7 +695,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// <param name="scriptFile"></param>
|
||||
/// <param name="connInfo"></param>
|
||||
/// <returns> Location with the URI of the script file</returns>
|
||||
internal Location[] GetDefinition(TextDocumentPosition textDocumentPosition, ScriptFile scriptFile, ConnectionInfo connInfo)
|
||||
internal DefinitionResult GetDefinition(TextDocumentPosition textDocumentPosition, ScriptFile scriptFile, ConnectionInfo connInfo)
|
||||
{
|
||||
// Parse sql
|
||||
ScriptParseInfo scriptParseInfo = GetScriptParseInfo(textDocumentPosition.TextDocument.Uri);
|
||||
@@ -723,29 +733,57 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
int parserLine = textDocumentPosition.Position.Line + 1;
|
||||
int parserColumn = textDocumentPosition.Position.Character + 1;
|
||||
IEnumerable<Declaration> declarationItems = Resolver.FindCompletions(
|
||||
scriptParseInfo.ParseResult,
|
||||
parserLine, parserColumn,
|
||||
scriptParseInfo.ParseResult,
|
||||
parserLine, parserColumn,
|
||||
bindingContext.MetadataDisplayInfoProvider);
|
||||
|
||||
// Match token with the suggestions(declaration items) returned
|
||||
string schemaName = this.GetSchemaName(scriptParseInfo, textDocumentPosition.Position, scriptFile);
|
||||
PeekDefinition peekDefinition = new PeekDefinition(connInfo);
|
||||
return peekDefinition.GetScript(declarationItems, tokenText, schemaName);
|
||||
|
||||
|
||||
string schemaName = this.GetSchemaName(scriptParseInfo, textDocumentPosition.Position, scriptFile);
|
||||
PeekDefinition peekDefinition = new PeekDefinition(bindingContext.ServerConnection, connInfo);
|
||||
return peekDefinition.GetScript(declarationItems, tokenText, schemaName);
|
||||
},
|
||||
timeoutOperation: (bindingContext) =>
|
||||
{
|
||||
// return error result
|
||||
return new DefinitionResult
|
||||
{
|
||||
IsErrorResult = true,
|
||||
Message = SR.PeekDefinitionTimedoutError,
|
||||
Locations = null
|
||||
};
|
||||
});
|
||||
|
||||
// wait for the queue item
|
||||
queueItem.ItemProcessed.WaitOne();
|
||||
return queueItem.GetResultAsT<Location[]>();
|
||||
return queueItem.GetResultAsT<DefinitionResult>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// if any exceptions are raised return error result with message
|
||||
Logger.Write(LogLevel.Error, "Exception in GetDefinition " + ex.ToString());
|
||||
return new DefinitionResult
|
||||
{
|
||||
IsErrorResult = true,
|
||||
Message = SR.PeekDefinitionError(ex.Message),
|
||||
Locations = null
|
||||
};
|
||||
}
|
||||
finally
|
||||
{
|
||||
Monitor.Exit(scriptParseInfo.BuildingMetadataLock);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
else
|
||||
{
|
||||
// User is not connected.
|
||||
return new DefinitionResult
|
||||
{
|
||||
IsErrorResult = true,
|
||||
Message = SR.PeekDefinitionNotConnectedError,
|
||||
Locations = null
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -754,7 +792,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// <param name="scriptParseInfo"></param>
|
||||
/// <param name="position"></param>
|
||||
/// <param name="scriptFile"></param>
|
||||
/// <returns> schema nama</returns>
|
||||
/// <returns> schema name</returns>
|
||||
private string GetSchemaName(ScriptParseInfo scriptParseInfo, Position position, ScriptFile scriptFile)
|
||||
{
|
||||
// Offset index by 1 for sql parser
|
||||
@@ -1040,11 +1078,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<bool> cancelTask = new TaskCompletionSource<bool>();
|
||||
cancelTask.SetCanceled();
|
||||
@@ -1168,7 +1202,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
}
|
||||
}
|
||||
|
||||
private bool RemoveScriptParseInfo(string uri)
|
||||
internal bool RemoveScriptParseInfo(string uri)
|
||||
{
|
||||
lock (this.parseMapLock)
|
||||
{
|
||||
@@ -1187,7 +1221,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// Returns a flag indicating if the ScriptFile refers to the output window.
|
||||
/// </summary>
|
||||
/// <param name="scriptFile"></param>
|
||||
private bool IsPreviewWindow(ScriptFile scriptFile)
|
||||
internal bool IsPreviewWindow(ScriptFile scriptFile)
|
||||
{
|
||||
if (scriptFile != null && !string.IsNullOrWhiteSpace(scriptFile.ClientFilePath))
|
||||
{
|
||||
|
||||
@@ -7,12 +7,12 @@ using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Data.SqlClient;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlServer.Management.SqlParser.Intellisense;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||
using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
@@ -23,7 +23,11 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// </summary>
|
||||
internal class PeekDefinition
|
||||
{
|
||||
private bool error;
|
||||
private string errorMessage;
|
||||
private ServerConnection serverConnection;
|
||||
private ConnectionInfo connectionInfo;
|
||||
private Database database;
|
||||
private string tempPath;
|
||||
|
||||
internal delegate StringCollection ScriptGetter(string objectName, string schemaName);
|
||||
@@ -35,38 +39,56 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
// Dictionary that holds the object name (as appears on the TSQL create statement)
|
||||
private Dictionary<DeclarationType, string> sqlObjectTypes = new Dictionary<DeclarationType, string>();
|
||||
|
||||
/// <summary>
|
||||
/// Initialize a Peek Definition helper object
|
||||
/// </summary>
|
||||
/// <param name="serverConnection">SMO Server connection</param>
|
||||
internal PeekDefinition(ServerConnection serverConnection, ConnectionInfo connInfo)
|
||||
{
|
||||
this.serverConnection = serverConnection;
|
||||
this.connectionInfo = connInfo;
|
||||
|
||||
DirectoryInfo tempScriptDirectory = Directory.CreateDirectory(Path.GetTempPath() + "mssql_definition");
|
||||
this.tempPath = tempScriptDirectory.FullName;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private Database Database
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.connectionInfo.SqlConnection != null)
|
||||
if (this.database == null)
|
||||
{
|
||||
try
|
||||
if (this.serverConnection != null && !string.IsNullOrEmpty(this.serverConnection.DatabaseName))
|
||||
{
|
||||
// Get server object from connection
|
||||
string connectionString = ConnectionService.BuildConnectionString(this.connectionInfo.ConnectionDetails);
|
||||
SqlConnection sqlConn = new SqlConnection(connectionString);
|
||||
sqlConn.Open();
|
||||
ServerConnection serverConn = new ServerConnection(sqlConn);
|
||||
Server server = new Server(serverConn);
|
||||
return server.Databases[this.connectionInfo.SqlConnection.Database];
|
||||
try
|
||||
{
|
||||
// Get server object from connection
|
||||
SqlConnection sqlConn = new SqlConnection(this.serverConnection.ConnectionString);
|
||||
sqlConn.Open();
|
||||
ServerConnection peekConnection = new ServerConnection(sqlConn);
|
||||
Server server = new Server(peekConnection);
|
||||
this.database = new Database(server, peekConnection.DatabaseName);
|
||||
}
|
||||
catch (ConnectionFailureException cfe)
|
||||
{
|
||||
Logger.Write(LogLevel.Error, "Exception at PeekDefinition Database.get() : " + cfe.Message);
|
||||
this.error = true;
|
||||
this.errorMessage = (connectionInfo != null && connectionInfo.IsAzure)? SR.PeekDefinitionAzureError(cfe.Message) : SR.PeekDefinitionError(cfe.Message);
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Write(LogLevel.Error, "Exception at PeekDefinition Database.get() : " + ex.Message);
|
||||
this.error = true;
|
||||
this.errorMessage = SR.PeekDefinitionError(ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Logger.Write(LogLevel.Error, "Exception at PeekDefinition Database.get() : " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal PeekDefinition(ConnectionInfo connInfo)
|
||||
{
|
||||
this.connectionInfo = connInfo;
|
||||
DirectoryInfo tempScriptDirectory = Directory.CreateDirectory(Path.GetTempPath() + "mssql_definition");
|
||||
this.tempPath = tempScriptDirectory.FullName;
|
||||
Initialize();
|
||||
}
|
||||
return this.database;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -103,7 +125,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
{
|
||||
if (Path.DirectorySeparatorChar.Equals('/'))
|
||||
{
|
||||
tempFileName = "file:" + tempFileName;
|
||||
tempFileName = "file:" + tempFileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -129,7 +151,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
string[] lines = script.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
|
||||
for (int lineNumber = 0; lineNumber < lines.Length; lineNumber++)
|
||||
{
|
||||
if (lines[lineNumber].IndexOf( createString, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
if (lines[lineNumber].IndexOf(createString, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
{
|
||||
return lineNumber;
|
||||
}
|
||||
@@ -144,7 +166,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// <param name="tokenText"></param>
|
||||
/// <param name="schemaName"></param>
|
||||
/// <returns>Location object of the script file</returns>
|
||||
internal Location[] GetScript(IEnumerable<Declaration> declarationItems, string tokenText, string schemaName)
|
||||
internal DefinitionResult GetScript(IEnumerable<Declaration> declarationItems, string tokenText, string schemaName)
|
||||
{
|
||||
foreach (Declaration declarationItem in declarationItems)
|
||||
{
|
||||
@@ -156,29 +178,38 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
if (declarationItem.Title.Equals(tokenText))
|
||||
{
|
||||
// Script object using SMO based on type
|
||||
DeclarationType type = declarationItem.Type;
|
||||
DeclarationType type = declarationItem.Type;
|
||||
if (sqlScriptGetters.ContainsKey(type) && sqlObjectTypes.ContainsKey(type))
|
||||
{
|
||||
// On *nix and mac systems, the defaultSchema property throws an Exception when accessed.
|
||||
// This workaround ensures that a schema name is present by attempting
|
||||
// to get the schema name from the declaration item
|
||||
// If all fails, the default schema name is assumed to be "dbo"
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && string.IsNullOrEmpty(schemaName))
|
||||
if ((connectionInfo != null && connectionInfo.ConnectionDetails.AuthenticationType.Equals(Constants.SqlLoginAuthenticationType)) && string.IsNullOrEmpty(schemaName))
|
||||
{
|
||||
string fullObjectName = declarationItem.DatabaseQualifiedName;
|
||||
schemaName = this.GetSchemaFromDatabaseQualifiedName(fullObjectName, tokenText);
|
||||
}
|
||||
return GetSqlObjectDefinition(
|
||||
Location[] locations = GetSqlObjectDefinition(
|
||||
sqlScriptGetters[type],
|
||||
tokenText,
|
||||
schemaName,
|
||||
sqlObjectTypes[type]
|
||||
);
|
||||
DefinitionResult result = new DefinitionResult
|
||||
{
|
||||
IsErrorResult = this.error,
|
||||
Message = this.errorMessage,
|
||||
Locations = locations
|
||||
};
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
// sql object type is currently not supported
|
||||
return GetDefinitionErrorResult(SR.PeekDefinitionTypeNotSupportedError);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
// no definition found
|
||||
return GetDefinitionErrorResult(SR.PeekDefinitionNoResultsError);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -192,9 +223,9 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
string[] tokens = fullObjectName.Split('.');
|
||||
for (int i = tokens.Length - 1; i > 0; i--)
|
||||
{
|
||||
if(tokens[i].Equals(objectName))
|
||||
if (tokens[i].Equals(objectName))
|
||||
{
|
||||
return tokens[i-1];
|
||||
return tokens[i - 1];
|
||||
}
|
||||
}
|
||||
return "dbo";
|
||||
@@ -208,8 +239,21 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// <returns>String collection of scripts</returns>
|
||||
internal StringCollection GetTableScripts(string tableName, string schemaName)
|
||||
{
|
||||
return (schemaName != null) ? Database?.Tables[tableName, schemaName]?.Script()
|
||||
: Database?.Tables[tableName]?.Script();
|
||||
try
|
||||
{
|
||||
Table table = string.IsNullOrEmpty(schemaName)
|
||||
? new Table(this.Database, tableName)
|
||||
: new Table(this.Database, tableName, schemaName);
|
||||
|
||||
table.Refresh();
|
||||
|
||||
return table.Script();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Write(LogLevel.Error, "Exception at PeekDefinition GetTableScripts : " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -220,8 +264,21 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// <returns>String collection of scripts</returns>
|
||||
internal StringCollection GetViewScripts(string viewName, string schemaName)
|
||||
{
|
||||
return (schemaName != null) ? Database?.Views[viewName, schemaName]?.Script()
|
||||
: Database?.Views[viewName]?.Script();
|
||||
try
|
||||
{
|
||||
View view = string.IsNullOrEmpty(schemaName)
|
||||
? new View(this.Database, viewName)
|
||||
: new View(this.Database, viewName, schemaName);
|
||||
|
||||
view.Refresh();
|
||||
|
||||
return view.Script();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Write(LogLevel.Error, "Exception at PeekDefinition GetViewScripts : " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -230,10 +287,23 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// <param name="storedProcedureName">Stored Procedure name</param>
|
||||
/// <param name="schemaName">Schema Name</param>
|
||||
/// <returns>String collection of scripts</returns>
|
||||
internal StringCollection GetStoredProcedureScripts(string viewName, string schemaName)
|
||||
internal StringCollection GetStoredProcedureScripts(string sprocName, string schemaName)
|
||||
{
|
||||
return (schemaName != null) ? Database?.StoredProcedures[viewName, schemaName]?.Script()
|
||||
: Database?.StoredProcedures[viewName]?.Script();
|
||||
try
|
||||
{
|
||||
StoredProcedure sproc = string.IsNullOrEmpty(schemaName)
|
||||
? new StoredProcedure(this.Database, sprocName)
|
||||
: new StoredProcedure(this.Database, sprocName, schemaName);
|
||||
|
||||
sproc.Refresh();
|
||||
|
||||
return sproc.Script();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Write(LogLevel.Error, "Exception at PeekDefinition GetStoredProcedureScripts : " + ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -250,30 +320,49 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
string schemaName,
|
||||
string objectType)
|
||||
{
|
||||
StringCollection scripts = sqlScriptGetter(objectName, schemaName);
|
||||
string tempFileName = (schemaName != null) ? Path.Combine(this.tempPath, string.Format("{0}.{1}.sql", schemaName, objectName))
|
||||
: Path.Combine(this.tempPath, string.Format("{0}.sql", objectName));
|
||||
StringCollection scripts = sqlScriptGetter(objectName, schemaName);
|
||||
string tempFileName = (schemaName != null) ? Path.Combine(this.tempPath, string.Format("{0}.{1}.sql", schemaName, objectName))
|
||||
: Path.Combine(this.tempPath, string.Format("{0}.sql", objectName));
|
||||
|
||||
if (scripts != null)
|
||||
if (scripts != null)
|
||||
{
|
||||
int lineNumber = 0;
|
||||
using (StreamWriter scriptFile = new StreamWriter(File.Open(tempFileName, FileMode.Create, FileAccess.ReadWrite)))
|
||||
{
|
||||
int lineNumber = 0;
|
||||
using (StreamWriter scriptFile = new StreamWriter(File.Open(tempFileName, FileMode.Create, FileAccess.ReadWrite)))
|
||||
{
|
||||
|
||||
foreach (string script in scripts)
|
||||
foreach (string script in scripts)
|
||||
{
|
||||
string createSyntax = string.Format("CREATE {0}", objectType);
|
||||
if (script.IndexOf(createSyntax, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
{
|
||||
string createSyntax = string.Format("CREATE {0}", objectType);
|
||||
if (script.IndexOf(createSyntax, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
{
|
||||
scriptFile.WriteLine(script);
|
||||
lineNumber = GetStartOfCreate(script, createSyntax);
|
||||
}
|
||||
scriptFile.WriteLine(script);
|
||||
lineNumber = GetStartOfCreate(script, createSyntax);
|
||||
}
|
||||
}
|
||||
return GetLocationFromFile(tempFileName, lineNumber);
|
||||
}
|
||||
return GetLocationFromFile(tempFileName, lineNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.error = true;
|
||||
this.errorMessage = SR.PeekDefinitionNoResultsError;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
/// <summary>
|
||||
/// Helper method to create definition error result object
|
||||
/// </summary>
|
||||
/// <param name="errorMessage">Error message</param>
|
||||
/// <returns> DefinitionResult</returns>
|
||||
internal DefinitionResult GetDefinitionErrorResult(string errorMessage)
|
||||
{
|
||||
return new DefinitionResult
|
||||
{
|
||||
IsErrorResult = true,
|
||||
Message = errorMessage,
|
||||
Locations = null
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// 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.Workspace.Contracts;
|
||||
namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
{
|
||||
/// <summary>
|
||||
/// /// Result object for PeekDefinition
|
||||
/// </summary>
|
||||
public class DefinitionResult
|
||||
{
|
||||
/// <summary>
|
||||
/// True, if definition error occured
|
||||
/// </summary>
|
||||
public bool IsErrorResult;
|
||||
|
||||
/// <summary>
|
||||
/// Error message, if any
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Location object representing the definition script file
|
||||
/// </summary>
|
||||
public Location[] Locations;
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
|
||||
/// <summary>
|
||||
/// Gets or sets an event to signal when this queue item has been processed
|
||||
/// </summary>
|
||||
public ManualResetEvent ItemProcessed { get; set; }
|
||||
public virtual ManualResetEvent ItemProcessed { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the result of the queued task
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Completion
|
||||
/// <summary>
|
||||
/// The token text in the file content used for completion list
|
||||
/// </summary>
|
||||
public string TokenText
|
||||
public virtual string TokenText
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// <summary>
|
||||
/// Internal representation of the messages so we can modify internally
|
||||
/// </summary>
|
||||
private readonly List<ResultMessage> resultMessages;
|
||||
internal readonly List<ResultMessage> resultMessages;
|
||||
|
||||
/// <summary>
|
||||
/// Internal representation of the result sets so we can modify internally
|
||||
@@ -379,7 +379,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender of the event</param>
|
||||
/// <param name="args">Arguments for the event</param>
|
||||
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.
|
||||
/// </summary>
|
||||
/// <param name="dbe">The exception to unwrap</param>
|
||||
private void UnwrapDbException(DbException dbe)
|
||||
internal void UnwrapDbException(DbException dbe)
|
||||
{
|
||||
SqlException se = dbe as SqlException;
|
||||
if (se != null)
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
|
||||
/// <summary>
|
||||
/// All types supported by the server, stored as a hash set to provide O(1) lookup
|
||||
/// </summary>
|
||||
private static readonly HashSet<string> AllServerDataTypes = new HashSet<string>
|
||||
internal static readonly HashSet<string> AllServerDataTypes = new HashSet<string>
|
||||
{
|
||||
"bigint",
|
||||
"binary",
|
||||
|
||||
@@ -20,15 +20,16 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
|
||||
/// </remarks>
|
||||
/// <typeparam name="T">Type of the values to store</typeparam>
|
||||
public class LongList<T> : IEnumerable<T>
|
||||
{
|
||||
{
|
||||
#region Member Variables
|
||||
|
||||
|
||||
private int expandListSize = int.MaxValue;
|
||||
private List<List<T>> expandedList;
|
||||
private readonly List<T> shortList;
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Creates a new long list
|
||||
/// </summary>
|
||||
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
|
||||
/// <returns>Index of the item that was just added</returns>
|
||||
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<List<T>> {shortList};
|
||||
}
|
||||
|
||||
int arrayIndex = (int)(Count/int.MaxValue); // 0 based
|
||||
int arrayIndex = (int)(Count / this.ExpandListSize); // 0 based
|
||||
|
||||
List<T> 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<T> 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
|
||||
/// <param name="index">The index to remove from the list</param>
|
||||
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<T> 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<T> arr1 = expandedList[i - 1];
|
||||
List<T> arr2 = expandedList[i];
|
||||
|
||||
arr1.Add(arr2[int.MaxValue - 1]);
|
||||
arr1.Add(arr2[this.ExpandListSize - 1]);
|
||||
arr2.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"Newtonsoft.Json": "9.0.1",
|
||||
"System.Data.Common": "4.1.0",
|
||||
"System.Data.SqlClient": "4.4.0-sqltools-24613-04",
|
||||
"Microsoft.SqlServer.Smo": "140.1.11",
|
||||
"Microsoft.SqlServer.Smo": "140.1.12",
|
||||
"System.Security.SecureString": "4.0.0",
|
||||
"System.Collections.Specialized": "4.0.1",
|
||||
"System.ComponentModel.TypeConverter": "4.1.0",
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Microsoft.SqlTools.ServiceLayer
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class SR
|
||||
{
|
||||
protected SR()
|
||||
internal SR()
|
||||
{ }
|
||||
|
||||
public static CultureInfo Culture
|
||||
@@ -341,6 +341,38 @@ namespace Microsoft.SqlTools.ServiceLayer
|
||||
}
|
||||
}
|
||||
|
||||
public static string PeekDefinitionNoResultsError
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.PeekDefinitionNoResultsError);
|
||||
}
|
||||
}
|
||||
|
||||
public static string PeekDefinitionNotConnectedError
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.PeekDefinitionNotConnectedError);
|
||||
}
|
||||
}
|
||||
|
||||
public static string PeekDefinitionTimedoutError
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.PeekDefinitionTimedoutError);
|
||||
}
|
||||
}
|
||||
|
||||
public static string PeekDefinitionTypeNotSupportedError
|
||||
{
|
||||
get
|
||||
{
|
||||
return Keys.GetString(Keys.PeekDefinitionTypeNotSupportedError);
|
||||
}
|
||||
}
|
||||
|
||||
public static string WorkspaceServicePositionLineOutOfRange
|
||||
{
|
||||
get
|
||||
@@ -384,6 +416,16 @@ namespace Microsoft.SqlTools.ServiceLayer
|
||||
return Keys.GetString(Keys.QueryServiceQueryFailed, message);
|
||||
}
|
||||
|
||||
public static string PeekDefinitionAzureError(string errorMessage)
|
||||
{
|
||||
return Keys.GetString(Keys.PeekDefinitionAzureError, errorMessage);
|
||||
}
|
||||
|
||||
public static string PeekDefinitionError(string errorMessage)
|
||||
{
|
||||
return Keys.GetString(Keys.PeekDefinitionError, errorMessage);
|
||||
}
|
||||
|
||||
public static string WorkspaceServicePositionColumnOutOfRange(int line)
|
||||
{
|
||||
return Keys.GetString(Keys.WorkspaceServicePositionColumnOutOfRange, line);
|
||||
@@ -397,7 +439,7 @@ namespace Microsoft.SqlTools.ServiceLayer
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class Keys
|
||||
{
|
||||
static ResourceManager resourceManager = new ResourceManager(typeof(SR));
|
||||
static ResourceManager resourceManager = new ResourceManager("Microsoft.SqlTools.ServiceLayer.SR", typeof(SR).GetTypeInfo().Assembly);
|
||||
|
||||
static CultureInfo _culture = null;
|
||||
|
||||
@@ -540,6 +582,24 @@ namespace Microsoft.SqlTools.ServiceLayer
|
||||
public const string QueryServiceResultSetNoColumnSchema = "QueryServiceResultSetNoColumnSchema";
|
||||
|
||||
|
||||
public const string PeekDefinitionAzureError = "PeekDefinitionAzureError";
|
||||
|
||||
|
||||
public const string PeekDefinitionError = "PeekDefinitionError";
|
||||
|
||||
|
||||
public const string PeekDefinitionNoResultsError = "PeekDefinitionNoResultsError";
|
||||
|
||||
|
||||
public const string PeekDefinitionNotConnectedError = "PeekDefinitionNotConnectedError";
|
||||
|
||||
|
||||
public const string PeekDefinitionTimedoutError = "PeekDefinitionTimedoutError";
|
||||
|
||||
|
||||
public const string PeekDefinitionTypeNotSupportedError = "PeekDefinitionTypeNotSupportedError";
|
||||
|
||||
|
||||
public const string WorkspaceServicePositionLineOutOfRange = "WorkspaceServicePositionLineOutOfRange";
|
||||
|
||||
|
||||
@@ -549,7 +609,7 @@ namespace Microsoft.SqlTools.ServiceLayer
|
||||
public const string WorkspaceServiceBufferPositionOutOfOrder = "WorkspaceServiceBufferPositionOutOfOrder";
|
||||
|
||||
|
||||
private Keys()
|
||||
internal Keys()
|
||||
{ }
|
||||
|
||||
public static CultureInfo Culture
|
||||
|
||||
@@ -308,6 +308,32 @@
|
||||
<value>Could not retrieve column schema for result set</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="PeekDefinitionAzureError" xml:space="preserve">
|
||||
<value>This feature is currently not supported on Azure SQL DB and Data Warehouse: {0}</value>
|
||||
<comment>.
|
||||
Parameters: 0 - errorMessage (string) </comment>
|
||||
</data>
|
||||
<data name="PeekDefinitionError" xml:space="preserve">
|
||||
<value>An unexpected error occurred during Peek Definition execution: {0}</value>
|
||||
<comment>.
|
||||
Parameters: 0 - errorMessage (string) </comment>
|
||||
</data>
|
||||
<data name="PeekDefinitionNoResultsError" xml:space="preserve">
|
||||
<value>No results were found.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="PeekDefinitionNotConnectedError" xml:space="preserve">
|
||||
<value>Please connect to a server.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="PeekDefinitionTimedoutError" xml:space="preserve">
|
||||
<value>Operation timed out.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="PeekDefinitionTypeNotSupportedError" xml:space="preserve">
|
||||
<value>This object type is currently not supported by this feature.</value>
|
||||
<comment></comment>
|
||||
</data>
|
||||
<data name="WorkspaceServicePositionLineOutOfRange" xml:space="preserve">
|
||||
<value>Position is outside of file line range</value>
|
||||
<comment></comment>
|
||||
|
||||
@@ -139,6 +139,21 @@ QueryServiceResultSetRowCountOutOfRange = Row count must be a positive integer
|
||||
|
||||
QueryServiceResultSetNoColumnSchema = Could not retrieve column schema for result set
|
||||
|
||||
############################################################################
|
||||
# Language Service
|
||||
|
||||
PeekDefinitionAzureError(string errorMessage) = This feature is currently not supported on Azure SQL DB and Data Warehouse: {0}
|
||||
|
||||
PeekDefinitionError(string errorMessage) = An unexpected error occurred during Peek Definition execution: {0}
|
||||
|
||||
PeekDefinitionNoResultsError = No results were found.
|
||||
|
||||
PeekDefinitionNotConnectedError = Please connect to a server.
|
||||
|
||||
PeekDefinitionTimedoutError = Operation timed out.
|
||||
|
||||
PeekDefinitionTypeNotSupportedError = This object type is currently not supported by this feature.
|
||||
|
||||
############################################################################
|
||||
# Workspace Service
|
||||
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
"description": "SQL Tools Service Layer",
|
||||
"main": "gulpfile.js",
|
||||
"dependencies": {
|
||||
"gulp": "github:gulpjs/gulp#4.0",
|
||||
"del": "^2.2.1",
|
||||
"gulp": "github:gulpjs/gulp#4.0",
|
||||
"gulp-hub": "frankwallis/gulp-hub#registry-init",
|
||||
"gulp-install": "^0.6.0",
|
||||
"request": "^2.73.0"
|
||||
"gulp-util": "^3.0.7",
|
||||
"request": "^2.73.0",
|
||||
"through2": "^2.0.3"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"author": "Microsoft",
|
||||
|
||||
@@ -3,4 +3,5 @@
|
||||
<package id="OpenCover" version="4.6.519" />
|
||||
<package id="OpenCoverToCoberturaConverter " version="0.2.4" />
|
||||
<package id="ReportGenerator" version="2.4.5" />
|
||||
<package id="coveralls.io" version="1.3.4" />
|
||||
</packages>
|
||||
|
||||
@@ -122,7 +122,7 @@ namespace Microsoft.SqlTools.ServiceLayer.PerfTests
|
||||
TestServerType serverType = TestServerType.OnPrem;
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
await VerifyBindingLoadScenario(testHelper, TestServerType.OnPrem, Scripts.TestDbSimpleSelectQuery, false);
|
||||
await VerifyBindingLoadScenario(testHelper, serverType, Scripts.TestDbSimpleSelectQuery, false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -170,10 +170,10 @@ namespace Microsoft.SqlTools.ServiceLayer.PerfTests
|
||||
[CreateTestDb(TestServerType.Azure)]
|
||||
public async Task BindingCacheColdOnPremComplexQuery()
|
||||
{
|
||||
TestServerType serverType = TestServerType.Azure;
|
||||
TestServerType serverType = TestServerType.OnPrem;
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
await VerifyBindingLoadScenario(testHelper, TestServerType.OnPrem, Scripts.TestDbComplexSelectQueries, false);
|
||||
await VerifyBindingLoadScenario(testHelper, serverType, Scripts.TestDbComplexSelectQueries, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,7 +257,10 @@ namespace Microsoft.SqlTools.ServiceLayer.PerfTests
|
||||
{
|
||||
string query = Scripts.SelectQuery;
|
||||
CompletionItem[] completions = await testHelper.RequestCompletion(ownerUri, query, 0, query.Length + 1);
|
||||
return completions != null && completions.Any(x => x.Label == databaseName);
|
||||
return completions != null &&
|
||||
(completions.Any(x => string.Compare(x.Label, databaseName, StringComparison.OrdinalIgnoreCase) == 0 ||
|
||||
string.Compare(x.Label, $"[{databaseName}]", StringComparison.OrdinalIgnoreCase) == 0 ||
|
||||
string.Compare(x.Label, $"\"{databaseName}\"", StringComparison.OrdinalIgnoreCase) == 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -536,6 +536,17 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection
|
||||
Assert.True(connectionString.Contains(connectionStringMarker));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Build connection string with an invalid auth type
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void BuildConnectionStringWithInvalidAuthType()
|
||||
{
|
||||
ConnectionDetails details = TestObjects.GetTestConnectionDetails();
|
||||
details.AuthenticationType = "NotAValidAuthType";
|
||||
Assert.Throws<ArgumentException>(() => ConnectionService.BuildConnectionString(details));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify that a connection changed event is fired when the database context changes.
|
||||
/// </summary>
|
||||
@@ -892,6 +903,29 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection
|
||||
});
|
||||
}
|
||||
|
||||
// <summary>
|
||||
/// Test that cancel connection with a null connection parameter
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void TestCancelConnectionNullParam()
|
||||
{
|
||||
var service = TestObjects.GetTestConnectionService();
|
||||
Assert.False(service.CancelConnect(null));
|
||||
}
|
||||
|
||||
// <summary>
|
||||
/// Test that cancel connection with a null connection parameter
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void TestListDatabasesInvalidParams()
|
||||
{
|
||||
var service = TestObjects.GetTestConnectionService();
|
||||
var listParams = new ListDatabasesParams();
|
||||
Assert.Throws<ArgumentException>(() => service.ListDatabases(listParams));
|
||||
listParams.OwnerUri = "file://notmyfile.sql";
|
||||
Assert.Throws<Exception>(() => service.ListDatabases(listParams));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test that the connection complete notification type can be created.
|
||||
/// </summary>
|
||||
|
||||
@@ -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<int>((s) => { throw new RetryLimitExceededException(); }, token), default(int));
|
||||
|
||||
// execute an action that throws a retry limit exeception with an inner exception
|
||||
Assert.Throws<Exception>(() =>
|
||||
{
|
||||
policy.ExecuteAction<int>((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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Environment variable that stores the name of the test server hosting the SQL Server instance.
|
||||
/// </summary>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// /// Tests ReliableConnectionHelper.IsDatabaseReadonly() with null builder parameter
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void TestIsDatabaseReadonlyWithNullBuilder()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => ReliableConnectionHelper.IsDatabaseReadonly(null));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify ANSI_NULL and QUOTED_IDENTIFIER settings can be set and retrieved for a session
|
||||
/// </summary>
|
||||
@@ -475,6 +539,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Connection
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test that TryGetServerVersion() fails with invalid connection string
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void TestTryGetServerVersionInvalidConnectionString()
|
||||
{
|
||||
TestUtils.RunIfWindows(() =>
|
||||
{
|
||||
ReliableConnectionHelper.ServerInfo info = null;
|
||||
Assert.False(ReliableConnectionHelper.TryGetServerVersion("this is not a valid connstr", out info));
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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<InvalidOperationException>(() => 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
|
||||
private Mock<RequestContext<CompletionItem[]>> requestContext;
|
||||
|
||||
private Mock<ScriptFile> scriptFile;
|
||||
|
||||
private Mock<IBinder> binder;
|
||||
|
||||
private ScriptParseInfo scriptParseInfo;
|
||||
|
||||
private TextDocumentPosition textDocument;
|
||||
|
||||
private void InitializeTestObjects()
|
||||
@@ -60,14 +64,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings = new SqlToolsSettings();
|
||||
|
||||
// set up file for returning the query
|
||||
var fileMock = new Mock<ScriptFile>();
|
||||
fileMock.SetupGet(file => file.Contents).Returns(Common.StandardQuery);
|
||||
fileMock.SetupGet(file => file.ClientFilePath).Returns(this.testScriptUri);
|
||||
scriptFile = new Mock<ScriptFile>();
|
||||
scriptFile.SetupGet(file => file.Contents).Returns(Common.StandardQuery);
|
||||
scriptFile.SetupGet(file => file.ClientFilePath).Returns(this.testScriptUri);
|
||||
|
||||
// set up workspace mock
|
||||
workspaceService = new Mock<WorkspaceService<SqlToolsSettings>>();
|
||||
workspaceService.Setup(service => service.Workspace.GetFile(It.IsAny<string>()))
|
||||
.Returns(fileMock.Object);
|
||||
.Returns(scriptFile.Object);
|
||||
|
||||
// setup binding queue mock
|
||||
bindingQueue = new Mock<ConnectedBindingQueue>();
|
||||
@@ -93,16 +97,113 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<BindMode>()));
|
||||
|
||||
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<SqlToolsSettings>.Instance.CurrentSettings.SqlTools.IntelliSense.EnableIntellisense = false;
|
||||
Assert.NotNull(LanguageService.HandleCompletionRequest(null, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HandleCompletionResolveRequestDisabled()
|
||||
{
|
||||
InitializeTestObjects();
|
||||
WorkspaceService<SqlToolsSettings>.Instance.CurrentSettings.SqlTools.IntelliSense.EnableIntellisense = false;
|
||||
Assert.NotNull(LanguageService.HandleCompletionResolveRequest(null, null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HandleSignatureHelpRequestDisabled()
|
||||
{
|
||||
InitializeTestObjects();
|
||||
WorkspaceService<SqlToolsSettings>.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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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;
|
||||
@@ -147,6 +149,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);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region "General Language Service tests"
|
||||
@@ -170,11 +222,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServer
|
||||
|
||||
connInfo = TestObjects.InitLiveConnectionInfo(out scriptFile);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Test the service initialization code path and verify nothing throws
|
||||
/// </summary>
|
||||
// Test is causing failures in build lab..investigating to reenable
|
||||
[Fact]
|
||||
public void ServiceInitialization()
|
||||
{
|
||||
@@ -190,12 +241,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServer
|
||||
Assert.True(LanguageService.ConnectionServiceInstance != null);
|
||||
Assert.True(LanguageService.Instance.CurrentSettings != null);
|
||||
Assert.True(LanguageService.Instance.CurrentWorkspace != null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test the service initialization code path and verify nothing throws
|
||||
/// </summary>
|
||||
// Test is causing failures in build lab..investigating to reenable
|
||||
[Fact]
|
||||
public void PrepopulateCommonMetadata()
|
||||
{
|
||||
|
||||
@@ -5,22 +5,27 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlServer.Management.SqlParser.Binder;
|
||||
using Microsoft.SqlServer.Management.SqlParser.Intellisense;
|
||||
using Microsoft.SqlServer.Management.SqlParser.MetadataProvider;
|
||||
using Microsoft.SqlServer.Management.SqlParser.Parser;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||
using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.LanguageServices;
|
||||
using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||
using Microsoft.SqlTools.ServiceLayer.Test.QueryExecution;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||
using Microsoft.SqlTools.Test.Utility;
|
||||
using Location = Microsoft.SqlTools.ServiceLayer.Workspace.Contracts.Location;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
using Location = Microsoft.SqlTools.ServiceLayer.Workspace.Contracts.Location;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
{
|
||||
@@ -89,6 +94,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
requestContext = new Mock<RequestContext<Location[]>>();
|
||||
requestContext.Setup(rc => rc.SendResult(It.IsAny<Location[]>()))
|
||||
.Returns(Task.FromResult(0));
|
||||
requestContext.Setup(rc => rc.SendError(It.IsAny<DefinitionError>())).Returns(Task.FromResult(0));;
|
||||
requestContext.Setup(r => r.SendEvent(It.IsAny<EventType<TelemetryParams>>(), It.IsAny<TelemetryParams>())).Returns(Task.FromResult(0));;
|
||||
requestContext.Setup(r => r.SendEvent(It.IsAny<EventType<StatusChangeParams>>(), It.IsAny<StatusChangeParams>())).Returns(Task.FromResult(0));;
|
||||
|
||||
// setup the IBinder mock
|
||||
binder = new Mock<IBinder>();
|
||||
@@ -99,7 +107,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
|
||||
var testScriptParseInfo = new ScriptParseInfo();
|
||||
LanguageService.Instance.AddOrUpdateScriptParseInfo(this.testScriptUri, testScriptParseInfo);
|
||||
testScriptParseInfo.IsConnected = true;
|
||||
testScriptParseInfo.IsConnected = false;
|
||||
testScriptParseInfo.ConnectionKey = LanguageService.Instance.BindingQueue.AddConnectionContext(connectionInfo);
|
||||
|
||||
// setup the binding context object
|
||||
@@ -111,18 +119,19 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Tests the definition event handler. When called with no active connection, no definition is sent
|
||||
/// Tests the definition event handler. When called with no active connection, an error is sent
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void DefinitionsHandlerWithNoConnectionTest()
|
||||
public async Task DefinitionsHandlerWithNoConnectionTest()
|
||||
{
|
||||
TestObjects.InitializeTestServices();
|
||||
InitializeTestObjects();
|
||||
// request the completion list
|
||||
Task handleCompletion = LanguageService.HandleDefinitionRequest(textDocument, requestContext.Object);
|
||||
handleCompletion.Wait(TaskTimeout);
|
||||
|
||||
// verify that send result was not called
|
||||
// request definition
|
||||
var definitionTask = await Task.WhenAny(LanguageService.HandleDefinitionRequest(textDocument, requestContext.Object), Task.Delay(TaskTimeout));
|
||||
await definitionTask;
|
||||
// verify that send result was not called and send error was called
|
||||
requestContext.Verify(m => m.SendResult(It.IsAny<Location[]>()), Times.Never());
|
||||
requestContext.Verify(m => m.SendError(It.IsAny<DefinitionError>()), Times.Once());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -132,7 +141,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
public void GetLocationFromFileForValidFilePathTest()
|
||||
{
|
||||
String filePath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "C:\\test\\script.sql" : "/test/script.sql";
|
||||
PeekDefinition peekDefinition = new PeekDefinition(null);
|
||||
PeekDefinition peekDefinition = new PeekDefinition(null, null);
|
||||
Location[] locations = peekDefinition.GetLocationFromFile(filePath, 0);
|
||||
|
||||
String expectedFilePath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "file:///C:/test/script.sql" : "file:/test/script.sql";
|
||||
@@ -145,11 +154,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
[Fact]
|
||||
public void GetSchemaFromDatabaseQualifiedNameWithValidNameTest()
|
||||
{
|
||||
PeekDefinition peekDefinition = new PeekDefinition(null);
|
||||
PeekDefinition peekDefinition = new PeekDefinition(null, null);
|
||||
string validDatabaseQualifiedName = "master.test.test_table";
|
||||
string objectName = "test_table";
|
||||
string expectedSchemaName = "test";
|
||||
|
||||
|
||||
string actualSchemaName = peekDefinition.GetSchemaFromDatabaseQualifiedName(validDatabaseQualifiedName, objectName);
|
||||
Assert.Equal(actualSchemaName, expectedSchemaName);
|
||||
}
|
||||
@@ -161,11 +170,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
[Fact]
|
||||
public void GetSchemaFromDatabaseQualifiedNameWithNoSchemaTest()
|
||||
{
|
||||
PeekDefinition peekDefinition = new PeekDefinition(null);
|
||||
PeekDefinition peekDefinition = new PeekDefinition(null, null);
|
||||
string validDatabaseQualifiedName = "test_table";
|
||||
string objectName = "test_table";
|
||||
string expectedSchemaName = "dbo";
|
||||
|
||||
|
||||
string actualSchemaName = peekDefinition.GetSchemaFromDatabaseQualifiedName(validDatabaseQualifiedName, objectName);
|
||||
Assert.Equal(actualSchemaName, expectedSchemaName);
|
||||
}
|
||||
@@ -176,15 +185,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
[Fact]
|
||||
public void GetSchemaFromDatabaseQualifiedNameWithInvalidNameTest()
|
||||
{
|
||||
PeekDefinition peekDefinition = new PeekDefinition(null);
|
||||
PeekDefinition peekDefinition = new PeekDefinition(null, null);
|
||||
string validDatabaseQualifiedName = "x.y.z";
|
||||
string objectName = "test_table";
|
||||
string expectedSchemaName = "dbo";
|
||||
|
||||
|
||||
string actualSchemaName = peekDefinition.GetSchemaFromDatabaseQualifiedName(validDatabaseQualifiedName, objectName);
|
||||
Assert.Equal(actualSchemaName, expectedSchemaName);
|
||||
}
|
||||
|
||||
|
||||
#if LIVE_CONNECTION_TESTS
|
||||
/// <summary>
|
||||
/// Test get definition for a table object with active connection
|
||||
@@ -192,10 +201,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
[Fact]
|
||||
public void GetValidTableDefinitionTest()
|
||||
{
|
||||
// Get live connectionInfo
|
||||
// Get live connectionInfo and serverConnection
|
||||
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
|
||||
PeekDefinition peekDefinition = new PeekDefinition(connInfo);
|
||||
string objectName = "test_table";
|
||||
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
|
||||
|
||||
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
|
||||
string objectName = "spt_monitor";
|
||||
|
||||
string schemaName = null;
|
||||
string objectType = "TABLE";
|
||||
|
||||
@@ -211,9 +223,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
[Fact]
|
||||
public void GetTableDefinitionInvalidObjectTest()
|
||||
{
|
||||
// Get live connectionInfo
|
||||
// Get live connectionInfo and serverConnection
|
||||
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
|
||||
PeekDefinition peekDefinition = new PeekDefinition(connInfo);
|
||||
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
|
||||
|
||||
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
|
||||
string objectName = "test_invalid";
|
||||
string schemaName = null;
|
||||
string objectType = "TABLE";
|
||||
@@ -229,25 +243,102 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
[Fact]
|
||||
public void GetTableDefinitionWithSchemaTest()
|
||||
{
|
||||
// Get live connectionInfo
|
||||
// Get live connectionInfo and serverConnection
|
||||
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
|
||||
PeekDefinition peekDefinition = new PeekDefinition(connInfo);
|
||||
string objectName = "test_table";
|
||||
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
|
||||
|
||||
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
|
||||
string objectName = "spt_monitor";
|
||||
|
||||
string schemaName = "dbo";
|
||||
string objectType = "TABLE";
|
||||
|
||||
// Get locations for valid table object with schema name
|
||||
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetTableScripts, objectName, schemaName, objectType);
|
||||
Assert.NotNull(locations);
|
||||
Cleanup(locations);
|
||||
Cleanup(locations);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetDefinition with an unsupported type(function)
|
||||
/// Test GetDefinition with an unsupported type(schema - dbo). Expect a error result.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void GetUnsupportedDefinitionForFullScript()
|
||||
public void GetUnsupportedDefinitionErrorTest()
|
||||
{
|
||||
ScriptFile scriptFile;
|
||||
TextDocumentPosition textDocument = new TextDocumentPosition
|
||||
{
|
||||
TextDocument = new TextDocumentIdentifier { Uri = OwnerUri },
|
||||
Position = new Position
|
||||
{
|
||||
Line = 0,
|
||||
// test for 'dbo'
|
||||
Character = 16
|
||||
}
|
||||
};
|
||||
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfo(out scriptFile);
|
||||
scriptFile.Contents = "select * from dbo.func ()";
|
||||
var languageService = new LanguageService();
|
||||
ScriptParseInfo scriptInfo = new ScriptParseInfo { IsConnected = true };
|
||||
languageService.ScriptParseInfoMap.Add(OwnerUri, scriptInfo);
|
||||
|
||||
// When I call the language service
|
||||
var result = languageService.GetDefinition(textDocument, scriptFile, connInfo);
|
||||
|
||||
// Then I expect null locations and an error to be reported
|
||||
Assert.NotNull(result);
|
||||
Assert.True(result.IsErrorResult);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Definition for a object with no definition. Expect a error result
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void GetDefinitionWithNoResultsFoundError()
|
||||
{
|
||||
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
|
||||
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
|
||||
|
||||
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
|
||||
string objectName = "from";
|
||||
|
||||
List<Declaration> declarations = new List<Declaration>();
|
||||
DefinitionResult result = peekDefinition.GetScript(declarations, objectName, null);
|
||||
|
||||
Assert.NotNull(result);
|
||||
Assert.True(result.IsErrorResult);
|
||||
Assert.Equal(SR.PeekDefinitionNoResultsError, result.Message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test GetDefinition with a forced timeout. Expect a error result.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void GetDefinitionTimeoutTest()
|
||||
{
|
||||
// Given a binding queue that will automatically time out
|
||||
var languageService = new LanguageService();
|
||||
Mock<ConnectedBindingQueue> queueMock = new Mock<ConnectedBindingQueue>();
|
||||
languageService.BindingQueue = queueMock.Object;
|
||||
ManualResetEvent mre = new ManualResetEvent(true); // Do not block
|
||||
Mock<QueueItem> itemMock = new Mock<QueueItem>();
|
||||
itemMock.Setup(i => i.ItemProcessed).Returns(mre);
|
||||
|
||||
DefinitionResult timeoutResult = null;
|
||||
|
||||
queueMock.Setup(q => q.QueueBindingOperation(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<Func<IBindingContext, CancellationToken, object>>(),
|
||||
It.IsAny<Func<IBindingContext, object>>(),
|
||||
It.IsAny<int?>(),
|
||||
It.IsAny<int?>()))
|
||||
.Callback<string, Func<IBindingContext, CancellationToken, object>, Func<IBindingContext, object>, int?, int?>(
|
||||
(key, bindOperation, timeoutOperation, blah, blah2) =>
|
||||
{
|
||||
timeoutResult = (DefinitionResult) timeoutOperation((IBindingContext)null);
|
||||
itemMock.Object.Result = timeoutResult;
|
||||
})
|
||||
.Returns(() => itemMock.Object);
|
||||
|
||||
ScriptFile scriptFile;
|
||||
TextDocumentPosition textDocument = new TextDocumentPosition
|
||||
@@ -262,12 +353,17 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfo(out scriptFile);
|
||||
scriptFile.Contents = "select * from dbo.func ()";
|
||||
|
||||
var languageService = LanguageService.Instance;
|
||||
ScriptParseInfo scriptInfo = new ScriptParseInfo { IsConnected = true };
|
||||
languageService.ScriptParseInfoMap.Add(OwnerUri, scriptInfo);
|
||||
|
||||
var locations = languageService.GetDefinition(textDocument, scriptFile, connInfo);
|
||||
Assert.Null(locations);
|
||||
// When I call the language service
|
||||
var result = languageService.GetDefinition(textDocument, scriptFile, connInfo);
|
||||
|
||||
// Then I expect null locations and an error to be reported
|
||||
Assert.NotNull(result);
|
||||
Assert.True(result.IsErrorResult);
|
||||
// Check timeout message
|
||||
Assert.Equal(SR.PeekDefinitionTimedoutError, result.Message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -277,7 +373,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
public void GetValidViewDefinitionTest()
|
||||
{
|
||||
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
|
||||
PeekDefinition peekDefinition = new PeekDefinition(connInfo);
|
||||
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
|
||||
|
||||
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
|
||||
string objectName = "objects";
|
||||
string schemaName = "sys";
|
||||
string objectType = "VIEW";
|
||||
@@ -293,8 +391,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
[Fact]
|
||||
public void GetViewDefinitionInvalidObjectTest()
|
||||
{
|
||||
// Get live connectionInfo and serverConnection
|
||||
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
|
||||
PeekDefinition peekDefinition = new PeekDefinition(connInfo);
|
||||
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
|
||||
|
||||
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
|
||||
string objectName = "objects";
|
||||
string schemaName = null;
|
||||
string objectType = "VIEW";
|
||||
@@ -309,9 +410,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
[Fact]
|
||||
public void GetStoredProcedureDefinitionTest()
|
||||
{
|
||||
// Get live connectionInfo and serverConnection
|
||||
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
|
||||
PeekDefinition peekDefinition = new PeekDefinition(connInfo);
|
||||
string objectName = "SP1";
|
||||
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
|
||||
|
||||
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
|
||||
string objectName = "sp_MSrepl_startup";
|
||||
|
||||
string schemaName = "dbo";
|
||||
string objectType = "PROCEDURE";
|
||||
|
||||
@@ -326,8 +431,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
[Fact]
|
||||
public void GetStoredProcedureDefinitionFailureTest()
|
||||
{
|
||||
// Get live connectionInfo and serverConnection
|
||||
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
|
||||
PeekDefinition peekDefinition = new PeekDefinition(connInfo);
|
||||
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
|
||||
|
||||
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
|
||||
string objectName = "SP2";
|
||||
string schemaName = "dbo";
|
||||
string objectType = "PROCEDURE";
|
||||
@@ -342,9 +450,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
|
||||
[Fact]
|
||||
public void GetStoredProcedureDefinitionWithoutSchemaTest()
|
||||
{
|
||||
// Get live connectionInfo and serverConnection
|
||||
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
|
||||
PeekDefinition peekDefinition = new PeekDefinition(connInfo);
|
||||
string objectName = "SP1";
|
||||
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
|
||||
|
||||
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
|
||||
string objectName = "sp_MSrepl_startup";
|
||||
string schemaName = null;
|
||||
string objectType = "PROCEDURE";
|
||||
|
||||
|
||||
@@ -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<int, int> requestType = RequestType<int, int>.Create("test/requestType");
|
||||
var dispatcher = new MessageDispatcher(new Mock<ChannelBase>().Object);
|
||||
dispatcher.SetRequestHandler<int, int>(
|
||||
requestType,
|
||||
(i, j) =>
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
},
|
||||
true);
|
||||
Assert.True(dispatcher.requestHandlers.Count > 0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetEventHandlerTest()
|
||||
{
|
||||
EventType<int> eventType = EventType<int>.Create("test/eventType");
|
||||
var dispatcher = new MessageDispatcher(new Mock<ChannelBase>().Object);
|
||||
dispatcher.SetEventHandler<int>(
|
||||
eventType,
|
||||
(i, j) =>
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
Assert.True(dispatcher.eventHandlers.Count > 0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetEventHandlerWithOverrideTest()
|
||||
{
|
||||
EventType<int> eventType = EventType<int>.Create("test/eventType");
|
||||
var dispatcher = new MessageDispatcher(new Mock<ChannelBase>().Object);
|
||||
dispatcher.SetEventHandler<int>(
|
||||
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<ChannelBase>().Object);
|
||||
dispatcher.UnhandledException += (s, e) => handlerCalled = true;
|
||||
dispatcher.OnListenTaskCompleted(t);
|
||||
Assert.True(handlerCalled);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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<ArgumentOutOfRangeException>(() => storageReader.GetBytesWithMaxCapacity(0, 0));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => storageReader.GetCharsWithMaxCapacity(0, 0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -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 + '.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ArgumentOutOfRangeException>(() => 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));
|
||||
|
||||
@@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// DbColumnWrapper tests
|
||||
/// </summary>
|
||||
public class DbColumnWrapperTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Test DbColumn derived class
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Basic data type and properites test
|
||||
/// </summary>
|
||||
[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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// constructor test
|
||||
/// </summary>
|
||||
[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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,5 +25,34 @@ namespace Microsoft.SqlTools.Test.Utility
|
||||
longList.RemoveAt(0);
|
||||
Assert.True(longList.Count == 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add and remove and item in a LongList causing an expansion
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void LongListExpandTest()
|
||||
{
|
||||
var longList = new LongList<int>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
25
test/Microsoft.SqlTools.ServiceLayer.Test/Utility/SrTests.cs
Normal file
25
test/Microsoft.SqlTools.ServiceLayer.Test/Utility/SrTests.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Add and remove and item in a LongList
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void SrPropertiesTest()
|
||||
{
|
||||
Assert.NotNull(SR.QueryServiceSubsetBatchNotCompleted);
|
||||
Assert.NotNull(SR.QueryServiceFileWrapperWriteOnly);
|
||||
Assert.NotNull(SR.QueryServiceFileWrapperNotInitialized);
|
||||
Assert.NotNull(SR.QueryServiceColumnNull);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -228,6 +230,12 @@ namespace Microsoft.SqlTools.Test.Utility
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static ServerConnection InitLiveServerConnectionForDefinition(ConnectionInfo connInfo)
|
||||
{
|
||||
SqlConnection sqlConn = new SqlConnection(ConnectionService.BuildConnectionString(connInfo.ConnectionDetails));
|
||||
return new ServerConnection(sqlConn);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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<ArgumentOutOfRangeException>(() => Validate.IsWithinRange("parameterName", 1, 2, 3));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsLessThanTest()
|
||||
{
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => Validate.IsLessThan("parameterName", 2, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsNotEqualTest()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => Validate.IsNotEqual<int>("parameterName", 1, 1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsNullOrWhiteSpaceTest()
|
||||
{
|
||||
Assert.Throws<ArgumentException>(() => Validate.IsNotNullOrWhitespaceString("parameterName", null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<ArgumentException>(() =>
|
||||
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<InvalidOperationException>(() => 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"));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"System.Runtime.Serialization.Primitives": "4.1.1",
|
||||
"System.Data.Common": "4.1.0",
|
||||
"System.Data.SqlClient": "4.4.0-sqltools-24613-04",
|
||||
"Microsoft.SqlServer.Smo": "140.1.11",
|
||||
"Microsoft.SqlServer.Smo": "140.1.12",
|
||||
"System.Security.SecureString": "4.0.0",
|
||||
"System.Collections.Specialized": "4.0.1",
|
||||
"System.ComponentModel.TypeConverter": "4.1.0",
|
||||
|
||||
Reference in New Issue
Block a user