Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ public void SetNullCallback_NotAllowed_ArgumentException()

var notNullCallback = new PostEvictionCallbackRegistration()
{
EvictionCallback = (_, _, _, _) => {}
EvictionCallback = (_, _, _, _) => { }
};

options.PostEvictionCallbacks.Add(notNullCallback);
Expand Down Expand Up @@ -570,61 +570,53 @@ public void SetGetAndRemoveWorksWithObjectKeysWhenDifferentReferences()

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/72879")] // issue in cache
[ActiveIssue("https://github.com/dotnet/runtime/issues/72890")] // issue in test
public void GetAndSet_AreThreadSafe_AndUpdatesNeverLeavesNullValues()
{
var cache = CreateCache();
string key = "myKey";
var cts = new CancellationTokenSource();
var readValueIsNull = false;
bool readValueIsNull = false;

cache.Set(key, new Guid());

var task0 = Task.Run(() =>
{
while (!cts.IsCancellationRequested)
{
cache.Set(key, Guid.NewGuid());
}
});
const int WriterCount = 2;
const int Iterations = 20_000;
using var barrier = new Barrier(WriterCount + 1);

var task1 = Task.Run(() =>
var writers = new Task[WriterCount];
for (int i = 0; i < WriterCount; i++)
{
while (!cts.IsCancellationRequested)
writers[i] = Task.Run(() =>
{
cache.Set(key, Guid.NewGuid());
}
});
barrier.SignalAndWait();
for (int j = 0; j < Iterations; j++)
{
cache.Set(key, Guid.NewGuid());
}
});
}

var task2 = Task.Run(() =>
var reader = Task.Run(() =>
{
while (!cts.IsCancellationRequested)
barrier.SignalAndWait();
for (int j = 0; j < Iterations; j++)
{
if (cache.Get(key) == null)
{
// Stop this task and update flag for assertion
readValueIsNull = true;
break;
}
}
});

var task3 = Task.Delay(TimeSpan.FromSeconds(7));

Task.WaitAny(task0, task1, task2, task3);
var all = new Task[WriterCount + 1];
Array.Copy(writers, all, WriterCount);
all[WriterCount] = reader;
Task.WaitAll(all);

Assert.False(readValueIsNull);
Assert.Equal(TaskStatus.Running, task0.Status);
Assert.Equal(TaskStatus.Running, task1.Status);
Assert.Equal(TaskStatus.Running, task2.Status);
Assert.Equal(TaskStatus.RanToCompletion, task3.Status);

cts.Cancel();
Task.WaitAll(task0, task1, task2, task3);
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/72890")]
public void OvercapacityPurge_AreThreadSafe()
{
var cache = new MemoryCache(new MemoryCacheOptions
Expand All @@ -633,64 +625,38 @@ public void OvercapacityPurge_AreThreadSafe()
SizeLimit = 10,
CompactionPercentage = 0.5
});
var cts = new CancellationTokenSource();
var limitExceeded = false;

var task0 = Task.Run(() =>
{
while (!cts.IsCancellationRequested)
{
if (cache.Size > 10)
{
limitExceeded = true;
break;
}
cache.Set(Guid.NewGuid(), Guid.NewGuid(), new MemoryCacheEntryOptions { Size = 1 });
}
}, cts.Token);
const int NumberOfThreads = 3;
const int IterationsPerThread = 10_000;
using var barrier = new Barrier(NumberOfThreads);
bool limitExceeded = false;

var task1 = Task.Run(() =>
var tasks = new Task[NumberOfThreads];
for (int i = 0; i < NumberOfThreads; i++)
{
while (!cts.IsCancellationRequested)
tasks[i] = Task.Run(() =>
{
if (cache.Size > 10)
barrier.SignalAndWait();
for (int j = 0; j < IterationsPerThread; j++)
{
limitExceeded = true;
break;
if (cache.Size > 10)
{
limitExceeded = true;
break;
}
cache.Set(Guid.NewGuid(), Guid.NewGuid(), new MemoryCacheEntryOptions { Size = 1 });
}
cache.Set(Guid.NewGuid(), Guid.NewGuid(), new MemoryCacheEntryOptions { Size = 1 });
}
}, cts.Token);

var task2 = Task.Run(() =>
{
while (!cts.IsCancellationRequested)
{
if (cache.Size > 10)
{
limitExceeded = true;
break;
}
cache.Set(Guid.NewGuid(), Guid.NewGuid(), new MemoryCacheEntryOptions { Size = 1 });
}
}, cts.Token);

cts.CancelAfter(TimeSpan.FromSeconds(5));
var task3 = Task.Delay(TimeSpan.FromSeconds(7));
});
}

