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;
            }
        }
示例#5
0
        /// <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;
            }
        }