public void TestLruPolicy()
        {
            var hundredBytes = new byte[100];
            ICache cache = new MemoryCache(1000, new LruCacheEvictionPolicy(), 900, 700);
            for(int i = 0; i < 9;i++)
            {
                cache.Insert("Entry " + i, hundredBytes, CachePriority.Normal);
                Thread.Sleep(20);
            }
            // Cache size is now 900 bytes

            cache.Insert("Entry 10", hundredBytes, CachePriority.Normal);
            Assert.IsFalse(cache.ContainsKey("Entry 0"));
            Assert.IsFalse(cache.ContainsKey("Entry 1"));
            Assert.IsTrue(cache.ContainsKey("Entry 2"));
            Assert.IsTrue(cache.ContainsKey("Entry 10"));
            
            // Cache size should now be 800 bytes
            cache.Lookup("Entry 2");
            cache.Insert("Entry 11", hundredBytes, CachePriority.Normal);
            cache.Insert("Entry 12", hundredBytes, CachePriority.Normal); // This insert should force eviction
            Assert.IsFalse(cache.ContainsKey("Entry 0")); // was previously evicted
            Assert.IsFalse(cache.ContainsKey("Entry 1")); // was previously evicted
            Assert.IsTrue(cache.ContainsKey("Entry 2"), "Expected Entry2 to remain in cache after second eviction"); // Won't be evicted due to recent access
            Assert.IsFalse(cache.ContainsKey("Entry 3")); // newly evicted
            Assert.IsFalse(cache.ContainsKey("Entry 4")); // newly evicted
            Assert.IsTrue(cache.ContainsKey("Entry 5"), "Expected Entry 5 to remain in cache after second eviction"); // shouldn't be evicted
            Assert.IsTrue(cache.ContainsKey("Entry 11"), "Expected Entry 11 to remain in cache after second eviction"); // should have been added before eviction
            Assert.IsTrue(cache.ContainsKey("Entry 12"), "Expected Entry 12 to be added to cache after second eviction"); // should have been added after eviction

        }
        public void TestQueryCacheInsertAndInvalidation()
        {
            var testCache = new MemoryCache(8192, new LruCacheEvictionPolicy());
            var client = GetClient(testCache);
            var storeName = "Client.TestQueryCacheInvalidation_" + DateTime.Now.Ticks;
            client.CreateStore(storeName);
            const string query = "SELECT ?s WHERE { ?s ?p ?o }";
            client.ExecuteQuery(storeName, query);
            var cacheKey = storeName + "_" + query.GetHashCode();
            Assert.IsTrue(testCache.ContainsKey(cacheKey));
            testCache.Insert(cacheKey, new CachedQueryResult(DateTime.UtcNow, "This is a test"), CachePriority.Normal);
            var resultStream = client.ExecuteQuery(storeName, query);
            string result;
            using (var resultReader = new StreamReader(resultStream))
            {
                result = resultReader.ReadToEnd();
            }
            Assert.AreEqual("This is a test", result);

            client.ExecuteTransaction(storeName, null, null,
                                      "<http://example.org/s> <http://example.org/p> <http://example.org/o> .",
                                      Constants.DefaultGraphUri, true);
            resultStream = client.ExecuteQuery(storeName, query);
            using (var resultReader = new StreamReader(resultStream))
            {
                result = resultReader.ReadToEnd();
            }
            // We should not get the test result we inserted into the cache this time.
            Assert.AreNotEqual("This is a test", result);

            // The cache should have been updated with the result received from the server.
            var cacheResult = testCache.Lookup<CachedQueryResult>(cacheKey);
            Assert.AreEqual(result, cacheResult.Result);
        }
        public void TestLruPriority()
        {
            var hundredBytes = new byte[100];
            ICache cache = new MemoryCache(1000, new LruCacheEvictionPolicy(), 900, 700);
            for (int i = 0; i < 9; i++)
            {
                cache.Insert("Entry " + i, hundredBytes, i%2 == 0 ? CachePriority.High : CachePriority.Normal);
                Thread.Sleep(20);
            }
            // Cache size is now 900 bytes

            cache.Insert("Entry 10", hundredBytes, CachePriority.High);
            Assert.IsTrue(cache.ContainsKey("Entry 0"), "Expected Entry 0 to remain after first eviction");
            Assert.IsFalse(cache.ContainsKey("Entry 1"), "Expected Entry 1 to be removed after first eviction");
            Assert.IsTrue(cache.ContainsKey("Entry 2"), "Expected Entry 2 to remain after first eviction");
            Assert.IsFalse(cache.ContainsKey("Entry 3"), "Expected Entry 3 to be removed after first eviction");
            Assert.IsTrue(cache.ContainsKey("Entry 4"));
            Assert.IsTrue(cache.ContainsKey("Entry 5"));
            Assert.IsTrue(cache.ContainsKey("Entry 10"));

            cache.Insert("Entry 11", hundredBytes, CachePriority.High);
            cache.Insert("Entry 12", hundredBytes, CachePriority.High);
            Assert.IsFalse(cache.ContainsKey("Entry 5"), "Expected Entry 5 to be removed after second eviction");
            Assert.IsFalse(cache.ContainsKey("Entry 7"), "Expected Entry 7 to be removed after second eviction");

            Assert.IsNotNull(cache.Lookup("Entry 2"));
            cache.Insert("Entry 13", hundredBytes, CachePriority.High);
            cache.Insert("Entry 14", hundredBytes, CachePriority.High);
            Assert.IsFalse(cache.ContainsKey("Entry 0")); // Should now start evicting high priority items
            Assert.IsTrue(cache.ContainsKey("Entry 2"), "Expected Entry 2 to remain after third eviction due to recent access");
            Assert.IsFalse(cache.ContainsKey("Entry 4"), "Expected Entry 4 to be removed after third eviction"); 
        }
        public void TestTwoLevelCache()
        {
            var hundredBytes = new byte[100];
            ICache primary = new MemoryCache(500, new LruCacheEvictionPolicy(), 400, 300);
            ICache secondary = new MemoryCache(1000, new LruCacheEvictionPolicy(), 900, 700);
            ICache cache = new TwoLevelCache(primary, secondary);

            for (int i = 0; i < 9; i++)
            {
                cache.Insert("Entry " + i, hundredBytes, CachePriority.Normal);
                Thread.Sleep(20);
            }

            for(int i = 0; i < 9; i++)
            {
                Assert.IsTrue(secondary.ContainsKey("Entry " + i), "Expected secondary cache to contain Entry {0} after initialization");
                if (i < 5) Assert.IsFalse(primary.ContainsKey("Entry " + i), "Expected primary cache to NOT contain Entry {0} after initialization", i);
                else Assert.IsTrue(primary.ContainsKey("Entry " + i), "Expected primary cache to contain Entry {0} after initialization", i);
            }

            cache.Insert("Entry 10", hundredBytes, CachePriority.Normal);
            Assert.IsFalse(cache.ContainsKey("Entry 0"));
            Assert.IsFalse(cache.ContainsKey("Entry 1"));
            Assert.IsTrue(cache.ContainsKey("Entry 2"));
            Assert.IsTrue(cache.ContainsKey("Entry 10"));
            Assert.IsTrue(primary.ContainsKey("Entry 10"));
            Assert.IsTrue(secondary.ContainsKey("Entry 10"));
        }