Files
sqltoolsservice/test/Microsoft.SqlTools.ServiceLayer.Test/LanguageServer/LanguageServiceTests.cs
Benjamin Russell db1e4ae351 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
2016-11-18 17:46:56 -08:00

217 lines
7.7 KiB
C#

//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.LanguageServices;
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
using Microsoft.SqlTools.Test.Utility;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServer
{
/// <summary>
/// Tests for the ServiceHost Language Service tests
/// </summary>
public class LanguageServiceTests
{
#region "Diagnostics tests"
/// <summary>
/// Verify that the latest SqlParser (2016 as of this writing) is used by default
/// </summary>
[Fact]
public void LatestSqlParserIsUsedByDefault()
{
// This should only parse correctly on SQL server 2016 or newer
const string sql2016Text =
@"CREATE SECURITY POLICY [FederatedSecurityPolicy]" + "\r\n" +
@"ADD FILTER PREDICATE [rls].[fn_securitypredicate]([CustomerId])" + "\r\n" +
@"ON [dbo].[Customer];";
LanguageService service = TestObjects.GetTestLanguageService();
// parse
var scriptFile = new ScriptFile();
scriptFile.SetFileContents(sql2016Text);
ScriptFileMarker[] fileMarkers = service.GetSemanticMarkers(scriptFile);
// verify that no errors are detected
Assert.Equal(0, fileMarkers.Length);
}
/// <summary>
/// Verify that the SQL parser correctly detects errors in text
/// </summary>
[Fact]
public void ParseSelectStatementWithoutErrors()
{
// sql statement with no errors
const string sqlWithErrors = "SELECT * FROM sys.objects";
// get the test service
LanguageService service = TestObjects.GetTestLanguageService();
// parse the sql statement
var scriptFile = new ScriptFile();
scriptFile.SetFileContents(sqlWithErrors);
ScriptFileMarker[] fileMarkers = service.GetSemanticMarkers(scriptFile);
// verify there are no errors
Assert.Equal(0, fileMarkers.Length);
}
/// <summary>
/// Verify that the SQL parser correctly detects errors in text
/// </summary>
[Fact]
public void ParseSelectStatementWithError()
{
// sql statement with errors
const string sqlWithErrors = "SELECT *** FROM sys.objects";
// get test service
LanguageService service = TestObjects.GetTestLanguageService();
// parse sql statement
var scriptFile = new ScriptFile();
scriptFile.SetFileContents(sqlWithErrors);
ScriptFileMarker[] fileMarkers = service.GetSemanticMarkers(scriptFile);
// verify there is one error
Assert.Equal(1, fileMarkers.Length);
// verify the position of the error
Assert.Equal(9, fileMarkers[0].ScriptRegion.StartColumnNumber);
Assert.Equal(1, fileMarkers[0].ScriptRegion.StartLineNumber);
Assert.Equal(10, fileMarkers[0].ScriptRegion.EndColumnNumber);
Assert.Equal(1, fileMarkers[0].ScriptRegion.EndLineNumber);
}
/// <summary>
/// Verify that the SQL parser correctly detects errors in text
/// </summary>
[Fact]
public void ParseMultilineSqlWithErrors()
{
// multiline sql with errors
const string sqlWithErrors =
"SELECT *** FROM sys.objects;\n" +
"GO\n" +
"SELECT *** FROM sys.objects;\n";
// get test service
LanguageService service = TestObjects.GetTestLanguageService();
// parse sql
var scriptFile = new ScriptFile();
scriptFile.SetFileContents(sqlWithErrors);
ScriptFileMarker[] fileMarkers = service.GetSemanticMarkers(scriptFile);
// verify there are two errors
Assert.Equal(2, fileMarkers.Length);
// check position of first error
Assert.Equal(9, fileMarkers[0].ScriptRegion.StartColumnNumber);
Assert.Equal(1, fileMarkers[0].ScriptRegion.StartLineNumber);
Assert.Equal(10, fileMarkers[0].ScriptRegion.EndColumnNumber);
Assert.Equal(1, fileMarkers[0].ScriptRegion.EndLineNumber);
// check position of second error
Assert.Equal(9, fileMarkers[1].ScriptRegion.StartColumnNumber);
Assert.Equal(3, fileMarkers[1].ScriptRegion.StartLineNumber);
Assert.Equal(10, fileMarkers[1].ScriptRegion.EndColumnNumber);
Assert.Equal(3, fileMarkers[1].ScriptRegion.EndLineNumber);
}
#endregion
#region "General Language Service tests"
#if LIVE_CONNECTION_TESTS
private static void GetLiveAutoCompleteTestObjects(
out TextDocumentPosition textDocument,
out ScriptFile scriptFile,
out ConnectionInfo connInfo)
{
textDocument = new TextDocumentPosition
{
TextDocument = new TextDocumentIdentifier {Uri = TestObjects.ScriptUri},
Position = new Position
{
Line = 0,
Character = 0
}
};
connInfo = TestObjects.InitLiveConnectionInfo(out scriptFile);
}
/// <summary>
/// Test the service initialization code path and verify nothing throws
/// </summary>
// Test is causing failures in build lab..investigating to reenable
[Fact]
public void ServiceInitialization()
{
try
{
TestObjects.InitializeTestServices();
}
catch (System.ArgumentException)
{
}
Assert.True(LanguageService.Instance.Context != null);
Assert.True(LanguageService.ConnectionServiceInstance != null);
Assert.True(LanguageService.Instance.CurrentSettings != null);
Assert.True(LanguageService.Instance.CurrentWorkspace != null);
}
/// <summary>
/// Test the service initialization code path and verify nothing throws
/// </summary>
// Test is causing failures in build lab..investigating to reenable
[Fact]
public void PrepopulateCommonMetadata()
{
ScriptFile scriptFile;
ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfo(out scriptFile);
ScriptParseInfo scriptInfo = new ScriptParseInfo {IsConnected = true};
AutoCompleteHelper.PrepopulateCommonMetadata(connInfo, scriptInfo, null);
}
// This test currently requires a live database connection to initialize
// SMO connected metadata provider. Since we don't want a live DB dependency
// in the CI unit tests this scenario is currently disabled.
[Fact]
public void AutoCompleteFindCompletions()
{
TextDocumentPosition textDocument;
ConnectionInfo connInfo;
ScriptFile scriptFile;
GetLiveAutoCompleteTestObjects(out textDocument, out scriptFile, out connInfo);
textDocument.Position.Character = 7;
scriptFile.Contents = "select ";
var autoCompleteService = LanguageService.Instance;
var completions = autoCompleteService.GetCompletionItems(
textDocument,
scriptFile,
connInfo);
Assert.True(completions.Length > 0);
}
#endif
#endregion
}
}