Object Explorer Service (#311)

* moving OE service from an old branch
This commit is contained in:
Leila Lali
2017-04-11 15:50:20 -07:00
committed by GitHub
parent 90861b7d9e
commit d903ba56a9
58 changed files with 24577 additions and 1057 deletions

View File

@@ -0,0 +1,215 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.Test.Common;
using Xunit;
using static Microsoft.SqlTools.ServiceLayer.ObjectExplorer.ObjectExplorerService;
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
{
public class ObjectExplorerServiceTests
{
private ObjectExplorerService _service = TestServiceProvider.Instance.ObjectExplorerService;
[Fact]
public async void CreateSessionAndExpandOnTheServerShouldReturnTheDatabases()
{
var query = "";
string uri = "CreateSessionAndExpand";
string databaseName = null;
using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri))
{
var session = await CreateSession(testDb.DatabaseName, uri);
await CreateSessionAndDatabaseNode(testDb.DatabaseName, session);
CancelConnection(uri);
}
}
private async Task<ObjectExplorerSession> CreateSession(string databaseName, string uri)
{
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);
ConnectionDetails details = connectParams.Connection;
return await _service.DoCreateSession(details, uri);
}
private async Task<NodeInfo> CreateSessionAndDatabaseNode(string databaseName, ObjectExplorerSession session)
{
Assert.NotNull(session);
Assert.NotNull(session.Root);
NodeInfo nodeInfo = session.Root.ToNodeInfo();
Assert.Equal(nodeInfo.IsLeaf, false);
Assert.Equal(nodeInfo.NodeType, NodeTypes.ServerInstance.ToString());
var children = session.Root.Expand();
//All server children should be folder nodes
foreach (var item in children)
{
Assert.Equal(item.NodeType, "Folder");
}
var databasesRoot = children.FirstOrDefault(x => x.NodeTypeId == NodeTypes.Databases);
var databasesChildren = await _service.ExpandNode(session, databasesRoot.GetNodePath());
var databases = databasesChildren.Where(x => x.NodeType == NodeTypes.DatabaseInstance.ToString());
//Verify the test databases is in the list
Assert.NotNull(databases);
var databaseNode = databases.FirstOrDefault(d => d.Label == databaseName);
Assert.NotNull(databaseNode);
return databaseNode;
}
private void CancelConnection(string uri)
{
//ConnectionService.Instance.CancelConnect(new CancelConnectParams
//{
// OwnerUri = uri,
// Type = ConnectionType.Default
//});
}
private async Task ExpandTree(NodeInfo node, ObjectExplorerSession session)
{
if(node != null && !node.IsLeaf)
{
var children = await _service.ExpandNode(session, node.NodePath);
Assert.NotNull(children);
if(children.Count() == 0 && !node.NodePath.Contains("System") &&
!node.NodePath.Contains("FileTables") && !node.NodePath.Contains("External Tables"))
{
var labaleToUpper = node.Label.ToUpper();
if (labaleToUpper.Contains("TABLE") || labaleToUpper.Contains("StoredProcedure")
|| labaleToUpper.Contains("VIEW"))
{
//TOOD: Add a better validation. For now at least check tables not to be empty
//Assert.True(false, "The list of tables, procedure and views cannot be empty");
}
}
foreach (var child in children)
{
//Console.WriteLine(child.Label);
await ExpandTree(child, session);
}
}
}
[Fact]
public async void VerifyAdventureWorksDatabaseObjects()
{
var query = Scripts.AdventureWorksScript;
string uri = "VerifyAdventureWorksDatabaseObjects";
string databaseName = null;
using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri))
{
var session = await CreateSession(testDb.DatabaseName, uri);
var databaseNodeInfo = await CreateSessionAndDatabaseNode(testDb.DatabaseName, session);
await ExpandTree(databaseNodeInfo, session);
CancelConnection(uri);
}
}
// [Fact]
public async void VerifySql2016Objects()
{
var query = LoadScript("Sql_2016_Additions.sql");
string uri = "VerifySql2016Objects";
string databaseName = null;
using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri))
{
var session = await CreateSession(testDb.DatabaseName, uri);
var databaseNodeInfo = await CreateSessionAndDatabaseNode(testDb.DatabaseName, session);
await ExpandTree(databaseNodeInfo, session);
CancelConnection(uri);
}
}
// [Fact]
public async void VerifySqlObjects()
{
var query = LoadScript("Sql_Additions.sql");
string uri = "VerifySqlObjects";
string databaseName = null;
using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri))
{
var session = await CreateSession(testDb.DatabaseName, uri);
var databaseNodeInfo = await CreateSessionAndDatabaseNode(testDb.DatabaseName, session);
await ExpandTree(databaseNodeInfo, session);
CancelConnection(uri);
}
}
// [Fact]
public async void VerifyFileTableTest()
{
var query = LoadScript("FileTableTest.sql");
string uri = "VerifyFileTableTest";
string databaseName = null;
using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri))
{
var session = await CreateSession(testDb.DatabaseName, uri);
var databaseNodeInfo = await CreateSessionAndDatabaseNode(testDb.DatabaseName, session);
await ExpandTree(databaseNodeInfo, session);
CancelConnection(uri);
}
}
//[Fact]
public async void VerifyColumnstoreindexSql16()
{
var query = LoadScript("ColumnstoreindexSql16.sql");
string uri = "VerifyColumnstoreindexSql16";
string databaseName = null;
using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName, query, uri))
{
var session = await CreateSession(testDb.DatabaseName, uri);
var databaseNodeInfo = await CreateSessionAndDatabaseNode(testDb.DatabaseName, session);
await ExpandTree(databaseNodeInfo, session);
CancelConnection(uri);
}
}
private static string TestLocationDirectory
{
get
{
return Path.Combine(RunEnvironmentInfo.GetTestDataLocation(), "ObjectExplorer");
}
}
public DirectoryInfo InputFileDirectory
{
get
{
string d = Path.Combine(TestLocationDirectory, "TestScripts");
return new DirectoryInfo(d);
}
}
public FileInfo GetInputFile(string fileName)
{
return new FileInfo(Path.Combine(InputFileDirectory.FullName, fileName));
}
private string LoadScript(string fileName)
{
FileInfo inputFile = GetInputFile(fileName);
return TestUtilities.ReadTextAndNormalizeLineEndings(inputFile.FullName);
}
}
}

View File

@@ -1,7 +1,10 @@
using System.Data.SqlClient;
using System;
using System.Data.SqlClient;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
@@ -27,11 +30,11 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility
}
public static TestConnectionResult InitLiveConnectionInfo()
public static TestConnectionResult InitLiveConnectionInfo(string databaseName = null)
{
string sqlFilePath = GetTestSqlFile();
ScriptFile scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(sqlFilePath);
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem);
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);
string ownerUri = scriptFile.ClientFilePath;
var connectionService = GetLiveTestConnectionService();
@@ -50,6 +53,35 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility
return new TestConnectionResult() { ConnectionInfo = connInfo, ScriptFile = scriptFile };
}
public static async Task<TestConnectionResult> InitLiveConnectionInfoAsync(string databaseName = null, string ownerUri = null)
{
ScriptFile scriptFile = null;
if (string.IsNullOrEmpty(ownerUri))
{
string sqlFilePath = GetTestSqlFile();
scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(sqlFilePath);
ownerUri = scriptFile.ClientFilePath;
}
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);
var connectionService = GetLiveTestConnectionService();
var connectionResult =
await connectionService
.Connect(new ConnectParams
{
OwnerUri = ownerUri,
Connection = connectParams.Connection
});
if (!string.IsNullOrEmpty(connectionResult.ErrorMessage))
{
Console.WriteLine(connectionResult.ErrorMessage);
}
ConnectionInfo connInfo = null;
connectionService.TryFindConnection(ownerUri, out connInfo);
return new TestConnectionResult() { ConnectionInfo = connInfo, ScriptFile = scriptFile };
}
public static ConnectionInfo InitLiveConnectionInfoForDefinition(string databaseName = null)
{
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);

File diff suppressed because one or more lines are too long

View File

