public void TestSingleThreaded( ) { int hits = 1000; using (CountdownEvent evt = new CountdownEvent(1000)) { var cache = CreateTimeoutCache <int, int>("Test cache"); ItemsRemovedEventHandler <int> handler = (sender, args) => { // ReSharper disable once AccessToDisposedClosure evt.Signal(args.Items.Count); }; cache.ItemsRemoved += handler; for (int i = 0; i < hits; i++) { cache.Add(i, i); } Assert.AreEqual(1000, cache.Count); evt.Wait(5000); cache.ItemsRemoved -= handler; Assert.AreEqual(0, cache.Count); } }
public void RecentValueTimesOut( ) { var innerFactory = new DummyCacheFactory(); var cache = CreateCache(innerFactory, new TimeSpan(0, 0, 1)); using (ManualResetEvent evt = new ManualResetEvent(false)) { ItemsRemovedEventHandler <string> handler = (sender, args) => { // ReSharper disable once AccessToDisposedClosure evt.Set( ); }; cache.ItemsRemoved += handler; cache.Add("a", "a"); cache.Add("b", "b"); innerFactory.Inner.Clear( ); evt.WaitOne(5000); cache.ItemsRemoved -= handler; } string value; Assert.That(cache.TryGetValue("a", out value), Is.False); Assert.That(cache.TryGetOrAdd("b", out value, (k) => "c"), Is.False); }
public void Test_Purging() { int testCount = 1000; var cacheExpiry = TimeSpan.FromMilliseconds(100); using (AutoResetEvent evt = new AutoResetEvent(false)) { int removedItemCount = 0; ItemsRemovedEventHandler <string> itemsRemoved = (sender, args) => { removedItemCount += args.Items.Count; // ReSharper disable once AccessToDisposedClosure evt.Set( ); }; var cache = CreateCache <string, string>(false, cacheExpiry); cache.ItemsRemoved += itemsRemoved; for (int i = 0; i < testCount; i++) { cache.Add(Guid.NewGuid( ).ToString( ), "a"); } evt.WaitOne(100); int loopCounter = 0; while (removedItemCount < testCount) { evt.WaitOne(100); loopCounter++; if (loopCounter > 20) { break; } } cache.Add(Guid.NewGuid( ).ToString( ), "a"); // Purging is triggered by an add // check that it is all purged Assert.That(cache.Count, Is.EqualTo(1)); cache.ItemsRemoved -= itemsRemoved; } }
public void Test_ItemsRemoved() { var cacheExpiry = TimeSpan.FromMilliseconds(100); var itemsRemoved = new List <int>(); var expectedRemoved = new List <int>(); using (AutoResetEvent evt = new AutoResetEvent(false)) { var cache = CreateCache <int, int>(false, cacheExpiry); ItemsRemovedEventHandler <int> itemsRemovedHandler = (sender, args) => { itemsRemoved.AddRange(args.Items); // ReSharper disable once AccessToDisposedClosure evt.Set( ); }; cache.ItemsRemoved += itemsRemovedHandler; foreach (var key in new [] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }) { cache.Add(key, key); expectedRemoved.Add(key); } evt.WaitOne(cacheExpiry); int loopCounter = 0; while (itemsRemoved.Count < 10) { evt.WaitOne(cacheExpiry); loopCounter++; if (loopCounter > 20) { break; } } // Generate strings so that the error message doesn't get confusing when the removedList is mutating underneath us. var expectedString = string.Join(", ", expectedRemoved); var removedString = string.Join(", ", itemsRemoved.OrderBy(a => a)); Assert.That(removedString, Is.EqualTo(expectedString), "Not removed"); cache.ItemsRemoved -= itemsRemovedHandler; } }
/// <summary> /// Raise the <see cref="ItemsRemoved"/> event. /// </summary> /// <param name="itemsRemovedEventArgs"> /// Event specific args. This cannot be null. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="itemsRemovedEventArgs"/> cannot be null. /// </exception> protected void OnItemsRemoved(ItemsRemovedEventArgs <TKey> itemsRemovedEventArgs) { if (itemsRemovedEventArgs == null) { throw new ArgumentNullException(nameof(itemsRemovedEventArgs)); } ItemsRemovedEventHandler <TKey> itemsRemovedEventHandler = ItemsRemoved; if (itemsRemovedEventHandler != null) { itemsRemovedEventHandler(this, itemsRemovedEventArgs); } }
public void TestMultiThreaded( ) { const int size = 50000; var cache = CreateTimeoutCache <int, int>("LRU Test"); for (int i = 0; i < size; i++) { cache.Add(i, i); } const int threadCount = 2; const int hits = 10000; var addThreads = new Thread [threadCount]; var removeThreads = new Thread [threadCount]; ParameterizedThreadStart addThreadStart = o => { var rand = new Random(new Guid( ).GetHashCode( )); for (int i = 0; i < hits; i++) { var randVal = rand.Next(size); int val; cache.TryGetOrAdd(randVal, out val, e => e); } }; ParameterizedThreadStart removeThreadStart = o => { var rand = new Random(new Guid( ).GetHashCode( )); for (int i = 0; i < hits; i++) { var randVal = rand.Next(size); cache.Remove(randVal); } }; using (ManualResetEvent evt = new ManualResetEvent(false)) { ItemsRemovedEventHandler <int> handler = (sender, args) => { if (cache.Count == 0) { // ReSharper disable once AccessToDisposedClosure evt.Set( ); } }; cache.ItemsRemoved += handler; for (int i = 0; i < threadCount; i++) { addThreads [i] = new Thread(addThreadStart) { IsBackground = true }; addThreads [i].Start( ); removeThreads [i] = new Thread(removeThreadStart) { IsBackground = true }; removeThreads [i].Start( ); } for (int i = 0; i < threadCount; i++) { addThreads [i].Join( ); removeThreads [i].Join( ); } evt.WaitOne(10000); cache.ItemsRemoved -= handler; Assert.That(cache.Count, Is.EqualTo(0)); } }
public void TestExpiration() { TimeSpan timeout = TimeSpan.FromSeconds(1); var cache = CreateCache <string, string>(false, TimeSpan.FromMilliseconds(100)); using (AutoResetEvent evt = new AutoResetEvent(false)) { int removedItemCount = 0; ItemsRemovedEventHandler <string> itemsRemoved = (sender, args) => { removedItemCount += args.Items.Count; // ReSharper disable once AccessToDisposedClosure evt.Set( ); }; cache.ItemsRemoved += itemsRemoved; ///// // Add 3 elements. ///// cache.Add("a", "A"); cache.Add("b", "B"); cache.Add("c", "C"); ///// // Wait (may remove variable number of items depending on timing) ///// evt.WaitOne(timeout); ///// // Add another 3 elements. ///// cache.Add("d", "D"); cache.Add("e", "E"); cache.Add("f", "F"); ///// // Wait (may remove variable number of items depending on timing) ///// evt.WaitOne(timeout); ///// // Add 3 elements. ///// cache.Add("g", "G"); cache.Add("h", "H"); cache.Add("i", "I"); ///// // Wait (may remove variable number of items depending on timing) ///// evt.WaitOne(timeout); ///// // If not all items have been removed (due to timing), wait for the next eviction pass. ///// if (removedItemCount < 9) { evt.WaitOne(timeout); } Assert.AreEqual(0, cache.Count); Assert.IsFalse(cache.ContainsKey("a")); Assert.IsFalse(cache.ContainsKey("b")); Assert.IsFalse(cache.ContainsKey("c")); cache.ItemsRemoved -= itemsRemoved; } }