Task.WaitAll(task0, task1, task2, task3);
Task.WaitAll(tasks);

Assert.Equal(TaskStatus.RanToCompletion, task0.Status);
Assert.Equal(TaskStatus.RanToCompletion, task1.Status);
Assert.Equal(TaskStatus.RanToCompletion, task2.Status);
Assert.Equal(TaskStatus.RanToCompletion, task3.Status);
CapacityTests.AssertCacheSize(cache.Count, cache);
Assert.InRange(cache.Count, 0, 10);
Assert.False(limitExceeded);
}

[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/72890")]
public void AddAndReplaceEntries_AreThreadSafe()
{
var cache = new MemoryCache(new MemoryCacheOptions
Expand All @@ -699,46 +665,28 @@ public void AddAndReplaceEntries_AreThreadSafe()
SizeLimit = 20,
CompactionPercentage = 0.5
});
var cts = new CancellationTokenSource();

var random = new Random();

var task0 = Task.Run(() =>
{
while (!cts.IsCancellationRequested)
{
var entrySize = random.Next(0, 5);
cache.Set(random.Next(0, 10), entrySize, new MemoryCacheEntryOptions { Size = entrySize });
}
});

var task1 = Task.Run(() =>
{
while (!cts.IsCancellationRequested)
{
var entrySize = random.Next(0, 5);
cache.Set(random.Next(0, 10), entrySize, new MemoryCacheEntryOptions { Size = entrySize });
}
});
const int NumberOfThreads = 3;
const int IterationsPerThread = 10_000;
using var barrier = new Barrier(NumberOfThreads);

var task2 = Task.Run(() =>
var tasks = new Task[NumberOfThreads];
for (int i = 0; i < NumberOfThreads; i++)
{
while (!cts.IsCancellationRequested)
// Each thread gets its own Random; Random is not thread-safe.
var random = new Random(i);
tasks[i] = Task.Run(() =>
{
var entrySize = random.Next(0, 5);
cache.Set(random.Next(0, 10), entrySize, new MemoryCacheEntryOptions { Size = entrySize });
}
});

cts.CancelAfter(TimeSpan.FromSeconds(5));
var task3 = Task.Delay(TimeSpan.FromSeconds(7));

Task.WaitAll(task0, task1, task2, task3);
barrier.SignalAndWait();
for (int j = 0; j < IterationsPerThread; j++)
{
var entrySize = random.Next(0, 5);
cache.Set(random.Next(0, 10), entrySize, new MemoryCacheEntryOptions { Size = entrySize });
}
});
}

Assert.Equal(TaskStatus.RanToCompletion, task0.Status);
Assert.Equal(TaskStatus.RanToCompletion, task1.Status);
Assert.Equal(TaskStatus.RanToCompletion, task2.Status);
Assert.Equal(TaskStatus.RanToCompletion, task3.Status);
Task.WaitAll(tasks);

var cacheSize = 0;
for (var i = 0; i < 10; i++)
Expand Down Expand Up @@ -777,15 +725,16 @@ public void SetDataToCacheWithNullKeyAndChangeTokenThrows()
public void TryGetValueFromCacheWithNullKeyThrows()
{
var cache = CreateCache();
Assert.Throws<ArgumentNullException>(() => cache.TryGetValue(null,out long result));
Assert.Throws<ArgumentNullException>(() => cache.TryGetValue(null, out long result));
}

[Fact]
public void GetOrCreateFromCacheWithNullKeyThrows()
{
var cache = CreateCache();
Assert.Throws<ArgumentNullException>(() => cache.GetOrCreate<object>(null, null))
; }
;
}

[Fact]
public async Task GetOrCreateAsyncFromCacheWithNullKeyThrows()
Expand Down
Loading