@@ -43,7 +43,9 @@ END
public static string CreateDatabaseQuery { get { return CreateDatabaseQueryInstance.Value; } }
public static string TestDbComplexSelectQueries { get { return TestDbSelectQueriesInstance.Value; } }
public static string TestDbComplexSelectQueries { get { return TestDbSelectQueriesInstance.Value; } }
public static string AdventureWorksScript { get { return AdventureWorksScriptInstance.Value; } }
private static readonly Lazy<string> CreateDatabaseObjectsQueryInstance = new Lazy<string>(() =>
{
@@ -58,6 +60,11 @@ END
private static readonly Lazy<string> TestDbSelectQueriesInstance = new Lazy<string>(() =>
{
return GetScriptFileContent(ResourceNameRefix + "TestDbTableQueries.sql");
});
private static readonly Lazy<string> AdventureWorksScriptInstance = new Lazy<string>(() =>
{
return GetScriptFileContent(ResourceNameRefix + "AdventureWorks.sql");
});
private static string GetScriptFileContent(string fileName)

View File

@@ -27,13 +27,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
/// <summary>
/// Create the test db if not already exists
/// </summary>
public static 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,
string dbNamePrefix = null)
{
SqlTestDb testDb = new SqlTestDb();
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
{
databaseName = databaseName ?? GetUniqueDBName("");
databaseName = databaseName ?? GetUniqueDBName(dbNamePrefix);
string createDatabaseQuery = Scripts.CreateDatabaseQuery.Replace("#DatabaseName#", databaseName);
TestServiceProvider.Instance.RunQuery(serverType, MasterDatabaseName, createDatabaseQuery);
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "Test database '{0}' is created", databaseName));

View File

@@ -0,0 +1,34 @@
CREATE TABLE CS_Delay_Table1
(ProductKey [int] NOT NULL,
OrderDateKey [int] NOT NULL,
DueDateKey [int] NOT NULL,
ShipDateKey [int] NOT NULL);
GO
CREATE CLUSTERED COLUMNSTORE INDEX CSI_1 ON CS_Delay_Table1
WITH (COMPRESSION_DELAY = 100 minutes);
GO
CREATE TABLE CS_Delay_Table2
(ProductKey [int] NOT NULL,
OrderDateKey [int] NOT NULL,
DueDateKey [int] NOT NULL,
ShipDateKey [int] NOT NULL);
GO
CREATE CLUSTERED INDEX CI_Table2 ON CS_Delay_Table2 (ProductKey);
GO
CREATE NONCLUSTERED COLUMNSTORE INDEX CSI_2
ON CS_Delay_Table2
(OrderDateKey, DueDateKey, ShipDateKey)
WITH (COMPRESSION_DELAY = 200);
GO
CREATE TABLE CS_Delay_Table3
(ProductKey [int] NOT NULL,
OrderDateKey [int] NOT NULL,
DueDateKey [int] NOT NULL,
ShipDateKey [int] NOT NULL,
INDEX CSI_3 CLUSTERED COLUMNSTORE WITH(COMPRESSION_DELAY = 50 minute));
GO

View File

@@ -0,0 +1,103 @@
CREATE DATABASE [$(DatabaseName)]
GO
ALTER DATABASE [$(DatabaseName)] SET TARGET_RECOVERY_TIME = 1 MINUTES
GO
USE [$(DatabaseName)]
GO
ALTER DATABASE [$(DatabaseName)]
SET FILESTREAM(
NON_TRANSACTED_ACCESS = FULL,
DIRECTORY_NAME = N'$(DatabaseName)'
) WITH NO_WAIT
GO
ALTER DATABASE $(DatabaseName)
ADD FILEGROUP [FileGroup1]
CONTAINS FILESTREAM
GO
ALTER DATABASE $(DatabaseName)
ADD FILE
(NAME = 'FileTableFile'
, FILENAME = '$(DefaultDataPath)$(DatabaseName)_FT'
)
TO FILEGROUP [FileGroup1]
GO
CREATE TABLE [dbo].[FileTablePass] AS FILETABLE WITH(
FileTable_Directory = 'docs',
FILETABLE_PRIMARY_KEY_CONSTRAINT_NAME=MyPk,
FILETABLE_STREAMID_UNIQUE_CONSTRAINT_NAME=MyStreamUQ,
FILETABLE_FULLPATH_UNIQUE_CONSTRAINT_NAME=MyPathUQ)
GO
ALTER TABLE [dbo].[FileTablePass] WITH CHECK ADD CONSTRAINT [MyCheck] CHECK ((stream_id IS NOT NULL))
GO
ALTER TABLE [dbo].[FileTablePass] ADD CONSTRAINT [MyDefault] DEFAULT ((NULL)) FOR [name]
GO
ALTER TABLE [dbo].[FileTablePass] ADD CONSTRAINT [MyQU] UNIQUE NONCLUSTERED ([name] ASC)
GO
ALTER TABLE [dbo].[FileTablePass] WITH CHECK ADD CONSTRAINT [MyFk] FOREIGN KEY([parent_path_locator])
REFERENCES [dbo].[FileTablePass] ([path_locator])
GO
CREATE TABLE [dbo].[t2] (
[c1] INT NOT NULL,
[c2] INT DEFAULT ((1)) NULL,
[c3] INT DEFAULT ((1)) NOT NULL,
[path_locator] hierarchyid,
PRIMARY KEY CLUSTERED ([c1] ASC),
UNIQUE NONCLUSTERED ([c2] ASC),
CHECK ([c2] > (0))
);
GO
CREATE STATISTICS stat1
ON dbo.[FileTablePass](stream_id)
WITH SAMPLE 50 PERCENT;
GO
CREATE INDEX IX_FileTablePass_Stream_id
ON dbo.FileTablePass(stream_id);
GO
CREATE TRIGGER FileTableTrigger
ON dbo.FileTablePass
AFTER INSERT
AS RAISERROR ('Block insert', 16, 10);
GO
CREATE INDEX IX_T2_C3
ON [dbo].[t2](c3);
GO
CREATE TRIGGER reminder2
ON dbo.t2
AFTER INSERT, UPDATE, DELETE
AS
PRINT 'reminder trigger';
GO
ALTER TABLE dbo.t2
ADD CONSTRAINT FK_TO_FILETABLE FOREIGN KEY (path_locator)
REFERENCES FileTablePass (path_locator) ;
GO
exec sp_addextendedproperty 'prop_ex', 'FileTable', 'SCHEMA', 'dbo', 'TABLE', 'FileTablePass'
exec sp_addextendedproperty 'prop_ex', 'MyPk', 'SCHEMA', 'dbo', 'TABLE', 'FileTablePass', 'CONSTRAINT', 'MyPk'
exec sp_addextendedproperty 'prop_ex', 'MyStreamUQ', 'SCHEMA', 'dbo', 'TABLE', 'FileTablePass', 'CONSTRAINT', 'MyStreamUQ'
exec sp_addextendedproperty 'prop_ex', 'MyPathUQ', 'SCHEMA', 'dbo', 'TABLE', 'FileTablePass', 'CONSTRAINT', 'MyPathUQ'
GO
CREATE USER test_user WITHOUT LOGIN
GO
GRANT SELECT ON dbo.FileTablePass TO test_user
GO

View File

@@ -0,0 +1,62 @@
CREATE PROCEDURE [dbo].[Encrypted_Additional_Numbered_Procedure]
( @param1 int)
WITH ENCRYPTION
AS
SELECT 1 AS Col1
GO
CREATE PROCEDURE [dbo].[Encrypted_Additional_Numbered_Procedure];2
( @param1 int)
WITH ENCRYPTION
AS
SELECT 2 AS Col1
GO
CREATE PROCEDURE [dbo].[Encrypted_Additional_Numbered_Procedure];3
( @param1 int)
WITH ENCRYPTION
AS
SELECT 3 AS Col1
GO
CREATE PROCEDURE [dbo].[Encrypted_Additional_Numbered_Procedure];4
( @param1 int)
WITH ENCRYPTION
AS
SELECT 4 AS Col1
GO
CREATE PROCEDURE [dbo].[Additional_Numbered_Procedure]
(@param1 int)
AS
SELECT 1 AS Col1
GO
CREATE PROCEDURE [dbo].[Additional_Numbered_Procedure];2
(@param1 int)
AS
SELECT 2 AS Col1
GO
CREATE PROCEDURE [dbo].[Additional_Numbered_Procedure];3
(@param1 int)
AS
SELECT 3 AS Col1
GO
CREATE PROCEDURE [dbo].[Additional_Numbered_Procedure];4
(@param1 int)
AS
SELECT 4 AS Col1

View File

@@ -0,0 +1,275 @@
ALTER DATABASE current SET COMPATIBILITY_LEVEL=130
GO
/* Dropping previous master key in master db that could have been created from other runs */
IF ( EXISTS(SELECT name FROM sys.symmetric_keys WHERE name = '##MS_DatabaseMasterKey##')) DROP MASTER KEY
CREATE MASTER KEY ENCRYPTION BY PASSWORD= 'Password01!';
OPEN MASTER KEY DECRYPTION BY PASSWORD = 'Password01!';
CREATE DATABASE SCOPED CREDENTIAL AlterEgo WITH IDENTITY = 'RettigB',
SECRET = 'sdrlk8$40-dksli87nNN8';
GO
-- Row-Level Security
CREATE TABLE [dbo].[Sales1]
(
OrderID INT,
SalesRep SYSNAME NOT NULL,
Product VARCHAR(10),
Qty INT
);
GO
CREATE TABLE [dbo].[Sales2]
(
OrderID INT,
SalesRep SYSNAME NOT NULL,
Product VARCHAR(10),
Qty INT
);
GO
CREATE FUNCTION [dbo].[fn_securitypredicate](@SalesRep AS SYSNAME)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN SELECT 1 AS fn_securitypredicate_result
WHERE @SalesRep = USER_NAME() OR USER_NAME() = 'Manager';
GO
CREATE SECURITY POLICY [dbo].[SalesFilter]
ADD FILTER PREDICATE [dbo].[fn_securitypredicate]([SalesRep]) ON [dbo].[Sales1],
ADD FILTER PREDICATE [dbo].[fn_securitypredicate]([SalesRep]) ON [dbo].[Sales2],
ADD BLOCK PREDICATE [dbo].[fn_securitypredicate]([SalesRep]) ON [dbo].[Sales1],
ADD BLOCK PREDICATE [dbo].[fn_securitypredicate]([SalesRep]) ON [dbo].[Sales2] AFTER UPDATE
WITH (STATE = OFF)
NOT FOR REPLICATION
GO
CREATE COLUMN MASTER KEY CMK1
WITH (
KEY_STORE_PROVIDER_NAME = 'MSSQL_CERTIFICATE_STORE',
KEY_PATH = 'Current User/Personal/f2260f28d909d21c642a3d8e0b45a830e79a1420'
);
GO
CREATE COLUMN MASTER KEY CMK2
WITH (
KEY_STORE_PROVIDER_NAME = 'MSSQL_CERTIFICATE_STORE',
KEY_PATH = 'Current User/Personal/f2260f28d909d21c642a3d8e0b45a830e79a1420'
);
GO
CREATE COLUMN ENCRYPTION KEY TwoValueCEK
WITH VALUES
(
COLUMN_MASTER_KEY = CMK1,
ALGORITHM = 'RSA_OAEP',
ENCRYPTED_VALUE = 0x016E000001630075007200720065006E00740075007300650072002F006D0079002F0037006300380061003100310033003400320037003800620037003000630038003100390062003900630039003400360061006600340039006500610030003200650038006200650038003400340065006C33A82ECF04A7185824B4545457AC5244CD9C219E64067B9520C0081B8399B58C2863F7494ABE3694BD87D55FFD7576FFDC47C28F94ECC99577DF4FB8FA19AA95764FEF889CDE0F176DA5897B74382FBB22756CE2921050A09201A0EB6AF3D6091014C30146EA62635EE8CBF0A8074DEDFF125CEA80D1C0F5E8C58750A07D270E2A8BF824EE4C0C156366BF26D38CCE49EBDD5639A2DF029A7DBAE5A5D111F2F2FA3246DF8C2FA83C1E542C10570FADA98F6B29478DC58CE5CBDD407CCEFCDB97814525F6F32BECA266014AC346AC39C4F185C6C0F0A24FEC4DFA015649624692DE7865B9827BA22C3B574C9FD169F822B609F902288C5880EB25F14BD990D871B1BC4BA3A5B237AF76D26354773FA2A25CF4511AF58C911E601CFCB1905128C997844EED056C2AE7F0B48700AB41307E470FF9520997D0EB0D887DE11AFE574FFE845B7DC6C03FEEE8D467236368FC0CB2FDBD54DADC65B10B3DE6C80DF8B7B3F8F3CE5BE914713EE7B1FA5B7A578359592B8A5FDFDDE5FF9F392BC87C3CD02FBA94582AC063BBB9FFAC803FD489E16BEB28C4E3374A8478C737236A0B232F5A9DDE4D119573F1AEAE94B2192B81575AD6F57E670C1B2AB91045124DFDAEC2898F3F0112026DFC93BF9391D667D1AD7ED7D4E6BB119BBCEF1D1ADA589DD3E1082C3DAD13223BE438EB9574DA04E9D8A06320CAC6D3EC21D5D1C2A0AA484C7C
),
(
COLUMN_MASTER_KEY = CMK2,
ALGORITHM = 'RSA_OAEP',
ENCRYPTED_VALUE = 0x016E000001630075007200720065006E00740075007300650072002F006D0079002F0064006500650063006200660034006100340031003000380034006200350033003200360066003200630062006200350030003600380065003900620061003000320030003600610037003800310066001DDA6134C3B73A90D349C8905782DD819B428162CF5B051639BA46EC69A7C8C8F81591A92C395711493B25DCBCCC57836E5B9F17A0713E840721D098F3F8E023ABCDFE2F6D8CC4339FC8F88630ED9EBADA5CA8EEAFA84164C1095B12AE161EABC1DF778C07F07D413AF1ED900F578FC00894BEE705EAC60F4A5090BBE09885D2EFE1C915F7B4C581D9CE3FDAB78ACF4829F85752E9FC985DEB8773889EE4A1945BD554724803A6F5DC0A2CD5EFE001ABED8D61E8449E4FAA9E4DD392DA8D292ECC6EB149E843E395CDE0F98D04940A28C4B05F747149B34A0BAEC04FFF3E304C84AF1FF81225E615B5F94E334378A0A888EF88F4E79F66CB377E3C21964AACB5049C08435FE84EEEF39D20A665C17E04898914A85B3DE23D56575EBC682D154F4F15C37723E04974DB370180A9A579BC84F6BC9B5E7C223E5CBEE721E57EE07EFDCC0A3257BBEBF9ADFFB00DBF7EF682EC1C4C47451438F90B4CF8DA709940F72CFDC91C6EB4E37B4ED7E2385B1FF71B28A1D2669FBEB18EA89F9D391D2FDDEA0ED362E6A591AC64EF4AE31CA8766C259ECB77D01A7F5C36B8418F91C1BEADDD4491C80F0016B66421B4B788C55127135DA2FA625FB7FD195FB40D90A6C67328602ECAF3EC4F5894BFD84A99EB4753BE0D22E0D4DE6A0ADFEDC80EB1B556749B4A8AD00E73B329C95827AB91C0256347E85E3C5FD6726D0E1FE82C925D3DF4A9
);
GO
CREATE TABLE Customers (
CustName nvarchar(60),
SSN varchar(11)
COLLATE Latin1_General_BIN2 ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = TwoValueCEK,
ENCRYPTION_TYPE = DETERMINISTIC ,
ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'),
Age int NULL,
ACTNO varchar(11)
ENCRYPTED WITH (COLUMN_ENCRYPTION_KEY = TwoValueCEK,
ENCRYPTION_TYPE = RANDOMIZED,
ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256')
);
GO
USE [$(DatabaseName)]
GO
DBCC TRACEON(4631,-1)
GO
OPEN MASTER KEY DECRYPTION BY PASSWORD = 'Password01!';
CREATE DATABASE SCOPED CREDENTIAL cred1 WITH IDENTITY = 'test_user', SECRET = '$(Secret)';
CREATE EXTERNAL DATA SOURCE eds1
WITH (
TYPE = HADOOP,
LOCATION = '$(DataSourceLocation)',
CREDENTIAL = cred1
);
CREATE EXTERNAL DATA SOURCE eds2
WITH (
TYPE = HADOOP,
LOCATION = '$(DataSourceLocation)'
);
CREATE EXTERNAL FILE FORMAT eff1
WITH (
FORMAT_TYPE = DELIMITEDTEXT
);
CREATE EXTERNAL FILE FORMAT eff2
WITH (
FORMAT_TYPE = ORC
);
CREATE EXTERNAL FILE FORMAT eff3
WITH (
FORMAT_TYPE = PARQUET
);
CREATE EXTERNAL FILE FORMAT eff4
WITH (
FORMAT_TYPE = RCFILE,
SERDE_METHOD = 'org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe'
);
CREATE EXTERNAL FILE FORMAT eff5
WITH (
FORMAT_TYPE = DELIMITEDTEXT,
FORMAT_OPTIONS (FIELD_TERMINATOR = '|', STRING_DELIMITER = ';', DATE_FORMAT = 'MM-dd-yyyy', USE_TYPE_DEFAULT = FALSE)
);
CREATE EXTERNAL FILE FORMAT eff6
WITH (
FORMAT_TYPE = DELIMITEDTEXT,
FORMAT_OPTIONS (FIELD_TERMINATOR = '|')
);
CREATE EXTERNAL FILE FORMAT eff7
WITH (
FORMAT_TYPE = DELIMITEDTEXT,
FORMAT_OPTIONS (DATE_FORMAT = 'MM-dd-yyyy', FIELD_TERMINATOR = '|')
);
CREATE EXTERNAL FILE FORMAT eff8
WITH (
FORMAT_TYPE = DELIMITEDTEXT,
FORMAT_OPTIONS (DATE_FORMAT = 'MM-dd-yyyy', FIELD_TERMINATOR = '|', STRING_DELIMITER = ';')
);
CREATE EXTERNAL FILE FORMAT eff9
WITH (
FORMAT_TYPE = DELIMITEDTEXT,
FORMAT_OPTIONS (DATE_FORMAT = 'MM-dd-yyyy', FIELD_TERMINATOR = '|', STRING_DELIMITER = ';'),
DATA_COMPRESSION = 'org.apache.hadoop.io.compress.GzipCodec'
);
CREATE EXTERNAL FILE FORMAT eff10
WITH (
FORMAT_TYPE = RCFILE,
SERDE_METHOD = 'org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe',
DATA_COMPRESSION = 'org.apache.hadoop.io.compress.DefaultCodec'
);
CREATE EXTERNAL FILE FORMAT eff11
WITH (
FORMAT_TYPE = ORC,
DATA_COMPRESSION = 'org.apache.hadoop.io.compress.SnappyCodec'
);
CREATE EXTERNAL FILE FORMAT eff12
WITH (
FORMAT_TYPE = PARQUET,
DATA_COMPRESSION = 'org.apache.hadoop.io.compress.SnappyCodec'
);
CREATE EXTERNAL TABLE bands1
(
id INTEGER NOT NULL,
name VARCHAR(50) NOT NULL,
origin CHAR(3),
rate FLOAT,
experience SMALLINT
)
WITH (
LOCATION = '/bands.dat',
DATA_SOURCE = eds1,
FILE_FORMAT = eff1
);
CREATE EXTERNAL TABLE bands2
(
id INTEGER NOT NULL,
name VARCHAR(50) NOT NULL,
origin CHAR(3),
rate FLOAT,
experience SMALLINT
)
WITH (
LOCATION = '/bands.dat',
DATA_SOURCE = eds2,
FILE_FORMAT = eff1
);
CREATE EXTERNAL TABLE bands3
(
id INTEGER NOT NULL,
name VARCHAR(50) NOT NULL,
origin CHAR(3),
rate FLOAT,
experience SMALLINT
)
WITH (
LOCATION = '/bands.dat',
DATA_SOURCE = eds2,
FILE_FORMAT = eff1,
REJECT_TYPE = VALUE,
REJECT_VALUE = 0
);
CREATE EXTERNAL TABLE bands4
(
id INTEGER NOT NULL,
name VARCHAR(50) NOT NULL,
origin CHAR(3),
rate FLOAT,
experience SMALLINT
)
WITH (
LOCATION = '/bands.dat',
DATA_SOURCE = eds1,
FILE_FORMAT = eff1,
REJECT_TYPE = PERCENTAGE,
REJECT_VALUE = 30.5,
REJECT_SAMPLE_VALUE = 10
);
CREATE EXTERNAL TABLE bands5
(
id INTEGER NOT NULL,
name VARCHAR(50) NOT NULL,
origin CHAR(3),
rate FLOAT,
experience SMALLINT
)
WITH (
LOCATION = '/bands.dat',
DATA_SOURCE = eds1,
FILE_FORMAT = eff1,
REJECT_TYPE = VALUE,
REJECT_VALUE = 30
);

View File

@@ -0,0 +1,298 @@
-- create signature
ADD SIGNATURE TO [Procedure1]
BY CERTIFICATE [Certificate1]
WITH PASSWORD = 'pGFD4bb925DGvbd2439587y' ;
GO
--Create a queue to receive messages.
CREATE QUEUE NotifyQueue ;
GO
--Create a service on the queue that references
--the event notifications contract.
CREATE SERVICE NotifyService
ON QUEUE NotifyQueue
([http://schemas.microsoft.com/SQL/Notifications/PostEventNotification]);
GO
--Create the event notification on queue.
CREATE EVENT NOTIFICATION Notify_ALTER_T1
ON QUEUE notifyqueue
FOR QUEUE_ACTIVATION
TO SERVICE 'NotifyService',
'8140a771-3c4b-4479-8ac0-81008ab17984';
GO
--Create the event notification on database
CREATE EVENT NOTIFICATION Notify_ALTER_T1
ON DATABASE
FOR ALTER_TABLE
TO SERVICE 'NotifyService',
'8140a771-3c4b-4479-8ac0-81008ab17984';
GO
CREATE FUNCTION [dbo].[TableFunctionWithComputedColumns]
(
-- Add the parameters for the function here
@p1 int = 2,
@p2 nchar(10) = NUll
)
RETURNS
@Table_Var TABLE
(
-- Add the column definitions for the TABLE variable here
c1 int,
c2 nchar(10),
c3 AS 1 * 3
)
AS
BEGIN
-- Fill the table variable with the rows for your result set
INSERT INTO @Table_Var
SELECT a.column_1, a.column_2
FROM Table_1 a
WHERE a.column_1 > 5
INSERT INTO @Table_Var
SELECT column_1, 'From 2'
FROM Table_2
WHERE @p1 > column_1
RETURN
END
GO
CREATE FUNCTION [dbo].[TableFunctionWithComputedColumnsEncrypted]
(
-- Add the parameters for the function here
@p1 int = 2,
@p2 nchar(10)
)
RETURNS
@Table_Var TABLE
(
-- Add the column definitions for the TABLE variable here
c1 int,
c2 nchar(10),
c3 AS 1 * 3
)
WITH ENCRYPTION
AS
BEGIN
-- Fill the table variable with the rows for your result set
INSERT INTO @Table_Var
SELECT a.column_1, a.column_2
FROM Table_1 a
WHERE a.column_1 > 5
INSERT INTO @Table_Var
SELECT column_1, 'From 2'
FROM Table_2
WHERE @p1 > column_1
RETURN
END
GO
Create table [dbo].[referenced_table] (C1 int, C2 int);
GO
CREATE PROCEDURE GetReferenedTable
AS
BEGIN
SELECT * from [dbo].[referenced_table];
END
GO
exec sp_addextendedproperty N'microsoft_database_tools_support', 'GetReferenedTable', N'SCHEMA', 'dbo', N'PROCEDURE' ,'GetReferenedTable'
GO
DISABLE TRIGGER [Trigger_1]
ON DATABASE;
GO
CREATE VIEW [dbo].[View_2] (c1)
AS
SELECT column_1 as c1
FROM dbo.Table_1
GO
exec sp_addextendedproperty 'prop_ex', 'Table_1', 'SCHEMA', 'dbo', 'TABLE', 'Table_1'
GO
exec sp_addextendedproperty 'prop_ex', 'column_1', 'SCHEMA', 'dbo', 'TABLE', 'Table_1', 'COLUMN', 'column_1'
GO
CREATE TABLE dbo.MultipleIndexTable
( [c1] INT NOT NULL CHECK (c1 > 0),
[c2] int default 10 null,
PRIMARY KEY NONCLUSTERED (c1 ASC),
UNIQUE CLUSTERED (c1 ASC, c2 DESC)
)
GO
CREATE TRIGGER [Trigger_2]
ON DATABASE
FOR DROP_TABLE
AS
SELECT COUNT(column_1) from dbo.Table_1
RAISERROR ('You must disable Trigger "Trigger_1" to drop synonyms!',10, 1)
ROLLBACK
GO
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
DISABLE TRIGGER [Trigger_1] ON DATABASE
GO
GO
CREATE TABLE dbo.Table_3
(
c1 int,
c2 int,
) ON PartitionScheme(c1)
GO
CREATE TABLE [dbo].[Different_WithAppend_Table](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Col] [char](1) NULL
) ON [PRIMARY]
GO
CREATE FUNCTION [dbo].[EncryptedFunctionWithConstraints]
(@p1 INT)
RETURNS
@GeneratedTableName TABLE (
[c0] INT NOT NULL PRIMARY KEY,
[c1] INT DEFAULT ((1)) NULL,
[c2] NCHAR (10) NULL,
[c3] INT UNIQUE ,
CHECK ([c1]>(0)))
WITH ENCRYPTION
AS
BEGIN
insert into @GeneratedTableName values (1,1, 'abc',1);
RETURN
END
GO
CREATE TABLE [[] (c1 int)
GO
CREATE TABLE []]] (c1 int)
GO
CREATE TABLE [asdf'[] (c1 int)
GO
CREATE TABLE [噂構申表5] (c1 int)
GO
-- Casing of NULL is explicit 'NUll'
CREATE PROC CasingOnDefaultValue @param1 int = NUll, @param2 nvarchar(123) = N'abc'
AS
BEGIN
select 1 as a
END
-- permissions
GO
CREATE USER nologon4 without login
GO
GRANT VIEW DEFINITION ON CasingOnDefaultValue to nologon4
GO
CREATE USER granter without login
GO
GRANT CONNECT TO granter WITH GRANT OPTION;
GO
DENY CONNECT TO nologon4 CASCADE AS granter;
GO
GRANT VIEW DEFINITION ON [噂構申表5] to nologon4
GO
GRANT VIEW DEFINITION ON [[] TO nologon4
GO
GRANT VIEW DEFINITION ON []]] TO nologon4
GO
GRANT VIEW DEFINITION ON [asdf'[] TO nologon4
GO
GRANT SELECT ON dbo.Table_1 to nologon4
GO
GRANT SELECT ON dbo.Table_2 to nologon4
GO
REVOKE SELECT ON dbo.Table_2(column_2) TO nologon4
GO
GRANT SELECT ON dbo.View_1 to nologon4
GO
GRANT SELECT ON dbo.EncryptedView(A) to nologon4
GO
GRANT EXECUTE ON dbo.Procedure1 TO nologon4
GO
GRANT EXECUTE ON dbo.CLR_SimpleResultsetProcedure TO nologon4
GO
GRANT EXECUTE ON dbo.EncryptedProcedure TO nologon4
GO
GRANT VIEW DEFINITION ON CERTIFICATE :: Certificate1 TO nologon4
GO
GRANT EXECUTE ON dbo.ScalarFunction1 TO nologon4
GO
GRANT EXECUTE ON dbo.EncryptedFunction TO nologon4
GO
GRANT SELECT ON dbo.InlineFunction_1 TO nologon4
GO
GRANT SELECT ON dbo.TableFunction1 TO nologon4
GO
GRANT SELECT ON dbo.CLRTableValueFunction TO nologon4
GO
GRANT VIEW DEFINITION ON TYPE::dbo.dataType To nologon4
GO
GRANT VIEW DEFINITION ON FULLTEXT CATALOG ::FullTextCatalog1 To nologon4
GO
GRANT VIEW DEFINITION ON XML SCHEMA COLLECTION :: dbo.XmlSchemaCollection To nologon4
GO
GRANT VIEW DEFINITION ON ASSEMBLY :: [Geometry] To nologon4
GO
GRANT VIEW DEFINITION ON TYPE:: dbo.Angle To nologon4
GO
GRANT VIEW DEFINITION ON dbo.[Concat] To nologon4
GO
GRANT VIEW DEFINITION ON dbo.Synonym_1 To nologon4
GO
GRANT VIEW DEFINITION ON SCHEMA :: Schema1 To nologon4
GO
GRANT VIEW DEFINITION ON SYMMETRIC KEY :: SymKey1 To nologon4
GO
GRANT VIEW DEFINITION ON ASYMMETRIC KEY :: AsmKey1 To nologon4
GO
GRANT VIEW DEFINITION ON dbo.Queue1 To nologon4
GO
GRANT VIEW DEFINITION ON dbo.NotifyQueue To nologon4
GO
GRANT VIEW DEFINITION ON SERVICE :: Service1 To nologon4
GO
GRANT VIEW DEFINITION ON SERVICE :: NotifyService To nologon4
GO
GRANT VIEW DEFINITION ON CONTRACT :: Contract1 To nologon4
GO
GRANT VIEW DEFINITION ON MESSAGE TYPE :: MessageType1 To nologon4
GO
GRANT VIEW DEFINITION ON ROUTE :: AutoCreatedLocal To nologon4
GO
GRANT VIEW DEFINITION ON ROUTE :: Route1 To nologon4
GO
GRANT VIEW DEFINITION ON REMOTE SERVICE BINDING :: ServiceBinding1 To nologon4
GO
GRANT SELECT ON dbo.referenced_table To nologon4
GO
GRANT SELECT ON dbo.TableFunctionWithComputedColumns To nologon4
GO
GRANT SELECT ON dbo.TableFunctionWithComputedColumnsEncrypted To nologon4
GO
GRANT SELECT ON dbo.View_2 TO nologon4
GO
GRANT SELECT ON dbo.MultipleIndexTable TO nologon4
GO
GRANT SELECT ON dbo.Table_3 TO nologon4
GO
GRANT SELECT ON dbo.Different_WithAppend_Table TO nologon4
GO
GRANT SELECT ON dbo.[EncryptedFunctionWithConstraints] TO nologon4
GO

View File

@@ -8,6 +8,7 @@ using Microsoft.SqlTools.Credentials;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
using Microsoft.SqlTools.ServiceLayer.QueryExecution;
using Microsoft.SqlTools.ServiceLayer.SqlContext;
using Microsoft.SqlTools.ServiceLayer.Workspace;
@@ -43,6 +44,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common
{
return CredentialService.Instance;
}
}
public ObjectExplorerService ObjectExplorerService
{
get
{
var serviceProvider = ServiceHost.Instance.ServiceProvider;
return serviceProvider.GetService<ObjectExplorerService>();
}
}
public TestConnectionProfileService ConnectionProfileService

View File

@@ -6,7 +6,8 @@
"includeFiles": [
"Scripts/CreateTestDatabaseObjects.sql",
"Scripts/CreateTestDatabase.sql",
"Scripts/TestDbTableQueries.sql"
"Scripts/TestDbTableQueries.sql",
"Scripts/AdventureWorks.sql"
]
}
},

