Skip to content

Commit f4a448d

Browse files
committed
Added test for MemoryLock
1 parent 731b616 commit f4a448d

File tree

3 files changed

+125
-0
lines changed

3 files changed

+125
-0
lines changed

Locks.sln

+12
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "source", "source", "{1E772E
77
EndProject
88
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Locks", "source\Locks\Locks.csproj", "{6F5A38A8-D6E1-4D1D-99B4-85CE7C40F468}"
99
EndProject
10+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{8AB8A443-B3CA-49F8-9BD6-6476AA7F9EEC}"
11+
EndProject
12+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Locks.Tests", "tests\Locks.Tests\Locks.Tests.csproj", "{4942FB20-6E79-4AA6-B607-728F67291811}"
13+
EndProject
1014
Global
1115
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1216
Debug|Any CPU = Debug|Any CPU
@@ -17,11 +21,19 @@ Global
1721
{6F5A38A8-D6E1-4D1D-99B4-85CE7C40F468}.Debug|Any CPU.Build.0 = Debug|Any CPU
1822
{6F5A38A8-D6E1-4D1D-99B4-85CE7C40F468}.Release|Any CPU.ActiveCfg = Release|Any CPU
1923
{6F5A38A8-D6E1-4D1D-99B4-85CE7C40F468}.Release|Any CPU.Build.0 = Release|Any CPU
24+
{4942FB20-6E79-4AA6-B607-728F67291811}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25+
{4942FB20-6E79-4AA6-B607-728F67291811}.Debug|Any CPU.Build.0 = Debug|Any CPU
26+
{4942FB20-6E79-4AA6-B607-728F67291811}.Release|Any CPU.ActiveCfg = Release|Any CPU
27+
{4942FB20-6E79-4AA6-B607-728F67291811}.Release|Any CPU.Build.0 = Release|Any CPU
2028
EndGlobalSection
2129
GlobalSection(SolutionProperties) = preSolution
2230
HideSolutionNode = FALSE
2331
EndGlobalSection
2432
GlobalSection(NestedProjects) = preSolution
2533
{6F5A38A8-D6E1-4D1D-99B4-85CE7C40F468} = {1E772EE5-484B-4803-9FA1-6681DC601553}
34+
{4942FB20-6E79-4AA6-B607-728F67291811} = {8AB8A443-B3CA-49F8-9BD6-6476AA7F9EEC}
35+
EndGlobalSection
36+
GlobalSection(ExtensibilityGlobals) = postSolution
37+
SolutionGuid = {3E2C15DA-E3F4-407A-9BD5-A87A4D07597C}
2638
EndGlobalSection
2739
EndGlobal

tests/Locks.Tests/Locks.Tests.csproj

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
8+
<IsPackable>false</IsPackable>
9+
<IsTestProject>true</IsTestProject>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
14+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.0" />
15+
<PackageReference Include="xunit" Version="2.4.2" />
16+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
17+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
18+
<PrivateAssets>all</PrivateAssets>
19+
</PackageReference>
20+
<PackageReference Include="coverlet.collector" Version="6.0.0">
21+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
22+
<PrivateAssets>all</PrivateAssets>
23+
</PackageReference>
24+
</ItemGroup>
25+
26+
<ItemGroup>
27+
<ProjectReference Include="..\..\source\Locks\Locks.csproj" />
28+
</ItemGroup>
29+
30+
</Project>

tests/Locks.Tests/MemoryLockTests.cs

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Xunit;
3+
4+
namespace Locks.Tests
5+
{
6+
public sealed class MemoryLockTests
7+
{
8+
private readonly IServiceProvider _serviceProvider = new ServiceCollection().AddMemoryLock().BuildServiceProvider();
9+
10+
[Fact(DisplayName = "Memory lock works correct in multi-thread enviroment")]
11+
public async Task Test()
12+
{
13+
var memoryLock = _serviceProvider.GetRequiredService<IMemoryLock>();
14+
15+
const string lockKeyA = "A";
16+
const string lockKeyB = "B";
17+
const string lockKeyC = "C";
18+
19+
for (var i = 0; i < 3; i++)
20+
{
21+
var a1 = memoryLock.Acquire(lockKeyA);
22+
var b1 = memoryLock.Acquire(lockKeyB);
23+
var c1 = memoryLock.Acquire(lockKeyC);
24+
25+
var a2 = memoryLock.Acquire(lockKeyA);
26+
var b2 = memoryLock.Acquire(lockKeyB);
27+
var c2 = memoryLock.Acquire(lockKeyC);
28+
29+
var a3 = memoryLock.Acquire(lockKeyA);
30+
var b3 = memoryLock.Acquire(lockKeyB);
31+
var c3 = memoryLock.Acquire(lockKeyC);
32+
33+
await Task.WhenAll(a1, b1, c1);
34+
35+
Assert.True(a1.IsCompleted, Message(nameof(a1)));
36+
Assert.True(b1.IsCompleted, Message(nameof(b1)));
37+
Assert.True(c1.IsCompleted, Message(nameof(c1)));
38+
39+
// Second tasks should wait when locks will be released
40+
Assert.False(a2.IsCompleted, Message(nameof(a2), nameof(a1)));
41+
Assert.False(b2.IsCompleted, Message(nameof(b2), nameof(b1)));
42+
Assert.False(c2.IsCompleted, Message(nameof(c2), nameof(c1)));
43+
44+
Assert.False(a3.IsCompleted, Message(nameof(a3), nameof(a1)));
45+
Assert.False(b3.IsCompleted, Message(nameof(b3), nameof(b1)));
46+
Assert.False(c3.IsCompleted, Message(nameof(c3), nameof(c1)));
47+
48+
// When first tasks release locks, second tasks can continue
49+
a1.Result.Dispose();
50+
b1.Result.Dispose();
51+
c1.Result.Dispose();
52+
53+
await Task.WhenAll(a2, b2, c2);
54+
55+
Assert.True(a2.IsCompleted, Message(nameof(a2)));
56+
Assert.True(b2.IsCompleted, Message(nameof(b2)));
57+
Assert.True(c2.IsCompleted, Message(nameof(c2)));
58+
59+
Assert.False(a3.IsCompleted, Message(nameof(a3), nameof(a2)));
60+
Assert.False(b3.IsCompleted, Message(nameof(b3), nameof(b2)));
61+
Assert.False(c3.IsCompleted, Message(nameof(c3), nameof(c2)));
62+
63+
a2.Result.Dispose();
64+
b2.Result.Dispose();
65+
c2.Result.Dispose();
66+
67+
await Task.WhenAll(a3, b3, c3);
68+
69+
Assert.True(a3.IsCompleted, Message(nameof(a3)));
70+
Assert.True(b3.IsCompleted, Message(nameof(b3)));
71+
Assert.True(c3.IsCompleted, Message(nameof(c3)));
72+
73+
a3.Result.Dispose();
74+
b3.Result.Dispose();
75+
c3.Result.Dispose();
76+
}
77+
}
78+
79+
private string Message(string x) => $"Task {x} should be completed.";
80+
81+
private string Message(string x, string y) => $"Task {x} did not wait for task {y} to release the distributed lock.";
82+
}
83+
}

0 commit comments

Comments
 (0)