public void NewCacheIsEmpty()
        {
            var capacity = 100;
            var cache    = new PseudoLRUCache <string>(capacity);

            Assert.IsTrue(cache.IsEmpty, "Cache does not know it is empty");
        }
        public void CacheHitRatioCase(int n, double cacheSizePercentage, double alpha, double expectedHitRate, int maxTrials)
        {
            var zipf          = new ZipfDistribution(n, alpha, 10, 0.0001);
            var capacity      = (int)(n * cacheSizePercentage / 100);
            var cache         = new PseudoLRUCache <string>(capacity);
            var allItems      = new PseudoLRUCache <string> .CacheItem[n + 1];
            var rankHistogram = new int[n + 1];

            for (var trial = 0; trial < maxTrials; trial++)
            {
                var rank = zipf.NextRandomRank();
                if (allItems[rank] == null)
                {
                    allItems[rank] = cache.Add(rank.ToString());
                }
                else
                {
                    allItems[rank].GetOrCreate(() => rank.ToString());
                }
                rankHistogram[rank]++;
            }
            Console.WriteLine($"The Hit Ratio is {cache.HitRatio}; hoped for {expectedHitRate}");
            var histogram = "Rank Histogram for first 100 items\n";
            var cumePct   = 0.0;

            for (var rank = 1; rank <= 100; rank++)
            {
                var pct = 100.0 * rankHistogram[rank] / (double)maxTrials;
                cumePct   += pct;
                histogram += $"{rank} chosen {rankHistogram[rank]} times ({pct}%, {cumePct}% cume)\n";
            }
            Console.WriteLine(histogram);
            Assert.GreaterOrEqual(cache.HitRatio, expectedHitRate, $"Cache Hit Ratio is lower than expected: {cache.HitRatio} < {expectedHitRate}");
        }
        public void SizeIncrementsIfYouAddItemsToCacheThatIsNotFull()
        {
            var capacity = 100;
            var cache    = new PseudoLRUCache <string>(capacity);

            Assert.AreEqual(0, cache.Size);
            cache.Add("item1");
            Assert.AreEqual(1, cache.Size);
            cache.Add("item2");
            Assert.AreEqual(2, cache.Size);
        }
        public void NoItemsEvictedWhenAddingToCacheThatsNotNotFull()
        {
            var capacity = 100;
            var cache    = new PseudoLRUCache <string>(capacity);
            var items    = new List <PseudoLRUCache <string> .CacheItem>();

            for (var i = 1; i <= capacity; i++)
            {
                items.Add(cache.Add(i.ToString()));
                var notCachedCount = items.Count(item => !item.IsCached);
                Assert.IsTrue(notCachedCount == 0, $"{notCachedCount} items are not cached after adding {i}.");
            }
        }
        public void ResizingFullCacheAboveSizeEvictsNoItems()
        {
            var capacity = 100;
            var cache    = new PseudoLRUCache <string>(capacity);
            var items    = new List <PseudoLRUCache <string> .CacheItem>();

            for (var i = 1; i <= capacity; i++)
            {
                items.Add(cache.Add(i.ToString()));
            }

            Assert.IsTrue(cache.IsFull, "Before Resize, cache should be full");
            cache.Resize(110);
            Assert.IsFalse(cache.IsFull, "After Resize, cache should NOT be full");
            var actualEjectedCount   = items.Count(i => !i.IsCached);
            var expectedEjectedCount = 0;

            Assert.AreEqual(expectedEjectedCount, actualEjectedCount, $"Should have ejected {expectedEjectedCount}, instead {actualEjectedCount}");
        }
        public void OneItemEvictedWhenAddingToFullCache()
        {
            var capacity = 100;
            var cache    = new PseudoLRUCache <string>(capacity);
            var items    = new List <PseudoLRUCache <string> .CacheItem>();

            for (var i = 1; i <= capacity + 1; i++)
            {
                items.Add(cache.Add(i.ToString()));
                var notCachedCount = items.Count(item => !item.IsCached);
                if (i <= capacity)
                {
                    Assert.IsFalse(cache.IsEmpty, $"Cache thinks it is empty when it is not, for i = {i}.");
                    Assert.AreEqual(i >= capacity, cache.IsFull, $"Cache IsFull = {cache.IsFull} for i = {i}.");
                    Assert.IsTrue(notCachedCount == 0, $"{notCachedCount} items are not cached after adding {i} when cache is NOT FULL.");
                }
                else
                {
                    Assert.IsTrue(cache.IsFull, $"Cache thinks it is not full when i = {i}.");
                    Assert.IsTrue(notCachedCount == 1, $"{notCachedCount} items are not cached after adding {i} when cache IS FULL.");
                }
            }
        }