public void GetItem_OfIntWhenInitialRetrievalTimesOut_ReturnsDefaultValueOfZero()
        {
            // Arrange
            InMemoryItemCache <int> cache = new InMemoryItemCache <int>(
                new NonCloningClonerFactory <int>(),
                null,
                () => { TimeDelay.WaitFor(200); return(125); },
                TimeSpan.FromMinutes(2),
                50, 50);
            int actualResult;
            int expectedResult = 0;

            // Act
            Task <int> task1 = new Task <int>(() => { return(cache.GetItem()); });
            Task <int> task2 = new Task <int>(() => { TimeDelay.WaitFor(50); return(cache.GetItem()); });

            // Start the 2 tasks, with task2 likely to have to wait on task1
            task1.Start();
            task2.Start();
            Task.WaitAll(task1, task2);
            actualResult = task2.Result;

            // Assert
            Assert.AreEqual(expectedResult, actualResult);
        }
        public void GetItem_OfCacheableClassWhenCalledTwice_DoesNotReturnSameInstance()
        {
            // Arrange
            InMemoryItemCache <CacheableClass> cache = new InMemoryItemCache <CacheableClass>(
                null,
                () => { return(new CacheableClass(125)); },
                TimeSpan.FromMilliseconds(100));
            CacheableClass cacheItem1;
            CacheableClass cacheItem2;

            // Act
            cacheItem1 = cache.GetItem();
            cacheItem2 = cache.GetItem();

            // Assert that full, deep cloning is being performed
            Assert.AreNotEqual(cacheItem1, cacheItem2);
            Assert.AreNotEqual(cacheItem1.Child, cacheItem2.Child);
        }
        public void GetItem_OfCacheableClassWhenCalledTwice_CreatesPerfectClone()
        {
            // Arrange
            InMemoryItemCache <CacheableClass> cache = new InMemoryItemCache <CacheableClass>(
                null,
                () => { return(new CacheableClass(125)); },
                TimeSpan.FromMilliseconds(100));
            CacheableClass cacheItem1;
            CacheableClass cacheItem2;

            // Act
            cacheItem1 = cache.GetItem();
            cacheItem2 = cache.GetItem();

            // Assert that the clone worked correctly
            Assert.AreEqual(cacheItem1.GetValue(), cacheItem2.GetValue());
            Assert.AreEqual(cacheItem1.NumberOfCalls, cacheItem2.NumberOfCalls);
            Assert.AreEqual(cacheItem1.CreatedAt, cacheItem2.CreatedAt);
        }
        public void GetItem_OfCacheableStructRequestedMultipleTimesInSuccession_CallsRetrievalDelegateJustOnce()
        {
            // Arrange
            CacheableStruct cacheableStruct           = new CacheableStruct(125);
            InMemoryItemCache <CacheableStruct> cache = new InMemoryItemCache <CacheableStruct>(
                null,
                () => { return(cacheableStruct.GetSelf()); },
                TimeSpan.FromMinutes(2));
            int actualResult;
            int expectedResult = 1;

            // Act
            _            = cache.GetItem();
            _            = cache.GetItem();
            _            = cache.GetItem();
            _            = cache.GetItem();
            actualResult = cacheableStruct.NumberOfGetSelfCalls;

            // Assert
            Assert.AreEqual(expectedResult, actualResult);
        }
        public void Invalidate_OfCacheableClassWhenCalledInvalidatedAndCalledAgain_ReturnsSecondCachedValue()
        {
            // Arrange
            int cachedValue = 100;
            InMemoryItemCache <CacheableClass> cache = new InMemoryItemCache <CacheableClass>(
                null,
                () => { cachedValue += 25; return(new CacheableClass(cachedValue)); },
                TimeSpan.FromMinutes(2));
            CacheableClass cachedClass;
            int            actualResult;
            int            expectedResult = 150;

            // Act
            _ = cache.GetItem();
            cache.Invalidate();
            cachedClass  = cache.GetItem();
            actualResult = cachedClass.GetValue();

            // Assert
            Assert.AreEqual(expectedResult, actualResult);
        }
        public void Invalidate_OfIntWhenCalledInvalidatedAndCalledAgain_ReturnsSecondCachedValue()
        {
            // Arrange
            int cachedValue = 100;
            InMemoryItemCache <int> cache = new InMemoryItemCache <int>(
                new NonCloningClonerFactory <int>(),
                null,
                () => { cachedValue += 25; return(cachedValue); },
                TimeSpan.FromMinutes(2),
                100, 100);
            int actualResult;
            int expectedResult = 150;

            // Act
            _ = cache.GetItem();
            cache.Invalidate();
            actualResult = cache.GetItem();

            // Assert
            Assert.AreEqual(expectedResult, actualResult);
        }
        public void GetItem_OfCacheableClassWhenCacheExpires_CallsRetrievalDelegateAgain()
        {
            // Arrange
            InMemoryItemCache <CacheableClass> cache = new InMemoryItemCache <CacheableClass>(
                null,
                () => { return(new CacheableClass(125)); },
                TimeSpan.FromMilliseconds(100));
            DateTime       initialCreatedAt;
            DateTime       finalCreatedAt;
            CacheableClass cacheItem;

            // Act
            cacheItem        = cache.GetItem();
            initialCreatedAt = cacheItem.CreatedAt;
            // Wait for the cache item to expire and then retry
            TimeDelay.WaitFor(150);
            cacheItem      = cache.GetItem();
            finalCreatedAt = cacheItem.CreatedAt;

            // Assert that the creation values are different
            Assert.AreNotEqual(initialCreatedAt, finalCreatedAt);
        }
        public void GetItem_OfCacheableClassRequestedMultipleTimesInSuccession_CallsRetrievalDelegateJustOnce()
        {
            // Arrange
            InMemoryItemCache <CacheableClass> cache = new InMemoryItemCache <CacheableClass>(
                null,
                () => { return(new CacheableClass(125)); },
                TimeSpan.FromMilliseconds(100));
            DateTime       initialCreatedAt;
            DateTime       finalCreatedAt;
            CacheableClass cacheItem;

            // Act
            cacheItem        = cache.GetItem();
            initialCreatedAt = cacheItem.CreatedAt;
            _              = cache.GetItem();
            _              = cache.GetItem();
            cacheItem      = cache.GetItem();
            finalCreatedAt = cacheItem.CreatedAt;

            // Assert
            Assert.AreEqual(initialCreatedAt, finalCreatedAt);
        }
        public void GetItem_OfCacheableStruct_ReturnsCorrectCachedValue()
        {
            // Arrange
            CacheableStruct cacheableStruct           = new CacheableStruct(125);
            InMemoryItemCache <CacheableStruct> cache = new InMemoryItemCache <CacheableStruct>(
                null,
                () => { return(cacheableStruct); },
                TimeSpan.FromMinutes(2));
            int actualResult;
            int expectedResult = 125;

            // Act
            actualResult = cache.GetItem().GetValue();

            // Assert
            Assert.AreEqual(expectedResult, actualResult);
        }
        public void GetItem_OfInt_ReturnsCorrectCachedValue()
        {
            // Arrange
            InMemoryItemCache <int> cache = new InMemoryItemCache <int>(
                new NonCloningClonerFactory <int>(),
                null,
                () => { return(125); },
                TimeSpan.FromMinutes(2),
                100, 100);
            int actualResult;
            int expectedResult = 125;

            // Act
            actualResult = cache.GetItem();

            // Assert
            Assert.AreEqual(expectedResult, actualResult);
        }
        public void GetItem_OfCacheableClass_ReturnsCorrectCachedValue()
        {
            // Arrange
            InMemoryItemCache <CacheableClass> cache = new InMemoryItemCache <CacheableClass>(
                async() => { return(new CacheableClass(100)); },
                () => { return(new CacheableClass(125)); },
                TimeSpan.FromMinutes(2),
                100, 100);
            CacheableClass cacheItem;
            int            actualResult;
            int            expectedResult = 125;

            // Act
            cacheItem    = cache.GetItem();
            actualResult = cacheItem.GetValue();

            // Assert
            Assert.AreEqual(expectedResult, actualResult);
        }
        public void GetItem_OfCacheableClassWhenInitialRetrievalTimesOut_ReturnsDefaultValueOfNull()
        {
            // Arrange
            InMemoryItemCache <CacheableClass> cache = new InMemoryItemCache <CacheableClass>(
                async() => { await TimeDelay.WaitForAsync(200); return(new CacheableClass(100)); },
                () => { TimeDelay.WaitFor(200); return(new CacheableClass(125)); },
                TimeSpan.FromMinutes(2),
                50, 50);
            CacheableClass cacheItem;

            // Act
            Task <CacheableClass> task1 = new Task <CacheableClass>(() => { return(cache.GetItem()); });
            Task <CacheableClass> task2 = new Task <CacheableClass>(() => { TimeDelay.WaitFor(60); return(cache.GetItem()); });

            // Start the 2 tasks, with task2 likely to have to wait on task1
            task1.Start();
            task2.Start();
            Task.WaitAll(task1, task2);
            cacheItem = task2.Result;

            // Assert
            Assert.IsNull(cacheItem);
        }