mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-18 09:35:38 -05:00
New test common project for database connections using the settings.json (#210)
* moved test driver tests and test common classes to separate projects
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// 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;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
||||
using Xunit;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Language Service end-to-end integration tests
|
||||
/// </summary>
|
||||
public class ConnectionTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Try to connect with invalid credentials
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task InvalidConnection()
|
||||
{
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
bool connected = await testService.Connect(queryTempFile.FilePath, InvalidConnectParams, 300000);
|
||||
Assert.False(connected, "Invalid connection is failed to connect");
|
||||
|
||||
await testService.Connect(queryTempFile.FilePath, InvalidConnectParams, 300000);
|
||||
|
||||
Thread.Sleep(1000);
|
||||
|
||||
await testService.CancelConnect(queryTempFile.FilePath);
|
||||
|
||||
await testService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate list databases request
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task ListDatabasesTest()
|
||||
{
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
bool connected = await testService.Connect(TestServerType.OnPrem, queryTempFile.FilePath);
|
||||
Assert.True(connected, "Connection successful");
|
||||
|
||||
var listDatabaseResult = await testService.ListDatabases(queryTempFile.FilePath);
|
||||
Assert.True(listDatabaseResult.DatabaseNames.Length > 0);
|
||||
|
||||
await testService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
private static ConnectParams InvalidConnectParams
|
||||
{
|
||||
get
|
||||
{
|
||||
return new ConnectParams()
|
||||
{
|
||||
Connection = new ConnectionDetails()
|
||||
{
|
||||
DatabaseName = "master",
|
||||
ServerName = "localhost",
|
||||
AuthenticationType = "SqlLogin",
|
||||
UserName = "invalid",
|
||||
Password = ".."
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,469 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||
using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Language Service end-to-end integration tests
|
||||
/// </summary>
|
||||
public class LanguageServiceTests
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Validate hover tooltip scenarios
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task HoverTest()
|
||||
{
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
string query = "SELECT * FROM sys.objects";
|
||||
|
||||
testService.WriteToFile(queryTempFile.FilePath, query);
|
||||
|
||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification
|
||||
{
|
||||
TextDocument = new TextDocumentItem
|
||||
{
|
||||
Uri = queryTempFile.FilePath,
|
||||
LanguageId = "enu",
|
||||
Version = 1,
|
||||
Text = query
|
||||
}
|
||||
};
|
||||
|
||||
await testService.RequestOpenDocumentNotification(openParams);
|
||||
|
||||
Thread.Sleep(500);
|
||||
|
||||
bool connected = await testService.Connect(TestServerType.OnPrem, queryTempFile.FilePath);
|
||||
Assert.True(connected, "Connection was not successful");
|
||||
|
||||
Thread.Sleep(10000);
|
||||
|
||||
Hover hover = await testService.RequestHover(queryTempFile.FilePath, query, 0, 15);
|
||||
|
||||
Assert.True(hover != null, "Hover tooltop is null");
|
||||
|
||||
await testService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validation autocompletion suggestions scenarios
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task CompletionTest()
|
||||
{
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
string query = "SELECT * FROM sys.objects";
|
||||
|
||||
testService.WriteToFile(queryTempFile.FilePath, query);
|
||||
|
||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification
|
||||
{
|
||||
TextDocument = new TextDocumentItem
|
||||
{
|
||||
Uri = queryTempFile.FilePath,
|
||||
LanguageId = "enu",
|
||||
Version = 1,
|
||||
Text = query
|
||||
}
|
||||
};
|
||||
|
||||
await testService.RequestOpenDocumentNotification(openParams);
|
||||
|
||||
Thread.Sleep(500);
|
||||
|
||||
bool connected = await testService.Connect(TestServerType.OnPrem, queryTempFile.FilePath);
|
||||
Assert.True(connected, "Connection is successful");
|
||||
|
||||
Thread.Sleep(10000);
|
||||
|
||||
CompletionItem[] completions = await testService.RequestCompletion(queryTempFile.FilePath, query, 0, 15);
|
||||
|
||||
Assert.True(completions != null && completions.Length > 0, "Completion items list is null or empty");
|
||||
|
||||
Thread.Sleep(50);
|
||||
|
||||
await testService.RequestResolveCompletion(completions[0]);
|
||||
|
||||
Assert.True(completions != null && completions.Length > 0, "Completion items list is null or empty");
|
||||
|
||||
await testService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate diagnostic scenarios
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task DiagnosticsTests()
|
||||
{
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
bool connected = await testService.Connect(TestServerType.OnPrem, queryTempFile.FilePath);
|
||||
Assert.True(connected, "Connection was not successful");
|
||||
|
||||
Thread.Sleep(500);
|
||||
|
||||
string query = "SELECT *** FROM sys.objects";
|
||||
|
||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification
|
||||
{
|
||||
TextDocument = new TextDocumentItem
|
||||
{
|
||||
Uri = queryTempFile.FilePath,
|
||||
LanguageId = "enu",
|
||||
Version = 1,
|
||||
Text = query
|
||||
}
|
||||
};
|
||||
|
||||
await testService.RequestOpenDocumentNotification(openParams);
|
||||
|
||||
Thread.Sleep(100);
|
||||
|
||||
var contentChanges = new TextDocumentChangeEvent[1];
|
||||
contentChanges[0] = new TextDocumentChangeEvent
|
||||
{
|
||||
Range = new Range
|
||||
{
|
||||
Start = new Position
|
||||
{
|
||||
Line = 0,
|
||||
Character = 5
|
||||
},
|
||||
End = new Position
|
||||
{
|
||||
Line = 0,
|
||||
Character = 6
|
||||
}
|
||||
},
|
||||
RangeLength = 1,
|
||||
Text = "z"
|
||||
};
|
||||
|
||||
DidChangeTextDocumentParams changeParams = new DidChangeTextDocumentParams()
|
||||
{
|
||||
ContentChanges = contentChanges,
|
||||
TextDocument = new VersionedTextDocumentIdentifier()
|
||||
{
|
||||
Version = 2,
|
||||
Uri = queryTempFile.FilePath
|
||||
}
|
||||
};
|
||||
|
||||
await testService.RequestChangeTextDocumentNotification(changeParams);
|
||||
|
||||
Thread.Sleep(100);
|
||||
|
||||
contentChanges[0] = new TextDocumentChangeEvent
|
||||
{
|
||||
Range = new Range
|
||||
{
|
||||
Start = new Position
|
||||
{
|
||||
Line = 0,
|
||||
Character = 5
|
||||
},
|
||||
End = new Position
|
||||
{
|
||||
Line = 0,
|
||||
Character = 6
|
||||
}
|
||||
},
|
||||
RangeLength = 1,
|
||||
Text = "t"
|
||||
};
|
||||
|
||||
changeParams = new DidChangeTextDocumentParams
|
||||
{
|
||||
ContentChanges = contentChanges,
|
||||
TextDocument = new VersionedTextDocumentIdentifier
|
||||
{
|
||||
Version = 3,
|
||||
Uri = queryTempFile.FilePath
|
||||
}
|
||||
};
|
||||
|
||||
await testService.RequestChangeTextDocumentNotification(changeParams);
|
||||
|
||||
Thread.Sleep(2500);
|
||||
|
||||
await testService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Peek Definition/ Go to definition
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Fact]
|
||||
public async Task DefinitionTest()
|
||||
{
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
string query = "SELECT * FROM sys.objects";
|
||||
int lineNumber = 0;
|
||||
int position = 23;
|
||||
|
||||
testService.WriteToFile(queryTempFile.FilePath, query);
|
||||
|
||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification
|
||||
{
|
||||
TextDocument = new TextDocumentItem
|
||||
{
|
||||
Uri = queryTempFile.FilePath,
|
||||
LanguageId = "enu",
|
||||
Version = 1,
|
||||
Text = query
|
||||
}
|
||||
};
|
||||
|
||||
await testService.RequestOpenDocumentNotification(openParams);
|
||||
|
||||
Thread.Sleep(500);
|
||||
|
||||
bool connected = await testService.Connect(TestServerType.OnPrem, queryTempFile.FilePath);
|
||||
Assert.True(connected, "Connection is successful");
|
||||
|
||||
Thread.Sleep(10000);
|
||||
// Request definition for "objects"
|
||||
Location[] locations = await testService.RequestDefinition(queryTempFile.FilePath, query, lineNumber, position);
|
||||
|
||||
Assert.True(locations != null, "Location is not null and not empty");
|
||||
await testService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate the configuration change event
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task ChangeConfigurationTest()
|
||||
{
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
bool connected = await testService.Connect(TestServerType.OnPrem, queryTempFile.FilePath);
|
||||
Assert.True(connected, "Connection was not successful");
|
||||
|
||||
Thread.Sleep(500);
|
||||
|
||||
var settings = new SqlToolsSettings();
|
||||
settings.SqlTools.IntelliSense.EnableIntellisense = false;
|
||||
DidChangeConfigurationParams<SqlToolsSettings> configParams = new DidChangeConfigurationParams<SqlToolsSettings>()
|
||||
{
|
||||
Settings = settings
|
||||
};
|
||||
|
||||
await testService.RequestChangeConfigurationNotification(configParams);
|
||||
|
||||
Thread.Sleep(2000);
|
||||
|
||||
await testService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NotificationIsSentAfterOnConnectionAutoCompleteUpdate()
|
||||
{
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
// Connect
|
||||
await testService.Connect(TestServerType.OnPrem, queryTempFile.FilePath);
|
||||
|
||||
// An event signalling that IntelliSense is ready should be sent shortly thereafter
|
||||
var readyParams = await testService.Driver.WaitForEvent(IntelliSenseReadyNotification.Type, 30000);
|
||||
Assert.NotNull(readyParams);
|
||||
Assert.Equal(queryTempFile.FilePath, readyParams.OwnerUri);
|
||||
|
||||
await testService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FunctionSignatureCompletionReturnsEmptySignatureHelpObjectWhenThereAreNoMatches()
|
||||
{
|
||||
string sqlText = "EXEC sys.fn_not_a_real_function ";
|
||||
|
||||
using (SelfCleaningTempFile tempFile = new SelfCleaningTempFile())
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
string ownerUri = tempFile.FilePath;
|
||||
File.WriteAllText(ownerUri, sqlText);
|
||||
|
||||
// Connect
|
||||
await testService.Connect(TestServerType.OnPrem, ownerUri);
|
||||
|
||||
// Wait for intellisense to be ready
|
||||
var readyParams = await testService.Driver.WaitForEvent(IntelliSenseReadyNotification.Type, 30000);
|
||||
Assert.NotNull(readyParams);
|
||||
Assert.Equal(ownerUri, readyParams.OwnerUri);
|
||||
|
||||
// Send a function signature help Request
|
||||
var position = new TextDocumentPosition()
|
||||
{
|
||||
TextDocument = new TextDocumentIdentifier()
|
||||
{
|
||||
Uri = ownerUri
|
||||
},
|
||||
Position = new Position()
|
||||
{
|
||||
Line = 0,
|
||||
Character = sqlText.Length
|
||||
}
|
||||
};
|
||||
var signatureHelp = await testService.Driver.SendRequest(SignatureHelpRequest.Type, position);
|
||||
|
||||
Assert.NotNull(signatureHelp);
|
||||
Assert.False(signatureHelp.ActiveSignature.HasValue);
|
||||
Assert.Null(signatureHelp.Signatures);
|
||||
|
||||
await testService.Disconnect(ownerUri);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FunctionSignatureCompletionReturnsCorrectFunction()
|
||||
{
|
||||
string sqlText = "EXEC sys.fn_isrolemember ";
|
||||
|
||||
using (SelfCleaningTempFile tempFile = new SelfCleaningTempFile())
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
string ownerUri = tempFile.FilePath;
|
||||
|
||||
// Connect
|
||||
await testService.ConnectForQuery(TestServerType.OnPrem, sqlText, ownerUri);
|
||||
|
||||
// Wait for intellisense to be ready
|
||||
var readyParams = await testService.Driver.WaitForEvent(IntelliSenseReadyNotification.Type, 30000);
|
||||
Assert.NotNull(readyParams);
|
||||
Assert.Equal(ownerUri, readyParams.OwnerUri);
|
||||
|
||||
// Send a function signature help Request
|
||||
var position = new TextDocumentPosition()
|
||||
{
|
||||
TextDocument = new TextDocumentIdentifier()
|
||||
{
|
||||
Uri = ownerUri
|
||||
},
|
||||
Position = new Position()
|
||||
{
|
||||
Line = 0,
|
||||
Character = sqlText.Length
|
||||
}
|
||||
};
|
||||
var signatureHelp = await testService.Driver.SendRequest(SignatureHelpRequest.Type, position);
|
||||
|
||||
Assert.NotNull(signatureHelp);
|
||||
Assert.True(signatureHelp.ActiveSignature.HasValue);
|
||||
Assert.NotEmpty(signatureHelp.Signatures);
|
||||
|
||||
var label = signatureHelp.Signatures[signatureHelp.ActiveSignature.Value].Label;
|
||||
Assert.NotNull(label);
|
||||
Assert.NotEmpty(label);
|
||||
Assert.True(label.Contains("fn_isrolemember"));
|
||||
|
||||
await testService.Disconnect(ownerUri);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FunctionSignatureCompletionReturnsCorrectParametersAtEachPosition()
|
||||
{
|
||||
string sqlText = "EXEC sys.fn_isrolemember 1, 'testing', 2";
|
||||
|
||||
using (SelfCleaningTempFile tempFile = new SelfCleaningTempFile())
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
string ownerUri = tempFile.FilePath;
|
||||
File.WriteAllText(ownerUri, sqlText);
|
||||
|
||||
// Connect
|
||||
await testService.Connect(TestServerType.OnPrem, ownerUri);
|
||||
|
||||
// Wait for intellisense to be ready
|
||||
var readyParams = await testService.Driver.WaitForEvent(IntelliSenseReadyNotification.Type, 30000);
|
||||
Assert.NotNull(readyParams);
|
||||
Assert.Equal(ownerUri, readyParams.OwnerUri);
|
||||
|
||||
// Verify all parameters when the cursor is inside of parameters and at separator boundaries (,)
|
||||
await VerifyFunctionSignatureHelpParameter(testService, ownerUri, 25, "fn_isrolemember", 0, "@mode int");
|
||||
await VerifyFunctionSignatureHelpParameter(testService, ownerUri, 26, "fn_isrolemember", 0, "@mode int");
|
||||
await VerifyFunctionSignatureHelpParameter(testService, ownerUri, 27, "fn_isrolemember", 1, "@login sysname");
|
||||
await VerifyFunctionSignatureHelpParameter(testService, ownerUri, 30, "fn_isrolemember", 1, "@login sysname");
|
||||
await VerifyFunctionSignatureHelpParameter(testService, ownerUri, 37, "fn_isrolemember", 1, "@login sysname");
|
||||
await VerifyFunctionSignatureHelpParameter(testService, ownerUri, 38, "fn_isrolemember", 2, "@tranpubid int");
|
||||
await VerifyFunctionSignatureHelpParameter(testService, ownerUri, 39, "fn_isrolemember", 2, "@tranpubid int");
|
||||
|
||||
await testService.Disconnect(ownerUri);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task VerifyFunctionSignatureHelpParameter(
|
||||
TestServiceDriverProvider TestService,
|
||||
string ownerUri,
|
||||
int character,
|
||||
string expectedFunctionName,
|
||||
int expectedParameterIndex,
|
||||
string expectedParameterName)
|
||||
{
|
||||
var position = new TextDocumentPosition()
|
||||
{
|
||||
TextDocument = new TextDocumentIdentifier()
|
||||
{
|
||||
Uri = ownerUri
|
||||
},
|
||||
Position = new Position()
|
||||
{
|
||||
Line = 0,
|
||||
Character = character
|
||||
}
|
||||
};
|
||||
var signatureHelp = await TestService.Driver.SendRequest(SignatureHelpRequest.Type, position);
|
||||
|
||||
Assert.NotNull(signatureHelp);
|
||||
Assert.NotNull(signatureHelp.ActiveSignature);
|
||||
Assert.True(signatureHelp.ActiveSignature.HasValue);
|
||||
Assert.NotEmpty(signatureHelp.Signatures);
|
||||
|
||||
var activeSignature = signatureHelp.Signatures[signatureHelp.ActiveSignature.Value];
|
||||
Assert.NotNull(activeSignature);
|
||||
|
||||
var label = activeSignature.Label;
|
||||
Assert.NotNull(label);
|
||||
Assert.NotEmpty(label);
|
||||
Assert.True(label.Contains(expectedFunctionName));
|
||||
|
||||
Assert.NotNull(signatureHelp.ActiveParameter);
|
||||
Assert.True(signatureHelp.ActiveParameter.HasValue);
|
||||
Assert.Equal(expectedParameterIndex, signatureHelp.ActiveParameter.Value);
|
||||
|
||||
var parameter = activeSignature.Parameters[signatureHelp.ActiveParameter.Value];
|
||||
Assert.NotNull(parameter);
|
||||
Assert.NotNull(parameter.Label);
|
||||
Assert.NotEmpty(parameter.Label);
|
||||
Assert.Equal(expectedParameterName, parameter.Label);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>e7cf630e-e084-4da4-bf69-f61bf0a8f5be</ProjectGuid>
|
||||
<RootNamespace>Microsoft.SqlTools.ServiceLayer.TestDriver.Tests</RootNamespace>
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.TestDriver.Driver;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
using Xunit;
|
||||
|
||||
[assembly: CollectionBehavior(DisableTestParallelization = true)]
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
internal static int Main(string[] args)
|
||||
{
|
||||
if (args.Length < 1)
|
||||
{
|
||||
Console.WriteLine("Microsoft.SqlTools.ServiceLayer.TestDriver.exe [tests]" + Environment.NewLine +
|
||||
" [tests] is a space-separated list of tests to run." + Environment.NewLine +
|
||||
" They are qualified within the Microsoft.SqlTools.ServiceLayer.TestDriver.Tests namespace" + Environment.NewLine +
|
||||
"Be sure to set the environment variable " + ServiceTestDriver.ServiceHostEnvironmentVariable + " to the full path of the sqltoolsservice executable.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Logger.Initialize("testdriver", LogLevel.Verbose);
|
||||
|
||||
int returnCode = 0;
|
||||
Task.Run(async () =>
|
||||
{
|
||||
string testNamespace = "Microsoft.SqlTools.ServiceLayer.TestDriver.Tests.";
|
||||
foreach (var test in args)
|
||||
{
|
||||
try
|
||||
{
|
||||
var testName = test.Contains(testNamespace) ? test.Replace(testNamespace, "") : test;
|
||||
bool containsTestName = testName.Contains(".");
|
||||
var className = containsTestName ? testName.Substring(0, testName.LastIndexOf('.')) : testName;
|
||||
var methodName = containsTestName ? testName.Substring(testName.LastIndexOf('.') + 1) : null;
|
||||
|
||||
var type = Type.GetType(testNamespace + className);
|
||||
if (type == null)
|
||||
{
|
||||
Console.WriteLine("Invalid class name");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(methodName))
|
||||
{
|
||||
var methods = type.GetMethods().Where(x => x.CustomAttributes.Any(a => a.AttributeType == typeof(FactAttribute)));
|
||||
foreach (var method in methods)
|
||||
{
|
||||
await RunTest(type, method, method.Name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MethodInfo methodInfo = type.GetMethod(methodName);
|
||||
await RunTest(type, methodInfo, test);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.ToString());
|
||||
returnCode = -1;
|
||||
}
|
||||
}
|
||||
}).Wait();
|
||||
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
private static async Task RunTest(Type type, MethodInfo methodInfo, string testName)
|
||||
{
|
||||
if (methodInfo == null)
|
||||
{
|
||||
Console.WriteLine("Invalid method name");
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var typeInstance = (IDisposable)Activator.CreateInstance(type))
|
||||
{
|
||||
Console.WriteLine("Running test " + testName);
|
||||
await (Task)methodInfo.Invoke(typeInstance, null);
|
||||
Console.WriteLine("Test ran successfully: " + testName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Microsoft.SqlTools.ServiceLayer.TestDriver.Tests")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("e7cf630e-e084-4da4-bf69-f61bf0a8f5be")]
|
||||
@@ -0,0 +1,354 @@
|
||||
//
|
||||
// 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.Test.Common;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
{
|
||||
public class QueryExecutionTests
|
||||
{
|
||||
/* Commenting out these tests until they are fixed (12/1/16)
|
||||
[Fact]
|
||||
public async Task TestQueryCancelReliability()
|
||||
{
|
||||
const string query = "SELECT * FROM sys.objects a CROSS JOIN sys.objects b CROSS JOIN sys.objects c";
|
||||
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestService testService = new TestService())
|
||||
{
|
||||
await TestService.Connect(queryTempFile.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
// Run and cancel 100 queries
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
var queryTask = TestService.RunQuery(queryTempFile.FilePath, query);
|
||||
|
||||
var cancelResult = await TestService.CancelQuery(queryTempFile.FilePath);
|
||||
Assert.NotNull(cancelResult);
|
||||
Assert.True(string.IsNullOrEmpty(cancelResult.Messages));
|
||||
|
||||
await queryTask;
|
||||
}
|
||||
|
||||
await TestService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestQueryDoesNotBlockOtherRequests()
|
||||
{
|
||||
const string query = "SELECT * FROM sys.objects a CROSS JOIN sys.objects b CROSS JOIN sys.objects c";
|
||||
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestService testService = new TestService())
|
||||
{
|
||||
await TestService.Connect(queryTempFile.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
// Start a long-running query
|
||||
var queryTask = TestService.RunQuery(queryTempFile.FilePath, query, 60000);
|
||||
|
||||
// Interact with the service. None of these requests should time out while waiting for the query to finish
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
using (SelfCleaningTempFile queryFile2 = new SelfCleaningTempFile())
|
||||
{
|
||||
await TestService.Connect(queryFile2.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
Assert.NotNull(await TestService.RequestCompletion(queryFile2.FilePath, "SELECT * FROM sys.objects", 0, 10));
|
||||
await TestService.Disconnect(queryFile2.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
await TestService.CancelQuery(queryTempFile.FilePath);
|
||||
await TestService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestParallelQueryExecution()
|
||||
{
|
||||
const int queryCount = 10;
|
||||
const string query = "SELECT * FROM sys.objects";
|
||||
|
||||
using (TestService testService = new TestService())
|
||||
{
|
||||
// Create n connections
|
||||
SelfCleaningTempFile[] ownerUris = new SelfCleaningTempFile[queryCount];
|
||||
for (int i = 0; i < queryCount; i++)
|
||||
{
|
||||
ownerUris[i] = new SelfCleaningTempFile();
|
||||
Assert.NotNull(await TestService.Connect(ownerUris[i].FilePath, ConnectionTestUtils.AzureTestServerConnection));
|
||||
}
|
||||
|
||||
// Run n queries at once
|
||||
var queryTasks = new Task<QueryExecuteCompleteParams>[queryCount];
|
||||
for (int i = 0; i < queryCount; i++)
|
||||
{
|
||||
queryTasks[i] = TestService.RunQuery(ownerUris[i].FilePath, query);
|
||||
}
|
||||
await Task.WhenAll(queryTasks);
|
||||
|
||||
// Verify that they all completed with results and Disconnect
|
||||
for (int i = 0; i < queryCount; i++)
|
||||
{
|
||||
Assert.NotNull(queryTasks[i].Result);
|
||||
Assert.NotNull(queryTasks[i].Result.BatchSummaries);
|
||||
await TestService.Disconnect(ownerUris[i].FilePath);
|
||||
ownerUris[i].Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestSaveResultsDoesNotBlockOtherRequests()
|
||||
{
|
||||
const string query = "SELECT * FROM sys.objects";
|
||||
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestService testService = new TestService())
|
||||
{
|
||||
await TestService.Connect(queryTempFile.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
// Execute a query
|
||||
await TestService.RunQuery(queryTempFile.FilePath, query);
|
||||
|
||||
// Spawn several tasks to save results
|
||||
var saveTasks = new Task<SaveResultRequestResult>[100];
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
saveTasks[i] = TestService.SaveAsCsv(queryTempFile.FilePath, System.IO.Path.GetTempFileName(), 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
saveTasks[i] = TestService.SaveAsJson(queryTempFile.FilePath, System.IO.Path.GetTempFileName(), 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Interact with the service. None of these requests should time out while waiting for the save results tasks to finish
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
using(SelfCleaningTempFile queryFile2 = new SelfCleaningTempFile())
|
||||
{
|
||||
await TestService.Connect(queryFile2.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
Assert.NotNull(await TestService.RequestCompletion(queryFile2.FilePath, "SELECT * FROM sys.objects", 0, 10));
|
||||
await TestService.Disconnect(queryFile2.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
await Task.WhenAll(saveTasks);
|
||||
|
||||
await TestService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestQueryingSubsetDoesNotBlockOtherRequests()
|
||||
{
|
||||
const string query = "SELECT * FROM sys.objects";
|
||||
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestService testService = new TestService())
|
||||
{
|
||||
await TestService.Connect(queryTempFile.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
// Execute a query
|
||||
await TestService.RunQuery(queryTempFile.FilePath, query);
|
||||
|
||||
// Spawn several tasks for subset requests
|
||||
var subsetTasks = new Task<QueryExecuteSubsetResult>[100];
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
subsetTasks[i] = TestService.ExecuteSubset(queryTempFile.FilePath, 0, 0, 0, 100);
|
||||
}
|
||||
|
||||
// Interact with the service. None of these requests should time out while waiting for the subset tasks to finish
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
using (SelfCleaningTempFile queryFile2 = new SelfCleaningTempFile())
|
||||
{
|
||||
await TestService.Connect(queryFile2.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
Assert.NotNull(await TestService.RequestCompletion(queryFile2.FilePath, "SELECT * FROM sys.objects", 0, 10));
|
||||
await TestService.Disconnect(queryFile2.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
await Task.WhenAll(subsetTasks);
|
||||
|
||||
await TestService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestCancelQueryWhileOtherOperationsAreInProgress()
|
||||
{
|
||||
const string query = "SELECT * FROM sys.objects a CROSS JOIN sys.objects b";
|
||||
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestService testService = new TestService())
|
||||
{
|
||||
List<Task> tasks = new List<Task>();
|
||||
|
||||
await TestService.Connect(queryTempFile.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
// Execute a long-running query
|
||||
var queryTask = TestService.RunQuery(queryTempFile.FilePath, query, 60000);
|
||||
|
||||
// Queue up some tasks that interact with the service
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
using (SelfCleaningTempFile queryFile2 = new SelfCleaningTempFile())
|
||||
{
|
||||
tasks.Add(Task.Run(async () =>
|
||||
{
|
||||
await TestService.Connect(queryFile2.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
await TestService.RequestCompletion(queryFile2.FilePath, "SELECT * FROM sys.objects", 0, 10);
|
||||
await TestService.RunQuery(queryFile2.FilePath, "SELECT * FROM sys.objects");
|
||||
await TestService.Disconnect(queryFile2.FilePath);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel the long-running query
|
||||
await TestService.CancelQuery(queryTempFile.FilePath);
|
||||
|
||||
await TestService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExecuteBasicQueryTest()
|
||||
{
|
||||
const string query = "SELECT * FROM sys.all_columns c";
|
||||
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestService testService = new TestService())
|
||||
{
|
||||
bool connected = await TestService.Connect(TestServerType.OnPrem, string.Empty, queryTempFile.FilePath);
|
||||
Assert.True(connected, "Connection is successful");
|
||||
|
||||
Thread.Sleep(500);
|
||||
|
||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification()
|
||||
{
|
||||
TextDocument = new TextDocumentItem()
|
||||
{
|
||||
Uri = queryTempFile.FilePath,
|
||||
LanguageId = "enu",
|
||||
Version = 1,
|
||||
Text = query
|
||||
}
|
||||
};
|
||||
|
||||
await TestService.RequestOpenDocumentNotification(openParams);
|
||||
|
||||
var queryResult = await TestService.RunQuery(queryTempFile.FilePath, query, 10000);
|
||||
|
||||
Assert.NotNull(queryResult);
|
||||
Assert.NotNull(queryResult.BatchSummaries);
|
||||
|
||||
foreach (var batchSummary in queryResult.BatchSummaries)
|
||||
{
|
||||
foreach (var resultSetSummary in batchSummary.ResultSetSummaries)
|
||||
{
|
||||
Assert.True(resultSetSummary.RowCount > 0);
|
||||
}
|
||||
}
|
||||
|
||||
var subsetRequest = new QueryExecuteSubsetParams()
|
||||
{
|
||||
OwnerUri = queryTempFile.FilePath,
|
||||
BatchIndex = 0,
|
||||
ResultSetIndex = 0,
|
||||
RowsStartIndex = 0,
|
||||
RowsCount = 100,
|
||||
};
|
||||
|
||||
var querySubset = await TestService.RequestQueryExecuteSubset(subsetRequest);
|
||||
Assert.NotNull(querySubset);
|
||||
Assert.True(querySubset.ResultSubset.RowCount == 100);
|
||||
|
||||
await TestService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestQueryingAfterCompletionRequests()
|
||||
{
|
||||
const string query = "SELECT * FROM sys.objects";
|
||||
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestService testService = new TestService())
|
||||
{
|
||||
List<Task> tasks = new List<Task>();
|
||||
|
||||
await TestService.Connect(queryTempFile.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
Enumerable.Range(0, 10).ToList().ForEach(arg => tasks.Add(TestService.RequestCompletion(queryTempFile.FilePath, query, 0, 10)));
|
||||
var queryTask = TestService.RunQuery(queryTempFile.FilePath, query);
|
||||
tasks.Add(queryTask);
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
Assert.NotNull(queryTask.Result);
|
||||
Assert.NotNull(queryTask.Result.BatchSummaries);
|
||||
|
||||
await TestService.Connect(queryTempFile.FilePath, ConnectionTestUtils.DataToolsTelemetryAzureConnection);
|
||||
tasks.Clear();
|
||||
Enumerable.Range(0, 10).ToList().ForEach(arg => tasks.Add(TestService.RequestCompletion(queryTempFile.FilePath, query, 0, 10)));
|
||||
queryTask = TestService.RunQuery(queryTempFile.FilePath, query);
|
||||
tasks.Add(queryTask);
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
Assert.NotNull(queryTask.Result);
|
||||
Assert.NotNull(queryTask.Result.BatchSummaries);
|
||||
|
||||
await TestService.Connect(queryTempFile.FilePath, ConnectionTestUtils.SqlDataToolsAzureConnection);
|
||||
tasks.Clear();
|
||||
Enumerable.Range(0, 10).ToList().ForEach(arg => tasks.Add(TestService.RequestCompletion(queryTempFile.FilePath, query, 0, 10)));
|
||||
queryTask = TestService.RunQuery(queryTempFile.FilePath, query);
|
||||
tasks.Add(queryTask);
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
Assert.NotNull(queryTask.Result);
|
||||
Assert.NotNull(queryTask.Result.BatchSummaries);
|
||||
|
||||
await TestService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
[Theory]
|
||||
[InlineData("-- no-op")]
|
||||
[InlineData("GO")]
|
||||
[InlineData("GO -- no-op")]
|
||||
public async Task NoOpQueryReturnsMessage(string query)
|
||||
{
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
|
||||
Assert.True(await testService.Connect(TestServerType.OnPrem, queryTempFile.FilePath));
|
||||
// If: the query is executed...
|
||||
var queryResult = await testService.RunQueryAsync(queryTempFile.FilePath, query);
|
||||
var message = await testService.WaitForMessage();
|
||||
|
||||
// Then:
|
||||
// ... I expect a query result to indicate successfully started query
|
||||
Assert.NotNull(queryResult);
|
||||
|
||||
// ... I expect a non-error message to be returned without a batch associated with it
|
||||
Assert.NotNull(message);
|
||||
Assert.NotNull(message.Message);
|
||||
Assert.NotNull(message.Message.Message);
|
||||
Assert.False(message.Message.IsError);
|
||||
Assert.Null(message.Message.BatchId);
|
||||
|
||||
await testService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
//
|
||||
// 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.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
{
|
||||
public class StressTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Simulate typing by a user to stress test the language service
|
||||
/// </summary>
|
||||
//[Fact]
|
||||
public async Task TestLanguageService()
|
||||
{
|
||||
const string textToType = "SELECT * FROM sys.objects GO " +
|
||||
"CREATE TABLE MyTable(" +
|
||||
"FirstName CHAR," +
|
||||
"LastName CHAR," +
|
||||
"DateOfBirth DATETIME," +
|
||||
"CONSTRAINT MyTableConstraint UNIQUE (FirstName, LastName, DateOfBirth)) GO " +
|
||||
"INSERT INTO MyTable (FirstName, LastName, DateOfBirth) VALUES ('John', 'Doe', '19800101') GO " +
|
||||
"SELECT * FROM MyTable GO " +
|
||||
"ALTER TABLE MyTable DROP CONSTRAINT MyTableConstraint GO " +
|
||||
"DROP TABLE MyTable GO ";
|
||||
|
||||
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
// Connect
|
||||
bool connected = await testService.Connect(TestServerType.OnPrem, string.Empty, queryTempFile.FilePath);
|
||||
Assert.True(connected, "Connection was not successful");
|
||||
|
||||
Thread.Sleep(10000); // Wait for intellisense to warm up
|
||||
|
||||
// Simulate typing
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
int version = 1;
|
||||
while (stopwatch.Elapsed < TimeSpan.FromMinutes(60))
|
||||
{
|
||||
for (int i = 0; i < textToType.Length; i++)
|
||||
{
|
||||
System.IO.File.WriteAllText(queryTempFile.FilePath, textToType.Substring(0, i + 1));
|
||||
|
||||
var contentChanges = new TextDocumentChangeEvent[1];
|
||||
contentChanges[0] = new TextDocumentChangeEvent()
|
||||
{
|
||||
Range = new Range()
|
||||
{
|
||||
Start = new Position()
|
||||
{
|
||||
Line = 0,
|
||||
Character = i
|
||||
},
|
||||
End = new Position()
|
||||
{
|
||||
Line = 0,
|
||||
Character = i
|
||||
}
|
||||
},
|
||||
RangeLength = 1,
|
||||
Text = textToType.Substring(i, 1)
|
||||
};
|
||||
|
||||
DidChangeTextDocumentParams changeParams = new DidChangeTextDocumentParams()
|
||||
{
|
||||
ContentChanges = contentChanges,
|
||||
TextDocument = new VersionedTextDocumentIdentifier()
|
||||
{
|
||||
Version = ++version,
|
||||
Uri = queryTempFile.FilePath
|
||||
}
|
||||
};
|
||||
|
||||
await testService.RequestChangeTextDocumentNotification(changeParams);
|
||||
|
||||
Thread.Sleep(50);
|
||||
|
||||
// If we just typed a space, request/resolve completion
|
||||
if (textToType[i] == ' ')
|
||||
{
|
||||
var completions = await testService.RequestCompletion(queryTempFile.FilePath, textToType.Substring(0, i + 1), 0, i + 1);
|
||||
Assert.True(completions != null && completions.Length > 0, "Completion items list was null or empty");
|
||||
|
||||
Thread.Sleep(50);
|
||||
|
||||
var item = await testService.RequestResolveCompletion(completions[0]);
|
||||
|
||||
Assert.NotNull(item);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the text document
|
||||
System.IO.File.WriteAllText(queryTempFile.FilePath, "");
|
||||
|
||||
var contentChanges2 = new TextDocumentChangeEvent[1];
|
||||
contentChanges2[0] = new TextDocumentChangeEvent()
|
||||
{
|
||||
Range = new Range()
|
||||
{
|
||||
Start = new Position()
|
||||
{
|
||||
Line = 0,
|
||||
Character = 0
|
||||
},
|
||||
End = new Position()
|
||||
{
|
||||
Line = 0,
|
||||
Character = textToType.Length - 1
|
||||
}
|
||||
},
|
||||
RangeLength = textToType.Length,
|
||||
Text = ""
|
||||
};
|
||||
|
||||
DidChangeTextDocumentParams changeParams2 = new DidChangeTextDocumentParams()
|
||||
{
|
||||
ContentChanges = contentChanges2,
|
||||
TextDocument = new VersionedTextDocumentIdentifier()
|
||||
{
|
||||
Version = ++version,
|
||||
Uri = queryTempFile.FilePath
|
||||
}
|
||||
};
|
||||
|
||||
await testService.RequestChangeTextDocumentNotification(changeParams2);
|
||||
}
|
||||
|
||||
await testService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Repeatedly execute queries to stress test the query execution service.
|
||||
/// </summary>
|
||||
//[Fact]
|
||||
public async Task TestQueryExecutionService()
|
||||
{
|
||||
const string queryToRun = "SELECT * FROM sys.all_objects GO " +
|
||||
"SELECT * FROM sys.objects GO " +
|
||||
"SELECT * FROM sys.tables GO " +
|
||||
"SELECT COUNT(*) FROM sys.objects";
|
||||
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
// Connect
|
||||
bool connected = await testService.Connect(TestServerType.OnPrem, string.Empty, queryTempFile.FilePath);
|
||||
Assert.True(connected, "Connection is successful");
|
||||
|
||||
// Run queries repeatedly
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
while (stopwatch.Elapsed < TimeSpan.FromMinutes(60))
|
||||
{
|
||||
var queryResult = await testService.RunQueryAndWaitToComplete(queryTempFile.FilePath, queryToRun, 10000);
|
||||
|
||||
Assert.NotNull(queryResult);
|
||||
Assert.NotNull(queryResult.BatchSummaries);
|
||||
Assert.NotEmpty(queryResult.BatchSummaries);
|
||||
Assert.NotNull(queryResult.BatchSummaries[0].ResultSetSummaries);
|
||||
Assert.NotNull(queryResult.BatchSummaries[1].ResultSetSummaries);
|
||||
Assert.NotNull(queryResult.BatchSummaries[2].ResultSetSummaries);
|
||||
Assert.NotNull(queryResult.BatchSummaries[3].ResultSetSummaries);
|
||||
|
||||
Assert.NotNull(await testService.ExecuteSubset(queryTempFile.FilePath, 0, 0, 0, 7));
|
||||
Assert.NotNull(await testService.ExecuteSubset(queryTempFile.FilePath, 1, 0, 0, 7));
|
||||
Assert.NotNull(await testService.ExecuteSubset(queryTempFile.FilePath, 2, 0, 0, 7));
|
||||
Assert.NotNull(await testService.ExecuteSubset(queryTempFile.FilePath, 3, 0, 0, 1));
|
||||
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
await testService.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Repeatedly connect and disconnect to stress test the connection service.
|
||||
/// </summary>
|
||||
//[Fact]
|
||||
public async Task TestConnectionService()
|
||||
{
|
||||
string ownerUri = "file:///my/test/file.sql";
|
||||
|
||||
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
var connection = await testService.GetConnectionParametersAsync(TestServerType.OnPrem);
|
||||
connection.Connection.Pooling = false;
|
||||
|
||||
// Connect/disconnect repeatedly
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
while (stopwatch.Elapsed < TimeSpan.FromMinutes(60))
|
||||
{
|
||||
// Connect
|
||||
bool connected = await testService.Connect(ownerUri, connection);
|
||||
Assert.True(connected, "Connection is successful");
|
||||
|
||||
// Disconnect
|
||||
bool disconnected = await testService.Disconnect(ownerUri);
|
||||
Assert.True(disconnected, "Disconnect is successful");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.Hosting.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Language Service end-to-end integration tests
|
||||
/// </summary>
|
||||
public class WorkspaceTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Validate workspace lifecycle events
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task InitializeRequestTest()
|
||||
{
|
||||
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
|
||||
{
|
||||
InitializeRequest initializeRequest = new InitializeRequest()
|
||||
{
|
||||
RootPath = Path.GetTempPath(),
|
||||
Capabilities = new ClientCapabilities()
|
||||
};
|
||||
|
||||
InitializeResult result = await testService.Driver.SendRequest(InitializeRequest.Type, initializeRequest);
|
||||
Assert.NotNull(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "Microsoft.SqlTools.ServiceLayer.TestDriver.Tests",
|
||||
"version": "1.0.0-*",
|
||||
"buildOptions": {
|
||||
"debugType": "portable",
|
||||
"emitEntryPoint": true
|
||||
},
|
||||
"dependencies": {
|
||||
"xunit": "2.1.0",
|
||||
"dotnet-test-xunit": "1.0.0-rc2-192208-24",
|
||||
"Microsoft.SqlTools.ServiceLayer": {
|
||||
"target": "project"
|
||||
},
|
||||
"Microsoft.SqlTools.ServiceLayer.TestDriver": "1.0.0-*",
|
||||
"Microsoft.SqlTools.ServiceLayer.Test.Common": "1.0.0-*"
|
||||
},
|
||||
"testRunner": "xunit",
|
||||
"frameworks": {
|
||||
"netcoreapp1.0": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"type": "platform",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
},
|
||||
"imports": [
|
||||
"dotnet5.4",
|
||||
"portable-net451+win8"
|
||||
]
|
||||
}
|
||||
},
|
||||
"runtimes": {
|
||||
"win7-x64": {}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user