Skip to content

Commit e465a4d

Browse files
author
Alex Peck
committed
tests
1 parent 1142598 commit e465a4d

File tree

2 files changed

+51
-5
lines changed

2 files changed

+51
-5
lines changed

BitFaster.Caching.UnitTests/Lru/ConcurrentLruSoakTests.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Threading;
45
using System.Threading.Tasks;
56
using BitFaster.Caching.Lru;
67
using FluentAssertions;
78
using Xunit;
89
using Xunit.Abstractions;
10+
using static BitFaster.Caching.UnitTests.Lru.LruItemSoakTests;
911

1012
namespace BitFaster.Caching.UnitTests.Lru
1113
{
@@ -282,6 +284,52 @@ await Threaded.Run(4, r => {
282284
RunIntegrityCheck();
283285
}
284286

287+
// This test will run forever if there is a live lock.
288+
// Since the cache bookkeeping has some overhead, it is harder to provoke
289+
// spinning inside the reader thread compared to LruItemSoakTests.DetectTornStruct.
290+
[Theory]
291+
[Repeat(10)]
292+
public async Task WhenValueIsBigStructNoLiveLock(int _)
293+
{
294+
using var source = new CancellationTokenSource();
295+
var started = new TaskCompletionSource<bool>();
296+
var cache = new ConcurrentLru<int, Guid>(1, capacity, EqualityComparer<int>.Default);
297+
298+
var setTask = Task.Run(() => Setter(cache, source.Token, started));
299+
await started.Task;
300+
Checker(cache, source);
301+
302+
await setTask;
303+
}
304+
305+
private void Setter(ICache<int, Guid> cache, CancellationToken cancelToken, TaskCompletionSource<bool> started)
306+
{
307+
started.SetResult(true);
308+
309+
while (true)
310+
{
311+
cache.AddOrUpdate(1, Guid.NewGuid());
312+
cache.AddOrUpdate(1, Guid.NewGuid());
313+
314+
if (cancelToken.IsCancellationRequested)
315+
{
316+
return;
317+
}
318+
}
319+
}
320+
321+
private void Checker(ICache<int, Guid> cache,CancellationTokenSource source)
322+
{
323+
// On my machine, without SeqLock, this consistently fails below 100 iterations
324+
// on debug build, and below 1000 on release build
325+
for (int count = 0; count < 100_000; ++count)
326+
{
327+
cache.TryGet(1, out _);
328+
}
329+
330+
source.Cancel();
331+
}
332+
285333
private void RunIntegrityCheck()
286334
{
287335
new ConcurrentLruIntegrityChecker<int, string, LruItem<int, string>, LruPolicy<int, string>, TelemetryPolicy<int, string>>(this.lru).Validate();

BitFaster.Caching.UnitTests/Lru/LruItemSoakTests.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ public class LruItemSoakTests
1616
// https://stackoverflow.com/questions/23262513/reproduce-torn-reads-of-decimal-in-c-sharp
1717
[Theory]
1818
[Repeat(soakIterations)]
19-
#pragma warning disable xUnit1026
20-
public async Task DetectTornStruct(int iteration)
21-
#pragma warning restore xUnit1026
19+
public async Task DetectTornStruct(int _)
2220
{
2321
using var source = new CancellationTokenSource();
2422
var started = new TaskCompletionSource<bool>();
@@ -30,7 +28,7 @@ public async Task DetectTornStruct(int iteration)
3028
await setTask;
3129
}
3230

33-
void Setter(CancellationToken cancelToken, TaskCompletionSource<bool> started)
31+
private void Setter(CancellationToken cancelToken, TaskCompletionSource<bool> started)
3432
{
3533
started.SetResult(true);
3634

@@ -46,7 +44,7 @@ void Setter(CancellationToken cancelToken, TaskCompletionSource<bool> started)
4644
}
4745
}
4846

49-
void Checker(CancellationTokenSource source)
47+
private void Checker(CancellationTokenSource source)
5048
{
5149
// On my machine, without SeqLock, this consistently fails below 100 iterations
5250
// on debug build, and below 1000 on release build

0 commit comments

Comments
 (0)