mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-14 01:25:40 -05:00
Fix Code Coverage (#151)
This is another large code review. I want to make a few more changes, but since these changes will stand on their own, I'll hold back on making this change set any larger than it already is. Changes in this request: To address Microsoft/vscode-mssql#326, instead of doing taskkill on the service layer when WaitForExit is executed, we now make an educated guess at which service layer was spawned when the test starts and do a Process.Kill on it when we shut down the test. All the perf tests have been moved into a new project. This was done to keep them easily separated from code coverage test runs. At the same time the perf tests were separated into separate classes for logical categorization. This process will likely be repeated on the stress tests. The tests can still easily be ran from Visual Studio Test Explorer To address Microsoft/vscode-mssql#349, a new SelfCleaningFile class was created to allow for easy cleanup of temporary files generated for integration tests via using blocks. Due to some of the refactoring done while moving the perf tests to a new project, the TestBase class had to be switched to more of a helper class style. As such, all tests that use inherit from TestBase now create a TestBase object on start via a using block. This also simplifies the cleanup at the end of the test. * Solution for hanging code coverage runs Code coverage runs would hang in certain scenarios if a test failed before the service process could be spawned. The taskkill command would fail to find the service process. The test would then wait for opencover to exit, but it would not since the service process it had spawned would still be running, causing the test run to hang indefinitely. Solution was to capture the service process after it launched and explicitly kill it when shutting down the test driver. * Setting the test name in the propery in the class and removign the parameter from each method * New project for perf tests * Reworking integration tests to cleanup temp files * Changes as per @llali review comments * Adding copyright notices * Renaming TestBase => TestHelper * Renaming SelfCleaningFile => SelfCleaningTempFile * Removing code that sets TestName property * Fixing compilation error due to removed code
This commit is contained in:
@@ -9,7 +9,10 @@
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol;
|
||||
@@ -33,7 +36,11 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Driver
|
||||
|
||||
public const string ServiceHostEnvironmentVariable = "SQLTOOLSSERVICE_EXE";
|
||||
|
||||
public bool IsCoverageRun { get; set; }
|
||||
public bool IsCoverageRun { get; set; }
|
||||
|
||||
private Process[] serviceProcesses;
|
||||
|
||||
private DateTime startTime;
|
||||
|
||||
public ServiceTestDriver()
|
||||
{
|
||||
@@ -71,8 +78,9 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Driver
|
||||
coverageOutput = "coverage.xml";
|
||||
}
|
||||
|
||||
serviceHostArguments = "-mergeoutput -target:" + serviceHostExecutable + " -targetargs:" + serviceHostArguments
|
||||
+ " -register:user -oldstyle -filter:\"+[Microsoft.SqlTools.*]* -[xunit*]*\" -output:" + coverageOutput + " -searchdirs:" + serviceHostDirectory;
|
||||
serviceHostArguments = $"-mergeoutput -target:{serviceHostExecutable} -targetargs:{serviceHostArguments} " +
|
||||
$"-register:user -oldstyle -filter:\"+[Microsoft.SqlTools.*]* -[xunit*]*\" -output:{coverageOutput} " +
|
||||
$"-searchdirs:{serviceHostDirectory};";
|
||||
serviceHostExecutable = coverageToolPath;
|
||||
|
||||
this.IsCoverageRun = true;
|
||||
@@ -88,9 +96,28 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Driver
|
||||
/// </summary>
|
||||
public async Task Start()
|
||||
{
|
||||
// Store the time we started
|
||||
startTime = DateTime.Now;
|
||||
|
||||
// Launch the process
|
||||
await this.protocolClient.Start();
|
||||
await Task.Delay(1000); // Wait for the service host to start
|
||||
|
||||
// If this is a code coverage run, we need access to the service layer separate from open cover
|
||||
if (IsCoverageRun)
|
||||
{
|
||||
CancellationTokenSource cancelSource = new CancellationTokenSource();
|
||||
Task getServiceProcess = GetServiceProcess(cancelSource.Token);
|
||||
Task timeoutTask = Task.Delay(TimeSpan.FromSeconds(15), cancelSource.Token);
|
||||
if (await Task.WhenAny(getServiceProcess, timeoutTask) == timeoutTask)
|
||||
{
|
||||
cancelSource.Cancel();
|
||||
throw new Exception("Failed to capture service process");
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("Successfully launched service");
|
||||
|
||||
// Setup events to queue for testing
|
||||
this.QueueEventsForType(ConnectionCompleteNotification.Type);
|
||||
this.QueueEventsForType(IntelliSenseReadyNotification.Type);
|
||||
@@ -103,7 +130,38 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Driver
|
||||
/// </summary>
|
||||
public async Task Stop()
|
||||
{
|
||||
await this.protocolClient.Stop();
|
||||
if (IsCoverageRun)
|
||||
{
|
||||
// Kill all the processes in the list
|
||||
foreach (Process p in serviceProcesses.Where(p => !p.HasExited))
|
||||
{
|
||||
p.Kill();
|
||||
}
|
||||
ServiceProcess?.WaitForExit();
|
||||
}
|
||||
else
|
||||
{
|
||||
await this.protocolClient.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task GetServiceProcess(CancellationToken token)
|
||||
{
|
||||
while (serviceProcesses == null && !token.IsCancellationRequested)
|
||||
{
|
||||
var processes = Process.GetProcessesByName("Microsoft.SqlTools.ServiceLayer")
|
||||
.Where(p => p.StartTime >= startTime).ToArray();
|
||||
|
||||
// Wait a second if we can't find the process
|
||||
if (processes.Any())
|
||||
{
|
||||
serviceProcesses = processes;
|
||||
}
|
||||
else
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(1), token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?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>
|
||||
@@ -15,5 +15,8 @@
|
||||
<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>
|
||||
</Project>
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// 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.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Scripts
|
||||
{
|
||||
public class Scripts
|
||||
{
|
||||
|
||||
public const string SimpleQuery = "SELECT * FROM sys.all_columns";
|
||||
|
||||
public const string DelayQuery = "WAITFOR DELAY '00:01:00'";
|
||||
|
||||
private static readonly Lazy<string> ComplexQueryInstance = new Lazy<string>(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
string assemblyLocation = typeof(Scripts).GetTypeInfo().Assembly.Location;
|
||||
string folderName = Path.GetDirectoryName(assemblyLocation);
|
||||
string filePath = Path.Combine(folderName, "Scripts/AdventureWorks.sql");
|
||||
return File.ReadAllText(filePath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Failed to load the sql script. error: {ex.Message}");
|
||||
return string.Empty;
|
||||
}
|
||||
});
|
||||
|
||||
public static string ComplexQuery { get { return ComplexQueryInstance.Value; } }
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Language Service end-to-end integration tests
|
||||
/// </summary>
|
||||
public class ConnectionTests : TestBase
|
||||
public class ConnectionTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Try to connect with invalid credentials
|
||||
@@ -21,23 +21,19 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
[Fact]
|
||||
public async Task InvalidConnection()
|
||||
{
|
||||
try
|
||||
{
|
||||
string ownerUri = System.IO.Path.GetTempFileName();
|
||||
bool connected = await Connect(ownerUri, ConnectionTestUtils.InvalidConnection, 300000);
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
bool connected = await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.InvalidConnection, 300000);
|
||||
Assert.False(connected, "Invalid connection is failed to connect");
|
||||
|
||||
await Connect(ownerUri, ConnectionTestUtils.InvalidConnection, 300000);
|
||||
await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.InvalidConnection, 300000);
|
||||
|
||||
Thread.Sleep(1000);
|
||||
|
||||
await CancelConnect(ownerUri);
|
||||
await testHelper.CancelConnect(queryTempFile.FilePath);
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,22 +43,17 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
[Fact]
|
||||
public async Task ListDatabasesTest()
|
||||
{
|
||||
try
|
||||
{
|
||||
string ownerUri = System.IO.Path.GetTempFileName();
|
||||
bool connected = await Connect(ownerUri, ConnectionTestUtils.LocalhostConnection);
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
bool connected = await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.LocalhostConnection);
|
||||
Assert.True(connected, "Connection successful");
|
||||
|
||||
var listDatabaseResult = await ListDatabases(ownerUri);
|
||||
var listDatabaseResult = await testHelper.ListDatabases(queryTempFile.FilePath);
|
||||
Assert.True(listDatabaseResult.DatabaseNames.Length > 0);
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts;
|
||||
@@ -20,7 +16,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Language Service end-to-end integration tests
|
||||
/// </summary>
|
||||
public class LanguageServiceTests : TestBase
|
||||
public class LanguageServiceTests
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
@@ -29,42 +25,38 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
[Fact]
|
||||
public async Task HoverTest()
|
||||
{
|
||||
try
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
string ownerUri = System.IO.Path.GetTempFileName();
|
||||
string query = "SELECT * FROM sys.objects";
|
||||
|
||||
WriteToFile(ownerUri, query);
|
||||
testHelper.WriteToFile(queryTempFile.FilePath, query);
|
||||
|
||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification()
|
||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification
|
||||
{
|
||||
TextDocument = new TextDocumentItem()
|
||||
TextDocument = new TextDocumentItem
|
||||
{
|
||||
Uri = ownerUri,
|
||||
Uri = queryTempFile.FilePath,
|
||||
LanguageId = "enu",
|
||||
Version = 1,
|
||||
Text = query
|
||||
}
|
||||
};
|
||||
|
||||
await RequestOpenDocumentNotification(openParams);
|
||||
await testHelper.RequestOpenDocumentNotification(openParams);
|
||||
|
||||
Thread.Sleep(500);
|
||||
|
||||
bool connected = await Connect(ownerUri, ConnectionTestUtils.LocalhostConnection);
|
||||
Assert.True(connected, "Connection is successful");
|
||||
bool connected = await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.LocalhostConnection);
|
||||
Assert.True(connected, "Connection was not successful");
|
||||
|
||||
Thread.Sleep(10000);
|
||||
|
||||
Hover hover = await RequestHover(ownerUri, query, 0, 15);
|
||||
Hover hover = await testHelper.RequestHover(queryTempFile.FilePath, query, 0, 15);
|
||||
|
||||
Assert.True(hover != null, "Hover tooltop is not null");
|
||||
Assert.True(hover != null, "Hover tooltop is null");
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,48 +66,44 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
[Fact]
|
||||
public async Task CompletionTest()
|
||||
{
|
||||
try
|
||||
{
|
||||
string ownerUri = System.IO.Path.GetTempFileName();
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
string query = "SELECT * FROM sys.objects";
|
||||
|
||||
WriteToFile(ownerUri, query);
|
||||
testHelper.WriteToFile(queryTempFile.FilePath, query);
|
||||
|
||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification()
|
||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification
|
||||
{
|
||||
TextDocument = new TextDocumentItem()
|
||||
TextDocument = new TextDocumentItem
|
||||
{
|
||||
Uri = ownerUri,
|
||||
Uri = queryTempFile.FilePath,
|
||||
LanguageId = "enu",
|
||||
Version = 1,
|
||||
Text = query
|
||||
}
|
||||
};
|
||||
|
||||
await RequestOpenDocumentNotification(openParams);
|
||||
await testHelper.RequestOpenDocumentNotification(openParams);
|
||||
|
||||
Thread.Sleep(500);
|
||||
|
||||
bool connected = await Connect(ownerUri, ConnectionTestUtils.LocalhostConnection);
|
||||
bool connected = await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.LocalhostConnection);
|
||||
Assert.True(connected, "Connection is successful");
|
||||
|
||||
Thread.Sleep(10000);
|
||||
|
||||
CompletionItem[] completions = await RequestCompletion(ownerUri, query, 0, 15);
|
||||
CompletionItem[] completions = await testHelper.RequestCompletion(queryTempFile.FilePath, query, 0, 15);
|
||||
|
||||
Assert.True(completions != null && completions.Length > 0, "Completion items list is not null and not empty");
|
||||
Assert.True(completions != null && completions.Length > 0, "Completion items list is null or empty");
|
||||
|
||||
Thread.Sleep(50);
|
||||
|
||||
CompletionItem item = await RequestResolveCompletion(completions[0]);
|
||||
await testHelper.RequestResolveCompletion(completions[0]);
|
||||
|
||||
Assert.True(completions != null && completions.Length > 0, "Completion items list is not null and not empty");
|
||||
Assert.True(completions != null && completions.Length > 0, "Completion items list is null or empty");
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,42 +113,42 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
[Fact]
|
||||
public async Task DiagnosticsTests()
|
||||
{
|
||||
try
|
||||
{
|
||||
string ownerUri = System.IO.Path.GetTempFileName();
|
||||
bool connected = await Connect(ownerUri, ConnectionTestUtils.LocalhostConnection);
|
||||
Assert.True(connected, "Connection is successful");
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
bool connected = await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.LocalhostConnection);
|
||||
Assert.True(connected, "Connection was not successful");
|
||||
|
||||
Thread.Sleep(500);
|
||||
|
||||
string query = "SELECT *** FROM sys.objects";
|
||||
|
||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification()
|
||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification
|
||||
{
|
||||
TextDocument = new TextDocumentItem()
|
||||
TextDocument = new TextDocumentItem
|
||||
{
|
||||
Uri = ownerUri,
|
||||
Uri = queryTempFile.FilePath,
|
||||
LanguageId = "enu",
|
||||
Version = 1,
|
||||
Text = query
|
||||
}
|
||||
};
|
||||
|
||||
await RequestOpenDocumentNotification(openParams);
|
||||
await testHelper.RequestOpenDocumentNotification(openParams);
|
||||
|
||||
Thread.Sleep(100);
|
||||
|
||||
var contentChanges = new TextDocumentChangeEvent[1];
|
||||
contentChanges[0] = new TextDocumentChangeEvent()
|
||||
contentChanges[0] = new TextDocumentChangeEvent
|
||||
{
|
||||
Range = new Range()
|
||||
Range = new Range
|
||||
{
|
||||
Start = new Position()
|
||||
Start = new Position
|
||||
{
|
||||
Line = 0,
|
||||
Character = 5
|
||||
},
|
||||
End = new Position()
|
||||
End = new Position
|
||||
{
|
||||
Line = 0,
|
||||
Character = 6
|
||||
@@ -176,24 +164,24 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
TextDocument = new VersionedTextDocumentIdentifier()
|
||||
{
|
||||
Version = 2,
|
||||
Uri = ownerUri
|
||||
Uri = queryTempFile.FilePath
|
||||
}
|
||||
};
|
||||
|
||||
await RequestChangeTextDocumentNotification(changeParams);
|
||||
await testHelper.RequestChangeTextDocumentNotification(changeParams);
|
||||
|
||||
Thread.Sleep(100);
|
||||
|
||||
contentChanges[0] = new TextDocumentChangeEvent()
|
||||
contentChanges[0] = new TextDocumentChangeEvent
|
||||
{
|
||||
Range = new Range()
|
||||
Range = new Range
|
||||
{
|
||||
Start = new Position()
|
||||
Start = new Position
|
||||
{
|
||||
Line = 0,
|
||||
Character = 5
|
||||
},
|
||||
End = new Position()
|
||||
End = new Position
|
||||
{
|
||||
Line = 0,
|
||||
Character = 6
|
||||
@@ -203,25 +191,21 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
Text = "t"
|
||||
};
|
||||
|
||||
changeParams = new DidChangeTextDocumentParams()
|
||||
changeParams = new DidChangeTextDocumentParams
|
||||
{
|
||||
ContentChanges = contentChanges,
|
||||
TextDocument = new VersionedTextDocumentIdentifier()
|
||||
TextDocument = new VersionedTextDocumentIdentifier
|
||||
{
|
||||
Version = 3,
|
||||
Uri = ownerUri
|
||||
Uri = queryTempFile.FilePath
|
||||
}
|
||||
};
|
||||
|
||||
await RequestChangeTextDocumentNotification(changeParams);
|
||||
await testHelper.RequestChangeTextDocumentNotification(changeParams);
|
||||
|
||||
Thread.Sleep(2500);
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,11 +215,11 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
[Fact]
|
||||
public async Task ChangeConfigurationTest()
|
||||
{
|
||||
try
|
||||
{
|
||||
string ownerUri = System.IO.Path.GetTempFileName();
|
||||
bool connected = await Connect(ownerUri, ConnectionTestUtils.LocalhostConnection);
|
||||
Assert.True(connected, "Connection is successful");
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
bool connected = await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.LocalhostConnection);
|
||||
Assert.True(connected, "Connection was not successful");
|
||||
|
||||
Thread.Sleep(500);
|
||||
|
||||
@@ -246,37 +230,29 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
Settings = settings
|
||||
};
|
||||
|
||||
await RequestChangeConfigurationNotification(configParams);
|
||||
await testHelper.RequestChangeConfigurationNotification(configParams);
|
||||
|
||||
Thread.Sleep(2000);
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NotificationIsSentAfterOnConnectionAutoCompleteUpdate()
|
||||
{
|
||||
try
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
// Connect
|
||||
string ownerUri = System.IO.Path.GetTempFileName();
|
||||
await Connect(ownerUri, ConnectionTestUtils.LocalhostConnection);
|
||||
await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.LocalhostConnection);
|
||||
|
||||
// An event signalling that IntelliSense is ready should be sent shortly thereafter
|
||||
var readyParams = await Driver.WaitForEvent(IntelliSenseReadyNotification.Type, 30000);
|
||||
var readyParams = await testHelper.Driver.WaitForEvent(IntelliSenseReadyNotification.Type, 30000);
|
||||
Assert.NotNull(readyParams);
|
||||
Assert.Equal(ownerUri, readyParams.OwnerUri);
|
||||
Assert.Equal(queryTempFile.FilePath, readyParams.OwnerUri);
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,582 +0,0 @@
|
||||
//
|
||||
// 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.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.TestDriver.Utility;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
{
|
||||
public class PerformanceTests : TestBase
|
||||
{
|
||||
|
||||
private static string ComplexQuery = LoadComplexScript();
|
||||
private static string SimpleQuery = "SELECT * FROM sys.all_columns";
|
||||
|
||||
private static string LoadComplexScript()
|
||||
{
|
||||
try
|
||||
{
|
||||
string assemblyLocation = Assembly.GetEntryAssembly().Location;
|
||||
string folderName = Path.GetDirectoryName(assemblyLocation);
|
||||
string filePath = Path.Combine(folderName, "Scripts/AdventureWorks.sql");
|
||||
return File.ReadAllText(filePath);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Console.WriteLine("Failed to load the sql script. error: " + ex.Message);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HoverTestOnPrem()
|
||||
{
|
||||
try
|
||||
{
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
string query = SimpleQuery;
|
||||
|
||||
await ConnectAsync(TestServerType.OnPrem, query, ownerUri);
|
||||
Hover hover = await CalculateRunTime(async () =>
|
||||
{
|
||||
return await RequestHover(ownerUri, query, 0, 15);
|
||||
});
|
||||
Assert.True(hover != null, "Hover tool-tip is not null");
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SuggestionsTest()
|
||||
{
|
||||
try
|
||||
{
|
||||
string query = SimpleQuery;
|
||||
TestServerType serverType = TestServerType.OnPrem;
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
|
||||
WriteToFile(ownerUri, query);
|
||||
|
||||
await ConnectAsync(serverType, query, ownerUri);
|
||||
await ValidateCompletionResponse(ownerUri, query, null);
|
||||
|
||||
await ValidateCompletionResponse(ownerUri, query);
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DiagnosticsTests()
|
||||
{
|
||||
try
|
||||
{
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
string query = "SELECT * FROM sys.objects";
|
||||
|
||||
await ConnectAsync(TestServerType.OnPrem, query, ownerUri);
|
||||
Thread.Sleep(500);
|
||||
|
||||
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 = ownerUri
|
||||
}
|
||||
};
|
||||
TestTimer timer = new TestTimer();
|
||||
await RequestChangeTextDocumentNotification(changeParams);
|
||||
|
||||
while (true)
|
||||
{
|
||||
var completeEvent = await Driver.WaitForEvent(PublishDiagnosticsNotification.Type, 15000);
|
||||
if (completeEvent != null && completeEvent.Diagnostics != null && completeEvent.Diagnostics.Length > 0)
|
||||
{
|
||||
timer.EndAndPrint();
|
||||
break;
|
||||
}
|
||||
if (timer.TotalMilliSecondsUntilNow >= 500000)
|
||||
{
|
||||
Assert.True(false, "Failed to get Diagnostics");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ValidateCompletionResponse(string ownerUri, string query, [CallerMemberName] string testName = "")
|
||||
{
|
||||
TestTimer timer = new TestTimer();
|
||||
CompletionItem completion = null;
|
||||
while (true)
|
||||
{
|
||||
CompletionItem[] completions = await RequestCompletion(ownerUri, query, 0, 15);
|
||||
|
||||
completion = completions != null ? completions.FirstOrDefault(x => x.Label == "master") : null;
|
||||
if (completion != null)
|
||||
{
|
||||
if (testName != null)
|
||||
{
|
||||
timer.EndAndPrint(testName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (timer.TotalMilliSecondsUntilNow >= 500000)
|
||||
{
|
||||
Assert.True(false, "Failed to get a valid auto-complete list");
|
||||
break;
|
||||
}
|
||||
|
||||
Thread.Sleep(50);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task VerifyBindingLoadScenario(TestServerType serverType, string query, [CallerMemberName] string testName = "")
|
||||
{
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
|
||||
WriteToFile(ownerUri, query);
|
||||
|
||||
await ConnectAsync(serverType, query, ownerUri);
|
||||
await ValidateCompletionResponse(ownerUri, query, testName);
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindingCacheColdAzureSimpleQuery()
|
||||
{
|
||||
try
|
||||
{
|
||||
string query = SimpleQuery;
|
||||
Thread.Sleep(5000);
|
||||
await VerifyBindingLoadScenario(TestServerType.Azure, query);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindingCacheColdOnPremSimpleQuery()
|
||||
{
|
||||
try
|
||||
{
|
||||
string query = SimpleQuery;
|
||||
await VerifyBindingLoadScenario(TestServerType.OnPrem, query);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindingCacheWarmAzureSimpleQuery()
|
||||
{
|
||||
try
|
||||
{
|
||||
string query = SimpleQuery;
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
TestServerType serverType = TestServerType.Azure;
|
||||
await ConnectAsync(serverType, query, ownerUri);
|
||||
Thread.Sleep(10000);
|
||||
await VerifyBindingLoadScenario(serverType, query);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindingCacheWarmOnPremSimpleQuery()
|
||||
{
|
||||
try
|
||||
{
|
||||
string query = SimpleQuery;
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
TestServerType serverType = TestServerType.OnPrem;
|
||||
await ConnectAsync(serverType, query, ownerUri);
|
||||
Thread.Sleep(10000);
|
||||
await VerifyBindingLoadScenario(serverType, query);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindingCacheColdAzureComplexQuery()
|
||||
{
|
||||
try
|
||||
{
|
||||
string query = ComplexQuery;
|
||||
await VerifyBindingLoadScenario(TestServerType.Azure, query);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindingCacheColdOnPremComplexQuery()
|
||||
{
|
||||
try
|
||||
{
|
||||
string query = ComplexQuery;
|
||||
await VerifyBindingLoadScenario(TestServerType.OnPrem, query);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindingCacheWarmAzureComplexQuery()
|
||||
{
|
||||
try
|
||||
{
|
||||
string query = ComplexQuery;
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
TestServerType serverType = TestServerType.Azure;
|
||||
await ConnectAsync(serverType, query, ownerUri);
|
||||
Thread.Sleep(100000);
|
||||
await VerifyBindingLoadScenario(serverType, query);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindingCacheWarmOnPremComplexQuery()
|
||||
{
|
||||
try
|
||||
{
|
||||
string query = ComplexQuery;
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
TestServerType serverType = TestServerType.OnPrem;
|
||||
await ConnectAsync(serverType, query, ownerUri);
|
||||
Thread.Sleep(10000);
|
||||
await VerifyBindingLoadScenario(serverType, query);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ConnectAzureTest()
|
||||
{
|
||||
try
|
||||
{
|
||||
string query = SimpleQuery;
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
TestServerType serverType = TestServerType.Azure;
|
||||
WriteToFile(ownerUri, query);
|
||||
|
||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification()
|
||||
{
|
||||
TextDocument = new TextDocumentItem()
|
||||
{
|
||||
Uri = ownerUri,
|
||||
LanguageId = "enu",
|
||||
Version = 1,
|
||||
Text = query
|
||||
}
|
||||
};
|
||||
|
||||
await RequestOpenDocumentNotification(openParams);
|
||||
|
||||
Thread.Sleep(500);
|
||||
var connected = await CalculateRunTime(async () =>
|
||||
{
|
||||
var connectParams = await GetDatabaseConnectionAsync(serverType);
|
||||
return await Connect(ownerUri, connectParams);
|
||||
});
|
||||
Assert.True(connected, "Connection is successful");
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ConnectOnPremTest()
|
||||
{
|
||||
try
|
||||
{
|
||||
string query = SimpleQuery;
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
TestServerType serverType = TestServerType.OnPrem;
|
||||
WriteToFile(ownerUri, query);
|
||||
|
||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification()
|
||||
{
|
||||
TextDocument = new TextDocumentItem()
|
||||
{
|
||||
Uri = ownerUri,
|
||||
LanguageId = "enu",
|
||||
Version = 1,
|
||||
Text = query
|
||||
}
|
||||
};
|
||||
|
||||
await RequestOpenDocumentNotification(openParams);
|
||||
|
||||
Thread.Sleep(500);
|
||||
var connected = await CalculateRunTime(async () =>
|
||||
{
|
||||
var connectParams = await GetDatabaseConnectionAsync(serverType);
|
||||
return await Connect(ownerUri, connectParams);
|
||||
});
|
||||
Assert.True(connected, "Connection is successful");
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DisconnectTest()
|
||||
{
|
||||
try
|
||||
{
|
||||
string query = SimpleQuery;
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
TestServerType serverType = TestServerType.OnPrem;
|
||||
await ConnectAsync(serverType, query, ownerUri);
|
||||
Thread.Sleep(1000);
|
||||
var connected = await CalculateRunTime(async () =>
|
||||
{
|
||||
return await base.Disconnect(ownerUri);
|
||||
});
|
||||
Assert.True(connected);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task QueryResultSummaryOnPremTest()
|
||||
{
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
TestServerType serverType = TestServerType.OnPrem;
|
||||
string query = SimpleQuery;
|
||||
|
||||
await ConnectAsync(serverType, query, ownerUri);
|
||||
|
||||
var queryTask = await CalculateRunTime(async () =>
|
||||
{
|
||||
return await RunQuery(ownerUri, query);
|
||||
});
|
||||
|
||||
Assert.NotNull(queryTask);
|
||||
Assert.True(queryTask.BatchSummaries.Any(x => x.ResultSetSummaries.Any( r => r.RowCount > 0)));
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task QueryResultFirstOnPremTest()
|
||||
{
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
TestServerType serverType = TestServerType.OnPrem;
|
||||
string query = SimpleQuery;
|
||||
|
||||
await ConnectAsync(serverType, query, ownerUri);
|
||||
|
||||
var queryResult = await CalculateRunTime(async () =>
|
||||
{
|
||||
var queryTask = await RunQuery(ownerUri, query);
|
||||
return await ExecuteSubset(ownerUri, 0, 0, 0, 100);
|
||||
});
|
||||
|
||||
Assert.NotNull(queryResult);
|
||||
Assert.NotNull(queryResult.ResultSubset);
|
||||
Assert.True(queryResult.ResultSubset.Rows.Count() > 0);
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task CancelQueryOnPremTest()
|
||||
{
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
TestServerType serverType = TestServerType.OnPrem;
|
||||
string query = "WAITFOR DELAY '00:01:00';";
|
||||
|
||||
await ConnectAsync(serverType, query, ownerUri);
|
||||
var queryParams = new QueryExecuteParams();
|
||||
queryParams.OwnerUri = ownerUri;
|
||||
queryParams.QuerySelection = null;
|
||||
|
||||
var result = await Driver.SendRequest(QueryExecuteRequest.Type, queryParams);
|
||||
if (result != null && string.IsNullOrEmpty(result.Messages))
|
||||
{
|
||||
TestTimer timer = new TestTimer();
|
||||
|
||||
while (true)
|
||||
{
|
||||
var queryTask = await CancelQuery(ownerUri);
|
||||
if (queryTask != null)
|
||||
{
|
||||
timer.EndAndPrint();
|
||||
break;
|
||||
}
|
||||
if (timer.TotalMilliSecondsUntilNow >= 100000)
|
||||
{
|
||||
Assert.True(false, "Failed to cancel query");
|
||||
break;
|
||||
}
|
||||
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.True(false, "Failed to run the query");
|
||||
}
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestSaveResultsToCsvTest()
|
||||
{
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
string query = SimpleQuery;
|
||||
TestServerType serverType = TestServerType.OnPrem;
|
||||
string output = Path.GetTempFileName();
|
||||
await ConnectAsync(serverType, query, ownerUri);
|
||||
|
||||
// Execute a query
|
||||
await RunQuery(ownerUri, query);
|
||||
|
||||
var saveTask = await CalculateRunTime(async () =>
|
||||
{
|
||||
return await SaveAsCsv(ownerUri, output, 0, 0);
|
||||
});
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestSaveResultsToJsonTest()
|
||||
{
|
||||
string ownerUri = Path.GetTempFileName();
|
||||
string query = SimpleQuery;
|
||||
TestServerType serverType = TestServerType.OnPrem;
|
||||
await ConnectAsync(serverType, query, ownerUri);
|
||||
string output = Path.GetTempFileName();
|
||||
// Execute a query
|
||||
await RunQuery(ownerUri, query);
|
||||
|
||||
var saveTask = await CalculateRunTime(async () =>
|
||||
{
|
||||
return await SaveAsJson(ownerUri, output, 0, 0);
|
||||
});
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
|
||||
private async Task<bool> ConnectAsync(TestServerType serverType, string query, string ownerUri)
|
||||
{
|
||||
WriteToFile(ownerUri, query);
|
||||
|
||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification()
|
||||
{
|
||||
TextDocument = new TextDocumentItem()
|
||||
{
|
||||
Uri = ownerUri,
|
||||
LanguageId = "enu",
|
||||
Version = 1,
|
||||
Text = query
|
||||
}
|
||||
};
|
||||
|
||||
await RequestOpenDocumentNotification(openParams);
|
||||
|
||||
Thread.Sleep(500);
|
||||
var connectParams = await GetDatabaseConnectionAsync(serverType);
|
||||
bool connected = await Connect(ownerUri, connectParams);
|
||||
Assert.True(connected, "Connection is successful");
|
||||
if (connected)
|
||||
{
|
||||
Console.WriteLine("Connection is successful");
|
||||
}
|
||||
|
||||
return connected;
|
||||
}
|
||||
|
||||
private async Task<T> CalculateRunTime<T>(Func<Task<T>> testToRun, [CallerMemberName] string testName = "")
|
||||
{
|
||||
TestTimer timer = new TestTimer();
|
||||
T result = await testToRun();
|
||||
timer.EndAndPrint(testName);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,219 +14,243 @@ using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
{
|
||||
public class QueryExecutionTests : TestBase
|
||||
public class QueryExecutionTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task TestQueryCancelReliability()
|
||||
{
|
||||
string ownerUri = System.IO.Path.GetTempFileName();
|
||||
string query = "SELECT * FROM sys.objects a CROSS JOIN sys.objects b CROSS JOIN sys.objects c";
|
||||
const string query = "SELECT * FROM sys.objects a CROSS JOIN sys.objects b CROSS JOIN sys.objects c";
|
||||
|
||||
await Connect(ownerUri, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
// Run and cancel 100 queries
|
||||
for (int i = 0; i < 100; i++)
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
var queryTask = RunQuery(ownerUri, query);
|
||||
await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
var cancelResult = await CancelQuery(ownerUri);
|
||||
Assert.NotNull(cancelResult);
|
||||
Assert.True(string.IsNullOrEmpty(cancelResult.Messages));
|
||||
// Run and cancel 100 queries
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
var queryTask = testHelper.RunQuery(queryTempFile.FilePath, query);
|
||||
|
||||
await queryTask;
|
||||
var cancelResult = await testHelper.CancelQuery(queryTempFile.FilePath);
|
||||
Assert.NotNull(cancelResult);
|
||||
Assert.True(string.IsNullOrEmpty(cancelResult.Messages));
|
||||
|
||||
await queryTask;
|
||||
}
|
||||
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestQueryDoesNotBlockOtherRequests()
|
||||
{
|
||||
string ownerUri = System.IO.Path.GetTempFileName();
|
||||
string query = "SELECT * FROM sys.objects a CROSS JOIN sys.objects b CROSS JOIN sys.objects c";
|
||||
const string query = "SELECT * FROM sys.objects a CROSS JOIN sys.objects b CROSS JOIN sys.objects c";
|
||||
|
||||
await Connect(ownerUri, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
// Start a long-running query
|
||||
var queryTask = RunQuery(ownerUri, 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 queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
string ownerUri2 = System.IO.Path.GetTempFileName();
|
||||
await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
await Connect(ownerUri2, ConnectionTestUtils.AzureTestServerConnection);
|
||||
Assert.NotNull(await RequestCompletion(ownerUri2, "SELECT * FROM sys.objects", 0, 10));
|
||||
await Disconnect(ownerUri2);
|
||||
// Start a long-running query
|
||||
var queryTask = testHelper.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 testHelper.Connect(queryFile2.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
Assert.NotNull(await testHelper.RequestCompletion(queryFile2.FilePath, "SELECT * FROM sys.objects", 0, 10));
|
||||
await testHelper.Disconnect(queryFile2.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
await testHelper.CancelQuery(queryTempFile.FilePath);
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
|
||||
await CancelQuery(ownerUri);
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestParallelQueryExecution()
|
||||
{
|
||||
int queryCount = 10;
|
||||
const int queryCount = 10;
|
||||
const string query = "SELECT * FROM sys.objects";
|
||||
|
||||
// Create n connections
|
||||
string[] ownerUris = new string[queryCount];
|
||||
for (int i = 0; i < queryCount; i++)
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
ownerUris[i] = System.IO.Path.GetTempFileName();
|
||||
Assert.NotNull(await Connect(ownerUris[i], ConnectionTestUtils.AzureTestServerConnection));
|
||||
}
|
||||
// Create n connections
|
||||
SelfCleaningTempFile[] ownerUris = new SelfCleaningTempFile[queryCount];
|
||||
for (int i = 0; i < queryCount; i++)
|
||||
{
|
||||
ownerUris[i] = new SelfCleaningTempFile();
|
||||
Assert.NotNull(await testHelper.Connect(ownerUris[i].FilePath, ConnectionTestUtils.AzureTestServerConnection));
|
||||
}
|
||||
|
||||
// Run n queries at once
|
||||
string query = "SELECT * FROM sys.objects";
|
||||
var queryTasks = new Task<QueryExecuteCompleteParams>[queryCount];
|
||||
for (int i = 0; i < queryCount; i++)
|
||||
{
|
||||
queryTasks[i] = RunQuery(ownerUris[i], query);
|
||||
}
|
||||
await Task.WhenAll(queryTasks);
|
||||
// Run n queries at once
|
||||
var queryTasks = new Task<QueryExecuteCompleteParams>[queryCount];
|
||||
for (int i = 0; i < queryCount; i++)
|
||||
{
|
||||
queryTasks[i] = testHelper.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 Disconnect(ownerUris[i]);
|
||||
// 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 testHelper.Disconnect(ownerUris[i].FilePath);
|
||||
ownerUris[i].Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestSaveResultsDoesNotBlockOtherRequests()
|
||||
{
|
||||
string ownerUri = System.IO.Path.GetTempFileName();
|
||||
string query = "SELECT * FROM sys.objects";
|
||||
const string query = "SELECT * FROM sys.objects";
|
||||
|
||||
await Connect(ownerUri, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
// Execute a query
|
||||
await RunQuery(ownerUri, query);
|
||||
|
||||
// Spawn several tasks to save results
|
||||
var saveTasks = new Task<SaveResultRequestResult>[100];
|
||||
for (int i = 0; i < 100; i++)
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
// Execute a query
|
||||
await testHelper.RunQuery(queryTempFile.FilePath, query);
|
||||
|
||||
// Spawn several tasks to save results
|
||||
var saveTasks = new Task<SaveResultRequestResult>[100];
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
saveTasks[i] = SaveAsCsv(ownerUri, System.IO.Path.GetTempFileName(), 0, 0);
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
saveTasks[i] = testHelper.SaveAsCsv(queryTempFile.FilePath, System.IO.Path.GetTempFileName(), 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
saveTasks[i] = testHelper.SaveAsJson(queryTempFile.FilePath, System.IO.Path.GetTempFileName(), 0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
// 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++)
|
||||
{
|
||||
saveTasks[i] = SaveAsJson(ownerUri, System.IO.Path.GetTempFileName(), 0, 0);
|
||||
using(SelfCleaningTempFile queryFile2 = new SelfCleaningTempFile())
|
||||
{
|
||||
await testHelper.Connect(queryFile2.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
Assert.NotNull(await testHelper.RequestCompletion(queryFile2.FilePath, "SELECT * FROM sys.objects", 0, 10));
|
||||
await testHelper.Disconnect(queryFile2.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
await Task.WhenAll(saveTasks);
|
||||
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
|
||||
// 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++)
|
||||
{
|
||||
string ownerUri2 = System.IO.Path.GetTempFileName();
|
||||
|
||||
await Connect(ownerUri2, ConnectionTestUtils.AzureTestServerConnection);
|
||||
Assert.NotNull(await RequestCompletion(ownerUri2, "SELECT * FROM sys.objects", 0, 10));
|
||||
await Disconnect(ownerUri2);
|
||||
}
|
||||
|
||||
await Task.WhenAll(saveTasks);
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestQueryingSubsetDoesNotBlockOtherRequests()
|
||||
{
|
||||
string ownerUri = System.IO.Path.GetTempFileName();
|
||||
string query = "SELECT * FROM sys.objects";
|
||||
const string query = "SELECT * FROM sys.objects";
|
||||
|
||||
await Connect(ownerUri, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
// Execute a query
|
||||
await RunQuery(ownerUri, query);
|
||||
|
||||
// Spawn several tasks for subset requests
|
||||
var subsetTasks = new Task<QueryExecuteSubsetResult>[100];
|
||||
for (int i = 0; i < 100; i++)
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
subsetTasks[i] = ExecuteSubset(ownerUri, 0, 0, 0, 100);
|
||||
await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
// Execute a query
|
||||
await testHelper.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] = testHelper.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 testHelper.Connect(queryFile2.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
Assert.NotNull(await testHelper.RequestCompletion(queryFile2.FilePath, "SELECT * FROM sys.objects", 0, 10));
|
||||
await testHelper.Disconnect(queryFile2.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
await Task.WhenAll(subsetTasks);
|
||||
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
|
||||
// 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++)
|
||||
{
|
||||
string ownerUri2 = System.IO.Path.GetTempFileName();
|
||||
|
||||
await Connect(ownerUri2, ConnectionTestUtils.AzureTestServerConnection);
|
||||
Assert.NotNull(await RequestCompletion(ownerUri2, "SELECT * FROM sys.objects", 0, 10));
|
||||
await Disconnect(ownerUri2);
|
||||
}
|
||||
|
||||
await Task.WhenAll(subsetTasks);
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestCancelQueryWhileOtherOperationsAreInProgress()
|
||||
{
|
||||
string ownerUri = System.IO.Path.GetTempFileName();
|
||||
string query = "SELECT * FROM sys.objects a CROSS JOIN sys.objects b";
|
||||
List<Task> tasks = new List<Task>();
|
||||
const string query = "SELECT * FROM sys.objects a CROSS JOIN sys.objects b";
|
||||
|
||||
await Connect(ownerUri, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
// Execute a long-running query
|
||||
var queryTask = RunQuery(ownerUri, query, 60000);
|
||||
|
||||
// Queue up some tasks that interact with the service
|
||||
for (int i = 0; i < 10; i++)
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
string ownerUri2 = System.IO.Path.GetTempFileName();
|
||||
List<Task> tasks = new List<Task>();
|
||||
|
||||
tasks.Add(Task.Run(async () =>
|
||||
await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
// Execute a long-running query
|
||||
var queryTask = testHelper.RunQuery(queryTempFile.FilePath, query, 60000);
|
||||
|
||||
// Queue up some tasks that interact with the service
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
await Connect(ownerUri2, ConnectionTestUtils.AzureTestServerConnection);
|
||||
await RequestCompletion(ownerUri2, "SELECT * FROM sys.objects", 0, 10);
|
||||
await RunQuery(ownerUri2, "SELECT * FROM sys.objects");
|
||||
await Disconnect(ownerUri2);
|
||||
}));
|
||||
using (SelfCleaningTempFile queryFile2 = new SelfCleaningTempFile())
|
||||
{
|
||||
tasks.Add(Task.Run(async () =>
|
||||
{
|
||||
await testHelper.Connect(queryFile2.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
await testHelper.RequestCompletion(queryFile2.FilePath, "SELECT * FROM sys.objects", 0, 10);
|
||||
await testHelper.RunQuery(queryFile2.FilePath, "SELECT * FROM sys.objects");
|
||||
await testHelper.Disconnect(queryFile2.FilePath);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel the long-running query
|
||||
await testHelper.CancelQuery(queryTempFile.FilePath);
|
||||
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
|
||||
// Cancel the long-running query
|
||||
await CancelQuery(ownerUri);
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExecuteBasicQueryTest()
|
||||
{
|
||||
try
|
||||
const string query = "SELECT * FROM sys.all_columns c";
|
||||
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
string ownerUri = System.IO.Path.GetTempFileName();
|
||||
bool connected = await Connect(ownerUri, ConnectionTestUtils.LocalhostConnection);
|
||||
bool connected = await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.LocalhostConnection);
|
||||
Assert.True(connected, "Connection is successful");
|
||||
|
||||
Thread.Sleep(500);
|
||||
|
||||
string query = "SELECT * FROM sys.all_columns c";
|
||||
|
||||
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification()
|
||||
{
|
||||
TextDocument = new TextDocumentItem()
|
||||
{
|
||||
Uri = ownerUri,
|
||||
Uri = queryTempFile.FilePath,
|
||||
LanguageId = "enu",
|
||||
Version = 1,
|
||||
Text = query
|
||||
}
|
||||
};
|
||||
|
||||
await RequestOpenDocumentNotification(openParams);
|
||||
await testHelper.RequestOpenDocumentNotification(openParams);
|
||||
|
||||
var queryResult = await RunQuery(ownerUri, query);
|
||||
var queryResult = await testHelper.RunQuery(queryTempFile.FilePath, query, 10000);
|
||||
|
||||
Assert.NotNull(queryResult);
|
||||
Assert.NotNull(queryResult.BatchSummaries);
|
||||
@@ -241,69 +265,62 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
|
||||
var subsetRequest = new QueryExecuteSubsetParams()
|
||||
{
|
||||
OwnerUri = ownerUri,
|
||||
OwnerUri = queryTempFile.FilePath,
|
||||
BatchIndex = 0,
|
||||
ResultSetIndex = 0,
|
||||
RowsStartIndex = 0,
|
||||
RowsCount = 100,
|
||||
};
|
||||
|
||||
var querySubset = await RequestQueryExecuteSubset(subsetRequest);
|
||||
var querySubset = await testHelper.RequestQueryExecuteSubset(subsetRequest);
|
||||
Assert.NotNull(querySubset);
|
||||
Assert.True(querySubset.ResultSubset.RowCount == 100);
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TestQueryingAfterCompletionRequests()
|
||||
{
|
||||
try
|
||||
const string query = "SELECT * FROM sys.objects";
|
||||
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
string ownerUri = System.IO.Path.GetTempFileName();
|
||||
string query = "SELECT * FROM sys.objects";
|
||||
List<Task> tasks = new List<Task>();
|
||||
|
||||
await Connect(ownerUri, ConnectionTestUtils.AzureTestServerConnection);
|
||||
await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.AzureTestServerConnection);
|
||||
|
||||
Enumerable.Range(0, 10).ToList().ForEach(arg => tasks.Add(RequestCompletion(ownerUri, query, 0, 10)));
|
||||
var queryTask = RunQuery(ownerUri, query);
|
||||
Enumerable.Range(0, 10).ToList().ForEach(arg => tasks.Add(testHelper.RequestCompletion(queryTempFile.FilePath, query, 0, 10)));
|
||||
var queryTask = testHelper.RunQuery(queryTempFile.FilePath, query);
|
||||
tasks.Add(queryTask);
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
Assert.NotNull(queryTask.Result);
|
||||
Assert.NotNull(queryTask.Result.BatchSummaries);
|
||||
|
||||
await Connect(ownerUri, ConnectionTestUtils.DataToolsTelemetryAzureConnection);
|
||||
await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.DataToolsTelemetryAzureConnection);
|
||||
tasks.Clear();
|
||||
Enumerable.Range(0, 10).ToList().ForEach(arg => tasks.Add(RequestCompletion(ownerUri, query, 0, 10)));
|
||||
queryTask = RunQuery(ownerUri, query);
|
||||
Enumerable.Range(0, 10).ToList().ForEach(arg => tasks.Add(testHelper.RequestCompletion(queryTempFile.FilePath, query, 0, 10)));
|
||||
queryTask = testHelper.RunQuery(queryTempFile.FilePath, query);
|
||||
tasks.Add(queryTask);
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
Assert.NotNull(queryTask.Result);
|
||||
Assert.NotNull(queryTask.Result.BatchSummaries);
|
||||
|
||||
await Connect(ownerUri, ConnectionTestUtils.SqlDataToolsAzureConnection);
|
||||
await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.SqlDataToolsAzureConnection);
|
||||
tasks.Clear();
|
||||
Enumerable.Range(0, 10).ToList().ForEach(arg => tasks.Add(RequestCompletion(ownerUri, query, 0, 10)));
|
||||
queryTask = RunQuery(ownerUri, query);
|
||||
Enumerable.Range(0, 10).ToList().ForEach(arg => tasks.Add(testHelper.RequestCompletion(queryTempFile.FilePath, query, 0, 10)));
|
||||
queryTask = testHelper.RunQuery(queryTempFile.FilePath, query);
|
||||
tasks.Add(queryTask);
|
||||
await Task.WhenAll(tasks);
|
||||
|
||||
Assert.NotNull(queryTask.Result);
|
||||
Assert.NotNull(queryTask.Result.BatchSummaries);
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ using Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
{
|
||||
public class StressTests : TestBase
|
||||
public class StressTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Simulate typing by a user to stress test the language service
|
||||
@@ -21,24 +21,24 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
//[Fact]
|
||||
public async Task TestLanguageService()
|
||||
{
|
||||
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 ";
|
||||
var ownerUri = System.IO.Path.GetTempFileName();
|
||||
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 ";
|
||||
|
||||
try
|
||||
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
// Connect
|
||||
bool connected = await Connect(ownerUri, ConnectionTestUtils.LocalhostConnection);
|
||||
Assert.True(connected, "Connection is successful");
|
||||
bool connected = await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.LocalhostConnection);
|
||||
Assert.True(connected, "Connection was not successful");
|
||||
|
||||
Thread.Sleep(10000); // Wait for intellisense to warm up
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
{
|
||||
for (int i = 0; i < textToType.Length; i++)
|
||||
{
|
||||
System.IO.File.WriteAllText(ownerUri, textToType.Substring(0, i + 1));
|
||||
System.IO.File.WriteAllText(queryTempFile.FilePath, textToType.Substring(0, i + 1));
|
||||
|
||||
var contentChanges = new TextDocumentChangeEvent[1];
|
||||
contentChanges[0] = new TextDocumentChangeEvent()
|
||||
@@ -78,30 +78,30 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
TextDocument = new VersionedTextDocumentIdentifier()
|
||||
{
|
||||
Version = ++version,
|
||||
Uri = ownerUri
|
||||
Uri = queryTempFile.FilePath
|
||||
}
|
||||
};
|
||||
|
||||
await RequestChangeTextDocumentNotification(changeParams);
|
||||
await testHelper.RequestChangeTextDocumentNotification(changeParams);
|
||||
|
||||
Thread.Sleep(50);
|
||||
|
||||
// If we just typed a space, request/resolve completion
|
||||
if (textToType[i] == ' ')
|
||||
{
|
||||
var completions = await RequestCompletion(ownerUri, textToType.Substring(0, i + 1), 0, i + 1);
|
||||
Assert.True(completions != null && completions.Length > 0, "Completion items list is not null and not empty");
|
||||
var completions = await testHelper.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 RequestResolveCompletion(completions[0]);
|
||||
var item = await testHelper.RequestResolveCompletion(completions[0]);
|
||||
|
||||
Assert.NotNull(item);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the text document
|
||||
System.IO.File.WriteAllText(ownerUri, "");
|
||||
System.IO.File.WriteAllText(queryTempFile.FilePath, "");
|
||||
|
||||
var contentChanges2 = new TextDocumentChangeEvent[1];
|
||||
contentChanges2[0] = new TextDocumentChangeEvent()
|
||||
@@ -129,23 +129,14 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
TextDocument = new VersionedTextDocumentIdentifier()
|
||||
{
|
||||
Version = ++version,
|
||||
Uri = ownerUri
|
||||
Uri = queryTempFile.FilePath
|
||||
}
|
||||
};
|
||||
|
||||
await RequestChangeTextDocumentNotification(changeParams2);
|
||||
await testHelper.RequestChangeTextDocumentNotification(changeParams2);
|
||||
}
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
System.IO.File.Delete(ownerUri);
|
||||
}
|
||||
catch {}
|
||||
WaitForExit();
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,13 +146,16 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
//[Fact]
|
||||
public async Task TestQueryExecutionService()
|
||||
{
|
||||
string queryToRun = "SELECT * FROM sys.all_objects GO SELECT * FROM sys.objects GO SELECT * FROM sys.tables GO SELECT COUNT(*) FROM sys.objects";
|
||||
var ownerUri = System.IO.Path.GetTempFileName();
|
||||
const string queryToRun = "SELECT * FROM sys.all_objects GO " +
|
||||
"SELECT * FROM sys.objects GO " +
|
||||
"SELECT * FROM sys.tables GO " +
|
||||
"SELECT COUNT(*) FROM sys.objects";
|
||||
|
||||
try
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
// Connect
|
||||
bool connected = await Connect(ownerUri, ConnectionTestUtils.LocalhostConnection);
|
||||
bool connected = await testHelper.Connect(queryTempFile.FilePath, ConnectionTestUtils.LocalhostConnection);
|
||||
Assert.True(connected, "Connection is successful");
|
||||
|
||||
// Run queries repeatedly
|
||||
@@ -169,7 +163,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
stopwatch.Start();
|
||||
while (stopwatch.Elapsed < TimeSpan.FromMinutes(60))
|
||||
{
|
||||
var queryResult = await RunQuery(ownerUri, queryToRun, 10000);
|
||||
var queryResult = await testHelper.RunQuery(queryTempFile.FilePath, queryToRun, 10000);
|
||||
|
||||
Assert.NotNull(queryResult);
|
||||
Assert.NotNull(queryResult.BatchSummaries);
|
||||
@@ -179,24 +173,15 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
Assert.NotNull(queryResult.BatchSummaries[2].ResultSetSummaries);
|
||||
Assert.NotNull(queryResult.BatchSummaries[3].ResultSetSummaries);
|
||||
|
||||
Assert.NotNull(await ExecuteSubset(ownerUri, 0, 0, 0, 7));
|
||||
Assert.NotNull(await ExecuteSubset(ownerUri, 1, 0, 0, 7));
|
||||
Assert.NotNull(await ExecuteSubset(ownerUri, 2, 0, 0, 7));
|
||||
Assert.NotNull(await ExecuteSubset(ownerUri, 3, 0, 0, 1));
|
||||
Assert.NotNull(await testHelper.ExecuteSubset(queryTempFile.FilePath, 0, 0, 0, 7));
|
||||
Assert.NotNull(await testHelper.ExecuteSubset(queryTempFile.FilePath, 1, 0, 0, 7));
|
||||
Assert.NotNull(await testHelper.ExecuteSubset(queryTempFile.FilePath, 2, 0, 0, 7));
|
||||
Assert.NotNull(await testHelper.ExecuteSubset(queryTempFile.FilePath, 3, 0, 0, 1));
|
||||
|
||||
Thread.Sleep(500);
|
||||
}
|
||||
|
||||
await Disconnect(ownerUri);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
System.IO.File.Delete(ownerUri);
|
||||
}
|
||||
catch {}
|
||||
WaitForExit();
|
||||
await testHelper.Disconnect(queryTempFile.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +196,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
var connection = ConnectionTestUtils.LocalhostConnection;
|
||||
connection.Connection.Pooling = false;
|
||||
|
||||
try
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
// Connect/disconnect repeatedly
|
||||
Stopwatch stopwatch = new Stopwatch();
|
||||
@@ -219,18 +204,14 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
while (stopwatch.Elapsed < TimeSpan.FromMinutes(60))
|
||||
{
|
||||
// Connect
|
||||
bool connected = await Connect(ownerUri, connection);
|
||||
bool connected = await testHelper.Connect(ownerUri, connection);
|
||||
Assert.True(connected, "Connection is successful");
|
||||
|
||||
// Disconnect
|
||||
bool disconnected = await Disconnect(ownerUri);
|
||||
bool disconnected = await testHelper.Disconnect(ownerUri);
|
||||
Assert.True(disconnected, "Disconnect is successful");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
|
||||
@@ -21,11 +20,11 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Base class for all test suites run by the test driver
|
||||
/// </summary>
|
||||
public class TestBase : IDisposable
|
||||
public sealed class TestHelper : IDisposable
|
||||
{
|
||||
private bool isRunning = false;
|
||||
|
||||
public TestBase()
|
||||
public TestHelper()
|
||||
{
|
||||
Driver = new ServiceTestDriver();
|
||||
Driver.Start().Wait();
|
||||
@@ -44,21 +43,13 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
{
|
||||
try
|
||||
{
|
||||
this.isRunning = false;
|
||||
|
||||
if (!Driver.IsCoverageRun)
|
||||
{
|
||||
Driver.Stop().Wait();
|
||||
}
|
||||
else
|
||||
{
|
||||
var p = Process.Start("taskkill", "/IM Microsoft.SqlTools.ServiceLayer.exe /F");
|
||||
p.WaitForExit();
|
||||
Driver.ServiceProcess?.WaitForExit();
|
||||
}
|
||||
this.isRunning = false;
|
||||
Driver.Stop().Wait();
|
||||
Console.WriteLine("Successfully killed process.");
|
||||
}
|
||||
catch
|
||||
{
|
||||
catch(Exception e)
|
||||
{
|
||||
Console.WriteLine($"Exception while waiting for service exit: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +68,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// Request a new connection to be created
|
||||
/// </summary>
|
||||
/// <returns>True if the connection completed successfully</returns>
|
||||
protected async Task<bool> Connect(string ownerUri, ConnectParams connectParams, int timeout = 15000)
|
||||
public async Task<bool> Connect(string ownerUri, ConnectParams connectParams, int timeout = 15000)
|
||||
{
|
||||
connectParams.OwnerUri = ownerUri;
|
||||
var connectResult = await Driver.SendRequest(ConnectionRequest.Type, connectParams);
|
||||
@@ -95,7 +86,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Request a disconnect
|
||||
/// </summary>
|
||||
protected async Task<bool> Disconnect(string ownerUri)
|
||||
public async Task<bool> Disconnect(string ownerUri)
|
||||
{
|
||||
var disconnectParams = new DisconnectParams();
|
||||
disconnectParams.OwnerUri = ownerUri;
|
||||
@@ -107,7 +98,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Request a cancel connect
|
||||
/// </summary>
|
||||
protected async Task<bool> CancelConnect(string ownerUri)
|
||||
public async Task<bool> CancelConnect(string ownerUri)
|
||||
{
|
||||
var cancelParams = new CancelConnectParams();
|
||||
cancelParams.OwnerUri = ownerUri;
|
||||
@@ -118,7 +109,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Request a cancel connect
|
||||
/// </summary>
|
||||
protected async Task<ListDatabasesResponse> ListDatabases(string ownerUri)
|
||||
public async Task<ListDatabasesResponse> ListDatabases(string ownerUri)
|
||||
{
|
||||
var listParams = new ListDatabasesParams();
|
||||
listParams.OwnerUri = ownerUri;
|
||||
@@ -129,7 +120,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Request the active SQL script is parsed for errors
|
||||
/// </summary>
|
||||
protected async Task<QueryExecuteSubsetResult> RequestQueryExecuteSubset(QueryExecuteSubsetParams subsetParams)
|
||||
public async Task<QueryExecuteSubsetResult> RequestQueryExecuteSubset(QueryExecuteSubsetParams subsetParams)
|
||||
{
|
||||
return await Driver.SendRequest(QueryExecuteSubsetRequest.Type, subsetParams);
|
||||
}
|
||||
@@ -137,7 +128,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Request the active SQL script is parsed for errors
|
||||
/// </summary>
|
||||
protected async Task RequestOpenDocumentNotification(DidOpenTextDocumentNotification openParams)
|
||||
public async Task RequestOpenDocumentNotification(DidOpenTextDocumentNotification openParams)
|
||||
{
|
||||
await Driver.SendEvent(DidOpenTextDocumentNotification.Type, openParams);
|
||||
}
|
||||
@@ -145,7 +136,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Request a configuration change notification
|
||||
/// </summary>
|
||||
protected async Task RequestChangeConfigurationNotification(DidChangeConfigurationParams<SqlToolsSettings> configParams)
|
||||
public async Task RequestChangeConfigurationNotification(DidChangeConfigurationParams<SqlToolsSettings> configParams)
|
||||
{
|
||||
await Driver.SendEvent(DidChangeConfigurationNotification<SqlToolsSettings>.Type, configParams);
|
||||
}
|
||||
@@ -153,7 +144,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// /// Request the active SQL script is parsed for errors
|
||||
/// </summary>
|
||||
protected async Task RequestChangeTextDocumentNotification(DidChangeTextDocumentParams changeParams)
|
||||
public async Task RequestChangeTextDocumentNotification(DidChangeTextDocumentParams changeParams)
|
||||
{
|
||||
await Driver.SendEvent(DidChangeTextDocumentNotification.Type, changeParams);
|
||||
}
|
||||
@@ -161,7 +152,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Request completion item resolve to look-up additional info
|
||||
/// </summary>
|
||||
protected async Task<CompletionItem> RequestResolveCompletion(CompletionItem item)
|
||||
public async Task<CompletionItem> RequestResolveCompletion(CompletionItem item)
|
||||
{
|
||||
var result = await Driver.SendRequest(CompletionResolveRequest.Type, item);
|
||||
return result;
|
||||
@@ -170,7 +161,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Request a Read Credential for given credential id
|
||||
/// </summary>
|
||||
protected async Task<Credential> ReadCredential(string credentialId)
|
||||
public async Task<Credential> ReadCredential(string credentialId)
|
||||
{
|
||||
var credentialParams = new Credential();
|
||||
credentialParams.CredentialId = credentialId;
|
||||
@@ -181,7 +172,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Returns database connection parameters for given server type
|
||||
/// </summary>
|
||||
protected async Task<ConnectParams> GetDatabaseConnectionAsync(TestServerType serverType)
|
||||
public async Task<ConnectParams> GetDatabaseConnectionAsync(TestServerType serverType)
|
||||
{
|
||||
ConnectionProfile connectionProfile = null;
|
||||
TestServerIdentity serverIdentiry = ConnectionTestUtils.TestServers.FirstOrDefault(x => x.ServerType == serverType);
|
||||
@@ -212,7 +203,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Request a list of completion items for a position in a block of text
|
||||
/// </summary>
|
||||
protected async Task<CompletionItem[]> RequestCompletion(string ownerUri, string text, int line, int character)
|
||||
public async Task<CompletionItem[]> RequestCompletion(string ownerUri, string text, int line, int character)
|
||||
{
|
||||
// Write the text to a backing file
|
||||
lock (fileLock)
|
||||
@@ -234,7 +225,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Request a a hover tooltop
|
||||
/// </summary>
|
||||
protected async Task<Hover> RequestHover(string ownerUri, string text, int line, int character)
|
||||
public async Task<Hover> RequestHover(string ownerUri, string text, int line, int character)
|
||||
{
|
||||
// Write the text to a backing file
|
||||
lock (fileLock)
|
||||
@@ -242,12 +233,15 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
System.IO.File.WriteAllText(ownerUri, text);
|
||||
}
|
||||
|
||||
var completionParams = new TextDocumentPosition();
|
||||
completionParams.TextDocument = new TextDocumentIdentifier();
|
||||
completionParams.TextDocument.Uri = ownerUri;
|
||||
completionParams.Position = new Position();
|
||||
completionParams.Position.Line = line;
|
||||
completionParams.Position.Character = character;
|
||||
var completionParams = new TextDocumentPosition
|
||||
{
|
||||
TextDocument = new TextDocumentIdentifier {Uri = ownerUri},
|
||||
Position = new Position
|
||||
{
|
||||
Line = line,
|
||||
Character = character
|
||||
}
|
||||
};
|
||||
|
||||
var result = await Driver.SendRequest(HoverRequest.Type, completionParams);
|
||||
return result;
|
||||
@@ -256,14 +250,16 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Run a query using a given connection bound to a URI
|
||||
/// </summary>
|
||||
protected async Task<QueryExecuteCompleteParams> RunQuery(string ownerUri, string query, int timeoutMilliseconds = 5000)
|
||||
public async Task<QueryExecuteCompleteParams> RunQuery(string ownerUri, string query, int timeoutMilliseconds = 5000)
|
||||
{
|
||||
// Write the query text to a backing file
|
||||
WriteToFile(ownerUri, query);
|
||||
|
||||
var queryParams = new QueryExecuteParams();
|
||||
queryParams.OwnerUri = ownerUri;
|
||||
queryParams.QuerySelection = null;
|
||||
var queryParams = new QueryExecuteParams
|
||||
{
|
||||
OwnerUri = ownerUri,
|
||||
QuerySelection = null
|
||||
};
|
||||
|
||||
var result = await Driver.SendRequest(QueryExecuteRequest.Type, queryParams);
|
||||
if (result != null && string.IsNullOrEmpty(result.Messages))
|
||||
@@ -280,10 +276,9 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Request to cancel an executing query
|
||||
/// </summary>
|
||||
protected async Task<QueryCancelResult> CancelQuery(string ownerUri)
|
||||
public async Task<QueryCancelResult> CancelQuery(string ownerUri)
|
||||
{
|
||||
var cancelParams = new QueryCancelParams();
|
||||
cancelParams.OwnerUri = ownerUri;
|
||||
var cancelParams = new QueryCancelParams {OwnerUri = ownerUri};
|
||||
|
||||
var result = await Driver.SendRequest(QueryCancelRequest.Type, cancelParams);
|
||||
return result;
|
||||
@@ -292,14 +287,16 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Request to save query results as CSV
|
||||
/// </summary>
|
||||
protected async Task<SaveResultRequestResult> SaveAsCsv(string ownerUri, string filename, int batchIndex, int resultSetIndex)
|
||||
public async Task<SaveResultRequestResult> SaveAsCsv(string ownerUri, string filename, int batchIndex, int resultSetIndex)
|
||||
{
|
||||
var saveParams = new SaveResultsAsCsvRequestParams();
|
||||
saveParams.OwnerUri = ownerUri;
|
||||
saveParams.BatchIndex = batchIndex;
|
||||
saveParams.ResultSetIndex = resultSetIndex;
|
||||
saveParams.FilePath = filename;
|
||||
|
||||
var saveParams = new SaveResultsAsCsvRequestParams
|
||||
{
|
||||
OwnerUri = ownerUri,
|
||||
BatchIndex = batchIndex,
|
||||
ResultSetIndex = resultSetIndex,
|
||||
FilePath = filename
|
||||
};
|
||||
|
||||
var result = await Driver.SendRequest(SaveResultsAsCsvRequest.Type, saveParams);
|
||||
return result;
|
||||
}
|
||||
@@ -307,14 +304,16 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Request to save query results as JSON
|
||||
/// </summary>
|
||||
protected async Task<SaveResultRequestResult> SaveAsJson(string ownerUri, string filename, int batchIndex, int resultSetIndex)
|
||||
public async Task<SaveResultRequestResult> SaveAsJson(string ownerUri, string filename, int batchIndex, int resultSetIndex)
|
||||
{
|
||||
var saveParams = new SaveResultsAsJsonRequestParams();
|
||||
saveParams.OwnerUri = ownerUri;
|
||||
saveParams.BatchIndex = batchIndex;
|
||||
saveParams.ResultSetIndex = resultSetIndex;
|
||||
saveParams.FilePath = filename;
|
||||
|
||||
var saveParams = new SaveResultsAsJsonRequestParams
|
||||
{
|
||||
OwnerUri = ownerUri,
|
||||
BatchIndex = batchIndex,
|
||||
ResultSetIndex = resultSetIndex,
|
||||
FilePath = filename
|
||||
};
|
||||
|
||||
var result = await Driver.SendRequest(SaveResultsAsJsonRequest.Type, saveParams);
|
||||
return result;
|
||||
}
|
||||
@@ -322,7 +321,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Request a subset of results from a query
|
||||
/// </summary>
|
||||
protected async Task<QueryExecuteSubsetResult> ExecuteSubset(string ownerUri, int batchIndex, int resultSetIndex, int rowStartIndex, int rowCount)
|
||||
public async Task<QueryExecuteSubsetResult> ExecuteSubset(string ownerUri, int batchIndex, int resultSetIndex, int rowStartIndex, int rowCount)
|
||||
{
|
||||
var subsetParams = new QueryExecuteSubsetParams();
|
||||
subsetParams.OwnerUri = ownerUri;
|
||||
@@ -335,7 +334,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void WriteToFile(string ownerUri, string query)
|
||||
public void WriteToFile(string ownerUri, string query)
|
||||
{
|
||||
lock (fileLock)
|
||||
{
|
||||
@@ -13,7 +13,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
/// <summary>
|
||||
/// Language Service end-to-end integration tests
|
||||
/// </summary>
|
||||
public class WorkspaceTests : TestBase
|
||||
public class WorkspaceTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Validate workspace lifecycle events
|
||||
@@ -21,7 +21,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
[Fact]
|
||||
public async Task InitializeRequestTest()
|
||||
{
|
||||
try
|
||||
using (TestHelper testHelper = new TestHelper())
|
||||
{
|
||||
InitializeRequest initializeRequest = new InitializeRequest()
|
||||
{
|
||||
@@ -29,13 +29,9 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
||||
Capabilities = new ClientCapabilities()
|
||||
};
|
||||
|
||||
InitializeResult result = await Driver.SendRequest(InitializeRequest.Type, initializeRequest);
|
||||
InitializeResult result = await testHelper.Driver.SendRequest(InitializeRequest.Type, initializeRequest);
|
||||
Assert.NotNull(result);
|
||||
}
|
||||
finally
|
||||
{
|
||||
WaitForExit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// 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.IO;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Utility
|
||||
{
|
||||
public class SelfCleaningTempFile : IDisposable
|
||||
{
|
||||
private bool disposed;
|
||||
|
||||
public SelfCleaningTempFile()
|
||||
{
|
||||
FilePath = Path.GetTempFileName();
|
||||
}
|
||||
|
||||
public string FilePath { get; private set; }
|
||||
|
||||
#region IDisposable Implementation
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposed && disposing)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Delete(FilePath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine($"Failed to cleanup {FilePath}");
|
||||
}
|
||||
}
|
||||
|
||||
disposed = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// 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 Xunit;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Utility
|
||||
{
|
||||
public class TestRunner
|
||||
{
|
||||
public static async Task<int> RunTests(string[] tests, string testNamespace)
|
||||
{
|
||||
foreach (var test in tests)
|
||||
{
|
||||
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());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static async Task RunTest(Type type, MethodBase 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user