Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split performance unit tests into its own project #306

Merged
merged 2 commits into from
Apr 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Akka.Persistence.SqlServer.sln
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.SqlServer"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Akka.Persistence.SqlServer.Tests", "src\Akka.Persistence.SqlServer.Tests\Akka.Persistence.SqlServer.Tests.csproj", "{DEAC600E-5B71-4124-BE4B-5BF26C21575E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Akka.Persistence.SqlServer.Performance.Tests", "src\Akka.Persistence.SqlServer.Performance.Tests\Akka.Persistence.SqlServer.Performance.Tests.csproj", "{5B792D05-2CCE-4513-BAAD-100394E9E161}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -38,6 +40,10 @@ Global
{DEAC600E-5B71-4124-BE4B-5BF26C21575E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DEAC600E-5B71-4124-BE4B-5BF26C21575E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DEAC600E-5B71-4124-BE4B-5BF26C21575E}.Release|Any CPU.Build.0 = Release|Any CPU
{5B792D05-2CCE-4513-BAAD-100394E9E161}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B792D05-2CCE-4513-BAAD-100394E9E161}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B792D05-2CCE-4513-BAAD-100394E9E161}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B792D05-2CCE-4513-BAAD-100394E9E161}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
2 changes: 2 additions & 0 deletions build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ Target "RunTests" (fun _ ->
let projects =
match (isWindows) with
| true -> !! "./src/**/*.Tests.csproj"
-- "./src/**/*.Performance.Tests.csproj"
| _ -> !! "./src/**/*.Tests.csproj" // if you need to filter specs for Linux vs. Windows, do it here
-- "./src/**/*.Performance.Tests.csproj"

let runSingleProject project =
let arguments =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Condition="'$(OS)' == 'Windows_NT'">
<TargetFrameworks>$(NetFrameworkTestVersion);$(NetCoreTestVersion)</TargetFrameworks>
<IsPackable>false</IsPackable>
</PropertyGroup>

<!-- disable .NET Framework (Mono) on Linux-->
<PropertyGroup Condition="'$(OS)' != 'Windows_NT'">
<TargetFramework>$(NetCoreTestVersion)</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Data.SqlClient" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Akka.Persistence.Sql.TestKit" />
<PackageReference Include="Docker.DotNet" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Akka.Persistence.SqlServer\Akka.Persistence.SqlServer.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
using Xunit;
using Xunit.Abstractions;

namespace Akka.Persistence.SqlServer.Tests
namespace Akka.Persistence.SqlServer.Performance.Tests
{
[Collection("SqlServerSpec")]
public class BatchingSqlServerJournalPerfSpec : JournalPerfSpec, IDisposable
Expand Down
84 changes: 84 additions & 0 deletions src/Akka.Persistence.SqlServer.Performance.Tests/DbUtils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// -----------------------------------------------------------------------
// <copyright file="DbUtils.cs" company="Akka.NET Project">
// Copyright (C) 2013 - 2023 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------

using System;
using System.IO;
using Microsoft.Data.SqlClient;

namespace Akka.Persistence.SqlServer.Performance.Tests
{
public static class DbUtils
{
private static SqlConnectionStringBuilder _builder;
public static string ConnectionString => _builder.ToString();

public static void Initialize(string connectionString)
{
_builder = new SqlConnectionStringBuilder(connectionString);
var databaseName = $"akka_persistence_tests_{Guid.NewGuid()}";
_builder.InitialCatalog = databaseName;

var connectionBuilder = new SqlConnectionStringBuilder(connectionString)
{
InitialCatalog = "master"
};

using (var conn = new SqlConnection(connectionBuilder.ToString()))
{
conn.Open();

using (var cmd = new SqlCommand())
{
cmd.CommandText = $@"
IF db_id('{databaseName}') IS NULL
BEGIN
CREATE DATABASE [{databaseName}];
END";
cmd.Connection = conn;
cmd.ExecuteScalar();
}
}

// Delete local snapshot flat file database
var path = "./snapshots";
if (Directory.Exists(path))
Directory.Delete(path, true);
}

public static void Clean()
{
var databaseName = $"akka_persistence_tests_{Guid.NewGuid()}";
_builder.InitialCatalog = databaseName;

var connectionBuilder = new SqlConnectionStringBuilder(ConnectionString)
{
InitialCatalog = "master"
};

using (var conn = new SqlConnection(connectionBuilder.ToString()))
{
conn.Open();

using (var cmd = new SqlCommand())
{
cmd.CommandText = $@"
IF db_id('{databaseName}') IS NULL
BEGIN
CREATE DATABASE [{databaseName}];
END
";
cmd.Connection = conn;
cmd.ExecuteScalar();
}
}

// Delete local snapshot flat file database
var path = "./snapshots";
if (Directory.Exists(path))
Directory.Delete(path, true);
}
}
}
186 changes: 186 additions & 0 deletions src/Akka.Persistence.SqlServer.Performance.Tests/SqlServerFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// -----------------------------------------------------------------------
// <copyright file="SqlServerFixture.cs" company="Akka.NET Project">
// Copyright (C) 2013 - 2023 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Akka.Util;
using Docker.DotNet;
using Docker.DotNet.Models;
using Xunit;
using Xunit.Sdk;

namespace Akka.Persistence.SqlServer.Performance.Tests
{
[CollectionDefinition("SqlServerSpec")]
public sealed class SqlServerSpecsFixture : ICollectionFixture<SqlServerFixture>
{
}

/// <summary>
/// Fixture used to run SQL Server
/// </summary>
public class SqlServerFixture : IAsyncLifetime
{
protected readonly string SqlContainerName = $"sqlserver-{Guid.NewGuid():N}";
protected DockerClient Client;

public SqlServerFixture()
{
DockerClientConfiguration config;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
config = new DockerClientConfiguration(new Uri("unix://var/run/docker.sock"));
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
config = new DockerClientConfiguration(new Uri("npipe://./pipe/docker_engine"));
else
throw new NotSupportedException($"Unsupported OS [{RuntimeInformation.OSDescription}]");

Client = config.CreateClient();
}

protected string ImageName => "mcr.microsoft.com/mssql/server";
protected string Tag => "2019-latest";

protected string SqlServerImageName => $"{ImageName}:{Tag}";

public string ConnectionString { get; private set; }

public async Task InitializeAsync()
{
var sysInfo = await Client.System.GetSystemInfoAsync();
if (sysInfo.OSType.ToLowerInvariant() != "linux")
throw new TestClassException("MSSQL docker image only available for linux containers");

var images = await Client.Images.ListImagesAsync(new ImagesListParameters
{
Filters = new Dictionary<string, IDictionary<string, bool>>
{
{
"reference",
new Dictionary<string, bool>
{
{ SqlServerImageName, true }
}
}
}
});

if (images.Count == 0)
await Client.Images.CreateImageAsync(
new ImagesCreateParameters { FromImage = ImageName, Tag = Tag }, null,
new Progress<JSONMessage>(message =>
{
Console.WriteLine(!string.IsNullOrEmpty(message.ErrorMessage)
? message.ErrorMessage
: $"{message.ID} {message.Status} {message.ProgressMessage}");
}));

var sqlServerHostPort = ThreadLocalRandom.Current.Next(9000, 10000);

// create the container
await Client.Containers.CreateContainerAsync(new CreateContainerParameters
{
Image = SqlServerImageName,
Name = SqlContainerName,
Tty = true,
ExposedPorts = new Dictionary<string, EmptyStruct>
{
{ "1433/tcp", new EmptyStruct() }
},
HostConfig = new HostConfig
{
PortBindings = new Dictionary<string, IList<PortBinding>>
{
{
"1433/tcp",
new List<PortBinding>
{
new PortBinding
{
HostPort = $"{sqlServerHostPort}"
}
}
}
}
},
Env = new[]
{
"ACCEPT_EULA=Y",
"MSSQL_SA_PASSWORD=l0l!Th1sIsOpenSource"
}
});

// start the container
await Client.Containers.StartContainerAsync(SqlContainerName, new ContainerStartParameters());

// Wait until MSSQL is completely ready
var logStream = await Client.Containers.GetContainerLogsAsync(SqlContainerName, new ContainerLogsParameters
{
Follow = true,
ShowStdout = true,
ShowStderr = true
});

string line = null;
var timeoutInMilis = 60000;
using (var reader = new StreamReader(logStream))
{
var stopwatch = Stopwatch.StartNew();
while (stopwatch.ElapsedMilliseconds < timeoutInMilis && (line = await reader.ReadLineAsync()) != null)
{
if (!string.IsNullOrWhiteSpace(line))
Console.WriteLine(line);
if (line.Contains("SQL Server is now ready for client connections.")) break;
}

stopwatch.Stop();
}
#if NETCOREAPP3_1_OR_GREATER
await logStream.DisposeAsync();
#else
logStream.Dispose();
#endif
if (!line?.Contains("SQL Server is now ready for client connections.") ?? false)
throw new Exception("MSSQL docker image failed to run.");

var connectionString = new DbConnectionStringBuilder
{
["Server"] = $"localhost,{sqlServerHostPort}",
["Database"] = "akka_persistence_tests",
["User Id"] = "sa",
["Password"] = "l0l!Th1sIsOpenSource"
};

ConnectionString = connectionString.ToString();
Console.WriteLine($"Connection string: [{ConnectionString}]");

await Task.Delay(10000);
}

public async Task DisposeAsync()
{
if (Client != null)
try
{
await Client.Containers.StopContainerAsync(SqlContainerName, new ContainerStopParameters());
await Client.Containers.RemoveContainerAsync(SqlContainerName,
new ContainerRemoveParameters { Force = true });
}
catch (DockerContainerNotFoundException)
{
// no-op
}
finally
{
Client.Dispose();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
using Xunit;
using Xunit.Abstractions;

namespace Akka.Persistence.SqlServer.Tests
namespace Akka.Persistence.SqlServer.Performance.Tests
{
[Collection("SqlServerSpec")]
public class SqlServerJournalPerfSpec : JournalPerfSpec, IDisposable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Condition="'$(OS)' == 'Windows_NT'">
<TargetFrameworks>$(NetFrameworkTestVersion);$(NetCoreTestVersion)</TargetFrameworks>
<IsPackable>false</IsPackable>
</PropertyGroup>

<!-- disable .NET Framework (Mono) on Linux-->
<PropertyGroup Condition="'$(OS)' != 'Windows_NT'">
<TargetFrameworks>$(NetCoreTestVersion)</TargetFrameworks>
<TargetFramework>$(NetCoreTestVersion)</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Data.SqlClient" />
<PackageReference Include="Microsoft.NET.Test.Sdk"/>
<PackageReference Include="Akka.Persistence.Sql.TestKit"/>
<PackageReference Include="Docker.DotNet"/>
<PackageReference Include="xunit"/>
<PackageReference Include="xunit.runner.visualstudio"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Akka.Persistence.Sql.TestKit" />
<PackageReference Include="Docker.DotNet" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Akka.Persistence.SqlServer\Akka.Persistence.SqlServer.csproj"/>
<ProjectReference Include="..\Akka.Persistence.SqlServer\Akka.Persistence.SqlServer.csproj" />
</ItemGroup>
</Project>