View File

@@ -0,0 +1,369 @@
//
// 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.Data.SqlClient;
using System.Globalization;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.Extensibility;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility;
using Moq;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
{
/// <summary>
/// Tests covering basic operation of Node based classes
/// </summary>
public class NodeTests : ObjectExplorerTestBase
{
private string defaultOwnerUri = "objectexplorer://myserver";
private ServerInfo defaultServerInfo;
private ConnectionDetails defaultConnectionDetails;
private ConnectionCompleteParams defaultConnParams;
private string fakeConnectionString = "Data Source=server;Initial Catalog=database;Integrated Security=False;User Id=user";
public NodeTests()
{
defaultServerInfo = TestObjects.GetTestServerInfo();
defaultConnectionDetails = new ConnectionDetails()
{
DatabaseName = "master",
ServerName = "localhost",
UserName = "serverAdmin",
Password = "..."
};
defaultConnParams = new ConnectionCompleteParams()
{
ServerInfo = defaultServerInfo,
ConnectionSummary = defaultConnectionDetails,
OwnerUri = defaultOwnerUri
};
// TODO can all tests use the standard service provider?
ServiceProvider = ExtensionServiceProvider.CreateDefaultServiceProvider();
}
[Fact]
public void ServerNodeConstructorValidatesFields()
{
Assert.Throws<ArgumentNullException>(() => new ServerNode(null, ServiceProvider));
Assert.Throws<ArgumentNullException>(() => new ServerNode(defaultConnParams, null));
}
[Fact]
public void ServerNodeConstructorShouldSetValuesCorrectly()
{
// Given a server node with valid inputs
ServerNode node = new ServerNode(defaultConnParams, ServiceProvider);
// Then expect all fields set correctly
Assert.False(node.IsAlwaysLeaf, "Server node should never be a leaf");
Assert.Equal(defaultConnectionDetails.ServerName, node.NodeValue);
string expectedLabel = defaultConnectionDetails.ServerName + " (SQL Server " + defaultServerInfo.ServerVersion + " - "
+ defaultConnectionDetails.UserName + ")";
Assert.Equal(expectedLabel, node.Label);
Assert.Equal(NodeTypes.ServerInstance.ToString(), node.NodeType);
string[] nodePath = node.GetNodePath().Split(TreeNode.PathPartSeperator);
Assert.Equal(1, nodePath.Length);
Assert.Equal(defaultConnectionDetails.ServerName, nodePath[0]);
}
[Fact]
public void ServerNodeLabelShouldIgnoreUserNameIfEmptyOrNull()
{
// Given no username set
ConnectionSummary integratedAuthSummary = new ConnectionSummary()
{
DatabaseName = defaultConnectionDetails.DatabaseName,
ServerName = defaultConnectionDetails.ServerName,
UserName = null
};
ConnectionCompleteParams connParams = new ConnectionCompleteParams()
{
ConnectionSummary = integratedAuthSummary,
ServerInfo = defaultServerInfo,
OwnerUri = defaultOwnerUri
};
// When querying label
string label = new ServerNode(connParams, ServiceProvider).Label;
// Then only server name and version shown
string expectedLabel = defaultConnectionDetails.ServerName + " (SQL Server " + defaultServerInfo.ServerVersion + ")";
Assert.Equal(expectedLabel, label);
}
[Fact]
public void ServerNodeConstructorShouldShowDbNameForCloud()
{
defaultServerInfo.IsCloud = true;
// Given a server node for a cloud DB, with master name
ServerNode node = new ServerNode(defaultConnParams, ServiceProvider);
// Then expect label to not include db name
string expectedLabel = defaultConnectionDetails.ServerName + " (SQL Server " + defaultServerInfo.ServerVersion + " - "
+ defaultConnectionDetails.UserName + ")";
Assert.Equal(expectedLabel, node.Label);
// But given a server node for a cloud DB that's not master
defaultConnectionDetails.DatabaseName = "NotMaster";
node = new ServerNode(defaultConnParams, ServiceProvider);
// Then expect label to include db name
expectedLabel = defaultConnectionDetails.ServerName + " (SQL Server " + defaultServerInfo.ServerVersion + " - "
+ defaultConnectionDetails.UserName + ", " + defaultConnectionDetails.DatabaseName + ")";
Assert.Equal(expectedLabel, node.Label);
}
[Fact]
public void ToNodeInfoIncludeAllFields()
{
// Given a server connection
ServerNode node = new ServerNode(defaultConnParams, ServiceProvider);
// When converting to NodeInfo
NodeInfo info = node.ToNodeInfo();
// Then all fields should match
Assert.Equal(node.IsAlwaysLeaf, info.IsLeaf);
Assert.Equal(node.Label, info.Label);
Assert.Equal(node.NodeType, info.NodeType);
string[] nodePath = node.GetNodePath().Split(TreeNode.PathPartSeperator);
string[] nodeInfoPathParts = info.NodePath.Split(TreeNode.PathPartSeperator);
Assert.Equal(nodePath.Length, nodeInfoPathParts.Length);
for (int i = 0; i < nodePath.Length; i++)
{
Assert.Equal(nodePath[i], nodeInfoPathParts[i]);
}
}
[Fact]
public void AddChildShouldSetParent()
{
TreeNode parent = new TreeNode("parent");
TreeNode child = new TreeNode("child");
Assert.Null(child.Parent);
parent.AddChild(child);
Assert.Equal(parent, child.Parent);
}
[Fact]
public void GetChildrenShouldReturnReadonlyList()
{
TreeNode node = new TreeNode("parent");
IList<TreeNode> children = node.GetChildren();
Assert.Throws<NotSupportedException>(() => children.Add(new TreeNode("child")));
}
[Fact]
public void GetChildrenShouldReturnAddedNodesInOrder()
{
TreeNode parent = new TreeNode("parent");
TreeNode[] expectedKids = new TreeNode[] { new TreeNode("1"), new TreeNode("2") };
foreach (TreeNode child in expectedKids)
{
parent.AddChild(child);
}
IList<TreeNode> children = parent.GetChildren();
Assert.Equal(expectedKids.Length, children.Count);
for (int i = 0; i < expectedKids.Length; i++)
{
Assert.Equal(expectedKids[i], children[i]);
}
}
public void MultiLevelTreeShouldFormatPath()
{
TreeNode root = new TreeNode("root");
Assert.Equal("/root" , root.GetNodePath());
TreeNode level1Child1 = new TreeNode("L1C1");
TreeNode level1Child2 = new TreeNode("L1C2");
root.AddChild(level1Child1);
root.AddChild(level1Child2);
Assert.Equal("/root/L1C1" , level1Child1.GetNodePath());
Assert.Equal("/root/L1C2", level1Child2.GetNodePath());
TreeNode level2Child1 = new TreeNode("L2C2");
level1Child1.AddChild(level2Child1);
Assert.Equal("/root/L1C1/L2C2", level2Child1.GetNodePath());
}
[Fact]
public void ServerNodeContextShouldIncludeServer()
{
// given a successful Server creation
SetupAndRegisterTestConnectionService();
Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString)));
ServerNode node = SetupServerNodeWithServer(smoServer);
// When I get the context for a ServerNode
var context = node.GetContextAs<SmoQueryContext>();
// Then I expect it to contain the server I created
Assert.NotNull(context);
Assert.Equal(smoServer, context.Server);
// And the server should be the parent
Assert.Equal(smoServer, context.Parent);
Assert.Null(context.Database);
}
[Fact]
public void ServerNodeContextShouldSetErrorMessageIfSqlConnectionIsNull()
{
// given a connectionInfo with no SqlConnection to use for queries
ConnectionService connService = SetupAndRegisterTestConnectionService();
connService.OwnerToConnectionMap.Remove(defaultOwnerUri);
Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString)));
ServerNode node = SetupServerNodeWithServer(smoServer);
// When I get the context for a ServerNode
var context = node.GetContextAs<SmoQueryContext>();
// Then I expect it to be in an error state
Assert.Null(context);
Assert.Equal(
string.Format(CultureInfo.CurrentCulture, SR.ServerNodeConnectionError, defaultConnectionDetails.ServerName),
node.ErrorStateMessage);
}
[Fact]
public void ServerNodeContextShouldSetErrorMessageIfConnFailureExceptionThrown()
{
// given a connectionInfo with no SqlConnection to use for queries
SetupAndRegisterTestConnectionService();
Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString)));
string expectedMsg = "ConnFailed!";
ServerNode node = SetupServerNodeWithExceptionCreator(new ConnectionFailureException(expectedMsg));
// When I get the context for a ServerNode
var context = node.GetContextAs<SmoQueryContext>();
// Then I expect it to be in an error state
Assert.Null(context);
Assert.Equal(
string.Format(CultureInfo.CurrentCulture, SR.TreeNodeError, expectedMsg),
node.ErrorStateMessage);
}
[Fact]
public void ServerNodeContextShouldSetErrorMessageIfExceptionThrown()
{
// given a connectionInfo with no SqlConnection to use for queries
SetupAndRegisterTestConnectionService();
Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString)));
string expectedMsg = "Failed!";
ServerNode node = SetupServerNodeWithExceptionCreator(new Exception(expectedMsg));
// When I get the context for a ServerNode
var context = node.GetContextAs<SmoQueryContext>();
// Then I expect it to be in an error state
Assert.Null(context);
Assert.Equal(
string.Format(CultureInfo.CurrentCulture, SR.TreeNodeError, expectedMsg),
node.ErrorStateMessage);
}
private ConnectionService SetupAndRegisterTestConnectionService()
{
ConnectionService connService = TestObjects.GetTestConnectionService();
ConnectionInfo connectionInfo = new ConnectionInfo(TestObjects.GetTestSqlConnectionFactory(),
defaultOwnerUri, defaultConnectionDetails);
connectionInfo.AddConnection("Default", new SqlConnection());
connService.OwnerToConnectionMap.Add(defaultOwnerUri, connectionInfo);
ServiceProvider.RegisterSingleService(connService);
return connService;
}
private ServerNode SetupServerNodeWithServer(Server smoServer)
{
Mock<SmoServerCreator> creator = new Mock<SmoServerCreator>();
creator.Setup(c => c.Create(It.IsAny<SqlConnection>()))
.Returns(() => smoServer);
ServerNode node = SetupServerNodeWithCreator(creator.Object);
return node;
}
private ServerNode SetupServerNodeWithExceptionCreator(Exception ex)
{
Mock<SmoServerCreator> creator = new Mock<SmoServerCreator>();
creator.Setup(c => c.Create(It.IsAny<SqlConnection>()))
.Throws(ex);
ServerNode node = SetupServerNodeWithCreator(creator.Object);
return node;
}
private ServerNode SetupServerNodeWithCreator(SmoServerCreator creator)
{
ServerNode node = new ServerNode(defaultConnParams, ServiceProvider);
node.ServerCreator = creator;
return node;
}
[Fact]
public void ServerNodeChildrenShouldIncludeFoldersAndDatabases()
{
// Given a server with 1 database
SetupAndRegisterTestConnectionService();
ServiceProvider.RegisterSingleService(new ObjectExplorerService());
string dbName = "DB1";
Mock<NamedSmoObject> smoObjectMock = new Mock<NamedSmoObject>();
smoObjectMock.SetupGet(s => s.Name).Returns(dbName);
Mock<SqlDatabaseQuerier> querierMock = new Mock<SqlDatabaseQuerier>();
querierMock.Setup(q => q.Query(It.IsAny<SmoQueryContext>()))
.Returns(smoObjectMock.Object.SingleItemAsEnumerable());
ServiceProvider.Register<SmoQuerier>(() => new[] { querierMock.Object });
Server smoServer = new Server(new ServerConnection(new SqlConnection(fakeConnectionString)));
ServerNode node = SetupServerNodeWithServer(smoServer);
// When I populate its children
IList<TreeNode> children = node.Expand();
// Then I expect it to contain server-level folders
Assert.Equal(3, children.Count);
VerifyTreeNode<FolderNode>(children[0], "Folder", SR.SchemaHierarchy_Databases);
VerifyTreeNode<FolderNode>(children[1], "Folder", SR.SchemaHierarchy_Security);
VerifyTreeNode<FolderNode>(children[2], "Folder", SR.SchemaHierarchy_ServerObjects);
// And the database is contained under it
TreeNode databases = children[0];
IList<TreeNode> dbChildren = databases.Expand();
Assert.Equal(2, dbChildren.Count);
Assert.Equal("System Databases", dbChildren[0].NodeValue);
TreeNode dbNode = dbChildren[1];
Assert.Equal(dbName, dbNode.NodeValue);
Assert.Equal(dbName, dbNode.Label);
Assert.False(dbNode.IsAlwaysLeaf);
// Note: would like to verify Database in the context, but cannot since it's a Sealed class and isn't easily mockable
}
private void VerifyTreeNode<T>(TreeNode node, string nodeType, string folderValue)
where T : TreeNode
{
T nodeAsT = node as T;
Assert.NotNull(nodeAsT);
Assert.Equal(nodeType, nodeAsT.NodeType);
Assert.Equal(folderValue, nodeAsT.NodeValue);
}
}
}

