mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-13 17:23:02 -05:00
Separating Migration into its own project (#1828)
* Moving Migration service to its own project * Adding loc files to the project * Adding Migration to build * Adding Migration Integration Tests * Trying loops * Fixing params * Fixing indent * Cleaning up yaml * Getting command line arg for auto flush log * Adding tde service
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using NUnit.Framework;
|
||||
|
||||
[assembly: NonParallelizable]
|
||||
@@ -0,0 +1,43 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<DebugType>portable</DebugType>
|
||||
<AssemblyName>Microsoft.SqlTools.Migration.IntegrationTests</AssemblyName>
|
||||
<PackageId>Microsoft.SqlTools.Migration.IntegrationTests</PackageId>
|
||||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||
<DefineConstants>$(DefineConstants);TRACE</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../src/Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj" />
|
||||
<ProjectReference Include="../../src/Microsoft.SqlTools.Migration/Microsoft.SqlTools.Migration.csproj" />
|
||||
<ProjectReference Include="../Microsoft.SqlTools.ServiceLayer.Test.Common/Microsoft.SqlTools.ServiceLayer.Test.Common.csproj" />
|
||||
<ProjectReference Include="../Microsoft.SqlTools.Test.CompletionExtension/Microsoft.SqlTools.Test.CompletionExtension.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Choose>
|
||||
<When Condition="'$(BUILD_DOTNET_TOOL)' == 'true'">
|
||||
<ItemGroup>
|
||||
<Compile Remove="Migration\*" />
|
||||
</ItemGroup>
|
||||
</When>
|
||||
</Choose>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Moq" />
|
||||
<PackageReference Include="System.Net.Http" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="nunit" />
|
||||
<PackageReference Include="nunit3testadapter" />
|
||||
<PackageReference Include="nunit.console" />
|
||||
<PackageReference Include="coverlet.collector">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Integration' ">
|
||||
<DefineConstants>$(DefineConstants);WINDOWS_ONLY_BUILD</DefineConstants>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,5 @@
|
||||
ServerName,DatabaseName,LogicalName,PhysicalFullName,FileType,SizeMB,IsMemoryOptimizedDataOptionEnabled,TimeDataCollected
|
||||
TEST,test,test,C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\test.mdf,Rows,3,False,2021-10-28 19:08:03
|
||||
TEST,test,test_log,C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\test_log.ldf,Log,1,False,2021-10-28 19:08:03
|
||||
TEST,test1,AdventureWorks2008R2_Data,C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\test1.mdf,Rows,195.9375,False,2021-10-28 19:08:03
|
||||
TEST,test1,AdventureWorks2008R2_Log,C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\test1_1.LDF,Log,3.75,False,2021-10-28 19:08:03
|
||||
|
@@ -0,0 +1,2 @@
|
||||
ServerName,Edition,HyperthreadRatio,IsClustered,IsHadrEnabled,LogicalCpuCount,MaxServerMemoryInUse,NumberCoresUsed,NumberOfUserDatabases,PhysicalCpuCount,ProductVersion,SqlStartTime,SumOfUserDatabasesSize,TempDbSize,NumOfLogins,TimeDataCollected
|
||||
TEST,Enterprise Edition (64-bit),2,False,False,2,2147483647,2,2,1,10.50.6592.0,2021-10-26 19:26:06,203,8,13,2021-10-28 19:08:03
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,121 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlTools.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.Migration.IntegrationTests.Utility;
|
||||
using Microsoft.SqlTools.Migration.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
||||
using Microsoft.SqlTools.ServiceLayer.Test.Common.RequestContextMocking;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Microsoft.SqlTools.Migration.IntegrationTests.Migration
|
||||
{
|
||||
public class MigrationServiceTests
|
||||
{
|
||||
[Test]
|
||||
public async Task TestHandleMigrationAssessmentRequest()
|
||||
{
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
{
|
||||
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath);
|
||||
|
||||
var requestParams = new MigrationAssessmentsParams()
|
||||
{
|
||||
ConnectionString = connectionResult.ConnectionInfo.ConnectionDetails.ConnectionString
|
||||
};
|
||||
|
||||
var requestContext = new Mock<RequestContext<MigrationAssessmentResult>>();
|
||||
|
||||
MigrationService service = new MigrationService();
|
||||
await service.HandleMigrationAssessmentsRequest(requestParams, requestContext.Object);
|
||||
requestContext.VerifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore("Disable failing test")]
|
||||
public async Task TestHandleMigrationGetSkuRecommendationsRequest()
|
||||
{
|
||||
GetSkuRecommendationsResult result = null;
|
||||
|
||||
var requestParams = new GetSkuRecommendationsParams()
|
||||
{
|
||||
DataFolder = Path.Combine("..", "..", "..", "Migration", "Data"),
|
||||
TargetPlatforms = new List<string> { "AzureSqlManagedInstance" },
|
||||
TargetSqlInstance = "Test",
|
||||
TargetPercentile = 95,
|
||||
StartTime = new DateTime(2020, 01, 01).ToString("yyyy-MM-dd HH:mm:ss"),
|
||||
EndTime = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||
PerfQueryIntervalInSec = 30,
|
||||
ScalingFactor = 1,
|
||||
DatabaseAllowList = new List<string> { "test", "test1" }
|
||||
};
|
||||
|
||||
var requestContext = RequestContextMocks.Create<GetSkuRecommendationsResult>(r => result = r).AddErrorHandling(null);
|
||||
|
||||
MigrationService service = new MigrationService();
|
||||
await service.HandleGetSkuRecommendationsRequest(requestParams, requestContext.Object);
|
||||
Assert.IsNotNull(result, "Get SKU Recommendation result is null");
|
||||
Assert.IsNotNull(result.SqlMiRecommendationResults, "Get MI SKU Recommendation baseline result is null");
|
||||
Assert.IsNotNull(result.ElasticSqlMiRecommendationResults, "Get MI SKU Recommendation elastic result is null");
|
||||
|
||||
// TODO: Include Negative Justification in future when we start recommending more than one SKU.
|
||||
Assert.Greater(result.SqlMiRecommendationResults.First().PositiveJustifications.Count, 0, "No positive justification for MI SKU Recommendation result");
|
||||
Assert.Greater(result.ElasticSqlMiRecommendationResults.First().PositiveJustifications.Count, 0, "No positive justification for MI SKU elastic Recommendation result");
|
||||
|
||||
Assert.IsNotNull(result.InstanceRequirements);
|
||||
Assert.AreEqual(result.InstanceRequirements.InstanceId, "TEST");
|
||||
Assert.AreEqual(result.InstanceRequirements.DatabaseLevelRequirements.Count, 2);
|
||||
Assert.AreEqual(result.InstanceRequirements.DatabaseLevelRequirements.Sum(db => db.FileLevelRequirements.Count), 4);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestHandleStartStopPerfDataCollectionRequest()
|
||||
{
|
||||
StartPerfDataCollectionResult result = null;
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
{
|
||||
var connectionResult = await LiveConnectionHelper.InitLiveConnectionInfoAsync("master", queryTempFile.FilePath);
|
||||
string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "SkuRecommendationTest");
|
||||
Directory.CreateDirectory(folderPath);
|
||||
|
||||
var requestParams = new StartPerfDataCollectionParams()
|
||||
{
|
||||
ConnectionString = connectionResult.ConnectionInfo.ConnectionDetails.ConnectionString,
|
||||
DataFolder = folderPath,
|
||||
PerfQueryIntervalInSec = 30,
|
||||
NumberOfIterations = 20,
|
||||
StaticQueryIntervalInSec = 3600,
|
||||
};
|
||||
|
||||
var requestContext = RequestContextMocks.Create<StartPerfDataCollectionResult>(r => result = r).AddErrorHandling(null);
|
||||
|
||||
MigrationService service = new MigrationService();
|
||||
await service.HandleStartPerfDataCollectionRequest(requestParams, requestContext.Object);
|
||||
Assert.IsNotNull(result, "Start Perf Data Collection result is null");
|
||||
Assert.IsNotNull(result.DateTimeStarted, "Time perf data collection started is null");
|
||||
|
||||
// Stop data collection
|
||||
StopPerfDataCollectionResult stopResult = null;
|
||||
var stopRequestParams = new StopPerfDataCollectionParams()
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
var stopRequestContext = RequestContextMocks.Create<StopPerfDataCollectionResult>(r => stopResult = r).AddErrorHandling(null);
|
||||
|
||||
await service.HandleStopPerfDataCollectionRequest(stopRequestParams, stopRequestContext.Object);
|
||||
Assert.IsNotNull(stopResult, "Stop Perf Data Collection result is null");
|
||||
Assert.IsNotNull(stopResult.DateTimeStopped, "Time perf data collection stoped is null");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Test.Common;
|
||||
using Microsoft.SqlTools.ServiceLayer.Workspace.Contracts;
|
||||
using NUnit.Framework;
|
||||
using System.Threading;
|
||||
|
||||
namespace Microsoft.SqlTools.Migration.IntegrationTests.Utility
|
||||
{
|
||||
public class LiveConnectionException : Exception
|
||||
{
|
||||
public LiveConnectionException(string message)
|
||||
: base(message) { }
|
||||
}
|
||||
|
||||
public class LiveConnectionHelper
|
||||
{
|
||||
public static string GetTestSqlFile(string fileName = null)
|
||||
{
|
||||
string filePath = null;
|
||||
if (string.IsNullOrEmpty(fileName))
|
||||
{
|
||||
filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "sqltest.sql");
|
||||
}
|
||||
else
|
||||
{
|
||||
filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), fileName + ".sql");
|
||||
}
|
||||
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
File.Delete(filePath);
|
||||
}
|
||||
File.WriteAllText(filePath, "SELECT * FROM sys.objects\n");
|
||||
return filePath;
|
||||
}
|
||||
|
||||
public static TestConnectionResult InitLiveConnectionInfo(string databaseName = null, string ownerUri = null)
|
||||
=> InitLiveConnectionInfoAsync(databaseName, ownerUri, ServiceLayer.Connection.ConnectionType.Default).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
|
||||
public static async Task<TestConnectionResult> InitLiveConnectionInfoAsync(string databaseName = "master", string ownerUri = null,
|
||||
string connectionType = ServiceLayer.Connection.ConnectionType.Default, TestServerType serverType = TestServerType.OnPrem)
|
||||
{
|
||||
ScriptFile scriptFile = null;
|
||||
if (string.IsNullOrEmpty(ownerUri))
|
||||
{
|
||||
ownerUri = GetTestSqlFile();
|
||||
scriptFile = TestServiceProvider.Instance.WorkspaceService.Workspace.GetFile(ownerUri);
|
||||
ownerUri = scriptFile.ClientUri;
|
||||
}
|
||||
if (string.IsNullOrEmpty(databaseName))
|
||||
{
|
||||
databaseName = "master";
|
||||
}
|
||||
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(serverType, databaseName);
|
||||
|
||||
// try to connect up to 3 times, sleeping in between retries
|
||||
const int RetryCount = 3;
|
||||
const int RetryDelayMs = 15000;
|
||||
for (int attempt = 0; attempt < RetryCount; ++attempt)
|
||||
{
|
||||
var connectionService = GetLiveTestConnectionService();
|
||||
var connectionResult =
|
||||
await connectionService.Connect(new ConnectParams
|
||||
{
|
||||
OwnerUri = ownerUri,
|
||||
Connection = connectParams.Connection,
|
||||
Type = connectionType
|
||||
});
|
||||
if (!string.IsNullOrEmpty(connectionResult.ErrorMessage))
|
||||
{
|
||||
Console.WriteLine(connectionResult.ErrorMessage);
|
||||
}
|
||||
|
||||
ConnectionInfo connInfo;
|
||||
connectionService.TryFindConnection(ownerUri, out connInfo);
|
||||
|
||||
// if the connection wasn't successful then cleanup and try again (up to max retry count)
|
||||
if (connInfo == null)
|
||||
{
|
||||
connectionService.Disconnect(new DisconnectParams()
|
||||
{
|
||||
OwnerUri = ownerUri
|
||||
});
|
||||
// don't sleep on the final iterations since we won't try again
|
||||
if (attempt < RetryCount - 1)
|
||||
{
|
||||
Thread.Sleep(RetryDelayMs);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new TestConnectionResult() { ConnectionInfo = connInfo, ScriptFile = scriptFile };
|
||||
}
|
||||
}
|
||||
|
||||
throw new LiveConnectionException(string.Format("Could not establish a connection to {0}:{1}",
|
||||
connectParams.Connection.ServerName, connectParams.Connection.DatabaseName));
|
||||
}
|
||||
|
||||
public static ConnectionInfo InitLiveConnectionInfoForDefinition(string databaseName = null)
|
||||
{
|
||||
using (SelfCleaningTempFile queryTempFile = new SelfCleaningTempFile())
|
||||
{
|
||||
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);
|
||||
string ownerUri = queryTempFile.FilePath;
|
||||
|
||||
InitLiveConnectionInfo(databaseName, ownerUri);
|
||||
|
||||
var connectionService = GetLiveTestConnectionService();
|
||||
ConnectionInfo connInfo;
|
||||
connectionService.TryFindConnection(ownerUri, out connInfo);
|
||||
|
||||
Assert.NotNull(connInfo);
|
||||
return connInfo;
|
||||
}
|
||||
}
|
||||
|
||||
public static ServerConnection InitLiveServerConnectionForDefinition(ConnectionInfo connInfo)
|
||||
{
|
||||
SqlConnection sqlConn = new SqlConnection(ConnectionService.BuildConnectionString(connInfo.ConnectionDetails));
|
||||
return new ServerConnection(sqlConn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a test sql connection factory instance
|
||||
/// </summary>
|
||||
public static ISqlConnectionFactory GetLiveTestSqlConnectionFactory()
|
||||
{
|
||||
// connect to a real server instance
|
||||
return ConnectionService.Instance.ConnectionFactory;
|
||||
}
|
||||
|
||||
public static ConnectionService GetLiveTestConnectionService()
|
||||
{
|
||||
// connect to a real server instance
|
||||
return ConnectionService.Instance;
|
||||
}
|
||||
|
||||
public class TestConnectionResult
|
||||
{
|
||||
public ConnectionInfo ConnectionInfo { get; set; }
|
||||
|
||||
public ScriptFile ScriptFile { get; set; }
|
||||
|
||||
public TextDocumentPosition TextDocumentPosition { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user