diff --git a/BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuSoakTests.cs b/BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuSoakTests.cs index d028a832..ad660bda 100644 --- a/BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuSoakTests.cs +++ b/BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuSoakTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; @@ -485,9 +486,11 @@ private async Task RunIntegrityCheckAsync(ConcurrentLfu lfu, int it { this.output.WriteLine($"iteration {iteration} keys={string.Join(" ", lfu.Keys)}"); - var scheduler = lfu.Scheduler as BackgroundThreadScheduler; - scheduler.Dispose(); - await scheduler.Completion; + if (lfu.Scheduler is BackgroundThreadScheduler scheduler) + { + scheduler.Dispose(); + await scheduler.Completion; + } RunIntegrityCheck(lfu, this.output); } @@ -517,6 +520,8 @@ internal class ConcurrentLfuIntegrityChecker { private readonly ConcurrentLfuCore cache; + private readonly ConcurrentDictionary dictionary; + private readonly LfuNodeList windowLru; private readonly LfuNodeList probationLru; private readonly LfuNodeList protectedLru; @@ -524,6 +529,8 @@ internal class ConcurrentLfuIntegrityChecker private readonly StripedMpscBuffer readBuffer; private readonly MpscBoundedBuffer writeBuffer; + private static FieldInfo dictionaryField = typeof(ConcurrentLfuCore).GetField("dictionary", BindingFlags.NonPublic | BindingFlags.Instance); + private static FieldInfo windowLruField = typeof(ConcurrentLfuCore).GetField("windowLru", BindingFlags.NonPublic | BindingFlags.Instance); private static FieldInfo probationLruField = typeof(ConcurrentLfuCore).GetField("probationLru", BindingFlags.NonPublic | BindingFlags.Instance); private static FieldInfo protectedLruField = typeof(ConcurrentLfuCore).GetField("protectedLru", BindingFlags.NonPublic | BindingFlags.Instance); @@ -535,6 +542,8 @@ public ConcurrentLfuIntegrityChecker(ConcurrentLfuCore cache) { this.cache = cache; + this.dictionary = (ConcurrentDictionary)dictionaryField.GetValue(cache); + // get lrus via reflection this.windowLru = (LfuNodeList)windowLruField.GetValue(cache); this.probationLru = (LfuNodeList)probationLruField.GetValue(cache); @@ -595,14 +604,14 @@ private void VerifyLruInDictionary(LfuNodeList lfuNodes, ITestOutputHelper private void VerifyDictionaryInLrus() { - foreach (var kvp in this.cache) + foreach (var kvp in this.dictionary) { var exists = Exists(kvp, this.windowLru) || Exists(kvp, this.probationLru) || Exists(kvp, this.protectedLru); - exists.Should().BeTrue($"key {kvp.Key} must exist in LRU lists"); + exists.Should().BeTrue($"key {kvp.Key} in {kvp.Value.Position} removed: {kvp.Value.WasRemoved} deleted {kvp.Value.WasDeleted} must exist in LRU lists"); } } - private static bool Exists(KeyValuePair kvp, LfuNodeList lfuNodes) + private static bool Exists(KeyValuePair kvp, LfuNodeList lfuNodes) { var node = lfuNodes.First;