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

tests: use testcontainers for all integration tests #212

Draft
wants to merge 30 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5f3f995
chore: upload postgres dependency
Meir017 May 24, 2024
c46cffb
chore: Use testcontainers for postgres tests
Meir017 May 27, 2024
791e3a8
pass connection-string from postgres to LockTaker process
Meir017 May 27, 2024
75aa661
working-redis
Meir017 Jun 3, 2024
55e4145
fix net472
Meir017 Jun 3, 2024
881f8c4
faster dead-redis setup
Meir017 Jun 3, 2024
5efd124
postgresql setup
Meir017 Jun 3, 2024
01e284f
only windows for now
Meir017 Jun 3, 2024
27a7680
postgresql fixes
Meir017 Jun 3, 2024
2fd6594
add mssql
Meir017 Jun 3, 2024
64d06ce
simplify docs
Meir017 Jun 3, 2024
067524e
sql server integration fix
Meir017 Jun 3, 2024
625ba4c
better redis parallel test
Meir017 Jun 3, 2024
0355abe
fix db cross-process
Meir017 Jun 4, 2024
808ba04
fix tests
Meir017 Jun 4, 2024
16079c4
fix dynamic test
Meir017 Jun 4, 2024
e52f516
remove unused file
Meir017 Jun 4, 2024
b954f20
remove unused file
Meir017 Jun 4, 2024
8a0fc88
fix mssql
Meir017 Jun 4, 2024
34dd6ca
fix mssql
Meir017 Jun 4, 2024
5269f51
Update ci.yaml
Meir017 Jun 4, 2024
5258551
fix redis
Meir017 Jun 5, 2024
bfee7fa
Merge branch 'tests/testcontainers-all' of https://github.com/meir017…
Meir017 Jun 5, 2024
58388f0
clean redis
Meir017 Jun 5, 2024
a5dcd71
Update RedisSynchronizationCoreTestCases.cs
Meir017 Jun 5, 2024
9e4a4ca
Update RedisSynchronizationCoreTestCases.cs
Meir017 Jun 5, 2024
bb42e90
add mysql & mariadb
Meir017 Jun 5, 2024
a4dffaa
Merge branch 'tests/testcontainers-all' of https://github.com/meir017…
Meir017 Jun 5, 2024
963c7ed
Merge remote-tracking branch 'origin/master' into tests/testcontainer…
Meir017 Aug 9, 2024
b49c988
fix compilation
Meir017 Aug 9, 2024
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
24 changes: 24 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: CI

on: [push]

jobs:
build:
strategy:
matrix:
category: [Redis, Postgres, SqlServer, MySql]
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Setup .NET 8
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x

- name: Build
run: dotnet build src

- name: Run Tests
run: dotnet test src --filter Name~${{ matrix.category }}
14 changes: 3 additions & 11 deletions docs/Developing DistributedLock.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,15 @@ If the Oracle tests fail with `ORA-12541: TNS:no listener`, you may have to star

### Postgres