View File

@@ -0,0 +1,151 @@
//
// 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.Threading.Tasks;
using Microsoft.SqlTools.Hosting.Protocol;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Contracts;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
using Microsoft.SqlTools.ServiceLayer.Test.Common;
using Microsoft.SqlTools.ServiceLayer.UnitTests.Utility;
using Moq;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
{
public class ObjectExplorerServiceTests : ObjectExplorerTestBase
{
private ObjectExplorerService service;
private Mock<ConnectionService> connectionServiceMock;
private Mock<IProtocolEndpoint> serviceHostMock;
public ObjectExplorerServiceTests()
{
connectionServiceMock = new Mock<ConnectionService>();
serviceHostMock = new Mock<IProtocolEndpoint>();
service = CreateOEService(connectionServiceMock.Object);
service.InitializeService(serviceHostMock.Object);
}
[Fact]
public async Task CreateSessionRequestErrorsIfConnectionDetailsIsNull()
{
object errorResponse = null;
var contextMock = RequestContextMocks.Create<CreateSessionResponse>(null)
.AddErrorHandling((errorMessage, errorCode, obj) => errorResponse = errorMessage);
await service.HandleCreateSessionRequest(null, contextMock.Object);
VerifyErrorSent(contextMock);
Assert.True(((string)errorResponse).Contains("ArgumentNullException"));
}
[Fact]
public async Task CreateSessionRequestReturnsFalseOnConnectionFailure()
{
// Given the connection service fails to connect
ConnectionDetails details = TestObjects.GetTestConnectionDetails();
ConnectionCompleteParams completeParams = null;
serviceHostMock.AddEventHandling(ConnectionCompleteNotification.Type, (et, p) => completeParams = p);
string expectedExceptionText = "Error!!!";
connectionServiceMock.Setup(c => c.Connect(It.IsAny<ConnectParams>()))
.Throws(new Exception(expectedExceptionText));
// when creating a new session
// then expect the create session request to return false
await RunAndVerify<CreateSessionResponse>(
test: (requestContext) => service.HandleCreateSessionRequest(details, requestContext),
verify: (actual =>
{
Assert.False(actual.Success);
Assert.Null(actual.SessionId);
Assert.Null(actual.RootNode);
}));
// And expect error notification to be sent
serviceHostMock.Verify(x => x.SendEvent(ConnectionCompleteNotification.Type, It.IsAny<ConnectionCompleteParams>()), Times.Once());
Assert.NotNull(completeParams);
Assert.True(completeParams.Messages.Contains(expectedExceptionText));
}
[Fact]
public async Task CreateSessionRequestReturnsSuccessAndNodeInfo()
{
// Given the connection service fails to connect
ConnectionDetails details = TestObjects.GetTestConnectionDetails();
serviceHostMock.AddEventHandling(ConnectionCompleteNotification.Type, null);
connectionServiceMock.Setup(c => c.Connect(It.IsAny<ConnectParams>()))
.Returns((ConnectParams connectParams) => Task.FromResult(GetCompleteParamsForConnection(connectParams.OwnerUri, details)));
// when creating a new session
// then expect the create session request to return false
await RunAndVerify<CreateSessionResponse>(
test: (requestContext) => service.HandleCreateSessionRequest(details, requestContext),
verify: (actual =>
{
Assert.True(actual.Success);
Assert.NotNull(actual.SessionId);
VerifyServerNode(actual.RootNode, details);
}));
// And expect no error notification to be sent
serviceHostMock.Verify(x => x.SendEvent(ConnectionCompleteNotification.Type,
It.IsAny<ConnectionCompleteParams>()), Times.Never());
}
private void VerifyServerNode(NodeInfo serverNode, ConnectionDetails details)
{
Assert.NotNull(serverNode);
Assert.Equal(NodeTypes.ServerInstance.ToString(), serverNode.NodeType);
string[] pathParts = serverNode.NodePath.Split(TreeNode.PathPartSeperator);
Assert.Equal(1, pathParts.Length);
Assert.Equal(details.ServerName, pathParts[0]);
Assert.True(serverNode.Label.Contains(details.ServerName));
Assert.False(serverNode.IsLeaf);
}
private static ConnectionCompleteParams GetCompleteParamsForConnection(string uri, ConnectionDetails details)
{
return new ConnectionCompleteParams()
{
OwnerUri = uri,
ConnectionSummary = new ConnectionSummary()
{
ServerName = details.ServerName,
DatabaseName = details.DatabaseName,
UserName = details.UserName
},
ServerInfo = TestObjects.GetTestServerInfo()
};
}
private async Task RunAndVerify<T>(Func<RequestContext<T>, Task> test, Action<T> verify)
{
T result = default(T);
var contextMock = RequestContextMocks.Create<T>(r => result = r).AddErrorHandling(null);
await test(contextMock.Object);
VerifyResult(contextMock, verify, result);
}
private void VerifyResult<T>(Mock<RequestContext<T>> contextMock, Action<T> verify, T actual)
{
contextMock.Verify(c => c.SendResult(It.IsAny<T>()), Times.Once);
contextMock.Verify(c => c.SendError(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<object>()), Times.Never);
verify(actual);
}
private void VerifyErrorSent<T>(Mock<RequestContext<T>> contextMock)
{
contextMock.Verify(c => c.SendResult(It.IsAny<T>()), Times.Never);
contextMock.Verify(c => c.SendError(It.IsAny<string>(), It.IsAny<int>(), It.IsAny<object>()), Times.Once);
}
}
}

