From 4a6d8a6530db0f7bd439060e6a98a0a5baca7d44 Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Mon, 3 Apr 2017 12:46:50 -0700 Subject: [PATCH] Improving cache concurrency unit tests --- src/Orchard.Tests/Caching/CacheTests.cs | 67 ++++++++++++++++++++----- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/src/Orchard.Tests/Caching/CacheTests.cs b/src/Orchard.Tests/Caching/CacheTests.cs index 5e1f9b872..27ffc3b62 100644 --- a/src/Orchard.Tests/Caching/CacheTests.cs +++ b/src/Orchard.Tests/Caching/CacheTests.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Threading; +using System.Threading.Tasks; using Autofac; using NUnit.Framework; using Orchard.Caching; @@ -84,33 +85,73 @@ namespace Orchard.Tests.Caching { public void CacheManagerIsNotBlocking() { var hits = 0; string result = ""; + string key = "key"; - Enumerable.Range(0, 5).AsParallel().ForAll(x => - result = _cacheManager.Get("testItem", ctx => { - // by waiting for 100ms we expect all the calls to Get - // to enter this lambda - Thread.Sleep(100); + var e1 = new ManualResetEvent(false); + var e2 = new ManualResetEvent(false); + var e3 = new ManualResetEvent(false); + + // task1 is started first, when inside the lambda, we are waiting + // for the test to give the green light. Then we unblock the task2 + var task1 = Task.Run(() => { + result = _cacheManager.Get(key, ctx => { + e1.WaitOne(TimeSpan.FromSeconds(5)); hits++; + e2.Set(); + e3.WaitOne(TimeSpan.FromSeconds(5)); + return "testResult"; - }) - ); + }); + }); + + // task2 is called once task1 is inside the lambda, ensuring it's not blocking. + var task2 = Task.Run(() => { + e2.WaitOne(TimeSpan.FromSeconds(5)); + result = _cacheManager.Get(key, ctx => { + hits++; + e3.Set(); + return "testResult"; + }); + }); + + e1.Set(); + Task.WaitAll(task1, task2); Assert.That(result, Is.EqualTo("testResult")); - Assert.That(hits, Is.GreaterThan(1)); + Assert.That(hits, Is.EqualTo(2)); } [Test] public void CacheManagerIsBlocking() { var hits = 0; string result = ""; + string key = "key"; - Enumerable.Range(0, 5).AsParallel().ForAll(x => - result = _cacheManager.Get("testItem", true, ctx => { - Thread.Sleep(100); + var e1 = new ManualResetEvent(false); + var e2 = new ManualResetEvent(false); + + // task1 is started first, when inside the lambda, we are waiting + // for the test to give the green light. Then we unblock the task2 + var task1 = Task.Run(() => { + result = _cacheManager.Get(key, true, ctx => { + e1.WaitOne(TimeSpan.FromSeconds(5)); + hits++; + e2.Set(); + return "testResult"; + }); + }); + + // task2 is called once task1 is inside the lambda. Here we expect the lamda not to be called. + var task2 = Task.Run(() => { + e2.WaitOne(TimeSpan.FromSeconds(5)); + result = _cacheManager.Get(key, true, ctx => { hits++; return "testResult"; - }) - ); + }); + }); + + e1.Set(); + Task.WaitAll(task1, task2); Assert.That(result, Is.EqualTo("testResult")); Assert.That(hits, Is.EqualTo(1));