You can install Postgres from [here](https://www.enterprisedb.com/downloads/postgres-postgresql-downloads).

In `C:\Program Files\PostgreSQL\<version>\data\postgresql.conf`, update `max_connections` to 200.

Add your username (e.g. postgres) and password to `DistributedLock.Tests/credentials/postgres.txt`, with the username on line 1 and the password on line 2.
Have docker installed, we are using https://testcontainers.com/modules/postgresql/

### SQL Server

Download SQL developer edition from [here](https://www.microsoft.com/en-us/sql-server/sql-server-downloads).

The tests connect via integrated security.
Have docker installed, we are using https://testcontainers.com/modules/mssql/

### Redis

Install Redis locally. On Windows, install it via WSL as described [here](https://developer.redis.com/create/windows/).

You do not need it running as a service: the tests will start and stop instances automatically.
Have docker installed, we are using https://testcontainers.com/modules/redis/

### ZooKeeper

Expand Down
5 changes: 5 additions & 0 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
<PackageVersion Include="System.Data.SqlClient" Version="4.8.6" />
<PackageVersion Include="Moq" Version="4.20.70" />
<PackageVersion Include="System.Threading.AccessControl" Version="8.0.0" Condition="'$(TargetFramework)' != 'net462'" />
<PackageVersion Include="Testcontainers.MariaDb" Version="3.8.0" />
<PackageVersion Include="Testcontainers.MsSql" Version="3.8.0" />
<PackageVersion Include="Testcontainers.MySql" Version="3.8.0" />
<PackageVersion Include="Testcontainers.PostgreSql" Version="3.8.0" />
<PackageVersion Include="Testcontainers.Redis" Version="3.8.0" />
<PackageVersion Include="ZooKeeperNetEx" Version="3.4.12.4" />
<PackageVersion Include="IsExternalInit" Version="1.0.3" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="8.0.0" Condition="'$(TargetFramework)' == 'netstandard2.0' OR '$(TargetFramework)' == 'net462'" />
Expand Down
24 changes: 0 additions & 24 deletions src/DistributedLock.Core/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"Microsoft.CodeAnalysis.PublicApiAnalyzers": {
"type": "Direct",
"requested": "[3.3.4, )",
"resolved": "3.3.4",
"contentHash": "kNLTfXtXUWDHVt5iaPkkiPuyHYlMgLI6SOFT4w88bfeI2vqSeGgHunFkdvlaCM8RDfcY0t2+jnesQtidRJJ/DA=="
},
"Microsoft.NETFramework.ReferenceAssemblies": {
"type": "Direct",
"requested": "[1.0.3, )",
Expand Down Expand Up @@ -81,12 +75,6 @@
"System.Threading.Tasks.Extensions": "4.5.4"
}
},
"Microsoft.CodeAnalysis.PublicApiAnalyzers": {
"type": "Direct",
"requested": "[3.3.4, )",
"resolved": "3.3.4",
"contentHash": "kNLTfXtXUWDHVt5iaPkkiPuyHYlMgLI6SOFT4w88bfeI2vqSeGgHunFkdvlaCM8RDfcY0t2+jnesQtidRJJ/DA=="
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
Expand Down Expand Up @@ -136,12 +124,6 @@
}
},
".NETStandard,Version=v2.1": {
"Microsoft.CodeAnalysis.PublicApiAnalyzers": {
"type": "Direct",
"requested": "[3.3.4, )",
"resolved": "3.3.4",
"contentHash": "kNLTfXtXUWDHVt5iaPkkiPuyHYlMgLI6SOFT4w88bfeI2vqSeGgHunFkdvlaCM8RDfcY0t2+jnesQtidRJJ/DA=="
},
"Microsoft.SourceLink.GitHub": {
"type": "Direct",
"requested": "[8.0.0, )",
Expand All @@ -164,12 +146,6 @@
}
},
"net8.0": {
"Microsoft.CodeAnalysis.PublicApiAnalyzers": {
"type": "Direct",
"requested": "[3.3.4, )",
"resolved": "3.3.4",
"contentHash": "kNLTfXtXUWDHVt5iaPkkiPuyHYlMgLI6SOFT4w88bfeI2vqSeGgHunFkdvlaCM8RDfcY0t2+jnesQtidRJJ/DA=="
},
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[8.0.4, )",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@ public abstract class ConnectionStringStrategyTestCases<TLockProvider, TStrategy
{
private TLockProvider _lockProvider = default!;

[SetUp] public void SetUp() => this._lockProvider = new TLockProvider();
[TearDown] public void TearDown() => this._lockProvider.Dispose();
[SetUp]
public async Task SetUp()
{
this._lockProvider = new TLockProvider();
await this._lockProvider.SetupAsync();
}
[TearDown]
public async Task TearDown() => await this._lockProvider.DisposeAsync();

/// <summary>
/// Tests that internally-owned connections are properly cleaned up by disposing the lock handle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ public abstract class DbSemaphoreTestCases<TSemaphoreProvider, TStrategy, TDb>
{
private TSemaphoreProvider _semaphoreProvider = default!;

[SetUp] public void SetUp() => this._semaphoreProvider = new TSemaphoreProvider();
[TearDown] public void TearDown() => this._semaphoreProvider.Dispose();
[SetUp]
public async Task SetUp()
{
this._semaphoreProvider = new TSemaphoreProvider();
await this._semaphoreProvider.SetupAsync();
}
[TearDown]
public async Task TearDown() => await this._semaphoreProvider.DisposeAsync();

/// <summary>
/// This case and several that follow test "self-deadlock", where a semaphore acquire cannot possibly succeed because
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,14 @@ public abstract class ExternalConnectionOrTransactionStrategyTestCases<TLockProv
{
private TLockProvider _lockProvider = default!;

[SetUp] public void SetUp() => this._lockProvider = new TLockProvider();
[TearDown] public void TearDown() => this._lockProvider.Dispose();
[SetUp]
public async Task SetUp()
{
this._lockProvider = new TLockProvider();
await this._lockProvider.SetupAsync();
}
[TearDown]
public async Task TearDown() => await this._lockProvider.DisposeAsync();

[Test]
[NonParallelizable, Retry(tryCount: 3)] // timing sensitive for SqlSemaphore (see comment in that file regarding the 32ms wait)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ public abstract class ExternalConnectionStrategyTestCases<TLockProvider, TDb>
{
private TLockProvider _lockProvider = default!;

[SetUp] public void SetUp() => this._lockProvider = new TLockProvider();
[TearDown] public void TearDown() => this._lockProvider.Dispose();
[SetUp]
public async Task SetUp()
{
this._lockProvider = new TLockProvider();
await this._lockProvider.SetupAsync();
}
[TearDown]
public async Task TearDown() => await this._lockProvider.DisposeAsync();

[Test]
public void TestCloseLockOnClosedConnection()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,17 @@ public abstract class ExternalTransactionStrategyTestCases<TLockProvider, TDb>
{
private TLockProvider _lockProvider = default!;

[SetUp] public void SetUp() => this._lockProvider = new TLockProvider();
[TearDown] public void TearDown() => this._lockProvider.Dispose();
[SetUp]
public async Task SetUp()
{
this._lockProvider = new TLockProvider();
await this._lockProvider.SetupAsync();
}
[TearDown]
public async Task TearDown() => await this._lockProvider.DisposeAsync();

[Test]
public void TestScopedToTransactionOnly()
public async Task TestScopedToTransactionOnly()
{
this._lockProvider.Strategy.StartAmbient();

Expand All @@ -24,7 +30,7 @@ public void TestScopedToTransactionOnly()
Assert.That(this._lockProvider.CreateLock(nameof(TestScopedToTransactionOnly)).IsHeld(), Is.True);

// create a lock of the same type on the underlying connection of the ambient transaction
using dynamic specificConnectionProvider = Activator.CreateInstance(
await using dynamic specificConnectionProvider = Activator.CreateInstance(
ReplaceGenericParameter(typeof(TLockProvider), this._lockProvider.Strategy.GetType(), typeof(SpecificConnectionStrategy))
)!;
specificConnectionProvider.Strategy.Test = this;
Expand All @@ -50,6 +56,11 @@ static Type ReplaceGenericParameter(Type type, Type old, Type @new)
/// </summary>
private class SpecificConnectionStrategy : TestingDbSynchronizationStrategy<TDb>
{
public SpecificConnectionStrategy()
{
Console.WriteLine("SpecificConnectionStrategy created");
}

public ExternalTransactionStrategyTestCases<TLockProvider, TDb>? Test { get; set; }

public override TestingDbConnectionOptions GetConnectionOptions() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,14 @@ public abstract class MultiplexingConnectionStrategyTestCases<TLockProvider, TDb
{
private TLockProvider _lockProvider = default!;

[SetUp] public void SetUp() => this._lockProvider = new TLockProvider();
[TearDown] public void TearDown() => this._lockProvider.Dispose();
[SetUp]
public async Task SetUp()
{
this._lockProvider = new TLockProvider();
await this._lockProvider.SetupAsync();
}
[TearDown]
public async Task TearDown() => await this._lockProvider.DisposeAsync();

/// <summary>
/// Similar to <see cref="DistributedLockCoreTestCases{TLockProvider, TStrategy}.TestLockAbandonment"/> but demonstrates
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@ public abstract class OwnedConnectionStrategyTestCases<TLockProvider, TDb>
{
private TLockProvider _lockProvider = default!;

[SetUp] public void SetUp() => this._lockProvider = new TLockProvider();
[TearDown] public void TearDown() => this._lockProvider.Dispose();
[SetUp]
public async Task SetUp()
{
this._lockProvider = new TLockProvider();
await this._lockProvider.SetupAsync();
}
[TearDown]
public async Task TearDown() => await this._lockProvider.DisposeAsync();

/// <summary>
/// Tests that our idle session killer works, therefore validating our other tests that use it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ public abstract class OwnedTransactionStrategyTestCases<TLockProvider, TDb>
{
private TLockProvider _lockProvider = default!;

[SetUp] public void SetUp() => this._lockProvider = new TLockProvider();
[TearDown] public void TearDown() => this._lockProvider.Dispose();
[SetUp]
public async Task SetUp()
{
this._lockProvider = new TLockProvider();
await this._lockProvider.SetupAsync();
}
[TearDown]
public async Task TearDown() => await this._lockProvider.DisposeAsync();

/// <summary>
/// Validates that we use the default isolation level to avoid the problem described
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ public abstract class UpgradeableReaderWriterLockConnectionStringStrategyTestCas
{
private TLockProvider _lockProvider = default!;

[SetUp] public void SetUp() => this._lockProvider = new TLockProvider();
[TearDown] public void TearDown() => this._lockProvider.Dispose();
[SetUp]
public async Task SetUp()
{
this._lockProvider = new TLockProvider();
await this._lockProvider.SetupAsync();
}
[TearDown]
public async Task TearDown() => await this._lockProvider.DisposeAsync();

/// <summary>
/// Tests the logic where upgrading a connection stops and restarts the keepalive
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,19 @@ public abstract class DistributedLockCoreTestCases<TLockProvider, TStrategy>
private TLockProvider _lockProvider = default!;
private readonly List<Action> _cleanupActions = [];

[SetUp] public void SetUp() => this._lockProvider = new TLockProvider();
[SetUp]
public async Task SetUp()
{
this._lockProvider = new TLockProvider();
await this._lockProvider.SetupAsync();
}

[TearDown]
public void TearDown()
public async Task TearDown()
{
this._cleanupActions.ForEach(a => a());
this._cleanupActions.Clear();
this._lockProvider.Dispose();
await this._lockProvider.DisposeAsync();
}

[Test]
Expand Down Expand Up @@ -390,7 +395,7 @@ public async Task TestLockAbandonment()
public void TestCrossProcess()
{
var lockName = this._lockProvider.GetUniqueSafeName();
var command = this.RunLockTaker(this._lockProvider, this._lockProvider.GetCrossProcessLockType(), lockName);
var command = this.RunLockTaker(this._lockProvider, this._lockProvider.GetCrossProcessLockType(), lockName, this._lockProvider.GetConnectionStringForCrossProcessTest());
Assert.That(command.StandardOutput.ReadLineAsync().Wait(TimeSpan.FromSeconds(10)), Is.True);
Assert.That(command.Task.Wait(TimeSpan.FromSeconds(.1)), Is.False);

Expand Down Expand Up @@ -421,7 +426,7 @@ public void TestCrossProcessAbandonmentWithKill()
private void CrossProcessAbandonmentHelper(bool asyncWait, bool kill)
{
var name = this._lockProvider.GetUniqueSafeName($"cpl-{asyncWait}-{kill}");
var command = this.RunLockTaker(this._lockProvider, this._lockProvider.GetCrossProcessLockType(), name);
var command = this.RunLockTaker(this._lockProvider, this._lockProvider.GetCrossProcessLockType(), name, this._lockProvider.GetConnectionStringForCrossProcessTest());
Assert.That(command.StandardOutput.ReadLineAsync().Wait(TimeSpan.FromSeconds(10)), Is.True);
Assert.That(command.Task.IsCompleted, Is.False);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,15 @@ public abstract class DistributedReaderWriterLockCoreTestCases<TLockProvider, TS
{
private TLockProvider _lockProvider = default!;

[SetUp] public void SetUp() => this._lockProvider = new TLockProvider();
[TearDown] public void TearDown() => this._lockProvider.Dispose();
[SetUp]
public async Task SetUp()
{
this._lockProvider = new TLockProvider();
await this._lockProvider.SetupAsync();
}

[TearDown]
public async Task TearDown() => await this._lockProvider.DisposeAsync();

[Test]
public async Task TestMultipleReadersSingleWriter()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@ public abstract class DistributedSemaphoreCoreTestCases<TSemaphoreProvider, TStr

private TSemaphoreProvider _semaphoreProvider = default!;

[SetUp] public void SetUp() => this._semaphoreProvider = new TSemaphoreProvider();
[TearDown] public void TearDown() => this._semaphoreProvider.Dispose();
[SetUp]
public async Task SetUp()
{
this._semaphoreProvider = new TSemaphoreProvider();
await this._semaphoreProvider.SetupAsync();
}
[TearDown]
public async Task TearDown() => await this._semaphoreProvider.DisposeAsync();

[Test]
public void TestMaxCount()
Expand Down Expand Up @@ -46,7 +52,7 @@ public void TestConcurrencyHandling()
Thread.Sleep(10);
Interlocked.Decrement(ref counter);
}
},
},
TaskCreationOptions.LongRunning // dedicated thread
))
.ToArray();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ public abstract class DistributedUpgradeableReaderWriterLockCoreTestCases<TLockP
{
private TLockProvider _lockProvider = default!;

[SetUp] public void SetUp() => this._lockProvider = new TLockProvider();
[TearDown] public void TearDown() => this._lockProvider.Dispose();
[SetUp]
public async Task SetUp()
{
this._lockProvider = new TLockProvider();
await this._lockProvider.SetupAsync();
}
[TearDown]
public async Task TearDown() => await this._lockProvider.DisposeAsync();

[Test]
public void TestMultipleReadersSingleWriter()
Expand Down
Loading