View File

@@ -0,0 +1,45 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using Microsoft.SqlTools.Extensibility;
using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
{
// Base class providing common test functionality for OE tests
public abstract class ObjectExplorerTestBase
{
protected RegisteredServiceProvider ServiceProvider
{
get;
set;
}
protected RegisteredServiceProvider CreateServiceProviderWithMinServices()
{
return CreateProvider()
.RegisterSingleService(new ConnectionService())
.RegisterSingleService(new ObjectExplorerService());
}
protected RegisteredServiceProvider CreateProvider()
{
ServiceProvider = new RegisteredServiceProvider();
return ServiceProvider;
}
protected ObjectExplorerService CreateOEService(ConnectionService connService)
{
CreateProvider()
.RegisterSingleService(connService)
.RegisterSingleService(new ObjectExplorerService());
// Create the service using the service provider, which will initialize dependencies
return ServiceProvider.GetService<ObjectExplorerService>();
}
}
}

View File

@@ -0,0 +1,65 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using System.Linq;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.Extensibility;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel;
using Xunit;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
{
public class SmoQueryModelTests
{
[Fact]
public void ShouldFindDatabaseQuerierFromRealPath()
{
// Given the extension type loader is set to find SmoCollectionQuerier objects
IMultiServiceProvider serviceProvider = ExtensionServiceProvider.CreateDefaultServiceProvider();
// When I request a database compatible querier
SmoQuerier querier = serviceProvider.GetService<SmoQuerier>(q => q.SupportedObjectTypes.Contains(typeof(Database)));
// Then I expect to get back the SqlDatabaseQuerier
Assert.NotNull(querier);
Assert.Equal(typeof(SqlDatabaseQuerier), querier.GetType());
// And I expect the service provider to have been set by the extension code
Assert.NotNull(querier.ServiceProvider);
}
[Fact]
public void ShouldFindQuerierIfInExtensionList()
{
VerifyQuerierLookup(typeof(Table), typeof(SqlTableQuerier), expectExists: true);
}
[Fact]
public void ShouldNotFindQuerierIfNotInExtensionList()
{
VerifyQuerierLookup(typeof(Database), null, expectExists: false);
}
private static void VerifyQuerierLookup(Type smoType, Type querierType, bool expectExists)
{
ExtensionServiceProvider serviceProvider = ExtensionServiceProvider.Create(new Type[] {
typeof(SqlTableQuerier),
typeof(SqlLinkedServerQuerier)
});
SmoQuerier querier = serviceProvider.GetService<SmoQuerier>(q => q.SupportedObjectTypes.Contains(smoType));
if (expectExists)
{
Assert.NotNull(querier);
Assert.Equal(querierType, querier.GetType());
Assert.NotNull(querier.ServiceProvider);
}
else
{
Assert.Null(querier);
}
}
}
}

