New test common project for database connections using the settings.json (#210)

* moved test driver tests and test common classes to separate projects
This commit is contained in:
Leila Lali
2017-01-11 13:47:56 -08:00
committed by GitHub
parent e71bcefb28
commit b353b2137e
56 changed files with 1396 additions and 1008 deletions

View File

@@ -0,0 +1,84 @@
//
// 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 System.Linq;
using Newtonsoft.Json;
namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{
/// <summary>
/// The model for deserializing settings.json
/// </summary>
public class ConnectionSetting
{
[JsonProperty("mssql.connections")]
public List<ConnectionProfile> Connections { get; set; }
public ConnectionProfile GetConnectionProfile(string profileName, string serverName)
{
if (!string.IsNullOrEmpty(profileName) && Connections != null)
{
var byProfileName = Connections.FirstOrDefault(x => x.ProfileName == profileName);
if (byProfileName != null)
{
return byProfileName;
}
}
return Connections.FirstOrDefault(x => x.ServerName == serverName);
}
}
/// <summary>
/// The model to deserializing the connections inside settings.json
/// </summary>
public class ConnectionProfile
{
public const string CRED_PREFIX = "Microsoft.SqlTools";
public const string CRED_SEPARATOR = "|";
public const string CRED_SERVER_PREFIX = "server:";
public const string CRED_DB_PREFIX = "db:";
public const string CRED_USER_PREFIX = "user:";
public const string CRED_ITEMTYPE_PREFIX = "itemtype:";
[JsonProperty("server")]
public string ServerName { get; set; }
public string Database { get; set; }
public string User { get; set; }
public string Password { get; set; }
public string ProfileName { get; set; }
public TestServerType ServerType { get; set; }
public AuthenticationType AuthenticationType { get; set; }
public string formatCredentialId(string itemType = "Profile")
{
if (!string.IsNullOrEmpty(ServerName))
{
List<string> cred = new List<string>();
cred.Add(CRED_PREFIX);
AddToList(itemType, CRED_ITEMTYPE_PREFIX, cred);
AddToList(ServerName, CRED_SERVER_PREFIX, cred);
AddToList(Database, CRED_DB_PREFIX, cred);
AddToList(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

@@ -0,0 +1,19 @@
<?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>b6f4bece-82ee-4ab6-99ac-108aee466274</ProjectGuid>
<RootNamespace>Microsoft.SqlTools.ServiceLayer.Test.Common</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,13 @@
USE master
GO
DECLARE @dbname nvarchar(128)
SET @dbname = N'#DatabaseName#'
IF NOT(EXISTS (SELECT name
FROM master.dbo.sysdatabases
WHERE ('[' + name + ']' = @dbname
OR name = @dbname)))
BEGIN
CREATE DATABASE #DatabaseName#
END

View File

@@ -0,0 +1,231 @@
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'Demo')
BEGIN
EXEC('CREATE SCHEMA [Demo]')
END
GO
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'HumanResources')
BEGIN
EXEC('CREATE SCHEMA [HumanResources]')
END
GO
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'Person')
BEGIN
EXEC('CREATE SCHEMA [Person]')
END
GO
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'Production')
BEGIN
EXEC('CREATE SCHEMA [Production]')
END
GO
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'Purchasing')
BEGIN
EXEC('CREATE SCHEMA [Purchasing]')
END
GO
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'Sales')
BEGIN
EXEC('CREATE SCHEMA [Sales]')
END
GO
IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'Security')
BEGIN
EXEC('CREATE SCHEMA [Security]')
END
GO
IF NOT EXISTS (SELECT * FROM sys.types WHERE name = 'AccountNumber')
BEGIN
CREATE TYPE [dbo].[AccountNumber] FROM [nvarchar](15) NULL
END
GO
IF NOT EXISTS (SELECT * FROM sys.types WHERE name = 'Flag')
BEGIN
CREATE TYPE [dbo].[Flag] FROM [bit] NOT NULL
END
GO
IF NOT EXISTS (SELECT * FROM sys.types WHERE name = 'Name')
BEGIN
CREATE TYPE [dbo].[Name] FROM [nvarchar](50) NULL
END
GO
IF NOT EXISTS (SELECT * FROM sys.types WHERE name = 'NameStyle')
BEGIN
CREATE TYPE [dbo].[NameStyle] FROM [bit] NOT NULL
END
GO
IF NOT EXISTS (SELECT * FROM sys.types WHERE name = 'OrderNumber')
BEGIN
CREATE TYPE [dbo].[OrderNumber] FROM [nvarchar](25) NULL
END
GO
GO
IF NOT EXISTS (SELECT * FROM sys.types WHERE name = 'Phone')
BEGIN
CREATE TYPE [dbo].[Phone] FROM [nvarchar](25) NULL
END
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Address')
BEGIN
CREATE TABLE [Person].[Address](
[AddressID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[AddressLine1] [nvarchar](60) NOT NULL,
[AddressLine2] [nvarchar](60) NULL,
[City] [nvarchar](30) NOT NULL,
[StateProvinceID] [int] NOT NULL,
[PostalCode] [nvarchar](15) NOT NULL,
[SpatialLocation] [geography] NULL,
[rowguid] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_Address_AddressID] PRIMARY KEY CLUSTERED
(
[AddressID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'AddressType')
BEGIN
CREATE TABLE [Person].[AddressType](
[AddressTypeID] [int] IDENTITY(1,1) NOT NULL,
[Name] [dbo].[Name] NOT NULL,
[rowguid] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_AddressType_AddressTypeID] PRIMARY KEY CLUSTERED
(
[AddressTypeID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
/****** Object: Table [Person].[ContactType] Script Date: 11/22/2016 9:25:52 AM ******/
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'ContactType')
BEGIN
CREATE TABLE [Person].[ContactType](
[ContactTypeID] [int] IDENTITY(1,1) NOT NULL,
[Name] [dbo].[Name] NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_ContactType_ContactTypeID] PRIMARY KEY CLUSTERED
(
[ContactTypeID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'EmailAddress')
BEGIN
CREATE TABLE [Person].[EmailAddress](
[BusinessEntityID] [int] NOT NULL,
[EmailAddressID] [int] IDENTITY(1,1) NOT NULL,
[EmailAddress] [nvarchar](50) NULL,
[rowguid] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_EmailAddress_BusinessEntityID_EmailAddressID] PRIMARY KEY CLUSTERED
(
[BusinessEntityID] ASC,
[EmailAddressID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Person')
BEGIN
CREATE TABLE [Person].[Person](
[BusinessEntityID] [int] NOT NULL,
[PersonType] [nchar](2) NOT NULL,
[NameStyle] [dbo].[NameStyle] NOT NULL,
[Title] [nvarchar](8) NULL,
[FirstName] [dbo].[Name] NOT NULL,
[MiddleName] [dbo].[Name] NULL,
[LastName] [dbo].[Name] NOT NULL,
[Suffix] [nvarchar](10) NULL,
[EmailPromotion] [int] NOT NULL,
[rowguid] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_Person_BusinessEntityID] PRIMARY KEY CLUSTERED
(
[BusinessEntityID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'PersonPhone')
BEGIN
CREATE TABLE [Person].[PersonPhone](
[BusinessEntityID] [int] NOT NULL,
[PhoneNumber] [dbo].[Phone] NOT NULL,
[PhoneNumberTypeID] [int] NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_PersonPhone_BusinessEntityID_PhoneNumber_PhoneNumberTypeID] PRIMARY KEY CLUSTERED
(
[BusinessEntityID] ASC,
[PhoneNumber] ASC,
[PhoneNumberTypeID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Location')
BEGIN
CREATE TABLE [Production].[Location](
[LocationID] [smallint] IDENTITY(1,1) NOT NULL,
[Name] [dbo].[Name] NOT NULL,
[CostRate] [smallmoney] NOT NULL,
[Availability] [decimal](8, 2) NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_Location_LocationID] PRIMARY KEY CLUSTERED
(
[LocationID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'Product')
BEGIN
CREATE TABLE [Production].[Product](
[ProductID] [int] IDENTITY(1,1) NOT NULL,
[Name] [dbo].[Name] NOT NULL,
[ProductNumber] [nvarchar](25) NOT NULL,
[MakeFlag] [dbo].[Flag] NOT NULL,
[FinishedGoodsFlag] [dbo].[Flag] NOT NULL,
[Color] [nvarchar](15) NULL,
[SafetyStockLevel] [smallint] NOT NULL,
[ReorderPoint] [smallint] NOT NULL,
[StandardCost] [money] NOT NULL,
[ListPrice] [money] NOT NULL,
[Size] [nvarchar](5) NULL,
[SizeUnitMeasureCode] [nchar](3) NULL,
[WeightUnitMeasureCode] [nchar](3) NULL,
[Weight] [decimal](8, 2) NULL,
[DaysToManufacture] [int] NOT NULL,
[ProductLine] [nchar](2) NULL,
[Class] [nchar](2) NULL,
[Style] [nchar](2) NULL,
[ProductSubcategoryID] [int] NULL,
[ProductModelID] [int] NULL,
[SellStartDate] [datetime] NOT NULL,
[SellEndDate] [datetime] NULL,
[DiscontinuedDate] [datetime] NULL,
[rowguid] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[ModifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_Product_ProductID] PRIMARY KEY CLUSTERED
(
[ProductID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO

View File

@@ -0,0 +1,85 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using System.IO;
using System.Reflection;
namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{
public class Scripts
{
private const string ResourceNameRefix = "Microsoft.SqlTools.ServiceLayer.Test.Common.Scripts.";
public const string MasterBasicQuery = "SELECT * FROM sys.all_columns"; //basic queries should return at least 10000 rows
public const string DelayQuery = "WAITFOR DELAY '00:01:00'";
public const string TestDbSimpleSelectQuery = "SELECT * FROM [Person].[Address]";
public const string SelectQuery = "SELECT * FROM ";
public const string DropDatabaseIfExist = @"
IF EXISTS (SELECT 1 FROM [sys].[databases] WHERE [name] = '{0}')
BEGIN
ALTER DATABASE [{0}]
SET READ_WRITE;
ALTER DATABASE [{0}]
SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE [{0}];
END
";
public const string DropDatabaseIfExistAzure = @"
IF EXISTS (SELECT 1 FROM [sys].[databases] WHERE [name] = '{0}')
BEGIN
DROP DATABASE [{0}];
END
";
public static string CreateDatabaseObjectsQuery { get { return CreateDatabaseObjectsQueryInstance.Value; } }
public static string CreateDatabaseQuery { get { return CreateDatabaseQueryInstance.Value; } }
public static string TestDbComplexSelectQueries { get { return TestDbSelectQueriesInstance.Value; } }
private static readonly Lazy<string> CreateDatabaseObjectsQueryInstance = new Lazy<string>(() =>
{
return GetScriptFileContent(ResourceNameRefix + "CreateTestDatabaseObjects.sql");
});
private static readonly Lazy<string> CreateDatabaseQueryInstance = new Lazy<string>(() =>
{
return GetScriptFileContent(ResourceNameRefix + "CreateTestDatabase.sql");
});
private static readonly Lazy<string> TestDbSelectQueriesInstance = new Lazy<string>(() =>
{
return GetScriptFileContent(ResourceNameRefix + "TestDbTableQueries.sql");
});
private static string GetScriptFileContent(string fileName)
{
string fileContent = string.Empty;
try
{
using (Stream stream = typeof(Scripts).GetTypeInfo().Assembly.GetManifestResourceStream(fileName))
{
using (StreamReader reader = new StreamReader(stream))
{
fileContent = reader.ReadToEnd();
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Failed to load the sql script. error: {ex.Message}");
}
return fileContent;
}
}
}

View File

@@ -0,0 +1,84 @@
SELECT * FROM [Person].[Address]
SELECT [AddressID]
,[AddressLine1]
,[AddressLine2]
,[City]
,[StateProvinceID]
,[PostalCode]
,[SpatialLocation]
,[rowguid]
,[ModifiedDate]
FROM [Person].[Address]
GO
SELECT [AddressTypeID]
,[Name]
,[rowguid]
,[ModifiedDate]
FROM [Person].[AddressType]
GO
SELECT [ContactTypeID]
,[Name]
,[ModifiedDate]
FROM [Person].[ContactType]
GO
SELECT [BusinessEntityID]
,[EmailAddressID]
,[EmailAddress]
,[rowguid]
,[ModifiedDate]
FROM [Person].[EmailAddress]
GO
SELECT [BusinessEntityID]
,[PersonType]
,[NameStyle]
,[Title]
,[FirstName]
,[MiddleName]
,[LastName]
,[Suffix]
,[EmailPromotion]
,[rowguid]
,[ModifiedDate]
FROM [Person].[Person]
GO
SELECT [BusinessEntityID]
,[PhoneNumber]
,[PhoneNumberTypeID]
,[ModifiedDate]
FROM [Person].[PersonPhone]
GO
SELECT [LocationID]
,[Name]
,[CostRate]
,[Availability]
,[ModifiedDate]
FROM [Production].[Location]
GO
SELECT [ProductID]
,[Name]
,[ProductNumber]
,[MakeFlag]
,[FinishedGoodsFlag]
,[Color]
,[SafetyStockLevel]
,[ReorderPoint]
,[StandardCost]
,[ListPrice]
,[Size]
,[SizeUnitMeasureCode]
,[WeightUnitMeasureCode]
,[Weight]
,[DaysToManufacture]
,[ProductLine]
,[Class]
,[Style]
,[ProductSubcategoryID]
,[ProductModelID]
,[SellStartDate]
,[SellEndDate]
,[DiscontinuedDate]
,[rowguid]
,[ModifiedDate]
FROM [Production].[Product]
GO

View File

@@ -0,0 +1,53 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using System.IO;
namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{
public class SelfCleaningTempFile : IDisposable
{
private bool disposed;
public SelfCleaningTempFile()
{
FilePath = Path.GetTempFileName();
}
public string FilePath { get; private set; }
#region IDisposable Implementation
public void Dispose()
{
if (!disposed)
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
public void Dispose(bool disposing)
{
if (!disposed && disposing)
{
try
{
File.Delete(FilePath);
}
catch
{
Console.WriteLine($"Failed to cleanup {FilePath}");
}
}
disposed = true;
}
#endregion
}
}

View File

@@ -0,0 +1,76 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using System.Globalization;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{
/// <summary>
/// Creates a new test database
/// </summary>
public class SqlTestDb : IDisposable
{
public const string MasterDatabaseName = "master";
public string DatabaseName { get; set; }
public TestServerType ServerType { get; set; }
public bool DoNotCleanupDb { get; set; }
/// <summary>
/// Create the test db if not already exists
/// </summary>
public static async Task<SqlTestDb> CreateNew(TestServerType serverType, bool doNotCleanupDb = false, string databaseName = null, string query = null)
{
SqlTestDb testDb = new SqlTestDb();
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
{
databaseName = databaseName ?? GetUniqueDBName("");
string createDatabaseQuery = Scripts.CreateDatabaseQuery.Replace("#DatabaseName#", databaseName);
await testService.RunQuery(serverType, MasterDatabaseName, createDatabaseQuery);
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Verified test database '{0}' is created", databaseName));
if (!string.IsNullOrEmpty(query))
{
await testService.RunQuery(serverType, databaseName, query);
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Verified test database '{0}' SQL types are created", databaseName));
}
testDb.DatabaseName = databaseName;
testDb.ServerType = serverType;
testDb.DoNotCleanupDb = doNotCleanupDb;
}
return testDb;
}
/// <summary>
/// Returns a mangled name that unique based on Prefix + Machine + Process
/// </summary>
/// <param name="namePrefix"></param>
/// <returns></returns>
public static string GetUniqueDBName(string namePrefix)
{
string safeMachineName = Environment.MachineName.Replace('-', '_');
return string.Format("{0}_{1}_{2}",
namePrefix, safeMachineName, Guid.NewGuid().ToString().Replace("-", ""));
}
public void Dispose()
{
if(!DoNotCleanupDb)
{
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{
string dropDatabaseQuery = string.Format(CultureInfo.InvariantCulture,
(ServerType == TestServerType.Azure ? Scripts.DropDatabaseIfExistAzure : Scripts.DropDatabaseIfExist), DatabaseName);
testService.RunQuery(ServerType, MasterDatabaseName, dropDatabaseQuery).Wait();
}
}
}
}
}

View File

@@ -0,0 +1,265 @@
//
// 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.Concurrent;
using System.Collections.Generic;
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.Credentials;
using Microsoft.SqlTools.ServiceLayer.Credentials.Contracts;
using Microsoft.SqlTools.ServiceLayer.TestDriver.Driver;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{
/// <summary>
/// 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
/// </summary>
public class TestConnectionProfileService
{
private readonly IEnumerable<TestServerIdentity> _testServers = TestServersLazyInstance.Value;
private readonly ConnectionSetting _setting = ConnectionSettingLazyInstance.Value;
private static string _connectionSettingsFilename;
private static ConcurrentDictionary<TestServerType, ConnectionProfile> _connectionProfilesCache = new ConcurrentDictionary<TestServerType, ConnectionProfile>();
public TestConnectionProfileService(ServiceTestDriver driver)
{
Driver = driver;
}
public TestConnectionProfileService()
{
}
private static readonly Lazy<IEnumerable<TestServerIdentity>> TestServersLazyInstance =
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 the server or profile name for given type to use for database connection
TestServerIdentity serverIdentity = _testServers != null ? _testServers.FirstOrDefault(x => x.ServerType == serverType) : null;
//Search for the connection info in settings.json
if (serverIdentity == null)
{
//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;
}
Assert.True(connectionProfile != null, "Cannot find any connection profile for server type " + serverType.ToString());
return connectionProfile;
}
/// <summary>
/// Returns database connection parameters for given server type
/// </summary>
public async Task<ConnectParams> GetConnectionParametersAsync(TestServerType serverType = TestServerType.OnPrem, string databaseName = null)
{
ConnectionProfile connectionProfile;
if (!_connectionProfilesCache.TryGetValue(serverType, out connectionProfile))
{
connectionProfile = GetConnectionProfile(serverType);
if (connectionProfile != null)
{
//If the password is empty, get the credential using the service
if (connectionProfile.AuthenticationType == AuthenticationType.SqlLogin && string.IsNullOrEmpty(connectionProfile.Password))
{
Credential credential = await ReadCredentialAsync(connectionProfile.formatCredentialId());
connectionProfile.Password = credential.Password;
}
_connectionProfilesCache.GetOrAdd(serverType, connectionProfile);
}
}
if (connectionProfile != null)
{
ConnectParams connenctParam = CreateConnectParams(connectionProfile, serverType, databaseName);
return connenctParam;
}
return null;
}
/// <summary>
/// Request a Read Credential for given credential id
/// </summary>
private async Task<Credential> ReadCredentialAsync(string credentialId)
{
var credentialParams = new Credential();
credentialParams.CredentialId = credentialId;
ServiceTestDriver driver = Driver;
if (driver == null)
{
TestServiceProvider.InitializeTestServices();
return await CredentialService.Instance.ReadCredentialAsync(credentialParams);
}
else
{
return await Driver.SendRequest(ReadCredentialRequest.Type, credentialParams);
}
}
/// <summary>
/// Create a connection parameters object
/// </summary>
private ConnectParams CreateConnectParams(ConnectionProfile connectionProfile, TestServerType serverType, string databaseName)
{
ConnectParams connectParams = new ConnectParams();
connectParams.Connection = new ConnectionDetails();
connectParams.Connection.ServerName = connectionProfile.ServerName;
connectParams.Connection.DatabaseName = connectionProfile.Database;
connectParams.Connection.UserName = connectionProfile.User;
connectParams.Connection.Password = connectionProfile.Password;
connectParams.Connection.AuthenticationType = connectionProfile.AuthenticationType.ToString();
if (!string.IsNullOrEmpty(databaseName))
{
connectParams.Connection.DatabaseName = databaseName;
}
if (serverType == TestServerType.Azure)
{
connectParams.Connection.ConnectTimeout = 30;
connectParams.Connection.Encrypt = true;
connectParams.Connection.TrustServerCertificate = false;
}
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,48 @@
//
// 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.Globalization;
using System.Threading.Tasks;
namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{
public class TestDatabaseService
{
public const string MasterDatabaseName = "master";
/// <summary>
/// Create the test db if not already exists
/// </summary>
internal static async Task CreateTestDatabase(TestServerType serverType, string databaseName = null, string query = null)
{
using (TestServiceDriverProvider testService = new TestServiceDriverProvider())
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{
databaseName = databaseName ?? GetUniqueDBName("");
string createDatabaseQuery = Scripts.CreateDatabaseQuery.Replace("#DatabaseName#", databaseName);
await testService.RunQuery(serverType, MasterDatabaseName, createDatabaseQuery);
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Verified test database '{0}' is created", databaseName));
if (!string.IsNullOrEmpty(query))
{
await testService.RunQuery(serverType, databaseName, query);// Scripts.CreateDatabaseObjectsQuery);
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Verified test database '{0}' SQL types are created", databaseName));
}
}
}
/// <summary>
/// Returns a mangled name that unique based on Prefix + Machine + Process
/// </summary>
/// <param name="namePrefix"></param>
/// <returns></returns>
public static string GetUniqueDBName(string namePrefix)
{
string safeMachineName = Environment.MachineName.Replace('-', '_');
return string.Format("{0}_{1}_{2}",
namePrefix, safeMachineName, Guid.NewGuid().ToString().Replace("-", ""));
}
}
}

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 class TestResult
{
public double ElapsedTime { get; set; }
}
}

View File

@@ -0,0 +1,32 @@
//
// 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
{
/// <summary>
/// The model to deserialize the server names json
/// </summary>
public class TestServerIdentity
{
public string ServerName { get; set; }
public string ProfileName { get; set; }
public TestServerType ServerType { get; set; }
}
public enum TestServerType
{
None,
Azure,
OnPrem
}
public enum AuthenticationType
{
Integrated,
SqlLogin
}
}

View File

@@ -0,0 +1,456 @@
//
// 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.CompilerServices;
using System.Threading.Tasks;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.LanguageServices.Contracts;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.ServiceLayer.SqlContext;
using Microsoft.SqlTools.ServiceLayer.TestDriver.Driver;
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{
/// <summary>
/// Service class to execute SQL tools commands using the test driver or calling the service classed directly
/// </summary>
public sealed class TestServiceDriverProvider : IDisposable
{
private bool isRunning = false;
private TestConnectionProfileService testConnectionService;
public TestServiceDriverProvider()
{
Driver = new ServiceTestDriver();
Driver.Start().Wait();
this.isRunning = true;
}
public void Dispose()
{
if (this.isRunning)
{
WaitForExit();
}
}
public void WaitForExit()
{
try
{
this.isRunning = false;
Driver.Stop().Wait();
Console.WriteLine("Successfully killed process.");
}
catch (Exception e)
{
Console.WriteLine($"Exception while waiting for service exit: {e.Message}");
}
}
/// <summary>
/// The driver object used to read/write data to the service
/// </summary>
public ServiceTestDriver Driver
{
get;
private set;
}
public TestConnectionProfileService TestConnectionService
{
get
{
return (testConnectionService = testConnectionService ?? new TestConnectionProfileService(Driver));
}
}
private object fileLock = new Object();
/// <summary>
/// Request a new connection to be created
/// </summary>
/// <returns>True if the connection completed successfully</returns>
public async Task<bool> Connect(string ownerUri, ConnectParams connectParams, int timeout = 15000)
{
connectParams.OwnerUri = ownerUri;
var connectResult = await Driver.SendRequest(ConnectionRequest.Type, connectParams);
if (connectResult)
{
var completeEvent = await Driver.WaitForEvent(ConnectionCompleteNotification.Type, timeout);
return !string.IsNullOrEmpty(completeEvent.ConnectionId);
}
else
{
return false;
}
}
/// <summary>
/// Request a new connection to be created for given query
/// </summary>
public async Task<bool> ConnectForQuery(TestServerType serverType, string query, string ownerUri, string databaseName = null, int timeout = 15000)
{
if (!string.IsNullOrEmpty(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);
}
/// <summary>
/// Request a new connection to be created for url
/// </summary>
public async Task<bool> Connect(TestServerType serverType, string ownerUri, string databaseName = null, int timeout = 15000)
{
var connectParams = await GetConnectionParametersAsync(serverType, databaseName);
bool connected = await Connect(ownerUri, connectParams, timeout);
Assert.True(connected, "Connection is successful");
Console.WriteLine($"Connection to {connectParams.Connection.ServerName} is successful");
return connected;
}
/// <summary>
/// Request a disconnect
/// </summary>
public async Task<bool> Disconnect(string ownerUri)
{
var disconnectParams = new DisconnectParams();
disconnectParams.OwnerUri = ownerUri;
var disconnectResult = await Driver.SendRequest(DisconnectRequest.Type, disconnectParams);
return disconnectResult;
}
/// <summary>
/// Request a cancel connect
/// </summary>
public async Task<bool> CancelConnect(string ownerUri)
{
var cancelParams = new CancelConnectParams();
cancelParams.OwnerUri = ownerUri;
return await Driver.SendRequest(CancelConnectRequest.Type, cancelParams);
}
/// <summary>
/// Request a cancel connect
/// </summary>
public async Task<ListDatabasesResponse> ListDatabases(string ownerUri)
{
var listParams = new ListDatabasesParams();
listParams.OwnerUri = ownerUri;
return await Driver.SendRequest(ListDatabasesRequest.Type, listParams);
}
/// <summary>
/// Request the active SQL script is parsed for errors
/// </summary>
public async Task<QueryExecuteSubsetResult> RequestQueryExecuteSubset(QueryExecuteSubsetParams subsetParams)
{
return await Driver.SendRequest(QueryExecuteSubsetRequest.Type, subsetParams);
}
/// <summary>
/// Request the active SQL script is parsed for errors
/// </summary>
public async Task RequestOpenDocumentNotification(DidOpenTextDocumentNotification openParams)
{
await Driver.SendEvent(DidOpenTextDocumentNotification.Type, openParams);
}
/// <summary>
/// Request a configuration change notification
/// </summary>
public async Task RequestChangeConfigurationNotification(DidChangeConfigurationParams<SqlToolsSettings> configParams)
{
await Driver.SendEvent(DidChangeConfigurationNotification<SqlToolsSettings>.Type, configParams);
}
/// <summary>
/// /// Request the active SQL script is parsed for errors
/// </summary>
public async Task RequestChangeTextDocumentNotification(DidChangeTextDocumentParams changeParams)
{
await Driver.SendEvent(DidChangeTextDocumentNotification.Type, changeParams);
}
/// <summary>
/// Request completion item resolve to look-up additional info
/// </summary>
public async Task<CompletionItem> RequestResolveCompletion(CompletionItem item)
{
var result = await Driver.SendRequest(CompletionResolveRequest.Type, item);
return result;
}
/// <summary>
/// Returns database connection parameters for given server type
/// </summary>
public async Task<ConnectParams> GetConnectionParametersAsync(TestServerType serverType, string databaseName = null)
{
return await TestConnectionService.GetConnectionParametersAsync(serverType, databaseName);
}
/// <summary>
/// Request a list of completion items for a position in a block of text
/// </summary>
public async Task<CompletionItem[]> RequestCompletion(string ownerUri, string text, int line, int character)
{
// Write the text to a backing file
lock (fileLock)
{
System.IO.File.WriteAllText(ownerUri, text);
}
var completionParams = new TextDocumentPosition();
completionParams.TextDocument = new TextDocumentIdentifier();
completionParams.TextDocument.Uri = ownerUri;
completionParams.Position = new Position();
completionParams.Position.Line = line;
completionParams.Position.Character = character;
var result = await Driver.SendRequest(CompletionRequest.Type, completionParams);
return result;
}
/// <summary>
/// Request a a hover tooltop
/// </summary>
public async Task<Hover> RequestHover(string ownerUri, string text, int line, int character)
{
// Write the text to a backing file
lock (fileLock)
{
System.IO.File.WriteAllText(ownerUri, text);
}
var completionParams = new TextDocumentPosition
{
TextDocument = new TextDocumentIdentifier { Uri = ownerUri },
Position = new Position
{
Line = line,
Character = character
}
};
var result = await Driver.SendRequest(HoverRequest.Type, completionParams);
return result;
}
/// <summary>
/// Request definition( peek definition/go to definition) for a sql object in a sql string
/// </summary>
public async Task<Location[]> RequestDefinition(string ownerUri, string text, int line, int character)
{
// Write the text to a backing file
lock (fileLock)
{
System.IO.File.WriteAllText(ownerUri, text);
}
var definitionParams = new TextDocumentPosition();
definitionParams.TextDocument = new TextDocumentIdentifier();
definitionParams.TextDocument.Uri = ownerUri;
definitionParams.Position = new Position();
definitionParams.Position.Line = line;
definitionParams.Position.Character = character;
// Send definition request
var result = await Driver.SendRequest(DefinitionRequest.Type, definitionParams);
return result;
}
/// <summary>
/// Run a query using a given connection bound to a URI
/// </summary>
public async Task<QueryExecuteCompleteParams> RunQueryAndWaitToComplete(string ownerUri, string query, int timeoutMilliseconds = 5000)
{
// Write the query text to a backing file
WriteToFile(ownerUri, query);
var queryParams = new QueryExecuteParams
{
OwnerUri = ownerUri,
QuerySelection = null
};
var result = await Driver.SendRequest(QueryExecuteRequest.Type, queryParams);
if (result != null)
{
var eventResult = await Driver.WaitForEvent(QueryExecuteCompleteEvent.Type, timeoutMilliseconds);
return eventResult;
}
else
{
return null;
}
}
/// <summary>
/// Run a query using a given connection bound to a URI. This method only waits for the initial response from query
/// execution (QueryExecuteResult). It is up to the caller to wait for the QueryExecuteCompleteEvent if they are interested.
/// </summary>
public async Task<QueryExecuteResult> RunQueryAsync(string ownerUri, string query, int timeoutMilliseconds = 5000)
{
WriteToFile(ownerUri, query);
var queryParams = new QueryExecuteParams
{
OwnerUri = ownerUri,
QuerySelection = null
};
return await Driver.SendRequest(QueryExecuteRequest.Type, queryParams);
}
public async Task RunQuery(TestServerType serverType, string databaseName, string query)
{
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{
await ConnectForQuery(serverType, query, queryTempFile.FilePath, databaseName);
var queryResult = await CalculateRunTime(() => RunQueryAndWaitToComplete(queryTempFile.FilePath, query, 50000), false);
await Disconnect(queryTempFile.FilePath);
}
}
public async Task<T> CalculateRunTime<T>(Func<Task<T>> testToRun, bool printResult, [CallerMemberName] string testName = "")
{
TestTimer timer = new TestTimer() { PrintResult = printResult };
T result = await testToRun();
timer.EndAndPrint(testName);
return result;
}
public async Task ExecuteWithTimeout(TestTimer timer, int timeout, Func<Task<bool>> repeatedCode,
TimeSpan? delay = null, [CallerMemberName] string testName = "")
{
while (true)
{
if (await repeatedCode())
{
timer.EndAndPrint(testName);
break;
}
if (timer.TotalMilliSecondsUntilNow >= timeout)
{
Assert.True(false, $"{testName} timed out after {timeout} milliseconds");
break;
}
if (delay.HasValue)
{
await Task.Delay(delay.Value);
}
}
}
/// <summary>
/// Request to cancel an executing query
/// </summary>
public async Task<QueryCancelResult> CancelQuery(string ownerUri)
{
var cancelParams = new QueryCancelParams { OwnerUri = ownerUri };
var result = await Driver.SendRequest(QueryCancelRequest.Type, cancelParams);
return result;
}
/// <summary>
/// Request to save query results as CSV
/// </summary>
public async Task<SaveResultRequestResult> SaveAsCsv(string ownerUri, string filename, int batchIndex, int resultSetIndex)
{
var saveParams = new SaveResultsAsCsvRequestParams
{
OwnerUri = ownerUri,
BatchIndex = batchIndex,
ResultSetIndex = resultSetIndex,
FilePath = filename
};
var result = await Driver.SendRequest(SaveResultsAsCsvRequest.Type, saveParams);
return result;
}
/// <summary>
/// Request to save query results as JSON
/// </summary>
public async Task<SaveResultRequestResult> SaveAsJson(string ownerUri, string filename, int batchIndex, int resultSetIndex)
{
var saveParams = new SaveResultsAsJsonRequestParams
{
OwnerUri = ownerUri,
BatchIndex = batchIndex,
ResultSetIndex = resultSetIndex,
FilePath = filename
};
var result = await Driver.SendRequest(SaveResultsAsJsonRequest.Type, saveParams);
return result;
}
/// <summary>
/// Request a subset of results from a query
/// </summary>
public async Task<QueryExecuteSubsetResult> ExecuteSubset(string ownerUri, int batchIndex, int resultSetIndex, int rowStartIndex, int rowCount)
{
var subsetParams = new QueryExecuteSubsetParams();
subsetParams.OwnerUri = ownerUri;
subsetParams.BatchIndex = batchIndex;
subsetParams.ResultSetIndex = resultSetIndex;
subsetParams.RowsStartIndex = rowStartIndex;
subsetParams.RowsCount = rowCount;
var result = await Driver.SendRequest(QueryExecuteSubsetRequest.Type, subsetParams);
return result;
}
/// <summary>
/// Waits for a message to be returned by the service
/// </summary>
/// <returns>A message from the service layer</returns>
public async Task<QueryExecuteMessageParams> WaitForMessage()
{
return await Driver.WaitForEvent(QueryExecuteMessageEvent.Type);
}
public void WriteToFile(string ownerUri, string query)
{
lock (fileLock)
{
System.IO.File.WriteAllText(ownerUri, query);
}
}
}
}

View File

@@ -0,0 +1,57 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Credentials;
using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.LanguageServices;
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
using Microsoft.SqlTools.ServiceLayer.SqlContext;
using Microsoft.SqlTools.ServiceLayer.Workspace;
namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{
/// <summary>
/// Class to provide SQL tools service classes
/// </summary>
public class TestServiceProvider
{
private static bool hasInitServices = false;
public static void InitializeTestServices()
{
if (TestServiceProvider.hasInitServices)
{
return;
}
TestServiceProvider.hasInitServices = true;
const string hostName = "SQ Tools Test Service Host";
const string hostProfileId = "SQLToolsTestService";
Version hostVersion = new Version(1, 0);
// set up the host details and profile paths
var hostDetails = new HostDetails(hostName, hostProfileId, hostVersion);
SqlToolsContext sqlToolsContext = new SqlToolsContext(hostDetails);
// Grab the instance of the service host
ServiceHost serviceHost = ServiceHost.Instance;
// Start the service
serviceHost.Start().Wait();
// Initialize the services that will be hosted here
WorkspaceService<SqlToolsSettings>.Instance.InitializeService(serviceHost);
LanguageService.Instance.InitializeService(serviceHost, sqlToolsContext);
ConnectionService.Instance.InitializeService(serviceHost);
CredentialService.Instance.InitializeService(serviceHost);
QueryExecutionService.Instance.InitializeService(serviceHost);
serviceHost.Initialize();
}
}
}

View File

@@ -0,0 +1,84 @@
//
// 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.Globalization;
using System.IO;
using System.Runtime.CompilerServices;
namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{
/// <summary>
/// Timer to calculate the test run time
/// </summary>
public class TestTimer
{
private static string resultFolder = InitResultFolder();
private static string InitResultFolder()
{
string resultFodler = Environment.GetEnvironmentVariable("ResultFolder");
if (string.IsNullOrEmpty(resultFodler))
{
string assemblyLocation = System.Reflection.Assembly.GetEntryAssembly().Location;
resultFodler = Path.GetDirectoryName(assemblyLocation);
}
return resultFodler;
}
public TestTimer()
{
Start();
}
public bool PrintResult { get; set; }
public void Start()
{
StartDateTime = DateTime.UtcNow;
}
public void End()
{
EndDateTime = DateTime.UtcNow;
}
public void EndAndPrint([CallerMemberName] string testName = "")
{
End();
if (PrintResult)
{
var currentColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Test Name: {0} Run time in milliSeconds: {1}", testName, TotalMilliSeconds));
Console.ForegroundColor = currentColor;
string resultContent = Newtonsoft.Json.JsonConvert.SerializeObject(new TestResult { ElapsedTime = TotalMilliSeconds });
string fileName = testName + ".json";
string resultFilePath = string.IsNullOrEmpty(resultFolder) ? fileName : Path.Combine(resultFolder, fileName);
File.WriteAllText(resultFilePath, resultContent);
Console.WriteLine("Result file: " + resultFilePath);
}
}
public double TotalMilliSeconds
{
get
{
return (EndDateTime - StartDateTime).TotalMilliseconds;
}
}
public double TotalMilliSecondsUntilNow
{
get
{
return (DateTime.UtcNow - StartDateTime).TotalMilliseconds;
}
}
public DateTime StartDateTime { get; private set; }
public DateTime EndDateTime { get; private set; }
}
}

View File

@@ -0,0 +1,46 @@
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": false,
"embed": {
"includeFiles": [
"Scripts/CreateTestDatabaseObjects.sql",
"Scripts/CreateTestDatabase.sql",
"Scripts/TestDbTableQueries.sql"
]
}
},
"dependencies": {
"Newtonsoft.Json": "9.0.1",
"System.Runtime.Serialization.Primitives": "4.1.1",
"System.Data.Common": "4.1.0",
"System.Data.SqlClient": "4.4.0-sqltools-24613-04",
"Microsoft.SqlServer.Smo": "140.1.12",
"System.Security.SecureString": "4.0.0",
"System.Collections.Specialized": "4.0.1",
"System.ComponentModel.TypeConverter": "4.1.0",
"xunit": "2.1.0",
"dotnet-test-xunit": "1.0.0-rc2-192208-24",
"Microsoft.SqlTools.ServiceLayer": {
"target": "project"
},
"Moq": "4.6.36-alpha",
"Microsoft.SqlTools.ServiceLayer.TestDriver": "1.0.0-*"
},
"testRunner": "xunit",
"frameworks": {
"netcoreapp1.0": {
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
}
},
"imports": [
"dotnet5.4",
"portable-net451+win8"
]
}
}
}