mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
Initial check-in of SqlProjects service addition to SqlToolsService (#1805)
* initial commit * Initial SqlProjects service + tests * Added SqlObject script tests; PR feedback * Added comments for contracts * Swapping SqlProjectResult for ResultStatus * Updating tests * Added automatic test base that provides a working directory and automatic cleanup.
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
<PackageReference Update="Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider" Version="1.1.1" />
|
||||
<PackageReference Update="Microsoft.SqlServer.Management.SmoMetadataProvider" Version="170.11.0" />
|
||||
<PackageReference Update="Microsoft.SqlServer.DacFx" Version="161.8055.0-preview" />
|
||||
<PackageReference Update="Microsoft.SqlServer.DacFx.Projects" Version="161.8056.0-alpha" />
|
||||
<PackageReference Update="Microsoft.Azure.Kusto.Data" Version="9.0.4" />
|
||||
<PackageReference Update="Microsoft.Azure.Kusto.Language" Version="9.0.4" />
|
||||
<PackageReference Update="Microsoft.SqlServer.Assessment" Version="[1.1.17]" />
|
||||
|
||||
Binary file not shown.
@@ -41,6 +41,7 @@ using Microsoft.SqlTools.ServiceLayer.AzureBlob;
|
||||
using Microsoft.SqlTools.ServiceLayer.ExecutionPlan;
|
||||
using Microsoft.SqlTools.ServiceLayer.ObjectManagement;
|
||||
using System.IO;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlProjects;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer
|
||||
{
|
||||
@@ -179,6 +180,9 @@ namespace Microsoft.SqlTools.ServiceLayer
|
||||
ObjectManagementService.Instance.InitializeService(serviceHost);
|
||||
serviceProvider.RegisterSingleService(ObjectManagementService.Instance);
|
||||
|
||||
SqlProjectsService.Instance.InitializeService(serviceHost);
|
||||
serviceProvider.RegisterSingleService(SqlProjectsService.Instance);
|
||||
|
||||
serviceHost.InitializeRequestHandlers();
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" />
|
||||
<PackageReference Include="Microsoft.SqlServer.DacFx" />
|
||||
<PackageReference Include="Microsoft.SqlServer.DacFx.Projects" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider" />
|
||||
<PackageReference Include="Microsoft.SqlServer.Assessment" />
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// 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 Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts
|
||||
{
|
||||
public class CloseSqlProjectRequest
|
||||
{
|
||||
public static readonly RequestType<SqlProjectParams, ResultStatus> Type = RequestType<SqlProjectParams, ResultStatus>.Create("sqlprojects/closeProject");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// 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.Dac.Projects;
|
||||
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters for creating a new SQL Project
|
||||
/// </summary>
|
||||
public class NewSqlProjectParams : SqlProjectParams
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of SQL Project: SDK-style or Legacy
|
||||
/// </summary>
|
||||
public ProjectType SqlProjectType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Database schema provider for the project, in the format
|
||||
/// "Microsoft.Data.Tools.Schema.Sql.SqlXYZDatabaseSchemaProvider".
|
||||
/// Case sensitive.
|
||||
/// </summary>
|
||||
public string? DatabaseSchemaProvider { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Version of the Microsoft.Build.Sql SDK for the project, if overriding the default
|
||||
/// </summary>
|
||||
public string? BuildSdkVersion { get; set; }
|
||||
}
|
||||
|
||||
public class NewSqlProjectRequest
|
||||
{
|
||||
public static readonly RequestType<NewSqlProjectParams, ResultStatus> Type = RequestType<NewSqlProjectParams, ResultStatus>.Create("sqlprojects/newProject");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// 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 Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts
|
||||
{
|
||||
public class OpenSqlProjectRequest
|
||||
{
|
||||
public static readonly RequestType<SqlProjectParams, ResultStatus> Type = RequestType<SqlProjectParams, ResultStatus>.Create("sqlprojects/openProject");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// 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 Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts
|
||||
{
|
||||
public class AddSqlObjectScriptRequest
|
||||
{
|
||||
public static readonly RequestType<SqlProjectScriptParams, ResultStatus> Type = RequestType<SqlProjectScriptParams, ResultStatus>.Create("sqlprojects/addSqlObjectScript");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// 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 Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts
|
||||
{
|
||||
public class DeleteSqlObjectScriptRequest
|
||||
{
|
||||
public static readonly RequestType<SqlProjectScriptParams, ResultStatus> Type = RequestType<SqlProjectScriptParams, ResultStatus>.Create("sqlprojects/deleteSqlObjectScript");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// 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 Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts
|
||||
{
|
||||
public class ExcludeSqlObjectScriptRequest
|
||||
{
|
||||
public static readonly RequestType<SqlProjectScriptParams, ResultStatus> Type = RequestType<SqlProjectScriptParams, ResultStatus>.Create("sqlprojects/excludeSqlObjectScript");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// 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.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts
|
||||
{
|
||||
/// <summary>
|
||||
/// Parameters for a generic SQL Project operation
|
||||
/// </summary>
|
||||
public class SqlProjectParams : GeneralRequestDetails
|
||||
{
|
||||
/// <summary>
|
||||
/// Absolute path of the project, including .sqlproj
|
||||
/// </summary>
|
||||
public string ProjectUri { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parameters for a SQL Project operation that targets a script
|
||||
/// </summary>
|
||||
public class SqlProjectScriptParams : SqlProjectParams
|
||||
{
|
||||
/// <summary>
|
||||
/// Path of the script, including .sql, relative to the .sqlproj
|
||||
/// </summary>
|
||||
public string Path { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlServer.Dac.Projects;
|
||||
using Microsoft.SqlTools.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.ServiceLayer.Hosting;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.SqlProjects
|
||||
{
|
||||
/// <summary>
|
||||
/// Main class for SqlProjects service
|
||||
/// </summary>
|
||||
class SqlProjectsService
|
||||
{
|
||||
private static readonly Lazy<SqlProjectsService> instance = new Lazy<SqlProjectsService>(() => new SqlProjectsService());
|
||||
|
||||
/// <summary>
|
||||
/// Gets the singleton instance object
|
||||
/// </summary>
|
||||
public static SqlProjectsService Instance => instance.Value;
|
||||
|
||||
private Lazy<ConcurrentDictionary<string, SqlProject>> projects = new Lazy<ConcurrentDictionary<string, SqlProject>>(() => new ConcurrentDictionary<string, SqlProject>(StringComparer.OrdinalIgnoreCase));
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="ConcurrentDictionary{String, TSqlModel}"/> that maps Project URI to Project
|
||||
/// </summary>
|
||||
public ConcurrentDictionary<string, SqlProject> Projects => projects.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the service instance
|
||||
/// </summary>
|
||||
/// <param name="serviceHost"></param>
|
||||
public void InitializeService(ServiceHost serviceHost)
|
||||
{
|
||||
// Project-level functions
|
||||
serviceHost.SetRequestHandler(OpenSqlProjectRequest.Type, HandleOpenSqlProjectRequest, isParallelProcessingSupported: true);
|
||||
serviceHost.SetRequestHandler(CloseSqlProjectRequest.Type, HandleCloseSqlProjectRequest, isParallelProcessingSupported: true);
|
||||
serviceHost.SetRequestHandler(NewSqlProjectRequest.Type, HandleNewSqlProjectRequest, isParallelProcessingSupported: true);
|
||||
|
||||
// SQL object script calls
|
||||
serviceHost.SetRequestHandler(AddSqlObjectScriptRequest.Type, HandleAddSqlObjectScriptRequest, isParallelProcessingSupported: false);
|
||||
serviceHost.SetRequestHandler(DeleteSqlObjectScriptRequest.Type, HandleDeleteSqlObjectScriptRequest, isParallelProcessingSupported: false);
|
||||
serviceHost.SetRequestHandler(ExcludeSqlObjectScriptRequest.Type, HandleExcludeSqlObjectScriptRequest, isParallelProcessingSupported: false);
|
||||
}
|
||||
|
||||
#region Handlers
|
||||
|
||||
#region Project-level functions
|
||||
|
||||
internal async Task HandleOpenSqlProjectRequest(SqlProjectParams requestParams, RequestContext<ResultStatus> requestContext)
|
||||
{
|
||||
await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri), requestContext);
|
||||
}
|
||||
|
||||
internal async Task HandleCloseSqlProjectRequest(SqlProjectParams requestParams, RequestContext<ResultStatus> requestContext)
|
||||
{
|
||||
await RunWithErrorHandling(() => Projects.TryRemove(requestParams.ProjectUri, out _), requestContext);
|
||||
}
|
||||
|
||||
internal async Task HandleNewSqlProjectRequest(NewSqlProjectParams requestParams, RequestContext<ResultStatus> requestContext)
|
||||
{
|
||||
await RunWithErrorHandling(async () =>
|
||||
{
|
||||
await SqlProject.CreateProjectAsync(requestParams.ProjectUri, requestParams.SqlProjectType, requestParams.DatabaseSchemaProvider);
|
||||
GetProject(requestParams.ProjectUri); // load into the cache
|
||||
|
||||
}, requestContext);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sql object script calls
|
||||
|
||||
internal async Task HandleAddSqlObjectScriptRequest(SqlProjectScriptParams requestParams, RequestContext<ResultStatus> requestContext)
|
||||
{
|
||||
await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri).SqlObjectScripts.Add(new SqlObjectScript(requestParams.Path)), requestContext);
|
||||
}
|
||||
|
||||
internal async Task HandleDeleteSqlObjectScriptRequest(SqlProjectScriptParams requestParams, RequestContext<ResultStatus> requestContext)
|
||||
{
|
||||
await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri).SqlObjectScripts.Delete(requestParams.Path), requestContext);
|
||||
}
|
||||
|
||||
internal async Task HandleExcludeSqlObjectScriptRequest(SqlProjectScriptParams requestParams, RequestContext<ResultStatus> requestContext)
|
||||
{
|
||||
await RunWithErrorHandling(() => GetProject(requestParams.ProjectUri).SqlObjectScripts.Exclude(requestParams.Path), requestContext);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helper methods
|
||||
|
||||
private async Task RunWithErrorHandling(Action action, RequestContext<ResultStatus> requestContext)
|
||||
{
|
||||
await RunWithErrorHandling(async () => await Task.Run(action), requestContext);
|
||||
}
|
||||
|
||||
private async Task RunWithErrorHandling(Func<Task> action, RequestContext<ResultStatus> requestContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
await action();
|
||||
|
||||
await requestContext.SendResult(new ResultStatus()
|
||||
{
|
||||
Success = true,
|
||||
ErrorMessage = null
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await requestContext.SendResult(new ResultStatus()
|
||||
{
|
||||
Success = false,
|
||||
ErrorMessage = ex.Message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private SqlProject GetProject(string projectUri)
|
||||
{
|
||||
if (!Projects.ContainsKey(projectUri))
|
||||
{
|
||||
Projects[projectUri] = new SqlProject(projectUri);
|
||||
}
|
||||
|
||||
return Projects[projectUri];
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
//
|
||||
// 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.Threading.Tasks;
|
||||
using Microsoft.SqlServer.Dac.Projects;
|
||||
using Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlProjects;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlProjects.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Test.Common.RequestContextMocking;
|
||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.SqlProjects
|
||||
{
|
||||
public class SqlProjectsServiceTests : TestBase
|
||||
{
|
||||
[Test]
|
||||
public async Task TestErrorDuringExecution()
|
||||
{
|
||||
SqlProjectsService service = new();
|
||||
string projectUri = await service.CreateSqlProject(); // validates result.Success == true
|
||||
|
||||
// Validate that result indicates failure when there's an exception
|
||||
MockRequest<ResultStatus> requestMock = new();
|
||||
await service.HandleNewSqlProjectRequest(new NewSqlProjectParams()
|
||||
{
|
||||
ProjectUri = projectUri,
|
||||
SqlProjectType = ProjectType.SdkStyle
|
||||
|
||||
}, requestMock.Object);
|
||||
|
||||
Assert.IsFalse(requestMock.Result.Success);
|
||||
Assert.IsTrue(requestMock.Result.ErrorMessage!.Contains("Cannot create a new SQL project"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestOpenCloseProject()
|
||||
{
|
||||
// Setup
|
||||
string sdkProjectUri = TestContext.CurrentContext.GetTestProjectPath(nameof(TestOpenCloseProject) + "Sdk");
|
||||
string legacyProjectUri = TestContext.CurrentContext.GetTestProjectPath(nameof(TestOpenCloseProject) + "Legacy");
|
||||
|
||||
if (File.Exists(sdkProjectUri)) File.Delete(sdkProjectUri);
|
||||
if (File.Exists(legacyProjectUri)) File.Delete(legacyProjectUri);
|
||||
|
||||
SqlProjectsService service = new();
|
||||
|
||||
Assert.AreEqual(0, service.Projects.Count);
|
||||
|
||||
// Validate creating SDK-style project
|
||||
MockRequest<ResultStatus> requestMock = new();
|
||||
await service.HandleNewSqlProjectRequest(new NewSqlProjectParams()
|
||||
{
|
||||
ProjectUri = sdkProjectUri,
|
||||
SqlProjectType = ProjectType.SdkStyle
|
||||
|
||||
}, requestMock.Object);
|
||||
|
||||
Assert.IsTrue(requestMock.Result.Success);
|
||||
Assert.AreEqual(1, service.Projects.Count);
|
||||
Assert.IsTrue(service.Projects.ContainsKey(sdkProjectUri));
|
||||
Assert.AreEqual(service.Projects[sdkProjectUri].SqlProjStyle, ProjectType.SdkStyle);
|
||||
|
||||
// Validate creating Legacy-style project
|
||||
requestMock = new();
|
||||
await service.HandleNewSqlProjectRequest(new NewSqlProjectParams()
|
||||
{
|
||||
ProjectUri = legacyProjectUri,
|
||||
SqlProjectType = ProjectType.LegacyStyle
|
||||
}, requestMock.Object);
|
||||
|
||||
Assert.IsTrue(requestMock.Result.Success);
|
||||
Assert.AreEqual(2, service.Projects.Count);
|
||||
Assert.IsTrue(service.Projects.ContainsKey(legacyProjectUri));
|
||||
Assert.AreEqual(service.Projects[legacyProjectUri].SqlProjStyle, ProjectType.LegacyStyle);
|
||||
|
||||
// Validate closing a project
|
||||
requestMock = new();
|
||||
await service.HandleCloseSqlProjectRequest(new SqlProjectParams() { ProjectUri = sdkProjectUri }, requestMock.Object);
|
||||
|
||||
Assert.IsTrue(requestMock.Result.Success);
|
||||
Assert.AreEqual(1, service.Projects.Count);
|
||||
Assert.IsTrue(!service.Projects.ContainsKey(sdkProjectUri));
|
||||
|
||||
// Validate opening a project
|
||||
requestMock = new();
|
||||
await service.HandleOpenSqlProjectRequest(new SqlProjectParams() { ProjectUri = sdkProjectUri }, requestMock.Object);
|
||||
|
||||
Assert.IsTrue(requestMock.Result.Success);
|
||||
Assert.AreEqual(2, service.Projects.Count);
|
||||
Assert.IsTrue(service.Projects.ContainsKey(sdkProjectUri));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestSqlObjectScriptAddDeleteExclude()
|
||||
{
|
||||
// Setup
|
||||
SqlProjectsService service = new();
|
||||
string projectUri = await service.CreateSqlProject();
|
||||
Assert.AreEqual(0, service.Projects[projectUri].SqlObjectScripts.Count);
|
||||
|
||||
// Validate adding a SQL object script
|
||||
MockRequest<ResultStatus> requestMock = new();
|
||||
string scriptRelativePath = "MyTable.sql";
|
||||
string scriptFullPath = Path.Join(Path.GetDirectoryName(projectUri), scriptRelativePath);
|
||||
await File.WriteAllTextAsync(scriptFullPath, "CREATE TABLE [MyTable] ([Id] INT)");
|
||||
|
||||
await service.HandleAddSqlObjectScriptRequest(new SqlProjectScriptParams()
|
||||
{
|
||||
ProjectUri = projectUri,
|
||||
Path = scriptRelativePath
|
||||
}, requestMock.Object);
|
||||
|
||||
Assert.IsTrue(requestMock.Result.Success);
|
||||
Assert.AreEqual(1, service.Projects[projectUri].SqlObjectScripts.Count);
|
||||
Assert.IsTrue(service.Projects[projectUri].SqlObjectScripts.Contains(scriptRelativePath));
|
||||
|
||||
// Validate excluding a SQL object script
|
||||
requestMock = new();
|
||||
await service.HandleExcludeSqlObjectScriptRequest(new SqlProjectScriptParams()
|
||||
{
|
||||
ProjectUri = projectUri,
|
||||
Path = scriptRelativePath
|
||||
}, requestMock.Object);
|
||||
|
||||
Assert.IsTrue(requestMock.Result.Success);
|
||||
Assert.AreEqual(0, service.Projects[projectUri].SqlObjectScripts.Count);
|
||||
Assert.IsTrue(File.Exists(scriptFullPath));
|
||||
|
||||
// Re-add to set up for Delete
|
||||
requestMock = new();
|
||||
await service.HandleAddSqlObjectScriptRequest(new SqlProjectScriptParams()
|
||||
{
|
||||
ProjectUri = projectUri,
|
||||
Path = scriptRelativePath
|
||||
}, requestMock.Object);
|
||||
|
||||
Assert.IsTrue(requestMock.Result.Success);
|
||||
Assert.AreEqual(1, service.Projects[projectUri].SqlObjectScripts.Count);
|
||||
|
||||
// Validate deleting a SQL object script
|
||||
requestMock = new();
|
||||
await service.HandleDeleteSqlObjectScriptRequest(new SqlProjectScriptParams()
|
||||
{
|
||||
ProjectUri = projectUri,
|
||||
Path = scriptRelativePath
|
||||
}, requestMock.Object);
|
||||
|
||||
Assert.IsTrue(requestMock.Result.Success);
|
||||
Assert.AreEqual(0, service.Projects[projectUri].SqlObjectScripts.Count);
|
||||
Assert.IsFalse(File.Exists(scriptFullPath));
|
||||
}
|
||||
}
|
||||
|
||||
internal static class SqlProjectsExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Uses the service to create a new SQL project
|
||||
/// </summary>
|
||||
/// <param name="service"></param>
|
||||
/// <returns></returns>
|
||||
public async static Task<string> CreateSqlProject(this SqlProjectsService service)
|
||||
{
|
||||
string projectUri = TestContext.CurrentContext.GetTestProjectPath();
|
||||
|
||||
MockRequest<ResultStatus> requestMock = new();
|
||||
await service.HandleNewSqlProjectRequest(new NewSqlProjectParams()
|
||||
{
|
||||
ProjectUri = projectUri,
|
||||
SqlProjectType = ProjectType.SdkStyle
|
||||
|
||||
}, requestMock.Object);
|
||||
|
||||
Assert.IsTrue(requestMock.Result.Success);
|
||||
|
||||
return projectUri;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility
|
||||
{
|
||||
[TestFixture]
|
||||
public abstract class TestBase
|
||||
{
|
||||
static TestBase()
|
||||
{
|
||||
RunTimestamp = DateTime.Now.ToString("yyyyMMdd-HHmmssffff");
|
||||
}
|
||||
|
||||
public static string RunTimestamp
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public static string TestRunFolder => Path.Join(TestContext.CurrentContext.WorkDirectory, "SqlToolsServiceTestRuns", $"Run{RunTimestamp}");
|
||||
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
if (!Directory.Exists(TestRunFolder))
|
||||
{
|
||||
Directory.CreateDirectory(TestRunFolder);
|
||||
}
|
||||
}
|
||||
|
||||
[OneTimeTearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
if (Directory.Exists(TestRunFolder))
|
||||
{
|
||||
Directory.Delete(TestRunFolder, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
//
|
||||
// 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 NUnit.Framework;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility
|
||||
{
|
||||
public static class TestContextHelpers
|
||||
{
|
||||
private static string TestName => TestContext.CurrentContext.Test.Name;
|
||||
|
||||
public static string GetTestWorkingFolder(this TestContext context) => Path.Join(TestBase.TestRunFolder, TestName);
|
||||
|
||||
public static string GetTestProjectPath(this TestContext context, string? projectName = null) => Path.Join(context.GetTestWorkingFolder(), $"{projectName ?? TestName}.sqlproj");
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common.RequestContextMocking
|
||||
{
|
||||
public static class RequestContextMocks
|
||||
{
|
||||
|
||||
public static Mock<RequestContext<TResponse>> Create<TResponse>(Action<TResponse> resultCallback)
|
||||
{
|
||||
var requestContext = new Mock<RequestContext<TResponse>>();
|
||||
@@ -61,4 +60,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Test.Common.RequestContextMocking
|
||||
return mock;
|
||||
}
|
||||
}
|
||||
|
||||
public class MockRequest<T>
|
||||
{
|
||||
private T? result;
|
||||
public T Result => result ?? throw new InvalidOperationException("No result has been sent for the request");
|
||||
|
||||
public Mock<RequestContext<T>> Mock;
|
||||
public RequestContext<T> Object => Mock.Object;
|
||||
|
||||
public MockRequest()
|
||||
{
|
||||
Mock = RequestContextMocks.Create<T>(actual => result = actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user