View File

@@ -43,6 +43,169 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ServiceHost
var queryServiceErrorFormat = SR.QueryServiceErrorFormat(1, 1, 1, 1, "\n", "..");
var queryServiceQueryFailed = SR.QueryServiceQueryFailed("..");
var workspaceServiceBufferPositionOutOfOrder = SR.WorkspaceServiceBufferPositionOutOfOrder(1, 2, 3, 4);
var treeNodeError = SR.TreeNodeError;
var serverNodeConnectionError = SR.ServerNodeConnectionError;
var schemaHierarchyAggregates = SR.SchemaHierarchy_Aggregates;
var SchemaHierarchy_ServerRoles = SR.SchemaHierarchy_ServerRoles;
var SchemaHierarchy_ApplicationRoles = SR.SchemaHierarchy_ApplicationRoles;
var SchemaHierarchy_Assemblies = SR.SchemaHierarchy_Assemblies;
var SchemaHierarchy_AssemblyFiles = SR.SchemaHierarchy_AssemblyFiles;
var SchemaHierarchy_AsymmetricKeys = SR.SchemaHierarchy_AsymmetricKeys;
var SchemaHierarchy_DatabaseAsymmetricKeys = SR.SchemaHierarchy_DatabaseAsymmetricKeys;
var SchemaHierarchy_DataCompressionOptions = SR.SchemaHierarchy_DataCompressionOptions;
var SchemaHierarchy_Certificates = SR.SchemaHierarchy_Certificates;
var SchemaHierarchy_FileTables = SR.SchemaHierarchy_FileTables;
var SchemaHierarchy_DatabaseCertificates = SR.SchemaHierarchy_DatabaseCertificates;
var SchemaHierarchy_CheckConstraints = SR.SchemaHierarchy_CheckConstraints;
var SchemaHierarchy_Columns = SR.SchemaHierarchy_Columns;
var SchemaHierarchy_Constraints = SR.SchemaHierarchy_Constraints;
var SchemaHierarchy_Contracts = SR.SchemaHierarchy_Contracts;
var SchemaHierarchy_Credentials = SR.SchemaHierarchy_Credentials;
var SchemaHierarchy_ErrorMessages = SR.SchemaHierarchy_ErrorMessages;
var SchemaHierarchy_ServerRoleMembership = SR.SchemaHierarchy_ServerRoleMembership;
var SchemaHierarchy_DatabaseOptions = SR.SchemaHierarchy_DatabaseOptions;
var SchemaHierarchy_DatabaseRoles = SR.SchemaHierarchy_DatabaseRoles;
var SchemaHierarchy_RoleMemberships = SR.SchemaHierarchy_RoleMemberships;
var SchemaHierarchy_DatabaseTriggers = SR.SchemaHierarchy_DatabaseTriggers;
var SchemaHierarchy_DefaultConstraints = SR.SchemaHierarchy_DefaultConstraints;
var SchemaHierarchy_Defaults = SR.SchemaHierarchy_Defaults;
var SchemaHierarchy_Sequences = SR.SchemaHierarchy_Sequences;
var SchemaHierarchy_Endpoints = SR.SchemaHierarchy_Endpoints;
var SchemaHierarchy_EventNotifications = SR.SchemaHierarchy_EventNotifications;
var SchemaHierarchy_ServerEventNotifications = SR.SchemaHierarchy_ServerEventNotifications;
var SchemaHierarchy_ExtendedProperties = SR.SchemaHierarchy_ExtendedProperties;
var SchemaHierarchy_FileGroups = SR.SchemaHierarchy_FileGroups;
var SchemaHierarchy_ForeignKeys = SR.SchemaHierarchy_ForeignKeys;
var SchemaHierarchy_FullTextCatalogs = SR.SchemaHierarchy_FullTextCatalogs;
var SchemaHierarchy_FullTextIndexes = SR.SchemaHierarchy_FullTextIndexes;
var SchemaHierarchy_Functions = SR.SchemaHierarchy_Functions;
var SchemaHierarchy_Indexes = SR.SchemaHierarchy_Indexes;
var SchemaHierarchy_InlineFunctions = SR.SchemaHierarchy_InlineFunctions;
var SchemaHierarchy_Keys = SR.SchemaHierarchy_Keys;
var SchemaHierarchy_LinkedServers = SR.SchemaHierarchy_LinkedServers;
var SchemaHierarchy_LinkedServerLogins = SR.SchemaHierarchy_LinkedServerLogins;
var SchemaHierarchy_Logins = SR.SchemaHierarchy_Logins;
var SchemaHierarchy_MasterKey = SR.SchemaHierarchy_MasterKey;
var SchemaHierarchy_MasterKeys = SR.SchemaHierarchy_MasterKeys;
var SchemaHierarchy_MessageTypes = SR.SchemaHierarchy_MessageTypes;
var SchemaHierarchy_MultiSelectFunctions = SR.SchemaHierarchy_MultiSelectFunctions;
var SchemaHierarchy_Parameters = SR.SchemaHierarchy_Parameters;
var SchemaHierarchy_PartitionFunctions = SR.SchemaHierarchy_PartitionFunctions;
var SchemaHierarchy_PartitionSchemes = SR.SchemaHierarchy_PartitionSchemes;
var SchemaHierarchy_Permissions = SR.SchemaHierarchy_Permissions;
var SchemaHierarchy_PrimaryKeys = SR.SchemaHierarchy_PrimaryKeys;
var schemaHierarchyPrimaryKeys = SR.SchemaHierarchy_PrimaryKeys;
var schemaHierarchyProgrammability = SR.SchemaHierarchy_Programmability;
var schemaHierarchyQueues = SR.SchemaHierarchy_Queues;
var schemaHierarchyRemoteServiceBindings = SR.SchemaHierarchy_RemoteServiceBindings;
var schemaHierarchyReturnedColumns = SR.SchemaHierarchy_ReturnedColumns;
var schemaHierarchyRoles = SR.SchemaHierarchy_Roles;
var schemaHierarchyRoutes = SR.SchemaHierarchy_Routes;
var schemaHierarchyRules = SR.SchemaHierarchy_Rules;
var schemaHierarchySchemas = SR.SchemaHierarchy_Schemas;
var schemaHierarchySecurity = SR.SchemaHierarchy_Security;
var schemaHierarchyServerObjects = SR.SchemaHierarchy_ServerObjects;
var schemaHierarchyManagement = SR.SchemaHierarchy_Management;
var schemaHierarchyServerTriggers = SR.SchemaHierarchy_ServerTriggers;
var schemaHierarchyServiceBroker = SR.SchemaHierarchy_ServiceBroker;
var schemaHierarchyServices = SR.SchemaHierarchy_Services;
var schemaHierarchySignatures = SR.SchemaHierarchy_LogFiles;
var schemaHierarchyStatistics = SR.SchemaHierarchy_Statistics;
var schemaHierarchyStorage = SR.SchemaHierarchy_Storage;
var schemaHierarchyStoredProcedures = SR.SchemaHierarchy_StoredProcedures;
var schemaHierarchySymmetricKeys = SR.SchemaHierarchy_SymmetricKeys;
var schemaHierarchySynonyms = SR.SchemaHierarchy_Synonyms;
var schemaHierarchyTables = SR.SchemaHierarchy_Tables;
var schemaHierarchyTriggers = SR.SchemaHierarchy_Triggers;
var schemaHierarchyTypes = SR.SchemaHierarchy_Types;
var schemaHierarchyUniqueKeys = SR.SchemaHierarchy_UniqueKeys;
var schemaHierarchyUserDefinedDataTypes = SR.SchemaHierarchy_UserDefinedDataTypes;
var schemaHierarchyUserDefinedTypes = SR.SchemaHierarchy_UserDefinedTypes;
var schemaHierarchyUsers = SR.SchemaHierarchy_Users;
var schemaHierarchyViews = SR.SchemaHierarchy_Views;
var schemaHierarchyXmlIndexes = SR.SchemaHierarchy_XmlIndexes;
var schemaHierarchyXMLSchemaCollections = SR.SchemaHierarchy_XMLSchemaCollections;
var schemaHierarchyUserDefinedTableTypes = SR.SchemaHierarchy_UserDefinedTableTypes;
var schemaHierarchyFilegroupFiles = SR.SchemaHierarchy_FilegroupFiles;
var missingCaption = SR.MissingCaption;
var schemaHierarchyBrokerPriorities = SR.SchemaHierarchy_BrokerPriorities;
var schemaHierarchyCryptographicProviders = SR.SchemaHierarchy_CryptographicProviders;
var schemaHierarchyDatabaseAuditSpecifications = SR.SchemaHierarchy_DatabaseAuditSpecifications;
var schemaHierarchyDatabaseEncryptionKeys = SR.SchemaHierarchy_DatabaseEncryptionKeys;
var schemaHierarchyEventSessions = SR.SchemaHierarchy_EventSessions;
var schemaHierarchyFullTextStopLists = SR.SchemaHierarchy_FullTextStopLists;
var schemaHierarchyResourcePools = SR.SchemaHierarchy_ResourcePools;
var schemaHierarchyServerAudits = SR.SchemaHierarchy_ServerAudits;
var schemaHierarchyServerAuditSpecifications = SR.SchemaHierarchy_ServerAuditSpecifications;
var schemaHierarchySpatialIndexes = SR.SchemaHierarchy_SpatialIndexes;
var schemaHierarchyWorkloadGroups = SR.SchemaHierarchy_WorkloadGroups;
var schemaHierarchySqlFiles = SR.SchemaHierarchy_SqlFiles;
var schemaHierarchyServerFunctions = SR.SchemaHierarchy_ServerFunctions;
var schemaHierarchySqlType = SR.SchemaHierarchy_SqlType;
var schemaHierarchyServerOptions = SR.SchemaHierarchy_ServerOptions;
var schemaHierarchyDatabaseDiagrams = SR.SchemaHierarchy_DatabaseDiagrams;
var schemaHierarchySystemTables = SR.SchemaHierarchy_SystemTables;
var schemaHierarchyDatabases = SR.SchemaHierarchy_Databases;
var schemaHierarchySystemContracts = SR.SchemaHierarchy_SystemContracts;
var schemaHierarchySystemDatabases = SR.SchemaHierarchy_SystemDatabases;
var schemaHierarchySystemMessageTypes = SR.SchemaHierarchy_SystemMessageTypes;
var schemaHierarchySystemQueues = SR.SchemaHierarchy_SystemQueues;
var schemaHierarchySystemServices = SR.SchemaHierarchy_SystemServices;
var schemaHierarchySystemStoredProcedures = SR.SchemaHierarchy_SystemStoredProcedures;
var schemaHierarchySystemViews = SR.SchemaHierarchy_SystemViews;
var schemaHierarchyDataTierApplications = SR.SchemaHierarchy_DataTierApplications;
var schemaHierarchyExtendedStoredProcedures = SR.SchemaHierarchy_ExtendedStoredProcedures;
var schemaHierarchySystemAggregateFunctions = SR.SchemaHierarchy_SystemAggregateFunctions;
var schemaHierarchySystemApproximateNumerics = SR.SchemaHierarchy_SystemApproximateNumerics;
var schemaHierarchySystemBinaryStrings = SR.SchemaHierarchy_SystemBinaryStrings;
var schemaHierarchySystemCharacterStrings = SR.SchemaHierarchy_SystemCharacterStrings;
var schemaHierarchySystemCLRDataTypes = SR.SchemaHierarchy_SystemCLRDataTypes;
var schemaHierarchySystemConfigurationFunctions = SR.SchemaHierarchy_SystemConfigurationFunctions;
var schemaHierarchySystemCursorFunctions = SR.SchemaHierarchy_SystemCursorFunctions;
var schemaHierarchySystemDataTypes = SR.SchemaHierarchy_SystemDataTypes;
var schemaHierarchySystemDateAndTime = SR.SchemaHierarchy_SystemDateAndTime;
var schemaHierarchySystemDateAndTimeFunctions = SR.SchemaHierarchy_SystemDateAndTimeFunctions;
var schemaHierarchySystemExactNumerics = SR.SchemaHierarchy_SystemExactNumerics;
var schemaHierarchySystemFunctions = SR.SchemaHierarchy_SystemFunctions;
var schemaHierarchySystemHierarchyIdFunctions = SR.SchemaHierarchy_SystemHierarchyIdFunctions;
var schemaHierarchySystemMathematicalFunctions = SR.SchemaHierarchy_SystemMathematicalFunctions;
var schemaHierarchySystemMetadataFunctionions = SR.SchemaHierarchy_SystemMetadataFunctions;
var schemaHierarchySystemOtherDataTypes = SR.SchemaHierarchy_SystemOtherDataTypes;
var schemaHierarchySystemOtherFunctions = SR.SchemaHierarchy_SystemOtherFunctions;
var schemaHierarchySystemRowsetFunctions = SR.SchemaHierarchy_SystemRowsetFunctions;
var schemaHierarchySystemSecurityFunctions = SR.SchemaHierarchy_SystemSecurityFunctions;
var schemaHierarchySystemSpatialDataTypes = SR.SchemaHierarchy_SystemSpatialDataTypes;
var schemaHierarchySystemStringFunctions = SR.SchemaHierarchy_SystemStringFunctions;
var schemaHierarchySystemSystemStatisticalFunctions = SR.SchemaHierarchy_SystemSystemStatisticalFunctions;
var schemaHierarchySystemTextAndImageFunctions = SR.SchemaHierarchy_SystemTextAndImageFunctions;
var schemaHierarchySystemUnicodeCharacterStrings = SR.SchemaHierarchy_SystemUnicodeCharacterStrings;
var schemaHierarchyAggregateFunctions = SR.SchemaHierarchy_AggregateFunctions;
var schemaHierarchyScalarValuedFunctions = SR.SchemaHierarchy_ScalarValuedFunctions;
var schemaHierarchyTableValuedFunctions = SR.SchemaHierarchy_TableValuedFunctions;
var schemaHierarchySystemExtendedStoredProcedures = SR.SchemaHierarchy_SystemExtendedStoredProcedures;
var schemaHierarchyBuiltInType = SR.SchemaHierarchy_BuiltInType;
var schemaHierarchyBuiltInServerRole = SR.SchemaHierarchy_BuiltInServerRole;
var schemaHierarchyUserWithPassword = SR.SchemaHierarchy_UserWithPassword;
var schemaHierarchySearchPropertyList = SR.SchemaHierarchy_SearchPropertyList;
var schemaHierarchySecurityPolicies = SR.SchemaHierarchy_SecurityPolicies;
var schemaHierarchySecurityPredicates = SR.SchemaHierarchy_SecurityPredicates;
var schemaHierarchyServerRole = SR.SchemaHierarchy_ServerRole;
var schemaHierarchySearchPropertyLists = SR.SchemaHierarchy_SearchPropertyLists;
var schemaHierarchyColumnStoreIndexes = SR.SchemaHierarchy_ColumnStoreIndexes;
var schemaHierarchyTableTypeIndexes = SR.SchemaHierarchy_TableTypeIndexes;
var schemaHierarchyServerInstance = SR.SchemaHierarchy_ServerInstance;
var schemaHierarchySelectiveXmlIndexes = SR.SchemaHierarchy_SelectiveXmlIndexes;
var schemaHierarchyXmlNamespaces = SR.SchemaHierarchy_XmlNamespaces;
var schemaHierarchyXmlTypedPromotedPaths = SR.SchemaHierarchy_XmlTypedPromotedPaths;
var schemaHierarchySqlTypedPromotedPaths = SR.SchemaHierarchy_SqlTypedPromotedPaths;
var schemaHierarchyDatabaseScopedCredentials = SR.SchemaHierarchy_DatabaseScopedCredentials;
var schemaHierarchyExternalDataSources = SR.SchemaHierarchy_ExternalDataSources;
var schemaHierarchyExternalFileFormats = SR.SchemaHierarchy_ExternalFileFormats;
var schemaHierarchyExternalResources = SR.SchemaHierarchy_ExternalResources;
var schemaHierarchyExternalTables = SR.SchemaHierarchy_ExternalTables;
var schemaHierarchyAlwaysEncryptedKeys = SR.SchemaHierarchy_AlwaysEncryptedKeys;
var schemaHierarchyColumnMasterKeys = SR.SchemaHierarchy_ColumnMasterKeys;
var schemaHierarchyColumnEncryptionKeys = SR.SchemaHierarchy_ColumnEncryptionKeys;
}
[Fact]

