New tool to store SQL connection configs locally (#218)

* added a new tool to store SQL connections locally. Modified the peek definition tests to create test database before running test


* fixed failing test QueryExecutionPlanInvalidParamsTest

* Fixes based on code review comments

* fixed failing test GetSignatureHelpReturnsNotNullIfParseInfoInitialized
This commit is contained in:
Leila Lali
2017-01-25 16:19:27 -08:00
committed by GitHub
parent 5464e4e63a
commit dcff5dd915
30 changed files with 1176 additions and 575 deletions

4
.gitignore vendored
View File

@@ -289,4 +289,6 @@ metadata
# Stuff from cake # Stuff from cake
/artifacts/ /artifacts/
/.tools/ /.tools/
/.dotnet/ /.dotnet/
/test/Microsoft.SqlTools.ServiceLayer.TestEnvConfig/Properties/launchSettings.json
/test/Microsoft.SqlTools.ServiceLayer.PerfTests/Properties/launchSettings.json

View File

@@ -59,6 +59,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.SqlTools.ServiceL
EndProject EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.SqlTools.ServiceLayer.TestDriver.Tests", "test\Microsoft.SqlTools.ServiceLayer.TestDriver.Tests\Microsoft.SqlTools.ServiceLayer.TestDriver.Tests.xproj", "{E7CF630E-E084-4DA4-BF69-F61BF0A8F5BE}" Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.SqlTools.ServiceLayer.TestDriver.Tests", "test\Microsoft.SqlTools.ServiceLayer.TestDriver.Tests\Microsoft.SqlTools.ServiceLayer.TestDriver.Tests.xproj", "{E7CF630E-E084-4DA4-BF69-F61BF0A8F5BE}"
EndProject EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.SqlTools.ServiceLayer.TestEnvConfig", "test\Microsoft.SqlTools.ServiceLayer.TestEnvConfig\Microsoft.SqlTools.ServiceLayer.TestEnvConfig.xproj", "{6CF2E945-C7D1-44B5-9E28-ADDD09E3E983}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -108,6 +110,12 @@ Global
{E7CF630E-E084-4DA4-BF69-F61BF0A8F5BE}.Integration|Any CPU.Build.0 = Debug|Any CPU {E7CF630E-E084-4DA4-BF69-F61BF0A8F5BE}.Integration|Any CPU.Build.0 = Debug|Any CPU
{E7CF630E-E084-4DA4-BF69-F61BF0A8F5BE}.Release|Any CPU.ActiveCfg = Release|Any CPU {E7CF630E-E084-4DA4-BF69-F61BF0A8F5BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E7CF630E-E084-4DA4-BF69-F61BF0A8F5BE}.Release|Any CPU.Build.0 = Release|Any CPU {E7CF630E-E084-4DA4-BF69-F61BF0A8F5BE}.Release|Any CPU.Build.0 = Release|Any CPU
{6CF2E945-C7D1-44B5-9E28-ADDD09E3E983}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6CF2E945-C7D1-44B5-9E28-ADDD09E3E983}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6CF2E945-C7D1-44B5-9E28-ADDD09E3E983}.Integration|Any CPU.ActiveCfg = Debug|Any CPU
{6CF2E945-C7D1-44B5-9E28-ADDD09E3E983}.Integration|Any CPU.Build.0 = Debug|Any CPU
{6CF2E945-C7D1-44B5-9E28-ADDD09E3E983}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6CF2E945-C7D1-44B5-9E28-ADDD09E3E983}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -122,5 +130,6 @@ Global
{08AF0209-D598-47BB-9DFD-FC9E74C0FE56} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} {08AF0209-D598-47BB-9DFD-FC9E74C0FE56} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4}
{B6F4BECE-82EE-4AB6-99AC-108AEE466274} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} {B6F4BECE-82EE-4AB6-99AC-108AEE466274} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4}
{E7CF630E-E084-4DA4-BF69-F61BF0A8F5BE} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4} {E7CF630E-E084-4DA4-BF69-F61BF0A8F5BE} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4}
{6CF2E945-C7D1-44B5-9E28-ADDD09E3E983} = {AB9CA2B8-6F70-431C-8A1D-67479D8A7BE4}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@@ -105,18 +105,23 @@ namespace Microsoft.SqlTools.ServiceLayer.Credentials
{ {
return await Task.Factory.StartNew(() => return await Task.Factory.StartNew(() =>
{ {
Credential.ValidateForLookup(credential); return ReadCredential(credential);
Credential result = Credential.Copy(credential);
string password;
if (credStore.TryGetPassword(credential.CredentialId, out password))
{
result.Password = password;
}
return result;
}); });
} }
public Credential ReadCredential(Credential credential)
{
Credential.ValidateForLookup(credential);
Credential result = Credential.Copy(credential);
string password;
if (credStore.TryGetPassword(credential.CredentialId, out password))
{
result.Password = password;
}
return result;
}
public async Task HandleSaveCredentialRequest(Credential credential, RequestContext<bool> requestContext) public async Task HandleSaveCredentialRequest(Credential credential, RequestContext<bool> requestContext)
{ {
Func<Task<bool>> doSave = () => Func<Task<bool>> doSave = () =>
@@ -126,15 +131,20 @@ namespace Microsoft.SqlTools.ServiceLayer.Credentials
await HandleRequest(doSave, requestContext, "HandleSaveCredentialRequest"); await HandleRequest(doSave, requestContext, "HandleSaveCredentialRequest");
} }
private async Task<bool> SaveCredentialAsync(Credential credential) public async Task<bool> SaveCredentialAsync(Credential credential)
{ {
return await Task.Factory.StartNew(() => return await Task.Factory.StartNew(() =>
{ {
Credential.ValidateForSave(credential); return SaveCredential(credential);
return credStore.Save(credential);
}); });
} }
public bool SaveCredential(Credential credential)
{
Credential.ValidateForSave(credential);
return credStore.Save(credential);
}
public async Task HandleDeleteCredentialRequest(Credential credential, RequestContext<bool> requestContext) public async Task HandleDeleteCredentialRequest(Credential credential, RequestContext<bool> requestContext)
{ {
Func<Task<bool>> doDelete = () => Func<Task<bool>> doDelete = () =>

View File

@@ -23,14 +23,14 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
public class ConnectionServiceTests public class ConnectionServiceTests
{ {
[Fact] [Fact]
public async Task RunningMultipleQueriesCreatesOnlyOneConnection() public void RunningMultipleQueriesCreatesOnlyOneConnection()
{ {
// Connect/disconnect twice to ensure reconnection can occur // Connect/disconnect twice to ensure reconnection can occur
ConnectionService service = ConnectionService.Instance; ConnectionService service = ConnectionService.Instance;
service.OwnerToConnectionMap.Clear(); service.OwnerToConnectionMap.Clear();
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
var result = await TestObjects.InitLiveConnectionInfo(); var result = TestObjects.InitLiveConnectionInfo();
ConnectionInfo connectionInfo = result.ConnectionInfo; ConnectionInfo connectionInfo = result.ConnectionInfo;
string uri = connectionInfo.OwnerUri; string uri = connectionInfo.OwnerUri;
@@ -65,11 +65,11 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
} }
[Fact] [Fact]
public async Task DatabaseChangesAffectAllConnections() public void DatabaseChangesAffectAllConnections()
{ {
// If we make a connection to a live database // If we make a connection to a live database
ConnectionService service = ConnectionService.Instance; ConnectionService service = ConnectionService.Instance;
var result = await TestObjects.InitLiveConnectionInfo(); var result = TestObjects.InitLiveConnectionInfo();
ConnectionInfo connectionInfo = result.ConnectionInfo; ConnectionInfo connectionInfo = result.ConnectionInfo;
ConnectionDetails details = connectionInfo.ConnectionDetails; ConnectionDetails details = connectionInfo.ConnectionDetails;
string uri = connectionInfo.OwnerUri; string uri = connectionInfo.OwnerUri;

View File

@@ -33,8 +33,6 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
/// </summary> /// </summary>
public class ReliableConnectionTests public class ReliableConnectionTests
{ {
private TestConnectionProfileService connectionProfileService = new TestConnectionProfileService();
internal class TestDataTransferErrorDetectionStrategy : DataTransferErrorDetectionStrategy internal class TestDataTransferErrorDetectionStrategy : DataTransferErrorDetectionStrategy
{ {
public bool InvokeCanRetrySqlException(SqlException exception) public bool InvokeCanRetrySqlException(SqlException exception)
@@ -235,9 +233,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
/// <summary> /// <summary>
/// Helper method to create an integrated auth connection builder for testing. /// Helper method to create an integrated auth connection builder for testing.
/// </summary> /// </summary>
private async Task<SqlConnectionStringBuilder> CreateTestConnectionStringBuilder() private SqlConnectionStringBuilder CreateTestConnectionStringBuilder()
{ {
ConnectParams connectParams = await this.connectionProfileService.GetConnectionParametersAsync(); ConnectParams connectParams = TestConnectionProfileService.Instance.GetConnectionParameters(TestServerType.OnPrem);
SqlConnectionStringBuilder csb = new SqlConnectionStringBuilder(); SqlConnectionStringBuilder csb = new SqlConnectionStringBuilder();
csb.DataSource = connectParams.Connection.ServerName; csb.DataSource = connectParams.Connection.ServerName;
csb.IntegratedSecurity = connectParams.Connection.AuthenticationType == AuthenticationType.Integrated.ToString(); csb.IntegratedSecurity = connectParams.Connection.AuthenticationType == AuthenticationType.Integrated.ToString();
@@ -259,9 +257,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
/// <summary> /// <summary>
/// Helper method to create an integrated auth reliable connection for testing. /// Helper method to create an integrated auth reliable connection for testing.
/// </summary> /// </summary>
private async Task<DbConnection> CreateTestConnection() private DbConnection CreateTestConnection()
{ {
SqlConnectionStringBuilder csb = await CreateTestConnectionStringBuilder(); SqlConnectionStringBuilder csb = CreateTestConnectionStringBuilder();
RetryPolicy connectionRetryPolicy = RetryPolicyFactory.CreateDefaultConnectionRetryPolicy(); RetryPolicy connectionRetryPolicy = RetryPolicyFactory.CreateDefaultConnectionRetryPolicy();
RetryPolicy commandRetryPolicy = RetryPolicyFactory.CreateDefaultConnectionRetryPolicy(); RetryPolicy commandRetryPolicy = RetryPolicyFactory.CreateDefaultConnectionRetryPolicy();
@@ -274,10 +272,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
/// Test ReliableConnectionHelper.GetDefaultDatabaseFilePath() /// Test ReliableConnectionHelper.GetDefaultDatabaseFilePath()
/// </summary> /// </summary>
[Fact] [Fact]
public async Task TestGetDefaultDatabaseFilePath() public void TestGetDefaultDatabaseFilePath()
{ {
var connectionBuilder = await CreateTestConnectionStringBuilder(); var connectionBuilder = CreateTestConnectionStringBuilder();
Assert.NotNull(connectionBuilder); Assert.NotNull(connectionBuilder);
string filePath = string.Empty; string filePath = string.Empty;
@@ -301,16 +299,16 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
/// Test ReliableConnectionHelper.GetServerVersion() /// Test ReliableConnectionHelper.GetServerVersion()
/// </summary> /// </summary>
[Fact] [Fact]
public async Task TestGetServerVersion() public void TestGetServerVersion()
{ {
using (var connection = await CreateTestConnection()) using (var connection = CreateTestConnection())
{ {
Assert.NotNull(connection); Assert.NotNull(connection);
connection.Open(); connection.Open();
ReliableConnectionHelper.ServerInfo serverInfo = ReliableConnectionHelper.GetServerVersion(connection); ReliableConnectionHelper.ServerInfo serverInfo = ReliableConnectionHelper.GetServerVersion(connection);
ReliableConnectionHelper.ServerInfo serverInfo2; ReliableConnectionHelper.ServerInfo serverInfo2;
using (var connection2 = await CreateTestConnection()) using (var connection2 = CreateTestConnection())
{ {
connection2.Open(); connection2.Open();
serverInfo2 = ReliableConnectionHelper.GetServerVersion(connection); serverInfo2 = ReliableConnectionHelper.GetServerVersion(connection);
@@ -346,9 +344,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
/// Tests ReliableConnectionHelper.IsDatabaseReadonly() /// Tests ReliableConnectionHelper.IsDatabaseReadonly()
/// </summary> /// </summary>
[Fact] [Fact]
public async Task TestIsDatabaseReadonly() public void TestIsDatabaseReadonly()
{ {
var connectionBuilder = await CreateTestConnectionStringBuilder(); var connectionBuilder = CreateTestConnectionStringBuilder();
Assert.NotNull(connectionBuilder); Assert.NotNull(connectionBuilder);
bool isReadOnly = ReliableConnectionHelper.IsDatabaseReadonly(connectionBuilder); bool isReadOnly = ReliableConnectionHelper.IsDatabaseReadonly(connectionBuilder);
@@ -368,9 +366,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
/// Verify ANSI_NULL and QUOTED_IDENTIFIER settings can be set and retrieved for a session /// Verify ANSI_NULL and QUOTED_IDENTIFIER settings can be set and retrieved for a session
/// </summary> /// </summary>
[Fact] [Fact]
public async Task VerifyAnsiNullAndQuotedIdentifierSettingsReplayed() public void VerifyAnsiNullAndQuotedIdentifierSettingsReplayed()
{ {
using (ReliableSqlConnection conn = (ReliableSqlConnection) ReliableConnectionHelper.OpenConnection(await CreateTestConnectionStringBuilder(), useRetry: true)) using (ReliableSqlConnection conn = (ReliableSqlConnection) ReliableConnectionHelper.OpenConnection(CreateTestConnectionStringBuilder(), useRetry: true))
{ {
VerifySessionSettings(conn, true); VerifySessionSettings(conn, true);
VerifySessionSettings(conn, false); VerifySessionSettings(conn, false);
@@ -477,9 +475,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
/// ReliableConnectionHelper.IsCloud() should be false for a local server /// ReliableConnectionHelper.IsCloud() should be false for a local server
/// </summary> /// </summary>
[Fact] [Fact]
public async Task TestIsCloudIsFalseForLocalServer() public void TestIsCloudIsFalseForLocalServer()
{ {
using (var connection = await CreateTestConnection()) using (var connection = CreateTestConnection())
{ {
Assert.NotNull(connection); Assert.NotNull(connection);
@@ -492,9 +490,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
/// Tests that ReliableConnectionHelper.OpenConnection() opens a connection if it is closed /// Tests that ReliableConnectionHelper.OpenConnection() opens a connection if it is closed
/// </summary> /// </summary>
[Fact] [Fact]
public async Task TestOpenConnectionOpensConnection() public void TestOpenConnectionOpensConnection()
{ {
using (var connection = await CreateTestConnection()) using (var connection = CreateTestConnection())
{ {
Assert.NotNull(connection); Assert.NotNull(connection);
@@ -508,10 +506,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
/// Tests that ReliableConnectionHelper.ExecuteNonQuery() runs successfully /// Tests that ReliableConnectionHelper.ExecuteNonQuery() runs successfully
/// </summary> /// </summary>
[Fact] [Fact]
public async Task TestExecuteNonQuery() public void TestExecuteNonQuery()
{ {
var result = ReliableConnectionHelper.ExecuteNonQuery( var result = ReliableConnectionHelper.ExecuteNonQuery(
await CreateTestConnectionStringBuilder(), CreateTestConnectionStringBuilder(),
"SET NOCOUNT ON; SET NOCOUNT OFF;", "SET NOCOUNT ON; SET NOCOUNT OFF;",
ReliableConnectionHelper.SetCommandTimeout, ReliableConnectionHelper.SetCommandTimeout,
null, null,
@@ -524,10 +522,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
/// Test that TryGetServerVersion() gets server information /// Test that TryGetServerVersion() gets server information
/// </summary> /// </summary>
[Fact] [Fact]
public async Task TestTryGetServerVersion() public void TestTryGetServerVersion()
{ {
ReliableConnectionHelper.ServerInfo info = null; ReliableConnectionHelper.ServerInfo info = null;
var connBuilder = await CreateTestConnectionStringBuilder(); var connBuilder = CreateTestConnectionStringBuilder();
Assert.True(ReliableConnectionHelper.TryGetServerVersion(connBuilder.ConnectionString, out info)); Assert.True(ReliableConnectionHelper.TryGetServerVersion(connBuilder.ConnectionString, out info));
Assert.NotNull(info); Assert.NotNull(info);
@@ -681,9 +679,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
} }
[Fact] [Fact]
public async Task ReliableConnectionHelperTest() public void ReliableConnectionHelperTest()
{ {
var result = await TestObjects.InitLiveConnectionInfo(); var result = TestObjects.InitLiveConnectionInfo();
ConnectionInfo connInfo = result.ConnectionInfo; ConnectionInfo connInfo = result.ConnectionInfo;
DbConnection connection = connInfo.ConnectionTypeToConnectionMap[ConnectionType.Default]; DbConnection connection = connInfo.ConnectionTypeToConnectionMap[ConnectionType.Default];
@@ -726,9 +724,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
} }
[Fact] [Fact]
public async Task InitReliableSqlConnectionTest() public void InitReliableSqlConnectionTest()
{ {
var result = await TestObjects.InitLiveConnectionInfo(); var result = TestObjects.InitLiveConnectionInfo();
ConnectionInfo connInfo = result.ConnectionInfo; ConnectionInfo connInfo = result.ConnectionInfo;
DbConnection dbConnection; DbConnection dbConnection;
connInfo.TryGetConnection(ConnectionType.Default, out dbConnection); connInfo.TryGetConnection(ConnectionType.Default, out dbConnection);

View File

@@ -3,6 +3,7 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
// //
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.SqlServer.Management.SqlParser.Parser; using Microsoft.SqlServer.Management.SqlParser.Parser;
using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Connection;
@@ -21,7 +22,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
/// </summary> /// </summary>
public class LanguageServiceTests public class LanguageServiceTests
{ {
private async static Task<TestConnectionResult> GetLiveAutoCompleteTestObjects() private TestConnectionResult GetLiveAutoCompleteTestObjects()
{ {
var textDocument = new TextDocumentPosition var textDocument = new TextDocumentPosition
{ {
@@ -33,7 +34,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
} }
}; };
var result = await TestObjects.InitLiveConnectionInfo(); var result = TestObjects.InitLiveConnectionInfo();
result.TextDocumentPosition = textDocument; result.TextDocumentPosition = textDocument;
return result; return result;
} }
@@ -46,7 +47,8 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
{ {
try try
{ {
TestServiceProvider.InitializeTestServices(); TestServiceProvider serviceProvider = TestServiceProvider.Instance;
Assert.NotNull(serviceProvider);
} }
catch (System.ArgumentException) catch (System.ArgumentException)
{ {
@@ -62,9 +64,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
/// Test the service initialization code path and verify nothing throws /// Test the service initialization code path and verify nothing throws
/// </summary> /// </summary>
[Fact] [Fact]
public async Task PrepopulateCommonMetadata() public void PrepopulateCommonMetadata()
{ {
var result = await TestObjects.InitLiveConnectionInfo(); var result = TestObjects.InitLiveConnectionInfo();
var connInfo = result.ConnectionInfo; var connInfo = result.ConnectionInfo;
ScriptParseInfo scriptInfo = new ScriptParseInfo { IsConnected = true }; ScriptParseInfo scriptInfo = new ScriptParseInfo { IsConnected = true };
@@ -76,9 +78,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
// SMO connected metadata provider. Since we don't want a live DB dependency // SMO connected metadata provider. Since we don't want a live DB dependency
// in the CI unit tests this scenario is currently disabled. // in the CI unit tests this scenario is currently disabled.
[Fact] [Fact]
public async Task AutoCompleteFindCompletions() public void AutoCompleteFindCompletions()
{ {
var result = await GetLiveAutoCompleteTestObjects(); var result = GetLiveAutoCompleteTestObjects();
result.TextDocumentPosition.Position.Character = 7; result.TextDocumentPosition.Position.Character = 7;
result.ScriptFile.Contents = "select "; result.ScriptFile.Contents = "select ";
@@ -102,7 +104,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
{ {
// When we make a connection to a live database // When we make a connection to a live database
Hosting.ServiceHost.SendEventIgnoreExceptions = true; Hosting.ServiceHost.SendEventIgnoreExceptions = true;
var result = await TestObjects.InitLiveConnectionInfo(); var result = TestObjects.InitLiveConnectionInfo();
// And we place the cursor after a function that should prompt for signature help // And we place the cursor after a function that should prompt for signature help
string queryWithFunction = "EXEC sys.fn_isrolemember "; string queryWithFunction = "EXEC sys.fn_isrolemember ";
@@ -123,6 +125,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
// If the SQL has already been parsed // If the SQL has already been parsed
var service = LanguageService.Instance; var service = LanguageService.Instance;
await service.UpdateLanguageServiceOnConnection(result.ConnectionInfo); await service.UpdateLanguageServiceOnConnection(result.ConnectionInfo);
Thread.Sleep(2000);
// We should get back a non-null ScriptParseInfo // We should get back a non-null ScriptParseInfo
ScriptParseInfo parseInfo = service.GetScriptParseInfo(result.ScriptFile.ClientFilePath); ScriptParseInfo parseInfo = service.GetScriptParseInfo(result.ScriptFile.ClientFilePath);

View File

@@ -5,22 +5,17 @@
using System; using System;
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using Microsoft.SqlServer.Management.Common; using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.SqlParser.Binder;
using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlServer.Management.SqlParser.MetadataProvider;
using Microsoft.SqlTools.ServiceLayer.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.LanguageServices; using Microsoft.SqlTools.ServiceLayer.LanguageServices;
using Microsoft.SqlTools.ServiceLayer.LanguageServices.Completion;
using Microsoft.SqlTools.ServiceLayer.SqlContext;
using Microsoft.SqlTools.ServiceLayer.Workspace;
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
using Microsoft.SqlTools.Test.Utility; using Microsoft.SqlTools.Test.Utility;
using Moq; using Moq;
using Xunit; using Xunit;
using Location = Microsoft.SqlTools.ServiceLayer.Workspace.Contracts.Location; using Location = Microsoft.SqlTools.ServiceLayer.Workspace.Contracts.Location;
using Microsoft.SqlServer.Management.SqlParser.Intellisense; using Microsoft.SqlServer.Management.SqlParser.Intellisense;
using Microsoft.SqlTools.ServiceLayer.Test.Common;
using static Microsoft.SqlTools.ServiceLayer.LanguageServices.PeekDefinition;
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
{ {
@@ -30,15 +25,66 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
public class PeekDefinitionTests public class PeekDefinitionTests
{ {
private const string OwnerUri = "testFile1"; private const string OwnerUri = "testFile1";
private const string ReturnTableFunctionName = "pd_returnTable";
private const string ReturnTableTableFunctionQuery = @"
CREATE FUNCTION [dbo].[" + ReturnTableFunctionName + @"] ()
RETURNS TABLE
AS
RETURN
(
select * from master.dbo.spt_monitor
);
GO";
private const string AddTwoFunctionName = "pd_addTwo";
private const string AddTwoFunctionQuery = @"
CREATE FUNCTION[dbo].[" + AddTwoFunctionName + @"](@number int)
RETURNS int
AS
BEGIN
RETURN @number + 2;
END;
GO";
private const string SsnTypeName = "pd_ssn";
private const string SsnTypeQuery = @"
CREATE TYPE [dbo].[" + SsnTypeName + @"] FROM [varchar](11) NOT NULL
GO";
private const string LocationTableTypeName = "pd_locationTableType";
private const string LocationTableTypeQuery = @"
CREATE TYPE [dbo].[" + LocationTableTypeName + @"] AS TABLE(
[LocationName] [varchar](50) NULL,
[CostRate] [int] NULL
)
GO";
private const string TestTableSynonymName = "pd_testTable";
private const string TestTableSynonymQuery = @"
CREATE SYNONYM [dbo].[pd_testTable] FOR master.dbo.spt_monitor
GO";
private const string TableValuedFunctionTypeName = "TableValuedFunction";
private const string ScalarValuedFunctionTypeName = "ScalarValuedFunction";
private const string UserDefinedDataTypeTypeName = "UserDefinedDataType";
private const string UserDefinedTableTypeTypeName = "UserDefinedTableType";
private const string SynonymTypeName = "Synonym";
private const string StoredProcedureTypeName = "StoredProcedure";
private const string ViewTypeName = "View";
private const string TableTypeName = "Table";
/// <summary> /// <summary>
/// Test get definition for a table object with active connection /// Test get definition for a table object with active connection
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetValidTableDefinitionTest() public void GetValidTableDefinitionTest()
{ {
// Get live connectionInfo and serverConnection // Get live connectionInfo and serverConnection
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition(); ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo); ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo); PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
@@ -57,10 +103,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Test get definition for a invalid table object with active connection /// Test get definition for a invalid table object with active connection
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetTableDefinitionInvalidObjectTest() public void GetTableDefinitionInvalidObjectTest()
{ {
// Get live connectionInfo and serverConnection // Get live connectionInfo and serverConnection
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition(); ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo); ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo); PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
@@ -77,10 +123,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Test get definition for a valid table object with schema and active connection /// Test get definition for a valid table object with schema and active connection
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetTableDefinitionWithSchemaTest() public void GetTableDefinitionWithSchemaTest()
{ {
// Get live connectionInfo and serverConnection // Get live connectionInfo and serverConnection
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition(); ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo); ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo); PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
@@ -99,7 +145,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Test GetDefinition with an unsupported type(schema - dbo). Expect a error result. /// Test GetDefinition with an unsupported type(schema - dbo). Expect a error result.
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetUnsupportedDefinitionErrorTest() public void GetUnsupportedDefinitionErrorTest()
{ {
TextDocumentPosition textDocument = new TextDocumentPosition TextDocumentPosition textDocument = new TextDocumentPosition
{ {
@@ -112,7 +158,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
} }
}; };
TestConnectionResult connectionResult = await TestObjects.InitLiveConnectionInfo(); TestConnectionResult connectionResult = TestObjects.InitLiveConnectionInfo();
connectionResult.ScriptFile.Contents = "select * from dbo.func ()"; connectionResult.ScriptFile.Contents = "select * from dbo.func ()";
var languageService = new LanguageService(); var languageService = new LanguageService();
ScriptParseInfo scriptInfo = new ScriptParseInfo { IsConnected = true }; ScriptParseInfo scriptInfo = new ScriptParseInfo { IsConnected = true };
@@ -130,9 +176,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Get Definition for a object with no definition. Expect a error result /// Get Definition for a object with no definition. Expect a error result
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetDefinitionWithNoResultsFoundError() public void GetDefinitionWithNoResultsFoundError()
{ {
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition(); ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo); ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo); PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
@@ -155,7 +201,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Test GetDefinition with a forced timeout. Expect a error result. /// Test GetDefinition with a forced timeout. Expect a error result.
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetDefinitionTimeoutTest() public void GetDefinitionTimeoutTest()
{ {
// Given a binding queue that will automatically time out // Given a binding queue that will automatically time out
var languageService = new LanguageService(); var languageService = new LanguageService();
@@ -175,10 +221,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
It.IsAny<int?>())) It.IsAny<int?>()))
.Callback<string, Func<IBindingContext, CancellationToken, object>, Func<IBindingContext, object>, int?, int?>( .Callback<string, Func<IBindingContext, CancellationToken, object>, Func<IBindingContext, object>, int?, int?>(
(key, bindOperation, timeoutOperation, t1, t2) => (key, bindOperation, timeoutOperation, t1, t2) =>
{ {
timeoutResult = (DefinitionResult) timeoutOperation((IBindingContext)null); timeoutResult = (DefinitionResult)timeoutOperation((IBindingContext)null);
itemMock.Object.Result = timeoutResult; itemMock.Object.Result = timeoutResult;
}) })
.Returns(() => itemMock.Object); .Returns(() => itemMock.Object);
TextDocumentPosition textDocument = new TextDocumentPosition TextDocumentPosition textDocument = new TextDocumentPosition
@@ -190,7 +236,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
Character = 20 Character = 20
} }
}; };
TestConnectionResult connectionResult = await TestObjects.InitLiveConnectionInfo(); TestConnectionResult connectionResult = TestObjects.InitLiveConnectionInfo();
ScriptFile scriptFile = connectionResult.ScriptFile; ScriptFile scriptFile = connectionResult.ScriptFile;
ConnectionInfo connInfo = connectionResult.ConnectionInfo; ConnectionInfo connInfo = connectionResult.ConnectionInfo;
scriptFile.Contents = "select * from dbo.func ()"; scriptFile.Contents = "select * from dbo.func ()";
@@ -212,9 +258,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Test get definition for a view object with active connection /// Test get definition for a view object with active connection
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetValidViewDefinitionTest() public void GetValidViewDefinitionTest()
{ {
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition(); ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo); ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo); PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
@@ -231,10 +277,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Test get definition for an invalid view object with no schema name and with active connection /// Test get definition for an invalid view object with no schema name and with active connection
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetViewDefinitionInvalidObjectTest() public void GetViewDefinitionInvalidObjectTest()
{ {
// Get live connectionInfo and serverConnection // Get live connectionInfo and serverConnection
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition(); ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo); ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo); PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
@@ -250,10 +296,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Test get definition for a stored procedure object with active connection /// Test get definition for a stored procedure object with active connection
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetStoredProcedureDefinitionTest() public void GetStoredProcedureDefinitionTest()
{ {
// Get live connectionInfo and serverConnection // Get live connectionInfo and serverConnection
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition(); ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo); ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo); PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
@@ -271,10 +317,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Test get definition for a stored procedure object that does not exist with active connection /// Test get definition for a stored procedure object that does not exist with active connection
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetStoredProcedureDefinitionFailureTest() public void GetStoredProcedureDefinitionFailureTest()
{ {
// Get live connectionInfo and serverConnection // Get live connectionInfo and serverConnection
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition(); ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo); ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo); PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
@@ -290,10 +336,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Test get definition for a stored procedure object with active connection and no schema /// Test get definition for a stored procedure object with active connection and no schema
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetStoredProcedureDefinitionWithoutSchemaTest() public void GetStoredProcedureDefinitionWithoutSchemaTest()
{ {
// Get live connectionInfo and serverConnection // Get live connectionInfo and serverConnection
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition(); ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo); ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo); PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
@@ -310,19 +356,76 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Test get definition for a scalar valued function object with active connection and explicit schema name. Expect non-null locations /// Test get definition for a scalar valued function object with active connection and explicit schema name. Expect non-null locations
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetScalarValuedFunctionDefinitionWithSchemaNameSuccessTest() public void GetScalarValuedFunctionDefinitionWithSchemaNameSuccessTest()
{
ExecuteAndValidatePeekTest(AddTwoFunctionQuery, AddTwoFunctionName, ScalarValuedFunctionTypeName);
}
private void ExecuteAndValidatePeekTest(string query, string objectName, string objectType, string schemaName = "dbo")
{
if (!string.IsNullOrEmpty(query))
{
using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, query))
{
ValidatePeekTest(testDb.DatabaseName, objectName, objectType, schemaName, true);
}
}
else
{
ValidatePeekTest(null, objectName, objectType, schemaName, false);
}
}
private void ValidatePeekTest(string databaseName, string objectName, string objectType, string schemaName, bool shouldReturnValidResult)
{ {
// Get live connectionInfo and serverConnection // Get live connectionInfo and serverConnection
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition(); ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition(databaseName);
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo); ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo); PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "pd_addTwo";
string schemaName = "dbo";
string objectType = "FUNCTION";
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetScalarValuedFunctionScripts, objectName, schemaName, objectType); ScriptGetter sqlScriptGetter = null;
Assert.NotNull(locations); switch (objectType)
{
case SynonymTypeName:
sqlScriptGetter = peekDefinition.GetSynonymScripts;
return;
case ScalarValuedFunctionTypeName:
sqlScriptGetter = peekDefinition.GetScalarValuedFunctionScripts;
objectType = "Function";
return;
case TableValuedFunctionTypeName:
sqlScriptGetter = peekDefinition.GetTableValuedFunctionScripts;
objectType = "Function";
return;
case TableTypeName:
sqlScriptGetter = peekDefinition.GetTableScripts;
return;
case ViewTypeName:
sqlScriptGetter = peekDefinition.GetViewScripts;
return;
case StoredProcedureTypeName:
sqlScriptGetter = peekDefinition.GetStoredProcedureScripts;
return;
case UserDefinedDataTypeTypeName:
sqlScriptGetter = peekDefinition.GetUserDefinedDataTypeScripts;
objectType = "Type";
return;
case UserDefinedTableTypeTypeName:
sqlScriptGetter = peekDefinition.GetUserDefinedTableTypeScripts;
objectType = "Type";
return;
}
Location[] locations = peekDefinition.GetSqlObjectDefinition(sqlScriptGetter, objectName, schemaName, objectType);
if (shouldReturnValidResult)
{
Assert.NotNull(locations);
}
else
{
Assert.Null(locations);
}
Cleanup(locations); Cleanup(locations);
} }
@@ -330,98 +433,52 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Test get definition for a table valued function object with active connection and explicit schema name. Expect non-null locations /// Test get definition for a table valued function object with active connection and explicit schema name. Expect non-null locations
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetTableValuedFunctionDefinitionWithSchemaNameSuccessTest() public void GetTableValuedFunctionDefinitionWithSchemaNameSuccessTest()
{ {
// Get live connectionInfo and serverConnection ExecuteAndValidatePeekTest(ReturnTableTableFunctionQuery, ReturnTableFunctionName, TableValuedFunctionTypeName);
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "pd_returnTable";
string schemaName = "dbo";
string objectType = "FUNCTION";
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetTableValuedFunctionScripts, objectName, schemaName, objectType);
Assert.NotNull(locations);
Cleanup(locations);
} }
/// <summary> /// <summary>
/// Test get definition for a scalar valued function object that doesn't exist with active connection. Expect null locations /// Test get definition for a scalar valued function object that doesn't exist with active connection. Expect null locations
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetScalarValuedFunctionDefinitionWithNonExistentFailureTest() public void GetScalarValuedFunctionDefinitionWithNonExistentFailureTest()
{ {
// Get live connectionInfo and serverConnection
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "doesNotExist"; string objectName = "doesNotExist";
string schemaName = "dbo"; string schemaName = "dbo";
string objectType = "FUNCTION"; string objectType = ScalarValuedFunctionTypeName;
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetScalarValuedFunctionScripts, objectName, schemaName, objectType); ExecuteAndValidatePeekTest(null, objectName, objectType, schemaName);
Assert.Null(locations);
} }
/// <summary> /// <summary>
/// Test get definition for a table valued function object that doesn't exist with active connection. Expect null locations /// Test get definition for a table valued function object that doesn't exist with active connection. Expect null locations
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetTableValuedFunctionDefinitionWithNonExistentObjectFailureTest() public void GetTableValuedFunctionDefinitionWithNonExistentObjectFailureTest()
{ {
// Get live connectionInfo and serverConnection
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "doesNotExist"; string objectName = "doesNotExist";
string schemaName = "dbo"; string schemaName = "dbo";
string objectType = "FUNCTION"; string objectType = TableValuedFunctionTypeName;
ExecuteAndValidatePeekTest(null, objectName, objectType, schemaName);
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetTableValuedFunctionScripts, objectName, schemaName, objectType);
Assert.Null(locations);
} }
/// <summary> /// <summary>
/// Test get definition for a scalar valued function object with active connection. Expect non-null locations /// Test get definition for a scalar valued function object with active connection. Expect non-null locations
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetScalarValuedFunctionDefinitionWithoutSchemaNameSuccessTest() public void GetScalarValuedFunctionDefinitionWithoutSchemaNameSuccessTest()
{ {
// Get live connectionInfo and serverConnection ExecuteAndValidatePeekTest(AddTwoFunctionQuery, AddTwoFunctionName, ScalarValuedFunctionTypeName, null);
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "pd_addTwo";
string schemaName = null;
string objectType = "FUNCTION";
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetScalarValuedFunctionScripts, objectName, schemaName, objectType);
Assert.NotNull(locations);
Cleanup(locations);
} }
/// <summary> /// <summary>
/// Test get definition for a table valued function object with active connection. Expect non-null locations /// Test get definition for a table valued function object with active connection. Expect non-null locations
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetTableValuedFunctionDefinitionWithoutSchemaNameSuccessTest() public void GetTableValuedFunctionDefinitionWithoutSchemaNameSuccessTest()
{ {
// Get live connectionInfo and serverConnection ExecuteAndValidatePeekTest(ReturnTableTableFunctionQuery, ReturnTableFunctionName, TableValuedFunctionTypeName, null);
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "pd_returnTable";
string schemaName = null;
string objectType = "FUNCTION";
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetTableValuedFunctionScripts, objectName, schemaName, objectType);
Assert.NotNull(locations);
Cleanup(locations);
} }
@@ -429,138 +486,70 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Test get definition for a user defined data type object with active connection and explicit schema name. Expect non-null locations /// Test get definition for a user defined data type object with active connection and explicit schema name. Expect non-null locations
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetUserDefinedDataTypeDefinitionWithSchemaNameSuccessTest() public void GetUserDefinedDataTypeDefinitionWithSchemaNameSuccessTest()
{ {
// Get live connectionInfo and serverConnection ExecuteAndValidatePeekTest(SsnTypeQuery, SsnTypeName, UserDefinedDataTypeTypeName);
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "pd_ssn";
string schemaName = "dbo";
string objectType = "Type";
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetUserDefinedDataTypeScripts, objectName, schemaName, objectType);
Assert.NotNull(locations);
Cleanup(locations);
} }
/// <summary> /// <summary>
/// Test get definition for a user defined data type object with active connection. Expect non-null locations /// Test get definition for a user defined data type object with active connection. Expect non-null locations
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetUserDefinedDataTypeDefinitionWithoutSchemaNameSuccessTest() public void GetUserDefinedDataTypeDefinitionWithoutSchemaNameSuccessTest()
{ {
// Get live connectionInfo and serverConnection ExecuteAndValidatePeekTest(SsnTypeQuery, SsnTypeName, UserDefinedDataTypeTypeName, null);
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "pd_ssn";
string schemaName = null;
string objectType = "Type";
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetUserDefinedDataTypeScripts, objectName, schemaName, objectType);
Assert.NotNull(locations);
Cleanup(locations);
} }
/// <summary> /// <summary>
/// Test get definition for a user defined data type object that doesn't exist with active connection. Expect null locations /// Test get definition for a user defined data type object that doesn't exist with active connection. Expect null locations
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetUserDefinedDataTypeDefinitionWithNonExistentFailureTest() public void GetUserDefinedDataTypeDefinitionWithNonExistentFailureTest()
{ {
// Get live connectionInfo and serverConnection
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "doesNotExist"; string objectName = "doesNotExist";
string schemaName = "dbo"; string schemaName = "dbo";
string objectType = "Type"; string objectType = UserDefinedDataTypeTypeName;
ExecuteAndValidatePeekTest(null, objectName, objectType, schemaName);
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetUserDefinedDataTypeScripts, objectName, schemaName, objectType);
Assert.Null(locations);
} }
/// <summary> /// <summary>
/// Test get definition for a user defined table type object with active connection and explicit schema name. Expect non-null locations /// Test get definition for a user defined table type object with active connection and explicit schema name. Expect non-null locations
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetUserDefinedTableTypeDefinitionWithSchemaNameSuccessTest() public void GetUserDefinedTableTypeDefinitionWithSchemaNameSuccessTest()
{ {
// Get live connectionInfo and serverConnection ExecuteAndValidatePeekTest(LocationTableTypeQuery, LocationTableTypeName, UserDefinedTableTypeTypeName);
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "pd_locationTableType";
string schemaName = "dbo";
string objectType = "Type";
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetUserDefinedTableTypeScripts, objectName, schemaName, objectType);
Assert.NotNull(locations);
Cleanup(locations);
} }
/// <summary> /// <summary>
/// Test get definition for a user defined table type object with active connection. Expect non-null locations /// Test get definition for a user defined table type object with active connection. Expect non-null locations
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetUserDefinedTableTypeDefinitionWithoutSchemaNameSuccessTest() public void GetUserDefinedTableTypeDefinitionWithoutSchemaNameSuccessTest()
{ {
// Get live connectionInfo and serverConnection ExecuteAndValidatePeekTest(LocationTableTypeQuery, LocationTableTypeName, UserDefinedTableTypeTypeName, null);
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "pd_locationTableType";
string schemaName = null;
string objectType = "Type";
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetUserDefinedTableTypeScripts, objectName, schemaName, objectType);
Assert.NotNull(locations);
Cleanup(locations);
} }
/// <summary> /// <summary>
/// Test get definition for a user defined table type object that doesn't exist with active connection. Expect null locations /// Test get definition for a user defined table type object that doesn't exist with active connection. Expect null locations
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetUserDefinedTableTypeDefinitionWithNonExistentFailureTest() public void GetUserDefinedTableTypeDefinitionWithNonExistentFailureTest()
{ {
// Get live connectionInfo and serverConnection
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "doesNotExist"; string objectName = "doesNotExist";
string schemaName = "dbo"; string schemaName = "dbo";
string objectType = "Type"; string objectType = UserDefinedTableTypeTypeName;
ExecuteAndValidatePeekTest(null, objectName, objectType, schemaName);
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetUserDefinedTableTypeScripts, objectName, schemaName, objectType);
Assert.Null(locations);
} }
/// <summary> /// <summary>
/// Test get definition for a synonym object with active connection and explicit schema name. Expect non-null locations /// Test get definition for a synonym object with active connection and explicit schema name. Expect non-null locations
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetSynonymDefinitionWithSchemaNameSuccessTest() public void GetSynonymDefinitionWithSchemaNameSuccessTest()
{ {
// Get live connectionInfo and serverConnection ExecuteAndValidatePeekTest(TestTableSynonymQuery, TestTableSynonymName, SynonymTypeName);
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "pd_testTable";
string schemaName = "dbo";
string objectType = "Synonym";
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetSynonymScripts, objectName, schemaName, objectType);
Assert.NotNull(locations);
Cleanup(locations);
} }
@@ -568,39 +557,21 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Test get definition for a Synonym object with active connection. Expect non-null locations /// Test get definition for a Synonym object with active connection. Expect non-null locations
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetSynonymDefinitionWithoutSchemaNameSuccessTest() public void GetSynonymDefinitionWithoutSchemaNameSuccessTest()
{ {
// Get live connectionInfo and serverConnection ExecuteAndValidatePeekTest(TestTableSynonymQuery, TestTableSynonymName, SynonymTypeName, null);
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "pd_testTable";
string schemaName = null;
string objectType = "Synonym";
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetSynonymScripts, objectName, schemaName, objectType);
Assert.NotNull(locations);
Cleanup(locations);
} }
/// <summary> /// <summary>
/// Test get definition for a Synonym object that doesn't exist with active connection. Expect null locations /// Test get definition for a Synonym object that doesn't exist with active connection. Expect null locations
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetSynonymDefinitionWithNonExistentFailureTest() public void GetSynonymDefinitionWithNonExistentFailureTest()
{ {
// Get live connectionInfo and serverConnection
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
string objectName = "doesNotExist"; string objectName = "doesNotExist";
string schemaName = "dbo"; string schemaName = "dbo";
string objectType = "Synonym"; string objectType = "Synonym";
ExecuteAndValidatePeekTest(null, objectName, objectType, schemaName);
Location[] locations = peekDefinition.GetSqlObjectDefinition(peekDefinition.GetSynonymScripts, objectName, schemaName, objectType);
Assert.Null(locations);
} }
/// <summary> /// <summary>
@@ -608,9 +579,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Expect a non-null result with location /// Expect a non-null result with location
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetDefinitionUsingDeclarationTypeWithValidObjectTest() public void GetDefinitionUsingDeclarationTypeWithValidObjectTest()
{ {
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition(); ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo); ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo); PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
@@ -630,9 +601,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Expect a non-null result with location /// Expect a non-null result with location
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetDefinitionUsingDeclarationTypeWithNonexistentObjectTest() public void GetDefinitionUsingDeclarationTypeWithNonexistentObjectTest()
{ {
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition(); ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo); ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo); PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
@@ -649,9 +620,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Expect a non-null result with location /// Expect a non-null result with location
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetDefinitionUsingQuickInfoTextWithValidObjectTest() public void GetDefinitionUsingQuickInfoTextWithValidObjectTest()
{ {
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition(); ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo); ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo); PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
@@ -672,9 +643,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
/// Expect a non-null result with location /// Expect a non-null result with location
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetDefinitionUsingQuickInfoTextWithNonexistentObjectTest() public void GetDefinitionUsingQuickInfoTextWithNonexistentObjectTest()
{ {
ConnectionInfo connInfo = await TestObjects.InitLiveConnectionInfoForDefinition(); ConnectionInfo connInfo = TestObjects.InitLiveConnectionInfoForDefinition();
ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo); ServerConnection serverConnection = TestObjects.InitLiveServerConnectionForDefinition(connInfo);
PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo); PeekDefinition peekDefinition = new PeekDefinition(serverConnection, connInfo);
@@ -699,7 +670,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServices
{ {
File.Delete(fileUri.LocalPath); File.Delete(fileUri.LocalPath);
} }
catch(Exception) catch (Exception)
{ {
} }

View File

@@ -16,9 +16,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.QueryExecution.DataSt
{ {
public class StorageDataReaderTests public class StorageDataReaderTests
{ {
private async Task<StorageDataReader> GetTestStorageDataReader(string query) private StorageDataReader GetTestStorageDataReader(string query)
{ {
var result = await TestObjects.InitLiveConnectionInfo(); var result = TestObjects.InitLiveConnectionInfo();
DbConnection connection; DbConnection connection;
result.ConnectionInfo.TryGetConnection(ConnectionType.Default, out connection); result.ConnectionInfo.TryGetConnection(ConnectionType.Default, out connection);
@@ -33,9 +33,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.QueryExecution.DataSt
/// Validate GetBytesWithMaxCapacity /// Validate GetBytesWithMaxCapacity
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetBytesWithMaxCapacityTest() public void GetBytesWithMaxCapacityTest()
{ {
var storageReader = await GetTestStorageDataReader( var storageReader = GetTestStorageDataReader(
"SELECT CAST([name] as TEXT) As TextName FROM sys.all_columns"); "SELECT CAST([name] as TEXT) As TextName FROM sys.all_columns");
DbDataReader reader = storageReader.DbDataReader; DbDataReader reader = storageReader.DbDataReader;
@@ -50,9 +50,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.QueryExecution.DataSt
/// Validate GetCharsWithMaxCapacity /// Validate GetCharsWithMaxCapacity
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetCharsWithMaxCapacityTest() public void GetCharsWithMaxCapacityTest()
{ {
var storageReader = await GetTestStorageDataReader( var storageReader = GetTestStorageDataReader(
"SELECT name FROM sys.all_columns"); "SELECT name FROM sys.all_columns");
DbDataReader reader = storageReader.DbDataReader; DbDataReader reader = storageReader.DbDataReader;
@@ -72,9 +72,9 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.QueryExecution.DataSt
/// Validate GetXmlWithMaxCapacity /// Validate GetXmlWithMaxCapacity
/// </summary> /// </summary>
[Fact] [Fact]
public async Task GetXmlWithMaxCapacityTest() public void GetXmlWithMaxCapacityTest()
{ {
var storageReader = await GetTestStorageDataReader( var storageReader = GetTestStorageDataReader(
"SELECT CAST('<xml>Test XML context</xml>' AS XML) As XmlColumn"); "SELECT CAST('<xml>Test XML context</xml>' AS XML) As XmlColumn");
DbDataReader reader = storageReader.DbDataReader; DbDataReader reader = storageReader.DbDataReader;

View File

@@ -17,12 +17,12 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.QueryExecution
public class ExecuteTests public class ExecuteTests
{ {
[Fact] [Fact]
public async Task RollbackTransactionFailsWithoutBeginTransaction() public void RollbackTransactionFailsWithoutBeginTransaction()
{ {
const string refactorText = "ROLLBACK TRANSACTION"; const string refactorText = "ROLLBACK TRANSACTION";
// Given a connection to a live database // Given a connection to a live database
var result = await TestObjects.InitLiveConnectionInfo(); var result = TestObjects.InitLiveConnectionInfo();
ConnectionInfo connInfo = result.ConnectionInfo; ConnectionInfo connInfo = result.ConnectionInfo;
var fileStreamFactory = Common.GetFileStreamFactory(new Dictionary<string, byte[]>()); var fileStreamFactory = Common.GetFileStreamFactory(new Dictionary<string, byte[]>());
@@ -36,13 +36,13 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.QueryExecution
} }
[Fact] [Fact]
public async Task TransactionsSucceedAcrossQueries() public void TransactionsSucceedAcrossQueries()
{ {
const string beginText = "BEGIN TRANSACTION"; const string beginText = "BEGIN TRANSACTION";
const string rollbackText = "ROLLBACK TRANSACTION"; const string rollbackText = "ROLLBACK TRANSACTION";
// Given a connection to a live database // Given a connection to a live database
var result = await TestObjects.InitLiveConnectionInfo(); var result = TestObjects.InitLiveConnectionInfo();
ConnectionInfo connInfo = result.ConnectionInfo; ConnectionInfo connInfo = result.ConnectionInfo;
var fileStreamFactory = Common.GetFileStreamFactory(new Dictionary<string, byte[]>()); var fileStreamFactory = Common.GetFileStreamFactory(new Dictionary<string, byte[]>());
@@ -55,13 +55,13 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.QueryExecution
} }
[Fact] [Fact]
public async Task TempTablesPersistAcrossQueries() public void TempTablesPersistAcrossQueries()
{ {
const string createTempText = "CREATE TABLE #someTempTable (id int)"; const string createTempText = "CREATE TABLE #someTempTable (id int)";
const string insertTempText = "INSERT INTO #someTempTable VALUES(1)"; const string insertTempText = "INSERT INTO #someTempTable VALUES(1)";
// Given a connection to a live database // Given a connection to a live database
var result = await TestObjects.InitLiveConnectionInfo(); var result = TestObjects.InitLiveConnectionInfo();
ConnectionInfo connInfo = result.ConnectionInfo; ConnectionInfo connInfo = result.ConnectionInfo;
var fileStreamFactory = Common.GetFileStreamFactory(new Dictionary<string, byte[]>()); var fileStreamFactory = Common.GetFileStreamFactory(new Dictionary<string, byte[]>());
@@ -74,14 +74,14 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.QueryExecution
} }
[Fact] [Fact]
public async Task DatabaseChangesWhenCallingUseDatabase() public void DatabaseChangesWhenCallingUseDatabase()
{ {
const string master = "master"; const string master = "master";
const string tempdb = "tempdb"; const string tempdb = "tempdb";
const string useQuery = "USE {0}"; const string useQuery = "USE {0}";
// Given a connection to a live database // Given a connection to a live database
var result = await TestObjects.InitLiveConnectionInfo(); var result = TestObjects.InitLiveConnectionInfo();
ConnectionInfo connInfo = result.ConnectionInfo; ConnectionInfo connInfo = result.ConnectionInfo;
DbConnection connection; DbConnection connection;
connInfo.TryGetConnection(ConnectionType.Default, out connection); connInfo.TryGetConnection(ConnectionType.Default, out connection);

View File

@@ -28,8 +28,7 @@ namespace Microsoft.SqlTools.ServiceLayer.PerfTests
public TestServerType ServerType { get; set; } public TestServerType ServerType { get; set; }
public override void Before(MethodInfo methodUnderTest) public override void Before(MethodInfo methodUnderTest)
{ {
Task task = SqlTestDb.CreateNew(ServerType, doNotCleanupDb: true, databaseName: Common.PerfTestDatabaseName, query: Scripts.CreateDatabaseObjectsQuery); SqlTestDb.CreateNew(ServerType, doNotCleanupDb: true, databaseName: Common.PerfTestDatabaseName, query: Scripts.CreateDatabaseObjectsQuery);
task.Wait();
} }
public override void After(MethodInfo methodUnderTest) public override void After(MethodInfo methodUnderTest)

View File

@@ -7,6 +7,9 @@ namespace Microsoft.SqlTools.ServiceLayer.PerfTests
{ {
public class Common public class Common
{ {
public const string PerfTestDatabaseName = "SQLToolsCrossPlatPerfTestDb"; /// <summary>
/// The name of the test db to be used for performance tests. Prefix "keep" is used so the db doesn't get deleted by cleanup jobs
/// </summary>
public const string PerfTestDatabaseName = "keep_SQLToolsCrossPlatPerfTestDb";
} }
} }

View File

@@ -41,7 +41,7 @@ namespace Microsoft.SqlTools.ServiceLayer.PerfTests
Thread.Sleep(500); Thread.Sleep(500);
var connected = await testService.CalculateRunTime(async () => var connected = await testService.CalculateRunTime(async () =>
{ {
var connectParams = await testService.GetConnectionParametersAsync(serverType, Common.PerfTestDatabaseName); var connectParams = testService.GetConnectionParameters(serverType, Common.PerfTestDatabaseName);
return await testService.Connect(queryTempFile.FilePath, connectParams); return await testService.Connect(queryTempFile.FilePath, connectParams);
}, true); }, true);
Assert.True(connected, "Connection was not successful"); Assert.True(connected, "Connection was not successful");
@@ -76,7 +76,7 @@ namespace Microsoft.SqlTools.ServiceLayer.PerfTests
Thread.Sleep(500); Thread.Sleep(500);
var connected = await testService.CalculateRunTime(async () => var connected = await testService.CalculateRunTime(async () =>
{ {
var connectParams = await testService.GetConnectionParametersAsync(serverType, Common.PerfTestDatabaseName); var connectParams = testService.GetConnectionParameters(serverType, Common.PerfTestDatabaseName);
return await testService.Connect(queryTempFile.FilePath, connectParams); return await testService.Connect(queryTempFile.FilePath, connectParams);
}, true); }, true);
Assert.True(connected, "Connection was not successful"); Assert.True(connected, "Connection was not successful");

View File

@@ -54,7 +54,7 @@ namespace Microsoft.SqlTools.ServiceLayer.PerfTests
public async Task DiagnosticsTests() public async Task DiagnosticsTests()
{ {
TestServerType serverType = TestServerType.OnPrem; TestServerType serverType = TestServerType.OnPrem;
await SqlTestDb.CreateNew(serverType, doNotCleanupDb: true, databaseName: Common.PerfTestDatabaseName, query: Scripts.CreateDatabaseObjectsQuery); SqlTestDb.CreateNew(serverType, doNotCleanupDb: true, databaseName: Common.PerfTestDatabaseName, query: Scripts.CreateDatabaseObjectsQuery);
using (TestServiceDriverProvider testService = new TestServiceDriverProvider()) using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
@@ -165,7 +165,7 @@ namespace Microsoft.SqlTools.ServiceLayer.PerfTests
} }
[Fact] [Fact]
[CreateTestDb(TestServerType.Azure)] [CreateTestDb(TestServerType.OnPrem)]
public async Task BindingCacheColdOnPremComplexQuery() public async Task BindingCacheColdOnPremComplexQuery()
{ {
TestServerType serverType = TestServerType.OnPrem; TestServerType serverType = TestServerType.OnPrem;

View File

@@ -3,8 +3,8 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
// //
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.Linq; using System.Linq;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -16,9 +16,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
public class ConnectionSetting public class ConnectionSetting
{ {
[JsonProperty("mssql.connections")] [JsonProperty("mssql.connections")]
public List<ConnectionProfile> Connections { get; set; } public List<InstanceInfo> Connections { get; set; }
public ConnectionProfile GetConnectionProfile(string profileName, string serverName) public InstanceInfo GetConnectionProfile(string profileName, string serverName)
{ {
if (!string.IsNullOrEmpty(profileName) && Connections != null) if (!string.IsNullOrEmpty(profileName) && Connections != null)
{ {
@@ -33,52 +33,94 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
} }
/// <summary> /// <summary>
/// The model to deserializing the connections inside settings.json /// The model to de-serializing the connections inside settings.json
/// </summary> /// </summary>
public class ConnectionProfile public class InstanceInfo
{ {
public const string CRED_PREFIX = "Microsoft.SqlTools"; public InstanceInfo(string versionKey)
public const string CRED_SEPARATOR = "|"; {
public const string CRED_SERVER_PREFIX = "server:"; ConnectTimeout = 15;
public const string CRED_DB_PREFIX = "db:"; VersionKey = versionKey;
public const string CRED_USER_PREFIX = "user:"; }
public const string CRED_ITEMTYPE_PREFIX = "itemtype:";
[JsonProperty("server")] [JsonProperty("server")]
public string ServerName { get; set; } public string ServerName { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Database { get; set; } public string Database { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string User { get; set; } public string User { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Password { get; set; } public string Password { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string ProfileName { get; set; } public string ProfileName { get; set; }
public TestServerType ServerType { get; set; } public TestServerType ServerType { get; set; }
public AuthenticationType AuthenticationType { get; set; } public AuthenticationType AuthenticationType { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string RemoteSharePath { get; set; }
public string formatCredentialId(string itemType = "Profile") public int ConnectTimeout { get; set; }
public string VersionKey { get; set; }
[JsonIgnore]
public string ConnectTimeoutAsString
{ {
if (!string.IsNullOrEmpty(ServerName)) get { return ConnectTimeout.ToString(); }
set
{ {
List<string> cred = new List<string>(); int temp;
cred.Add(CRED_PREFIX); if (int.TryParse(value, out temp))
AddToList(itemType, CRED_ITEMTYPE_PREFIX, cred); {
AddToList(ServerName, CRED_SERVER_PREFIX, cred); this.ConnectTimeout = temp;
AddToList(Database, CRED_DB_PREFIX, cred); }
AddToList(User, CRED_USER_PREFIX, cred); else
return string.Join(CRED_SEPARATOR, cred.ToArray()); {
} this.ConnectTimeout = 15;
return null; }
}
private void AddToList(string item, string prefix, List<string> list)
{
if (!string.IsNullOrEmpty(item))
{
list.Add(string.Format(CultureInfo.InvariantCulture, "{0}{1}", prefix, item));
} }
} }
[JsonIgnore]
public string MachineName
{
get
{
string serverName = ServerName;
int index = ServerName.IndexOf('\\');
if (index > 0)
{
serverName = ServerName.Substring(0, index);
}
if (StringComparer.OrdinalIgnoreCase.Compare("(local)", serverName) == 0
|| StringComparer.OrdinalIgnoreCase.Compare(".", serverName) == 0)
{
serverName = Environment.MachineName;
}
return serverName;
}
}
[JsonIgnore]
public string InstanceName
{
get
{
string name = null;
int index = ServerName.IndexOf('\\');
if (index > 0)
{
name = ServerName.Substring(index + 1);
}
return name;
}
}
} }
} }

View File

@@ -0,0 +1,12 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{
public static class Constants
{
public const string SqlConectionSettingsEnvironmentVariable = "SettingsFileName";
}
}

View File

@@ -0,0 +1,71 @@
//
// 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.Runtime.InteropServices;
namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{
public static class FileUtils
{
public static string UserRootFolder
{
get
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return Environment.GetEnvironmentVariable("USERPROFILE");
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return Environment.GetEnvironmentVariable("HOME");
}
else
{
return Environment.GetEnvironmentVariable("HOME");
}
}
}
public static string VsCodeSettingsFileName
{
get
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return Environment.GetEnvironmentVariable("APPDATA") + @"\Code\User\settings.json";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return Environment.GetEnvironmentVariable("HOME") + @"/Library/Application Support/Code/User/settings.json";
}
else
{
return Environment.GetEnvironmentVariable("HOME") + @"/.config/Code/User/settings.json";
}
}
}
public static string TestServerNamesDefaultFileName
{
get
{
string testServerFileName = "testServerNames.json";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return Environment.GetEnvironmentVariable("APPDATA") + @"\\" + testServerFileName;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return Environment.GetEnvironmentVariable("HOME") + @"/" + testServerFileName;
}
else
{
return Environment.GetEnvironmentVariable("HOME") + @"/" + testServerFileName;
}
}
}
}
}

View File

@@ -5,7 +5,6 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.ServiceLayer.Test.Common namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{ {
@@ -25,19 +24,20 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
/// <summary> /// <summary>
/// Create the test db if not already exists /// Create the test db if not already exists
/// </summary> /// </summary>
public static async Task<SqlTestDb> CreateNew(TestServerType serverType, bool doNotCleanupDb = false, string databaseName = null, string query = null) public static SqlTestDb CreateNew(TestServerType serverType, bool doNotCleanupDb = false, string databaseName = null, string query = null)
{ {
SqlTestDb testDb = new SqlTestDb(); SqlTestDb testDb = new SqlTestDb();
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{ {
databaseName = databaseName ?? GetUniqueDBName(""); databaseName = databaseName ?? GetUniqueDBName("");
string createDatabaseQuery = Scripts.CreateDatabaseQuery.Replace("#DatabaseName#", databaseName); string createDatabaseQuery = Scripts.CreateDatabaseQuery.Replace("#DatabaseName#", databaseName);
await testService.RunQuery(serverType, MasterDatabaseName, createDatabaseQuery); TestServiceProvider.Instance.RunQuery(serverType, MasterDatabaseName, createDatabaseQuery);
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Verified test database '{0}' is created", databaseName)); Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Test database '{0}' is created", databaseName));
if (!string.IsNullOrEmpty(query)) if (!string.IsNullOrEmpty(query))
{ {
await testService.RunQuery(serverType, databaseName, query); TestServiceProvider.Instance.RunQuery(serverType, databaseName, query);
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Verified test database '{0}' SQL types are created", databaseName)); Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Test database '{0}' SQL types are created", databaseName));
} }
testDb.DatabaseName = databaseName; testDb.DatabaseName = databaseName;
testDb.ServerType = serverType; testDb.ServerType = serverType;
@@ -47,6 +47,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
return testDb; return testDb;
} }
/// <summary>
/// Create the test db if not already exists
/// </summary>
public static SqlTestDb CreateNew(TestServerType serverType, string query = null)
{
return CreateNew(serverType, false, null, query);
}
/// <summary> /// <summary>
/// Returns a mangled name that unique based on Prefix + Machine + Process /// Returns a mangled name that unique based on Prefix + Machine + Process
/// </summary> /// </summary>
@@ -59,18 +67,22 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
namePrefix, safeMachineName, Guid.NewGuid().ToString().Replace("-", "")); namePrefix, safeMachineName, Guid.NewGuid().ToString().Replace("-", ""));
} }
public void Dispose() public void Cleanup()
{ {
if(!DoNotCleanupDb) if (!DoNotCleanupDb)
{ {
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{ {
string dropDatabaseQuery = string.Format(CultureInfo.InvariantCulture, string dropDatabaseQuery = string.Format(CultureInfo.InvariantCulture,
(ServerType == TestServerType.Azure ? Scripts.DropDatabaseIfExistAzure : Scripts.DropDatabaseIfExist), DatabaseName); (ServerType == TestServerType.Azure ? Scripts.DropDatabaseIfExistAzure : Scripts.DropDatabaseIfExist), DatabaseName);
testService.RunQuery(ServerType, MasterDatabaseName, dropDatabaseQuery).Wait(); TestServiceProvider.Instance.RunQuery(ServerType, MasterDatabaseName, dropDatabaseQuery);
} }
} }
} }
public void Dispose()
{
Cleanup();
}
} }
} }

View File

@@ -0,0 +1,158 @@
//
// 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.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{
public sealed class TestConfigPersistenceHelper
{
private static string DefaultSettingFileName = Path.Combine(FileUtils.UserRootFolder, "sqlConnectionSettings.json");
private static TestCredentialService credentialService = TestCredentialService.Instance;
public static bool Write(IEnumerable<InstanceInfo> instances)
{
try
{
ConnectionSetting connectionSetting = new Common.ConnectionSetting()
{
Connections = new List<InstanceInfo>(instances)
};
//Remove the passwords and store in credential store and then store the copy without passwords in the file
foreach (var instance in connectionSetting.Connections)
{
if (!string.IsNullOrEmpty(instance.Password))
{
if (!credentialService.SaveCredential(instance))
{
Console.WriteLine("Failed to store the password for server: " + instance.ServerName);
}
instance.Password = null; //Make sure the password is not stored in sqlConnectionSettings.json
instance.AuthenticationType = AuthenticationType.SqlLogin;
}
else
{
instance.AuthenticationType = AuthenticationType.Integrated;
}
}
Console.WriteLine("The SQL connection instances will be written to " + DefaultSettingFileName);
string jsonContent = JsonConvert.SerializeObject(connectionSetting);
if (File.Exists(DefaultSettingFileName))
{
Console.WriteLine("The file " + DefaultSettingFileName + " already exists and it will be overwritten.");
}
File.WriteAllText(DefaultSettingFileName, jsonContent);
Environment.SetEnvironmentVariable(Constants.SqlConectionSettingsEnvironmentVariable, DefaultSettingFileName);
return true;
}
catch (Exception ex)
{
Console.WriteLine("Failed to store the instances.", ex);
return false;
}
}
internal static IEnumerable<TestServerIdentity> InitTestServerNames()
{
try
{
string testServerNamesFileContent = GetTestServerNamesFileContent();
if (!string.IsNullOrEmpty(testServerNamesFileContent))
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<IList<TestServerIdentity>>(testServerNamesFileContent);
}
else
{
return Enumerable.Empty<TestServerIdentity>();
}
}
catch (Exception ex)
{
return Enumerable.Empty<TestServerIdentity>();
}
}
internal static ConnectionSetting InitSetting()
{
try
{
string settingsFileContents = GetSettingFileContent();
ConnectionSetting setting = Newtonsoft.Json.JsonConvert.DeserializeObject<ConnectionSetting>(settingsFileContents);
Console.WriteLine("Connection Settings loaded successfully");
return setting;
}
catch (Exception ex)
{
Console.WriteLine("Failed to load the connection settings. error: " + ex.Message);
return new ConnectionSetting();
}
}
/// <summary>
/// Get the location of testServerNames.json. Returns the value of environment variable 'SettingsFileName' and if it's empty returns
/// the location of vs code testServerNames.json
/// </summary>
/// <returns></returns>
private static string GetTestServerNamesFileContent()
{
var testServerNameFilePath = Environment.GetEnvironmentVariable("TestServerNamesFile");
if (string.IsNullOrEmpty(testServerNameFilePath))
{
testServerNameFilePath = FileUtils.TestServerNamesDefaultFileName;
}
string testServerNamesFileContent = string.IsNullOrEmpty(testServerNameFilePath) ? string.Empty : File.ReadAllText(testServerNameFilePath);
return testServerNamesFileContent;
}
/// <summary>
/// Get the location of setting.json. Returns the value of environment variable 'SettingsFileName' and if it's empty returns
/// the location of vs code settings.json
/// </summary>
/// <returns></returns>
private static string GetSettingFileContent()
{
var settingsFileName = Environment.GetEnvironmentVariable(Constants.SqlConectionSettingsEnvironmentVariable);
if (string.IsNullOrEmpty(settingsFileName))
{
if (File.Exists(DefaultSettingFileName))
{
settingsFileName = DefaultSettingFileName;
Console.WriteLine(DefaultSettingFileName + " SQL connection instances are not configured. Will try to get connections from VS code settings.json");
}
else
{
//If the SQL connection settings is not set use the VS code one
settingsFileName = FileUtils.VsCodeSettingsFileName;
}
}
if (string.IsNullOrEmpty(settingsFileName))
{
Console.WriteLine("SQL connection instances are not configured. Run dotnet run Microsoft.SqlTools.ServiceLayer.TestEnvConfig from the command line to configure");
}
else
{
Console.WriteLine("SQL Connection settings are loaded from: " + settingsFileName);
}
string settingsFileContents = string.IsNullOrEmpty(settingsFileName) ? string.Empty : File.ReadAllText(settingsFileName);
return settingsFileContents;
}
}
}

View File

@@ -4,136 +4,179 @@
// //
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.Credentials;
using Microsoft.SqlTools.ServiceLayer.Credentials.Contracts; using Microsoft.SqlTools.ServiceLayer.Credentials.Contracts;
using Microsoft.SqlTools.ServiceLayer.TestDriver.Driver;
using Xunit; using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.Test.Common namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{ {
/// <summary> /// <summary>
/// Service to get connection profiles from the configured settings /// Service to get connection profiles from the configured settings
/// to get the credentials, test driver will be used if available otherwise the credential service will be called directly /// credential service will be used to get the credentials
/// </summary> /// </summary>
public class TestConnectionProfileService public class TestConnectionProfileService
{ {
private readonly IEnumerable<TestServerIdentity> _testServers = TestServersLazyInstance.Value; private static Dictionary<string, InstanceInfo> connectionProfilesCache = new Dictionary<string, InstanceInfo>();
private readonly ConnectionSetting _setting = ConnectionSettingLazyInstance.Value; private static TestConnectionProfileService instance = new TestConnectionProfileService();
private static string _connectionSettingsFilename;
private static ConcurrentDictionary<TestServerType, ConnectionProfile> _connectionProfilesCache = new ConcurrentDictionary<TestServerType, ConnectionProfile>();
public TestConnectionProfileService(ServiceTestDriver driver) public const string DefaultSql2005InstanceKey = "defaultSql2005";
public const string DefaultSql2008InstanceKey = "defaultSql2008";
public const string DefaultSql2011InstanceKey = "defaultSql2011";
public const string DefaultSql2012Pcu1InstanceKey = "defaultSql2012pcu1";
public const string DefaultSql2014InstanceKey = "defaultSql2014";
public const string DefaultSqlAzureInstanceKey = "defaultSqlAzure";
public const string DefaultServerlessInstanceKey = "defaultServerless";
public const string DefaultSqlPdwInstanceKey = "defaultSqlPdw";
public const string DefaultSqlAzureV12InstanceKey = "defaultSqlAzureV12";
public const string DefaultSql2016InstanceKey = "defaultSql2016";
public const string DefaultSqlvNextInstanceKey = "defaultSqlvNext";
private TestConnectionProfileService()
{ {
Driver = driver; LoadInstanceSettings();
} }
public TestConnectionProfileService() public static TestConnectionProfileService Instance
{ {
get
{
return instance;
}
} }
private static readonly Lazy<IEnumerable<TestServerIdentity>> TestServersLazyInstance = public static InstanceInfo DefaultSql2012Pcu1
new Lazy<IEnumerable<TestServerIdentity>>(InitTestServerNames);
private static readonly Lazy<ConnectionSetting> ConnectionSettingLazyInstance =
new Lazy<ConnectionSetting>(InitSetting);
private ServiceTestDriver Driver { get; set; }
private ConnectionProfile GetConnectionProfile(TestServerType serverType)
{ {
ConnectionProfile connectionProfile = null; get { return GetInstance(DefaultSql2012Pcu1InstanceKey); }
}
//Get the server or profile name for given type to use for database connection public static InstanceInfo DefaultSql2014
TestServerIdentity serverIdentity = _testServers != null ? _testServers.FirstOrDefault(x => x.ServerType == serverType) : null; {
get { return GetInstance(DefaultSql2014InstanceKey); }
}
//Search for the connection info in settings.json public static InstanceInfo DefaultSqlAzure
if (serverIdentity == null) {
{ get { return GetInstance(DefaultSqlAzureInstanceKey); }
//If not server name found, try to find the connection info for given type }
connectionProfile = _setting != null && _setting.Connections != null ? _setting.Connections.FirstOrDefault(x => x.ServerType == serverType) : null;
if (connectionProfile == null && _setting != null && _setting.Connections != null)
{
Console.WriteLine(string.Format(CultureInfo.InvariantCulture,
"Cannot find any connection profile for server type '{0}'. "
+ " Make sure the serverType attribute is set in {1}. " +
"Or run CreateTestServerNameSettings.cmd to create a template for the server names", serverType, _connectionSettingsFilename));
}
}
else
{
//Find the connection info for specific server name or profile name
connectionProfile = _setting != null ? _setting.GetConnectionProfile(serverIdentity.ProfileName, serverIdentity.ServerName) : null;
} public static InstanceInfo DefaultSqlAzureV12
{
get { return GetInstance(DefaultSqlAzureV12InstanceKey); }
}
Assert.True(connectionProfile != null, "Cannot find any connection profile for server type " + serverType.ToString()); public static InstanceInfo DefaultSql2016
{
return connectionProfile; get { return GetInstance(DefaultSql2016InstanceKey); }
}
public static InstanceInfo DefaultSqlvNext
{
get { return GetInstance(DefaultSqlvNextInstanceKey); }
} }
/// <summary> /// <summary>
/// Returns database connection parameters for given server type /// Returns the SQL connection info for given version key
/// </summary> /// </summary>
public async Task<ConnectParams> GetConnectionParametersAsync(TestServerType serverType = TestServerType.OnPrem, string databaseName = null) public static InstanceInfo GetInstance(string key)
{ {
ConnectionProfile connectionProfile; InstanceInfo instanceInfo;
if (!_connectionProfilesCache.TryGetValue(serverType, out connectionProfile)) connectionProfilesCache.TryGetValue(key, out instanceInfo);
{ Assert.True(instanceInfo != null, string.Format(CultureInfo.InvariantCulture, "Cannot find any instance for version key: {0}", key));
connectionProfile = GetConnectionProfile(serverType); return instanceInfo;
}
if (connectionProfile != null) public ConnectParams GetConnectionParameters(string key = DefaultSql2016InstanceKey, string databaseName = null)
{ {
//If the password is empty, get the credential using the service InstanceInfo instanceInfo = GetInstance(key);
if (connectionProfile.AuthenticationType == AuthenticationType.SqlLogin && string.IsNullOrEmpty(connectionProfile.Password)) if (instanceInfo != null)
{
Credential credential = await ReadCredentialAsync(connectionProfile.formatCredentialId());
connectionProfile.Password = credential.Password;
}
_connectionProfilesCache.GetOrAdd(serverType, connectionProfile);
}
}
if (connectionProfile != null)
{ {
ConnectParams connenctParam = CreateConnectParams(connectionProfile, serverType, databaseName); ConnectParams connenctParam = CreateConnectParams(instanceInfo, key, databaseName);
return connenctParam; return connenctParam;
} }
return null; return null;
} }
/// <summary> /// <summary>
/// Request a Read Credential for given credential id /// Returns database connection parameters for given server type
/// </summary> /// </summary>
private async Task<Credential> ReadCredentialAsync(string credentialId) public ConnectParams GetConnectionParameters(TestServerType serverType = TestServerType.OnPrem, string databaseName = null)
{ {
var credentialParams = new Credential(); string key = ConvertServerTypeToVersionKey(serverType);
credentialParams.CredentialId = credentialId; return GetConnectionParameters(key, databaseName);
}
ServiceTestDriver driver = Driver; /// <summary>
if (driver == null) /// Forces the InstanceManager to load/reload it's instance list
/// </summary>
internal void LoadInstanceSettings()
{
try
{ {
TestServiceProvider.InitializeTestServices(); connectionProfilesCache = new Dictionary<string, InstanceInfo>();
return await CredentialService.Instance.ReadCredentialAsync(credentialParams); IEnumerable<TestServerIdentity> testServers = TestConfigPersistenceHelper.InitTestServerNames();
ConnectionSetting settings = TestConfigPersistenceHelper.InitSetting();
if (settings == null)
{
Console.WriteLine("DBTestInstance not configured. Run 'dotnet run Microsoft.SqlTools.ServiceLayer.TestEnvConfig from the command line to configure");
}
if (testServers != null && settings != null)
{
foreach (var serverIdentity in testServers)
{
var instance = settings != null ? settings.GetConnectionProfile(serverIdentity.ProfileName, serverIdentity.ServerName) : null;
if (instance.ServerType == TestServerType.None)
{
instance.ServerType = serverIdentity.ServerType;
AddInstance(instance);
}
}
}
if (settings != null)
{
foreach (var instance in settings.Connections)
{
AddInstance(instance);
}
}
} }
else catch(Exception ex)
{ {
return await Driver.SendRequest(ReadCredentialRequest.Type, credentialParams); Assert.True(false, "Fail to load the SQL connection instances. error: " + ex.Message);
} }
} }
private static void AddInstance(InstanceInfo instance)
{
if (instance != null && (instance.ServerType != TestServerType.None || !string.IsNullOrEmpty(instance.VersionKey)))
{
TestServerType serverType = instance.ServerType == TestServerType.None ? TestServerType.OnPrem : instance.ServerType; //Default to onPrem
string versionKey = string.IsNullOrEmpty(instance.VersionKey) ? ConvertServerTypeToVersionKey(serverType) : instance.VersionKey;
if (!connectionProfilesCache.ContainsKey(versionKey))
{
//If the password is empty, get the credential using the service
if (instance.AuthenticationType == AuthenticationType.SqlLogin && string.IsNullOrEmpty(instance.Password))
{
Credential credential = TestCredentialService.Instance.ReadCredential(instance);
instance.Password = credential.Password;
}
connectionProfilesCache.Add(versionKey, instance);
}
}
}
private static string ConvertServerTypeToVersionKey(TestServerType serverType)
{
return serverType == TestServerType.OnPrem ? DefaultSql2016InstanceKey : DefaultSqlAzureV12InstanceKey;
}
/// <summary> /// <summary>
/// Create a connection parameters object /// Create a connection parameters object
/// </summary> /// </summary>
private ConnectParams CreateConnectParams(ConnectionProfile connectionProfile, TestServerType serverType, string databaseName) private ConnectParams CreateConnectParams(InstanceInfo connectionProfile, string key, string databaseName)
{ {
ConnectParams connectParams = new ConnectParams(); ConnectParams connectParams = new ConnectParams();
connectParams.Connection = new ConnectionDetails(); connectParams.Connection = new ConnectionDetails();
@@ -146,7 +189,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{ {
connectParams.Connection.DatabaseName = databaseName; connectParams.Connection.DatabaseName = databaseName;
} }
if (serverType == TestServerType.Azure) if (key == DefaultSqlAzureInstanceKey || key == DefaultSqlAzureV12InstanceKey)
{ {
connectParams.Connection.ConnectTimeout = 30; connectParams.Connection.ConnectTimeout = 30;
connectParams.Connection.Encrypt = true; connectParams.Connection.Encrypt = true;
@@ -154,112 +197,5 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
} }
return connectParams; return connectParams;
} }
private static IEnumerable<TestServerIdentity> InitTestServerNames()
{
try
{
string testServerNamesFileContent = GetTestServerNamesFileContent();
if (!string.IsNullOrEmpty(testServerNamesFileContent))
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<IList<TestServerIdentity>>(testServerNamesFileContent);
}
else
{
return Enumerable.Empty<TestServerIdentity>();
}
}
catch (Exception ex)
{
Console.WriteLine("Failed to load the database connection server name settings. error: " + ex.Message);
return Enumerable.Empty<TestServerIdentity>();
}
}
private static ConnectionSetting InitSetting()
{
try
{
string settingsFileContents = GetSettingFileContent();
ConnectionSetting setting = Newtonsoft.Json.JsonConvert.DeserializeObject<ConnectionSetting>(settingsFileContents);
Console.WriteLine("Connection Settings loaded successfully");
return setting;
}
catch (Exception ex)
{
Console.WriteLine("Failed to load the connection settings. error: " + ex.Message);
return new ConnectionSetting();
}
}
/// <summary>
/// Get the location of testServerNames.json. Returns the value of environment variable 'SettingsFileName' and if it's empty returns
/// the location of vs code testServerNames.json
/// </summary>
/// <returns></returns>
private static string GetTestServerNamesFileContent()
{
var testServerNameFilePath = Environment.GetEnvironmentVariable("TestServerNamesFile");
string testServerFileName = "testServerNames.json";
if (string.IsNullOrEmpty(testServerNameFilePath))
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
testServerNameFilePath = Environment.GetEnvironmentVariable("APPDATA") + @"\\" + testServerFileName;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
testServerNameFilePath = Environment.GetEnvironmentVariable("HOME") + @"/" + testServerFileName;
}
else
{
testServerNameFilePath = Environment.GetEnvironmentVariable("HOME") + @"/" + testServerFileName;
}
}
string testServerNamesFileContent = string.IsNullOrEmpty(testServerNameFilePath) ? string.Empty : File.ReadAllText(testServerNameFilePath);
return testServerNamesFileContent;
}
/// <summary>
/// Get the location of setting.json. Returns the value of environment variable 'SettingsFileName' and if it's empty returns
/// the location of vs code settings.json
/// </summary>
/// <returns></returns>
private static string GetSettingFileContent()
{
var settingsFilename = Environment.GetEnvironmentVariable("SettingsFileName");
if (string.IsNullOrEmpty(settingsFilename))
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
settingsFilename = Environment.GetEnvironmentVariable("APPDATA") + @"\Code\User\settings.json";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
settingsFilename = Environment.GetEnvironmentVariable("HOME") + @"/Library/Application Support/Code/User/settings.json";
}
else
{
settingsFilename = Environment.GetEnvironmentVariable("HOME") + @"/.config/Code/User/settings.json";
}
}
if (string.IsNullOrEmpty(settingsFilename))
{
Console.WriteLine("Cannot find any connection settings. Please run CreateConnectionSettings.cmd to generate a template for the connection settings.");
}
else
{
Console.WriteLine("Connection settings: " + settingsFilename);
_connectionSettingsFilename = settingsFilename;
}
string settingsFileContents = string.IsNullOrEmpty(settingsFilename) ? string.Empty : File.ReadAllText(settingsFilename);
return settingsFileContents;
}
} }
} }

View File

@@ -0,0 +1,98 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Collections.Generic;
using System.Globalization;
using Microsoft.SqlTools.ServiceLayer.Credentials;
using Microsoft.SqlTools.ServiceLayer.Credentials.Contracts;
namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{
public class TestCredentialService
{
private CredentialService credentialService = TestServiceProvider.Instance.CredentialService;
private static TestCredentialService instance = new TestCredentialService();
/// <summary>
/// The singleton instance of the service
/// </summary>
public static TestCredentialService Instance
{
get
{
return instance;
}
}
private const string MSSQL_CRED_PREFIX = "Microsoft.SqlTools";
private const string TEST_CRED_PREFIX = "SqlToolsTestInstance";
private const string CRED_SEPARATOR = "|";
private const string CRED_SERVER_PREFIX = "server:";
private const string CRED_DB_PREFIX = "db:";
private const string CRED_USER_PREFIX = "user:";
private const string CRED_ITEMTYPE_PREFIX = "itemtype:";
/// <summary>
/// Read Credential for given instance Info. Tries the test credential id and if no password found
/// will try the MSSQL credential id
/// </summary>
public Credential ReadCredential(InstanceInfo connectionProfile)
{
var credentialParams = new Credential();
credentialParams.CredentialId = FormatCredentialIdForTest(connectionProfile);
Credential credential = credentialService.ReadCredential(credentialParams);
if (credential == null || string.IsNullOrEmpty(credential.Password))
{
credentialParams.CredentialId = FormatCredentialIdForMsSql(connectionProfile);
credential = credentialService.ReadCredential(credentialParams);
}
return credential;
}
/// <summary>
/// Stored the credential to credential store using the test prefix
/// </summary>
public bool SaveCredential(InstanceInfo connectionProfile)
{
Credential credential = new Credential(FormatCredentialIdForTest(connectionProfile), connectionProfile.Password);
return credentialService.SaveCredential(credential);
}
private string FormatCredentialIdForMsSql(InstanceInfo connectionProfile, string itemType = "Profile")
{
return FormatCredentialId(connectionProfile, itemType, MSSQL_CRED_PREFIX);
}
private string FormatCredentialIdForTest(InstanceInfo connectionProfile, string itemType = "Profile")
{
return FormatCredentialId(connectionProfile, itemType, TEST_CRED_PREFIX);
}
private string FormatCredentialId(InstanceInfo connectionProfile, string itemType = "Profile", string credPrefix = TEST_CRED_PREFIX)
{
if (!string.IsNullOrEmpty(connectionProfile.ServerName))
{
List<string> cred = new List<string>();
cred.Add(credPrefix);
AddToList(itemType, CRED_ITEMTYPE_PREFIX, cred);
AddToList(connectionProfile.ServerName, CRED_SERVER_PREFIX, cred);
AddToList(connectionProfile.Database, CRED_DB_PREFIX, cred);
AddToList(connectionProfile.User, CRED_USER_PREFIX, cred);
return string.Join(CRED_SEPARATOR, cred.ToArray());
}
return null;
}
private void AddToList(string item, string prefix, List<string> list)
{
if (!string.IsNullOrEmpty(item))
{
list.Add(string.Format(CultureInfo.InvariantCulture, "{0}{1}", prefix, item));
}
}
}
}

View File

@@ -66,7 +66,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{ {
get get
{ {
return (testConnectionService = testConnectionService ?? new TestConnectionProfileService(Driver)); return (testConnectionService = testConnectionService ?? TestConnectionProfileService.Instance);
} }
} }
@@ -101,23 +101,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
WriteToFile(ownerUri, query); WriteToFile(ownerUri, query);
} }
/*
DidOpenTextDocumentNotification openParams = new DidOpenTextDocumentNotification
{
TextDocument = new TextDocumentItem
{
Uri = ownerUri,
LanguageId = "enu",
Version = 1,
Text = query
}
};
await RequestOpenDocumentNotification(openParams);
Thread.Sleep(500);
*/
return await Connect(serverType, ownerUri, databaseName, timeout); return await Connect(serverType, ownerUri, databaseName, timeout);
} }
@@ -127,7 +110,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
public async Task<bool> Connect(TestServerType serverType, string ownerUri, string databaseName = null, int timeout = 15000) public async Task<bool> Connect(TestServerType serverType, string ownerUri, string databaseName = null, int timeout = 15000)
{ {
var connectParams = await GetConnectionParametersAsync(serverType, databaseName); var connectParams = GetConnectionParameters(serverType, databaseName);
bool connected = await Connect(ownerUri, connectParams, timeout); bool connected = await Connect(ownerUri, connectParams, timeout);
Assert.True(connected, "Connection is successful"); Assert.True(connected, "Connection is successful");
@@ -215,9 +198,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
/// <summary> /// <summary>
/// Returns database connection parameters for given server type /// Returns database connection parameters for given server type
/// </summary> /// </summary>
public async Task<ConnectParams> GetConnectionParametersAsync(TestServerType serverType, string databaseName = null) public ConnectParams GetConnectionParameters(TestServerType serverType, string databaseName = null)
{ {
return await TestConnectionService.GetConnectionParametersAsync(serverType, databaseName); return TestConnectionService.GetConnectionParameters(serverType, databaseName);
} }
/// <summary> /// <summary>
@@ -339,6 +322,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{ {
await ConnectForQuery(serverType, query, queryTempFile.FilePath, databaseName); await ConnectForQuery(serverType, query, queryTempFile.FilePath, databaseName);
var queryResult = await CalculateRunTime(() => RunQueryAndWaitToComplete(queryTempFile.FilePath, query, 50000), false); var queryResult = await CalculateRunTime(() => RunQueryAndWaitToComplete(queryTempFile.FilePath, query, 50000), false);
Assert.NotNull(queryResult);
Assert.NotNull(queryResult.BatchSummaries);
await Disconnect(queryTempFile.FilePath); await Disconnect(queryTempFile.FilePath);
} }

View File

@@ -4,13 +4,20 @@
// //
using System; using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Microsoft.SqlTools.ServiceLayer.Connection; using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.Credentials; using Microsoft.SqlTools.ServiceLayer.Credentials;
using Microsoft.SqlTools.ServiceLayer.Hosting; using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.LanguageServices; using Microsoft.SqlTools.ServiceLayer.LanguageServices;
using Microsoft.SqlTools.ServiceLayer.QueryExecution; using Microsoft.SqlTools.ServiceLayer.QueryExecution;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage;
using Microsoft.SqlTools.ServiceLayer.SqlContext; using Microsoft.SqlTools.ServiceLayer.SqlContext;
using Microsoft.SqlTools.ServiceLayer.Workspace; using Microsoft.SqlTools.ServiceLayer.Workspace;
using Moq;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.Test.Common namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{ {
@@ -19,39 +26,140 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
/// </summary> /// </summary>
public class TestServiceProvider public class TestServiceProvider
{ {
private TestServiceProvider()
{
InitializeTestServices();
}
private static object _lockObject = new object();
private static TestServiceProvider _instance = new TestServiceProvider();
public static TestServiceProvider Instance
{
get
{
return _instance;
}
}
public CredentialService CredentialService
{
get
{
return CredentialService.Instance;
}
}
public TestConnectionProfileService ConnectionProfileService
{
get
{
return TestConnectionProfileService.Instance;
}
}
public WorkspaceService<SqlToolsSettings> WorkspaceService
{
get
{
return WorkspaceService<SqlToolsSettings>.Instance;
}
}
/// <summary>
/// Runs a query by calling the services directly (not using the test driver)
/// </summary>
public void RunQuery(TestServerType serverType, string databaseName, string queryText)
{
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{
ConnectionInfo connInfo = InitLiveConnectionInfo(serverType, databaseName, queryTempFile.FilePath);
Query query = new Query(queryText, connInfo, new QueryExecutionSettings(), GetFileStreamFactory(new Dictionary<string, byte[]>()));
query.Execute();
query.ExecutionTask.Wait();
}
}
private ConnectionInfo InitLiveConnectionInfo(TestServerType serverType, string databaseName, string scriptFilePath)
{
ConnectParams connectParams = ConnectionProfileService.GetConnectionParameters(serverType, databaseName);
string ownerUri = scriptFilePath;
var connectionService = ConnectionService.Instance;
var connectionResult = connectionService.Connect(new ConnectParams()
{
OwnerUri = ownerUri,
Connection = connectParams.Connection
});
connectionResult.Wait();
ConnectionInfo connInfo = null;
connectionService.TryFindConnection(ownerUri, out connInfo);
Assert.NotNull(connInfo);
return connInfo;
}
private static IFileStreamFactory GetFileStreamFactory(Dictionary<string, byte[]> storage)
{
Mock<IFileStreamFactory> mock = new Mock<IFileStreamFactory>();
mock.Setup(fsf => fsf.CreateFile())
.Returns(() =>
{
string fileName = Guid.NewGuid().ToString();
storage.Add(fileName, new byte[8192]);
return fileName;
});
mock.Setup(fsf => fsf.GetReader(It.IsAny<string>()))
.Returns<string>(output => new ServiceBufferFileStreamReader(new MemoryStream(storage[output])));
mock.Setup(fsf => fsf.GetWriter(It.IsAny<string>()))
.Returns<string>(output => new ServiceBufferFileStreamWriter(new MemoryStream(storage[output]), 1024, 1024));
return mock.Object;
}
private static bool hasInitServices = false; private static bool hasInitServices = false;
public static void InitializeTestServices() private static void InitializeTestServices()
{ {
if (TestServiceProvider.hasInitServices) if (TestServiceProvider.hasInitServices)
{ {
return; return;
} }
TestServiceProvider.hasInitServices = true; lock (_lockObject)
{
if (TestServiceProvider.hasInitServices)
{
return;
}
TestServiceProvider.hasInitServices = true;
const string hostName = "SQ Tools Test Service Host"; const string hostName = "SQ Tools Test Service Host";
const string hostProfileId = "SQLToolsTestService"; const string hostProfileId = "SQLToolsTestService";
Version hostVersion = new Version(1, 0); Version hostVersion = new Version(1, 0);
// set up the host details and profile paths // set up the host details and profile paths
var hostDetails = new HostDetails(hostName, hostProfileId, hostVersion); var hostDetails = new HostDetails(hostName, hostProfileId, hostVersion);
SqlToolsContext sqlToolsContext = new SqlToolsContext(hostDetails); SqlToolsContext sqlToolsContext = new SqlToolsContext(hostDetails);
// Grab the instance of the service host // Grab the instance of the service host
ServiceHost serviceHost = ServiceHost.Instance; ServiceHost serviceHost = ServiceHost.Instance;
// Start the service // Start the service
serviceHost.Start().Wait(); serviceHost.Start().Wait();
// Initialize the services that will be hosted here // Initialize the services that will be hosted here
WorkspaceService<SqlToolsSettings>.Instance.InitializeService(serviceHost); WorkspaceService<SqlToolsSettings>.Instance.InitializeService(serviceHost);
LanguageService.Instance.InitializeService(serviceHost, sqlToolsContext); LanguageService.Instance.InitializeService(serviceHost, sqlToolsContext);
ConnectionService.Instance.InitializeService(serviceHost); ConnectionService.Instance.InitializeService(serviceHost);
CredentialService.Instance.InitializeService(serviceHost); CredentialService.Instance.InitializeService(serviceHost);
QueryExecutionService.Instance.InitializeService(serviceHost); QueryExecutionService.Instance.InitializeService(serviceHost);
serviceHost.Initialize(); serviceHost.Initialize();
}
} }
} }
} }

View File

@@ -126,7 +126,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
[Fact] [Fact]
public async Task DefinitionsHandlerWithNoConnectionTest() public async Task DefinitionsHandlerWithNoConnectionTest()
{ {
TestServiceProvider.InitializeTestServices();
InitializeTestObjects(); InitializeTestObjects();
// request definition // request definition
var definitionTask = await Task.WhenAny(LanguageService.HandleDefinitionRequest(textDocument, requestContext.Object), Task.Delay(TaskTimeout)); var definitionTask = await Task.WhenAny(LanguageService.HandleDefinitionRequest(textDocument, requestContext.Object), Task.Delay(TaskTimeout));
@@ -204,9 +203,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
{ {
PeekDefinition peekDefinition = new PeekDefinition(null, null); PeekDefinition peekDefinition = new PeekDefinition(null, null);
var languageService = LanguageService.Instance; var languageService = LanguageService.Instance;
Assert.True(Directory.Exists(FileUtils.PeekDefinitionTempFolder)); Assert.True(Directory.Exists(ServiceLayer.QueryExecution.FileUtils.PeekDefinitionTempFolder));
languageService.DeletePeekDefinitionScripts(); languageService.DeletePeekDefinitionScripts();
Assert.False(Directory.Exists(FileUtils.PeekDefinitionTempFolder)); Assert.False(Directory.Exists(ServiceLayer.QueryExecution.FileUtils.PeekDefinitionTempFolder));
} }
/// <summary> /// <summary>
@@ -217,8 +216,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.LanguageServices
{ {
var languageService = LanguageService.Instance; var languageService = LanguageService.Instance;
PeekDefinition peekDefinition = new PeekDefinition(null, null); PeekDefinition peekDefinition = new PeekDefinition(null, null);
FileUtils.SafeDirectoryDelete(FileUtils.PeekDefinitionTempFolder, true); ServiceLayer.QueryExecution.FileUtils.SafeDirectoryDelete(ServiceLayer.QueryExecution.FileUtils.PeekDefinitionTempFolder, true);
Assert.False(Directory.Exists(FileUtils.PeekDefinitionTempFolder)); Assert.False(Directory.Exists(ServiceLayer.QueryExecution.FileUtils.PeekDefinitionTempFolder));
// Expected not to throw any exception // Expected not to throw any exception
languageService.DeletePeekDefinitionScripts(); languageService.DeletePeekDefinitionScripts();
} }

View File

@@ -96,6 +96,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.QueryExecution
public static Query GetBasicExecutedQuery(QueryExecutionSettings querySettings) public static Query GetBasicExecutedQuery(QueryExecutionSettings querySettings)
{ {
ConnectionInfo ci = CreateTestConnectionInfo(new[] {StandardTestData}, false); ConnectionInfo ci = CreateTestConnectionInfo(new[] {StandardTestData}, false);
// Query won't be able to request a new query DbConnection unless the ConnectionService has a
// ConnectionInfo with the same URI as the query, so we will manually set it
ConnectionService.Instance.OwnerToConnectionMap[ci.OwnerUri] = ci;
Query query = new Query(StandardQuery, ci, querySettings, GetFileStreamFactory(new Dictionary<string, byte[]>())); Query query = new Query(StandardQuery, ci, querySettings, GetFileStreamFactory(new Dictionary<string, byte[]>()));
query.Execute(); query.Execute();
query.ExecutionTask.Wait(); query.ExecutionTask.Wait();

View File

@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Data; using System.Data;
using System.Data.Common; using System.Data.Common;
using System.Data.SqlClient; using System.Data.SqlClient;
using System.Globalization;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -20,6 +21,7 @@ using Microsoft.SqlTools.ServiceLayer.Test.Common;
using Microsoft.SqlTools.ServiceLayer.Test.Utility; using Microsoft.SqlTools.ServiceLayer.Test.Utility;
using Microsoft.SqlTools.ServiceLayer.Workspace; using Microsoft.SqlTools.ServiceLayer.Workspace;
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts; using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
using Xunit;
namespace Microsoft.SqlTools.Test.Utility namespace Microsoft.SqlTools.Test.Utility
{ {
@@ -28,7 +30,9 @@ namespace Microsoft.SqlTools.Test.Utility
/// </summary> /// </summary>
public class TestObjects public class TestObjects
{ {
public const string ScriptUriTemplate = "file://some/{0}.sql";
public const string ScriptUri = "file://some/file.sql"; public const string ScriptUri = "file://some/file.sql";
private static TestServiceProvider _serviceProvider = TestServiceProvider.Instance;
/// <summary> /// <summary>
/// Creates a test connection service /// Creates a test connection service
@@ -124,14 +128,11 @@ namespace Microsoft.SqlTools.Test.Utility
return filePath; return filePath;
} }
public static async Task<TestConnectionResult> InitLiveConnectionInfo() public static TestConnectionResult InitLiveConnectionInfo()
{ {
TestServiceProvider.InitializeTestServices();
string sqlFilePath = GetTestSqlFile(); string sqlFilePath = GetTestSqlFile();
ScriptFile scriptFile = WorkspaceService<SqlToolsSettings>.Instance.Workspace.GetFile(sqlFilePath); ScriptFile scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(sqlFilePath);
TestConnectionProfileService connectionProfileService = new TestConnectionProfileService(); ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem);
ConnectParams connectParams = await connectionProfileService.GetConnectionParametersAsync();
string ownerUri = scriptFile.ClientFilePath; string ownerUri = scriptFile.ClientFilePath;
var connectionService = TestObjects.GetLiveTestConnectionService(); var connectionService = TestObjects.GetLiveTestConnectionService();
@@ -150,13 +151,11 @@ namespace Microsoft.SqlTools.Test.Utility
return new TestConnectionResult () { ConnectionInfo = connInfo, ScriptFile = scriptFile }; return new TestConnectionResult () { ConnectionInfo = connInfo, ScriptFile = scriptFile };
} }
public static async Task<ConnectionInfo> InitLiveConnectionInfoForDefinition() public static ConnectionInfo InitLiveConnectionInfoForDefinition(string databaseName = null)
{ {
TestServiceProvider.InitializeTestServices(); ConnectParams connectParams = _serviceProvider.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);
TestConnectionProfileService connectionProfileService = new TestConnectionProfileService();
ConnectParams connectParams = await connectionProfileService.GetConnectionParametersAsync();
string ownerUri = ScriptUri; string ownerUri = string.Format(CultureInfo.InvariantCulture, ScriptUriTemplate, string.IsNullOrEmpty(databaseName) ? "file" : databaseName);
var connectionService = TestObjects.GetLiveTestConnectionService(); var connectionService = TestObjects.GetLiveTestConnectionService();
var connectionResult = var connectionResult =
connectionService connectionService
@@ -170,6 +169,8 @@ namespace Microsoft.SqlTools.Test.Utility
ConnectionInfo connInfo = null; ConnectionInfo connInfo = null;
connectionService.TryFindConnection(ownerUri, out connInfo); connectionService.TryFindConnection(ownerUri, out connInfo);
Assert.NotNull(connInfo);
return connInfo; return connInfo;
} }

View File

@@ -196,7 +196,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
using (TestServiceDriverProvider testService = new TestServiceDriverProvider()) using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
{ {
var connection = await testService.GetConnectionParametersAsync(TestServerType.OnPrem); var connection = testService.GetConnectionParameters(TestServerType.OnPrem);
connection.Connection.Pooling = false; connection.Connection.Pooling = false;
// Connect/disconnect repeatedly // Connect/disconnect repeatedly

View File

@@ -0,0 +1,21 @@
<?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>6cf2e945-c7d1-44b5-9e28-addd09e3e983</ProjectGuid>
<RootNamespace>Microsoft.SqlTools.ServiceLayer.TestEnvConfig</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

View File

@@ -0,0 +1,115 @@
//
// 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.Xml.Linq;
using Microsoft.SqlTools.ServiceLayer.Test.Common;
namespace Microsoft.SqlTools.ServiceLayer.TestEnvConfig
{
class Program
{
static void Main(string[] args)
{
if (args.Length == 1)
{
string arg = args[0];
if (arg.Equals("-?", StringComparison.OrdinalIgnoreCase) ||
arg.Equals("/?", StringComparison.OrdinalIgnoreCase) ||
arg.Equals("-help", StringComparison.OrdinalIgnoreCase) ||
arg.Equals("/help", StringComparison.OrdinalIgnoreCase))
{
ShowUsage();
}
else if (File.Exists(arg) == false)
{
Console.WriteLine("setting file {0} does not exist.", arg);
}
else
{
try
{
SaveSettings(arg);
Console.WriteLine("Completed saving the settings");
}
catch (Exception ex)
{
Console.WriteLine("Error encountered: {0}", ex.Message);
}
}
}
else
{
ShowUsage();
}
}
private static void ShowUsage()
{
Console.WriteLine(@"Usage:
TestEnvConfig
Show this help message
TestEnvConfig -?
Show this help message
TestEnvConfig setting_file
Run the program as a command line application
The program reads the test configurations from the setting_file and
saves them locally. the passwords will be stored in the credential store
The following is an example of a setting_file:
<Configuration>
<Instance Name=""defaultSql2005"">
<DataSource>SQL2005 servername</DataSource>
<BackupMethod>RemoteShare</BackupMethod>
<RemoteShare>SQL 2005 remote share</RemoteShare>
</Instance>
<Instance Name=""defaultSql2008"">
<DataSource>SQL2008 servername</DataSource>
<BackupMethod>RemoteShare</BackupMethod>
<RemoteShare>SQL 2008 remote share</RemoteShare>
</Instance>
<Instance Name=""defaultSql2011"">
<DataSource>SQL2011 servername</DataSource>
<BackupMethod>RemoteShare</BackupMethod>
<RemoteShare>SQL 20011 remote share</RemoteShare>
</Instance>
<Instance Name=""defaultSqlAzureV12"">
<DataSource>SQLAzure servername</DataSource>
<BackupMethod>RemoteShare</BackupMethod>
<RemoteShare>SQLAzure remote share</RemoteShare>
<UserId>user id</UserId>
<Password>password</Password>
</Instance>
</Configuration>
");
}
private static void SaveSettings(string settingFile)
{
var xdoc = XDocument.Load(settingFile);
var settings =
from setting in xdoc.Descendants("Instance")
select new InstanceInfo(setting.Attribute("VersionKey").Value) // VersionKey is required
{
ServerName = setting.Element("DataSource").Value, // DataSource is required
ConnectTimeoutAsString = (string)setting.Element("ConnectTimeout"), //ConnectTimeout is optional
User = (string)setting.Element("UserId"), // UserID is optional
Password = (string)setting.Element("Password"),
RemoteSharePath = (string)setting.Element("RemoteShare"), // RemoteShare is optional
AuthenticationType = string.IsNullOrEmpty((string)setting.Element("UserId")) ? AuthenticationType.Integrated : AuthenticationType.SqlLogin
};
TestConfigPersistenceHelper.Write(settings);
}
}
}

View File

@@ -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.TestEnvConfig")]
[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("6cf2e945-c7d1-44b5-9e28-addd09e3e983")]

View File

@@ -0,0 +1,25 @@
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true
},
"dependencies": {
"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"
]
}
}
}