From 3626d000fdeb8be3f664bcd39633297c6097971f Mon Sep 17 00:00:00 2001 From: Leila Lali Date: Wed, 15 Jan 2020 11:21:07 -0800 Subject: [PATCH] Added service class for machine learning services operations (#906) * Added service class for server configurations and language extension --- .../HostLoader.cs | 8 + .../ExternalLanguageStatusRequest.cs | 43 +++ .../LanguageExtensionOperations.cs | 51 ++++ .../LanguageExtensionsService.cs | 98 +++++++ .../Contracts/ServerConfigListRequest.cs | 44 ++++ .../Contracts/ServerConfigProperty.cs | 43 +++ .../Contracts/ServerConfigUpdateRequest.cs | 48 ++++ .../Contracts/ServerConfigViewRequest.cs | 43 +++ .../ServerConfigException.cs | 27 ++ .../ServerConfigService.cs | 244 ++++++++++++++++++ .../DisasterRecovery/BackupServiceTests.cs | 190 +++++++------- .../LanguageExtensionsTests.cs | 64 +++++ .../ServerConfigurationsServiceTests.cs | 150 +++++++++++ .../Utility/LiveConnectionHelper.cs | 4 +- 14 files changed, 964 insertions(+), 93 deletions(-) create mode 100644 src/Microsoft.SqlTools.ServiceLayer/LanguageExtensions/Contracts/ExternalLanguageStatusRequest.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/LanguageExtensions/LanguageExtensionOperations.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/LanguageExtensions/LanguageExtensionsService.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigListRequest.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigProperty.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigUpdateRequest.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigViewRequest.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/ServerConfigException.cs create mode 100644 src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/ServerConfigService.cs create mode 100644 test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageExtensions/LanguageExtensionsTests.cs create mode 100644 test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ServerConfigurations/ServerConfigurationsServiceTests.cs diff --git a/src/Microsoft.SqlTools.ServiceLayer/HostLoader.cs b/src/Microsoft.SqlTools.ServiceLayer/HostLoader.cs index 225906fa..8542f9bf 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/HostLoader.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/HostLoader.cs @@ -18,6 +18,8 @@ using Microsoft.SqlTools.ServiceLayer.EditData; using Microsoft.SqlTools.ServiceLayer.FileBrowser; using Microsoft.SqlTools.ServiceLayer.Hosting; using Microsoft.SqlTools.ServiceLayer.LanguageServices; +using Microsoft.SqlTools.ServiceLayer.ServerConfigurations; +using Microsoft.SqlTools.ServiceLayer.LanguageExtensions; using Microsoft.SqlTools.ServiceLayer.Metadata; using Microsoft.SqlTools.ServiceLayer.Profiler; using Microsoft.SqlTools.ServiceLayer.QueryExecution; @@ -122,6 +124,12 @@ namespace Microsoft.SqlTools.ServiceLayer SchemaCompare.SchemaCompareService.Instance.InitializeService(serviceHost); serviceProvider.RegisterSingleService(SchemaCompareService.Instance); + ServerConfigService.Instance.InitializeService(serviceHost); + serviceProvider.RegisterSingleService(ServerConfigService.Instance); + + LanguageExtensionsService.Instance.InitializeService(serviceHost); + serviceProvider.RegisterSingleService(LanguageExtensionsService.Instance); + InitializeHostedServices(serviceProvider, serviceHost); serviceHost.ServiceProvider = serviceProvider; diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageExtensions/Contracts/ExternalLanguageStatusRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageExtensions/Contracts/ExternalLanguageStatusRequest.cs new file mode 100644 index 00000000..08915284 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageExtensions/Contracts/ExternalLanguageStatusRequest.cs @@ -0,0 +1,43 @@ +// +// 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.Hosting.Protocol.Contracts; + +namespace Microsoft.SqlTools.ServiceLayer.LanguageExtensions.Contracts +{ + public class ExternalLanguageStatusRequestParams + { + /// + /// Connection uri + /// + public string OwnerUri { get; set; } + + /// + /// Language name + /// + public string LanguageName { get; set; } + } + + /// + /// Response class for external language status + /// + public class ExternalLanguageStatusResponseParams + { + /// + /// Language status + /// + public bool Status { get; set; } + } + + /// + /// Request class for external language status + /// + public class ExternalLanguageStatusRequest + { + public static readonly + RequestType Type = + RequestType.Create("languageextension/status"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageExtensions/LanguageExtensionOperations.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageExtensions/LanguageExtensionOperations.cs new file mode 100644 index 00000000..1af54a06 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageExtensions/LanguageExtensionOperations.cs @@ -0,0 +1,51 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System.Data; + +namespace Microsoft.SqlTools.ServiceLayer.LanguageExtensions +{ + public class LanguageExtensionOperations + { + private const string LanguageStatusScript = @"SELECT is_installed +FROM sys.dm_db_external_language_stats s, sys.external_languages l +WHERE s.external_language_id = l.external_language_id AND language = @LanguageName"; + + /// + /// Returns the status of external languages in a connection + /// + /// + /// + /// + public bool GetLanguageStatus(IDbConnection connection, string languageName) + { + bool status = false; + try + { + using (IDbCommand command = connection.CreateCommand()) + { + command.CommandText = LanguageStatusScript; + var parameter = command.CreateParameter(); + parameter.ParameterName = "@LanguageName"; + parameter.Value = languageName; + command.Parameters.Add(parameter); + using (IDataReader reader = command.ExecuteReader()) + { + while (reader.Read()) + { + status = (reader[0].ToString() == "True"); + } + } + } + } + catch + { + status = false; + } + + return status; + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/LanguageExtensions/LanguageExtensionsService.cs b/src/Microsoft.SqlTools.ServiceLayer/LanguageExtensions/LanguageExtensionsService.cs new file mode 100644 index 00000000..90fbdef1 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/LanguageExtensions/LanguageExtensionsService.cs @@ -0,0 +1,98 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.Hosting; +using Microsoft.SqlTools.ServiceLayer.LanguageExtensions.Contracts; +using Microsoft.SqlTools.Utility; +using System; +using System.Data; +using System.Diagnostics; +using System.Threading.Tasks; + +namespace Microsoft.SqlTools.ServiceLayer.LanguageExtensions +{ + public class LanguageExtensionsService + { + private LanguageExtensionOperations serviceOperations = new LanguageExtensionOperations(); + private ConnectionService connectionService = null; + private static readonly Lazy instance = new Lazy(() => new LanguageExtensionsService()); + + /// + /// Gets the singleton instance object + /// + public static LanguageExtensionsService Instance + { + get { return instance.Value; } + } + + /// + /// Internal for testing purposes only + /// + internal ConnectionService ConnectionServiceInstance + { + get + { + if (connectionService == null) + { + connectionService = ConnectionService.Instance; + } + return connectionService; + } + + set + { + connectionService = value; + } + } + + public void InitializeService(ServiceHost serviceHost) + { + serviceHost.SetRequestHandler(ExternalLanguageStatusRequest.Type, this.HandleExternalLanguageStatusRequest); + } + + /// + /// Handles external language status request + /// + /// Request parameters + /// Request Context + /// + public async Task HandleExternalLanguageStatusRequest(ExternalLanguageStatusRequestParams parameters, RequestContext requestContext) + { + Logger.Write(TraceEventType.Verbose, "HandleExternalLanguageStatusRequest"); + try + { + ConnectionInfo connInfo; + ConnectionServiceInstance.TryFindConnection( + parameters.OwnerUri, + out connInfo); + ExternalLanguageStatusResponseParams response = new ExternalLanguageStatusResponseParams + { + Status = false, + }; + + if (connInfo == null) + { + await requestContext.SendError(new Exception(SR.ProfilerConnectionNotFound)); + } + else + { + using (IDbConnection dbConnection = ConnectionService.OpenSqlConnection(connInfo)) + { + response.Status = serviceOperations.GetLanguageStatus(dbConnection, parameters.LanguageName); + } + + await requestContext.SendResult(response); + } + } + catch (Exception e) + { + // Exception related to run task will be captured here + await requestContext.SendError(e); + } + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigListRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigListRequest.cs new file mode 100644 index 00000000..8c34f945 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigListRequest.cs @@ -0,0 +1,44 @@ +// +// 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.Hosting.Protocol.Contracts; +using System.Collections.Generic; + +namespace Microsoft.SqlTools.ServiceLayer.ServerConfigurations.Contracts +{ + public class ServerConfigListRequestParams + { + /// + /// Connection uri + /// + public string OwnerUri { get; set; } + + /// + /// Config Number + /// + public int ConfigNumber { get; set; } + } + + /// + /// Response class for config list + /// + public class ServerConfigListResponseParams + { + /// + /// Config Property + /// + public List ConfigProperties { get; set; } + } + + /// + /// Request class for config list + /// + public class ServerConfigListRequest + { + public static readonly + RequestType Type = + RequestType.Create("config/List"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigProperty.cs b/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigProperty.cs new file mode 100644 index 00000000..6a53c431 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigProperty.cs @@ -0,0 +1,43 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlServer.Management.Smo; + +namespace Microsoft.SqlTools.ServiceLayer.ServerConfigurations.Contracts +{ + /// + /// A wrapper for SMO config property + /// + public class ServerConfigProperty + { + public int Number { get; set; } + + public string DisplayName { get; set; } + + public string Description { get; set; } + + public int ConfigValue { get; set; } + + public int Maximum { get; set; } + + public int Minimum { get; set; } + + public static ServerConfigProperty ToServerConfigProperty(ConfigProperty configProperty) + { + if (configProperty != null) + { + return new ServerConfigProperty + { + Number = configProperty.Number, + DisplayName = configProperty.DisplayName, + ConfigValue = configProperty.ConfigValue, + Maximum = configProperty.Maximum, + Minimum = configProperty.Minimum + }; + } + return null; + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigUpdateRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigUpdateRequest.cs new file mode 100644 index 00000000..cdf7e60e --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigUpdateRequest.cs @@ -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 Microsoft.SqlTools.Hosting.Protocol.Contracts; + +namespace Microsoft.SqlTools.ServiceLayer.ServerConfigurations.Contracts +{ + public class ServerConfigUpdateRequestParams + { + /// + /// Connection uri + /// + public string OwnerUri { get; set; } + + /// + /// Config number + /// + public int ConfigNumber { get; set; } + + /// + /// Config value + /// + public int ConfigValue { get; set; } + } + + /// + /// Response class for config update + /// + public class ServerConfigUpdateResponseParams + { + /// + /// Config Property + /// + public ServerConfigProperty ConfigProperty { get; set; } + } + + /// + /// Request class for config update + /// + public class ServerConfigUpdateRequest + { + public static readonly + RequestType Type = + RequestType.Create("config/update"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigViewRequest.cs b/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigViewRequest.cs new file mode 100644 index 00000000..1a0574c4 --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/Contracts/ServerConfigViewRequest.cs @@ -0,0 +1,43 @@ +// +// 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.Hosting.Protocol.Contracts; + +namespace Microsoft.SqlTools.ServiceLayer.ServerConfigurations.Contracts +{ + public class ServerConfigViewRequestParams + { + /// + /// Connection uri + /// + public string OwnerUri { get; set; } + + /// + /// Config Number + /// + public int ConfigNumber { get; set; } + } + + /// + /// Response class for config view + /// + public class ServerConfigViewResponseParams + { + /// + /// Config Property + /// + public ServerConfigProperty ConfigProperty { get; set; } + } + + /// + /// Request class for config view + /// + public class ServerConfigViewRequest + { + public static readonly + RequestType Type = + RequestType.Create("config/view"); + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/ServerConfigException.cs b/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/ServerConfigException.cs new file mode 100644 index 00000000..71aff39c --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/ServerConfigException.cs @@ -0,0 +1,27 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; + +namespace Microsoft.SqlTools.ServiceLayer.ServerConfigurations +{ + /// + /// Exception raised from machine learning services operations + /// + public class ServerConfigException : Exception + { + internal ServerConfigException() : base() + { + } + + internal ServerConfigException(string m) : base(m) + { + } + + internal ServerConfigException(string m, Exception innerException) : base(m, innerException) + { + } + } +} diff --git a/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/ServerConfigService.cs b/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/ServerConfigService.cs new file mode 100644 index 00000000..35ed474f --- /dev/null +++ b/src/Microsoft.SqlTools.ServiceLayer/ServerConfigurations/ServerConfigService.cs @@ -0,0 +1,244 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlServer.Management.Common; +using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlTools.Hosting.Protocol; +using Microsoft.SqlTools.ServiceLayer.Connection; +using Microsoft.SqlTools.ServiceLayer.Hosting; +using Microsoft.SqlTools.ServiceLayer.ServerConfigurations.Contracts; +using Microsoft.SqlTools.Utility; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading.Tasks; + +namespace Microsoft.SqlTools.ServiceLayer.ServerConfigurations +{ + public class ServerConfigService + { + private ConnectionService connectionService = null; + private static readonly Lazy instance = new Lazy(() => new ServerConfigService()); + + /// + /// Gets the singleton instance object + /// + public static ServerConfigService Instance + { + get { return instance.Value; } + } + + /// + /// Internal for testing purposes only + /// + internal ConnectionService ConnectionServiceInstance + { + get + { + if (connectionService == null) + { + connectionService = ConnectionService.Instance; + } + return connectionService; + } + + set + { + connectionService = value; + } + } + + public void InitializeService(ServiceHost serviceHost) + { + serviceHost.SetRequestHandler(ServerConfigViewRequest.Type, this.HandleServerConfigViewRequest); + serviceHost.SetRequestHandler(ServerConfigUpdateRequest.Type, this.HandleServerConfigUpdateRequest); + serviceHost.SetRequestHandler(ServerConfigListRequest.Type, this.HandleServerConfigListRequest); + } + + /// + /// Handles config view request + /// + /// Request parameters + /// Request Context + /// + public async Task HandleServerConfigViewRequest(ServerConfigViewRequestParams parameters, RequestContext requestContext) + { + Logger.Write(TraceEventType.Verbose, "HandleServerConfigViewRequest"); + try + { + ConnectionInfo connInfo; + ConnectionServiceInstance.TryFindConnection( + parameters.OwnerUri, + out connInfo); + if (connInfo == null) + { + await requestContext.SendError(new Exception(SR.ProfilerConnectionNotFound)); + } + else + { + var serverConnection = ConnectionService.OpenServerConnection(connInfo); + ServerConfigProperty serverConfig = GetConfig(serverConnection, parameters.ConfigNumber); + await requestContext.SendResult(new ServerConfigViewResponseParams + { + ConfigProperty = serverConfig + }); + } + } + catch (Exception e) + { + // Exception related to run task will be captured here + await requestContext.SendError(e); + } + } + + /// + /// Handles config update request + /// + /// Request parameters + /// Request Context + /// + public async Task HandleServerConfigUpdateRequest(ServerConfigUpdateRequestParams parameters, RequestContext requestContext) + { + Logger.Write(TraceEventType.Verbose, "HandleServerConfigUpdateRequest"); + try + { + ConnectionInfo connInfo; + ConnectionServiceInstance.TryFindConnection( + parameters.OwnerUri, + out connInfo); + ServerConfigUpdateResponseParams response = new ServerConfigUpdateResponseParams + { + }; + + if (connInfo == null) + { + await requestContext.SendError(new Exception(SR.ProfilerConnectionNotFound)); + } + else + { + var serverConnection = ConnectionService.OpenServerConnection(connInfo); + UpdateConfig(serverConnection, parameters.ConfigNumber, parameters.ConfigValue); + response.ConfigProperty = GetConfig(serverConnection, parameters.ConfigNumber); + await requestContext.SendResult(response); + } + } + catch (Exception e) + { + // Exception related to run task will be captured here + await requestContext.SendError(e); + } + } + + /// + /// Handles config list request + /// + /// Request parameters + /// Request Context + public async Task HandleServerConfigListRequest(ServerConfigListRequestParams parameters, RequestContext requestContext) + { + Logger.Write(TraceEventType.Verbose, "HandleServerConfigListRequest"); + try + { + ConnectionInfo connInfo; + ConnectionServiceInstance.TryFindConnection( + parameters.OwnerUri, + out connInfo); + ServerConfigListResponseParams response = new ServerConfigListResponseParams + { + }; + + if (connInfo == null) + { + await requestContext.SendError(new Exception(SR.ProfilerConnectionNotFound)); + } + else + { + var serverConnection = ConnectionService.OpenServerConnection(connInfo); + response.ConfigProperties = GetConfigs(serverConnection); + await requestContext.SendResult(response); + } + } + catch (Exception e) + { + // Exception related to run task will be captured here + await requestContext.SendError(e); + } + } + + + /// + /// Updates external script in a given server. Throws exception if server doesn't support external script + /// + /// + /// + public void UpdateConfig(ServerConnection serverConnection, int configNumber, int configValue) + { + Server server = new Server(serverConnection); + ConfigProperty serverConfig = GetSmoConfig(server, configNumber); + + if (serverConfig != null) + { + try + { + serverConfig.ConfigValue = configValue; + server.Configuration.Alter(true); + } + catch (FailedOperationException ex) + { + throw new ServerConfigException($"Failed to update config. config number: ${configNumber}", ex); + } + } + else + { + throw new ServerConfigException($"Server doesn't have config. config number: ${configNumber}"); + } + } + + /// + /// Returns current value of external script config + /// + /// + /// + private ServerConfigProperty GetConfig(ServerConnection serverConnection, int configNumber) + { + Server server = new Server(serverConnection); + ConfigProperty serverConfig = GetSmoConfig(server, configNumber); + return serverConfig != null ? ServerConfigProperty.ToServerConfigProperty(serverConfig) : null; + } + + private List GetConfigs(ServerConnection serverConnection) + { + Server server = new Server(serverConnection); + List list = new List(); + foreach (ConfigProperty serverConfig in server.Configuration.Properties) + { + list.Add(serverConfig != null ? ServerConfigProperty.ToServerConfigProperty(serverConfig) : null); + } + return list; + } + + private ConfigProperty GetSmoConfig(Server server, int configNumber) + { + try + { + ConfigProperty serverConfig = null; + foreach (ConfigProperty configProperty in server.Configuration.Properties) + { + if (configProperty.Number == configNumber) + { + serverConfig = configProperty; + break; + } + } + + return serverConfig; + } + catch (Exception ex) + { + throw new ServerConfigException($"Failed to get config. config number: ${configNumber}", ex); + } + } + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DisasterRecovery/BackupServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DisasterRecovery/BackupServiceTests.cs index e7abed8c..bc044b62 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DisasterRecovery/BackupServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/DisasterRecovery/BackupServiceTests.cs @@ -78,23 +78,25 @@ CREATE CERTIFICATE {1} WITH SUBJECT = 'Backup Encryption Certificate'; "; DisasterRecoveryService service = new DisasterRecoveryService(); string databaseName = "SqlToolsService_TestBackup_" + new Random().Next(10000000, 99999999); - var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName)) - using (DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true)) - using (SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo)) { - string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); + var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); + using (DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true)) + using (SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo)) + { + string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); - BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, - BackupType.Full, - new List() { backupPath }, - new Dictionary() { { backupPath, (int)DeviceType.File } }); - BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); + BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, + BackupType.Full, + new List() { backupPath }, + new Dictionary() { { backupPath, (int)DeviceType.File } }); + BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); - // Backup the database - service.PerformBackup(backupOperation); + // Backup the database + service.PerformBackup(backupOperation); - VerifyAndCleanBackup(sqlConn, backupPath); + VerifyAndCleanBackup(sqlConn, backupPath); + } } } @@ -104,29 +106,31 @@ CREATE CERTIFICATE {1} WITH SUBJECT = 'Backup Encryption Certificate'; "; DisasterRecoveryService service = new DisasterRecoveryService(); string databaseName = "SqlToolsService_TestBackup_" + new Random().Next(10000000, 99999999); - var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName)) - using (DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true)) - using (SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo)) { - string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); + var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); + using (DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true)) + using (SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo)) + { + string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); - BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, - BackupType.Full, - new List() { backupPath }, - new Dictionary() { { backupPath, (int)DeviceType.File } }); - BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); + BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, + BackupType.Full, + new List() { backupPath }, + new Dictionary() { { backupPath, (int)DeviceType.File } }); + BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); - // Generate script for backup - service.ScriptBackup(backupOperation); - string script = backupOperation.ScriptContent; - Assert.True(!string.IsNullOrEmpty(script)); + // Generate script for backup + service.ScriptBackup(backupOperation); + string script = backupOperation.ScriptContent; + Assert.True(!string.IsNullOrEmpty(script)); - // Execute the script - testDb.RunQuery(script); + // Execute the script + testDb.RunQuery(script); - VerifyAndCleanBackup(sqlConn, backupPath); + VerifyAndCleanBackup(sqlConn, backupPath); + } } } @@ -139,45 +143,47 @@ CREATE CERTIFICATE {1} WITH SUBJECT = 'Backup Encryption Certificate'; "; DisasterRecoveryService service = new DisasterRecoveryService(); string databaseName = "SqlToolsService_TestBackup_" + new Random().Next(10000000, 99999999); - var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName)) - using (DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true)) - using (SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo)) { - string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); + var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); + using (DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true)) + using (SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo)) + { + string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); - string certificateName = CreateCertificate(testDb); - string cleanupCertificateQuery = string.Format(CleanupCertificateQueryFormat, certificateName); + string certificateName = CreateCertificate(testDb); + string cleanupCertificateQuery = string.Format(CleanupCertificateQueryFormat, certificateName); - BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, - BackupType.Full, - new List() { backupPath }, - new Dictionary() { { backupPath, (int)DeviceType.File } }); - backupInfo.ContinueAfterError = true; - backupInfo.FormatMedia = true; - backupInfo.SkipTapeHeader = true; - backupInfo.Initialize = true; - backupInfo.MediaName = "backup test media"; - backupInfo.MediaDescription = "backup test"; - backupInfo.RetainDays = 90; - backupInfo.CompressionOption = (int)BackupCompressionOptions.On; - backupInfo.EncryptionAlgorithm = (int)BackupEncryptionAlgorithm.Aes128; - backupInfo.EncryptorType = (int)BackupEncryptorType.ServerCertificate; - backupInfo.EncryptorName = certificateName; + BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, + BackupType.Full, + new List() { backupPath }, + new Dictionary() { { backupPath, (int)DeviceType.File } }); + backupInfo.ContinueAfterError = true; + backupInfo.FormatMedia = true; + backupInfo.SkipTapeHeader = true; + backupInfo.Initialize = true; + backupInfo.MediaName = "backup test media"; + backupInfo.MediaDescription = "backup test"; + backupInfo.RetainDays = 90; + backupInfo.CompressionOption = (int)BackupCompressionOptions.On; + backupInfo.EncryptionAlgorithm = (int)BackupEncryptionAlgorithm.Aes128; + backupInfo.EncryptorType = (int)BackupEncryptorType.ServerCertificate; + backupInfo.EncryptorName = certificateName; - BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); + BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); - // Backup the database - Console.WriteLine("Perform backup operation.."); - service.PerformBackup(backupOperation); + // Backup the database + Console.WriteLine("Perform backup operation.."); + service.PerformBackup(backupOperation); - // Remove the backup file - Console.WriteLine("Verify the backup file exists and remove.."); - VerifyAndCleanBackup(sqlConn, backupPath); + // Remove the backup file + Console.WriteLine("Verify the backup file exists and remove.."); + VerifyAndCleanBackup(sqlConn, backupPath); - // Delete certificate and master key - Console.WriteLine("Remove certificate and master key.."); - testDb.RunQuery(cleanupCertificateQuery); + // Delete certificate and master key + Console.WriteLine("Remove certificate and master key.."); + testDb.RunQuery(cleanupCertificateQuery); + } } } @@ -190,47 +196,49 @@ CREATE CERTIFICATE {1} WITH SUBJECT = 'Backup Encryption Certificate'; "; DisasterRecoveryService service = new DisasterRecoveryService(); string databaseName = "SqlToolsService_TestBackup_" + new Random().Next(10000000, 99999999); - var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); using (SqlTestDb testDb = SqlTestDb.CreateNew(TestServerType.OnPrem, false, databaseName)) - using (DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true)) - using (SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo)) { - string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); + var liveConnection = LiveConnectionHelper.InitLiveConnectionInfo(databaseName); + using (DatabaseTaskHelper helper = AdminService.CreateDatabaseTaskHelper(liveConnection.ConnectionInfo, databaseExists: true)) + using (SqlConnection sqlConn = ConnectionService.OpenSqlConnection(liveConnection.ConnectionInfo)) + { + string backupPath = GetDefaultBackupFullPath(service, databaseName, helper.DataContainer, sqlConn); - string certificateName = CreateCertificate(testDb); - string cleanupCertificateQuery = string.Format(CleanupCertificateQueryFormat, certificateName); + string certificateName = CreateCertificate(testDb); + string cleanupCertificateQuery = string.Format(CleanupCertificateQueryFormat, certificateName); - BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, - BackupType.Full, - new List() { backupPath }, - new Dictionary() { { backupPath, (int)DeviceType.File } }); - backupInfo.FormatMedia = true; - backupInfo.SkipTapeHeader = true; - backupInfo.Initialize = true; - backupInfo.MediaName = "backup test media"; - backupInfo.MediaDescription = "backup test"; - backupInfo.EncryptionAlgorithm = (int)BackupEncryptionAlgorithm.Aes128; - backupInfo.EncryptorType = (int)BackupEncryptorType.ServerCertificate; - backupInfo.EncryptorName = certificateName; + BackupInfo backupInfo = CreateDefaultBackupInfo(databaseName, + BackupType.Full, + new List() { backupPath }, + new Dictionary() { { backupPath, (int)DeviceType.File } }); + backupInfo.FormatMedia = true; + backupInfo.SkipTapeHeader = true; + backupInfo.Initialize = true; + backupInfo.MediaName = "backup test media"; + backupInfo.MediaDescription = "backup test"; + backupInfo.EncryptionAlgorithm = (int)BackupEncryptionAlgorithm.Aes128; + backupInfo.EncryptorType = (int)BackupEncryptorType.ServerCertificate; + backupInfo.EncryptorName = certificateName; - BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); + BackupOperation backupOperation = CreateBackupOperation(service, liveConnection.ConnectionInfo.OwnerUri, backupInfo, helper.DataContainer, sqlConn); - // Backup the database - Console.WriteLine("Generate script for backup operation.."); - service.ScriptBackup(backupOperation); - string script = backupOperation.ScriptContent; + // Backup the database + Console.WriteLine("Generate script for backup operation.."); + service.ScriptBackup(backupOperation); + string script = backupOperation.ScriptContent; - // Run the script - Console.WriteLine("Execute the script.."); - testDb.RunQuery(script); + // Run the script + Console.WriteLine("Execute the script.."); + testDb.RunQuery(script); - // Remove the backup file - Console.WriteLine("Verify the backup file exists and remove.."); - VerifyAndCleanBackup(sqlConn, backupPath); + // Remove the backup file + Console.WriteLine("Verify the backup file exists and remove.."); + VerifyAndCleanBackup(sqlConn, backupPath); - // Delete certificate and master key - Console.WriteLine("Remove certificate and master key.."); - testDb.RunQuery(cleanupCertificateQuery); + // Delete certificate and master key + Console.WriteLine("Remove certificate and master key.."); + testDb.RunQuery(cleanupCertificateQuery); + } } } diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageExtensions/LanguageExtensionsTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageExtensions/LanguageExtensionsTests.cs new file mode 100644 index 00000000..bb36ec68 --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/LanguageExtensions/LanguageExtensionsTests.cs @@ -0,0 +1,64 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; +using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility; +using Microsoft.SqlTools.ServiceLayer.LanguageExtensions; +using Microsoft.SqlTools.ServiceLayer.LanguageExtensions.Contracts; +using Microsoft.SqlTools.ServiceLayer.Test.Common; +using Microsoft.SqlTools.ServiceLayer.Test.Common.RequestContextMocking; +using Moq; +using System; +using Xunit; + +namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageExtensions +{ + public class LanguageExtensionsTests + { + [Fact] + public async void VerifyExternalLanguageStatusRequest() + { + using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) + { + var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath); + ExternalLanguageStatusResponseParams result = null; + var requestContext = RequestContextMocks.Create(r => result = r).AddErrorHandling(null); + + ExternalLanguageStatusRequestParams requestParams = new ExternalLanguageStatusRequestParams + { + OwnerUri = connectionResult.ConnectionInfo.OwnerUri, + LanguageName = "Python" + }; + + await LanguageExtensionsService.Instance.HandleExternalLanguageStatusRequest(requestParams, requestContext.Object); + Assert.NotNull(result); + + LanguageExtensionsService.Instance.ConnectionServiceInstance.Disconnect(new DisconnectParams + { + OwnerUri = queryTempFile.FilePath, + Type = ServiceLayer.Connection.ConnectionType.Default + }); + } + } + + [Fact] + public async void VerifyExternalLanguageStatusRequestSendErrorGivenInvalidConnection() + { + ExternalLanguageStatusResponseParams result = null; + var requestContext = RequestContextMocks.Create(r => result = r).AddErrorHandling(null); + requestContext.Setup(x => x.SendError(It.IsAny())).Returns(System.Threading.Tasks.Task.FromResult(true)); + + ExternalLanguageStatusRequestParams requestParams = new ExternalLanguageStatusRequestParams + { + OwnerUri = "invalid uri", + LanguageName = "Python" + }; + + await LanguageExtensionsService.Instance.HandleExternalLanguageStatusRequest(requestParams, requestContext.Object); + requestContext.Verify(x => x.SendError(It.IsAny())); + } + + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ServerConfigurations/ServerConfigurationsServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ServerConfigurations/ServerConfigurationsServiceTests.cs new file mode 100644 index 00000000..f532c768 --- /dev/null +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/ServerConfigurations/ServerConfigurationsServiceTests.cs @@ -0,0 +1,150 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using Microsoft.SqlTools.ServiceLayer.Connection.Contracts; +using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility; +using Microsoft.SqlTools.ServiceLayer.ServerConfigurations; +using Microsoft.SqlTools.ServiceLayer.ServerConfigurations.Contracts; +using Microsoft.SqlTools.ServiceLayer.Test.Common; +using Microsoft.SqlTools.ServiceLayer.Test.Common.RequestContextMocking; +using Moq; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.MachineLearningServices +{ + public class ServerConfigurationsServiceTests + { + [Fact] + public async void VerifyListingConfigs() + { + List configs = await GetAllConfigs(); + Assert.NotNull(configs); + Assert.True(configs.Count > 0); + } + + [Fact] + public async void VerifyUpdatingConfigs() + { + using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) + { + var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath); + List configs = await GetAllConfigs(); + Assert.NotNull(configs); + Assert.True(configs.Count > 0); + ServerConfigProperty sampleConfig = configs[0]; + + ServerConfigViewResponseParams result = null; + ServerConfigUpdateResponseParams updateResult = null; + int newValue = sampleConfig.ConfigValue == sampleConfig.Minimum ? sampleConfig.Maximum : sampleConfig.Minimum; + + var requestContext = RequestContextMocks.Create(r => result = r).AddErrorHandling(null); + var updateRequestContext = RequestContextMocks.Create(r => updateResult = r).AddErrorHandling(null); + + ServerConfigViewRequestParams requestParams = new ServerConfigViewRequestParams + { + OwnerUri = connectionResult.ConnectionInfo.OwnerUri, + ConfigNumber = sampleConfig.Number + }; + ServerConfigUpdateRequestParams updateRequestParams = new ServerConfigUpdateRequestParams + { + OwnerUri = connectionResult.ConnectionInfo.OwnerUri, + ConfigNumber = sampleConfig.Number, + ConfigValue = newValue + }; + + await ServerConfigService.Instance.HandleServerConfigViewRequest(requestParams, requestContext.Object); + Assert.NotNull(result); + Assert.Equal(result.ConfigProperty.ConfigValue, sampleConfig.ConfigValue); + await ServerConfigService.Instance.HandleServerConfigUpdateRequest(updateRequestParams, updateRequestContext.Object); + Assert.NotNull(updateResult); + Assert.Equal(updateResult.ConfigProperty.ConfigValue, newValue); + updateRequestParams.ConfigValue = sampleConfig.ConfigValue; + await ServerConfigService.Instance.HandleServerConfigUpdateRequest(updateRequestParams, updateRequestContext.Object); + Assert.NotNull(updateResult); + Assert.Equal(updateResult.ConfigProperty.ConfigValue, sampleConfig.ConfigValue); + ServerConfigService.Instance.ConnectionServiceInstance.Disconnect(new DisconnectParams + { + OwnerUri = queryTempFile.FilePath, + Type = ServiceLayer.Connection.ConnectionType.Default + }); + } + } + + public async Task> GetAllConfigs() + { + using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile()) + { + var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath); + + ServerConfigListResponseParams result = null; + + var requestContext = RequestContextMocks.Create(r => result = r).AddErrorHandling(null); + + ServerConfigListRequestParams requestParams = new ServerConfigListRequestParams + { + OwnerUri = connectionResult.ConnectionInfo.OwnerUri + }; + + await ServerConfigService.Instance.HandleServerConfigListRequest(requestParams, requestContext.Object); + Assert.NotNull(result); + return result.ConfigProperties; + } + } + + + [Fact] + public async void VerifyConfigViewRequestSendErrorGivenInvalidConnection() + { + ServerConfigViewResponseParams result = null; + var requestContext = RequestContextMocks.Create(r => result = r).AddErrorHandling(null); + requestContext.Setup(x => x.SendError(It.IsAny())).Returns(System.Threading.Tasks.Task.FromResult(true)); + + ServerConfigViewRequestParams requestParams = new ServerConfigViewRequestParams + { + OwnerUri = "invalid uri" + }; + + await ServerConfigService.Instance.HandleServerConfigViewRequest(requestParams, requestContext.Object); + requestContext.Verify(x => x.SendError(It.IsAny())); + } + + [Fact] + public async void VerifyConfigUpdateRequestSendErrorGivenInvalidConnection() + { + ServerConfigUpdateResponseParams result = null; + var requestContext = RequestContextMocks.Create(r => result = r).AddErrorHandling(null); + requestContext.Setup(x => x.SendError(It.IsAny())).Returns(System.Threading.Tasks.Task.FromResult(true)); + + ServerConfigUpdateRequestParams requestParams = new ServerConfigUpdateRequestParams + { + OwnerUri = "invalid uri", + ConfigValue = 1 + }; + + await ServerConfigService.Instance.HandleServerConfigUpdateRequest(requestParams, requestContext.Object); + requestContext.Verify(x => x.SendError(It.IsAny())); + } + + [Fact] + public async void VerifyConfigListRequestSendErrorGivenInvalidConnection() + { + ServerConfigListResponseParams result = null; + var requestContext = RequestContextMocks.Create(r => result = r).AddErrorHandling(null); + requestContext.Setup(x => x.SendError(It.IsAny())).Returns(System.Threading.Tasks.Task.FromResult(true)); + + ServerConfigListRequestParams requestParams = new ServerConfigListRequestParams + { + OwnerUri = "invalid uri", + }; + + await ServerConfigService.Instance.HandleServerConfigListRequest(requestParams, requestContext.Object); + requestContext.Verify(x => x.SendError(It.IsAny())); + } + + } +} diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Utility/LiveConnectionHelper.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Utility/LiveConnectionHelper.cs index d5764e85..06b0ec18 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Utility/LiveConnectionHelper.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Utility/LiveConnectionHelper.cs @@ -63,7 +63,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility } public static async Task InitLiveConnectionInfoAsync(string databaseName = null, string ownerUri = null, - string connectionType = ServiceLayer.Connection.ConnectionType.Default) + string connectionType = ServiceLayer.Connection.ConnectionType.Default, TestServerType serverType = TestServerType.OnPrem) { ScriptFile scriptFile = null; if (string.IsNullOrEmpty(ownerUri)) @@ -72,7 +72,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(ownerUri); ownerUri = scriptFile.ClientUri; } - ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName); + ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(serverType, databaseName); var connectionService = GetLiveTestConnectionService(); var connectionResult =