View File

@@ -0,0 +1,33 @@
//
// 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.Threading.Tasks;
using Microsoft.SqlTools.Hosting.Protocol;
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
using Moq;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
{
public static class ProtocolEndpointMocks
{
public static Mock<IProtocolEndpoint> AddEventHandling<TParams>(
this Mock<IProtocolEndpoint> mock,
EventType<TParams> expectedEvent,
Action<EventType<TParams>, TParams> eventCallback)
{
var flow = mock.Setup(h => h.SendEvent(
It.Is<EventType<TParams>>(m => m == expectedEvent),
It.IsAny<TParams>()))
.Returns(Task.FromResult(0));
if (eventCallback != null)
{
flow.Callback(eventCallback);
}
return mock;
}
}
}

View File

@@ -53,6 +53,30 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
};
}
public static ServerInfo GetTestServerInfo()
{
return new ServerInfo()
{
ServerVersion = "14.0.1.0",
ServerMajorVersion = 14,
ServerMinorVersion = 0,
EngineEditionId = 3,
OsVersion = "Linux (Ubuntu 15.10)",
IsCloud = false,
ServerEdition = "Developer Edition",
ServerLevel = ""
};
}
/// <summary>
/// Creates a test sql connection factory instance
/// </summary>
public static ISqlConnectionFactory GetTestSqlConnectionFactory()
{
// use mock database connection
return new TestSqlConnectionFactory();
}
/// <summary>
/// Creates a test connection details object
/// </summary>