public void TestUpdatesCacheParams()
        {
            CloseableReference <int> originalRef = NewReference(700);
            CloseableReference <int> cachedRef   = _cache.Cache(KEYS[2], originalRef);

            originalRef.Dispose();
            cachedRef.Dispose();

            _cache.Get(KEY);
            Assert.AreEqual(1, _paramsSupplier.GetCallCount);

            _cache.Get(KEY);
            Assert.AreEqual(1, _paramsSupplier.GetCallCount);
            _cache.Get(KEY);
            Assert.AreEqual(1, _paramsSupplier.GetCallCount);

            AssertTotalSize(1, 700);
            AssertExclusivelyOwnedSize(1, 700);

            _params = new MemoryCacheParams(
                500 /* cache max size */,
                CACHE_MAX_COUNT,
                CACHE_EVICTION_QUEUE_MAX_SIZE,
                CACHE_EVICTION_QUEUE_MAX_COUNT,
                CACHE_ENTRY_MAX_SIZE);
            _paramsSupplier = new MockSupplier <MemoryCacheParams>(_params);
            _cache.ForceUpdateCacheParams(_paramsSupplier);

            _cache.Get(KEY);
            Assert.AreEqual(1, _paramsSupplier.GetCallCount);

            AssertTotalSize(0, 0);
            AssertExclusivelyOwnedSize(0, 0);
            Assert.IsTrue(_releaseValues.Contains(700));
        }
        public void Initialize()
        {
            _releaseCallCount = 0;
            _releaseValues    = new List <int>();
            _releaser         = new ResourceReleaserImpl <int>(
                v =>
            {
                ++_releaseCallCount;
                _releaseValues.Add(v);
            });

            _onExclusivityChangedCallCount = 0;
            _isExclusive        = null;
            _entryStateObserver = new EntryStateObserverImpl <string>(
                (v, b) =>
            {
                ++_onExclusivityChangedCallCount;
                _isExclusive = b;
            });

            _cacheTrimStrategy = new CacheTrimStrategyImpl(v => _trimRatio);
            _valueDescriptor   = new ValueDescriptorImpl <int>(v => v);
            _params            = new MemoryCacheParams(
                CACHE_MAX_SIZE,
                CACHE_MAX_COUNT,
                CACHE_EVICTION_QUEUE_MAX_SIZE,
                CACHE_EVICTION_QUEUE_MAX_COUNT,
                CACHE_ENTRY_MAX_SIZE);

            _paramsSupplier        = new MockSupplier <MemoryCacheParams>(_params);
            _platformBitmapFactory = new MockPlatformBitmapFactory();
            _bitmap          = new SoftwareBitmap(BitmapPixelFormat.Rgba8, 50, 50);
            _bitmapReference = CloseableReference <SoftwareBitmap> .of(
                _bitmap, BITMAP_RESOURCE_RELEASER);

            _cache = new CountingMemoryCache <string, int>(
                _valueDescriptor,
                _cacheTrimStrategy,
                _paramsSupplier,
                _platformBitmapFactory,
                true);
        }
        public void TestTrimming()
        {
            double memoryTrimType = MemoryTrimType.OnCloseToDalvikHeapLimit;

            _params         = new MemoryCacheParams(1100, 10, 1100, 10, 110);
            _paramsSupplier = new MockSupplier <MemoryCacheParams>(_params);
            _cache.ForceUpdateCacheParams(_paramsSupplier);

            // Create original references
            CloseableReference <int>[] originalRefs = new CloseableReference <int> [10];
            for (int i = 0; i < 10; i++)
            {
                originalRefs[i] = NewReference(100 + i);
            }

            // Cache items & close the original references
            CloseableReference <int>[] cachedRefs = new CloseableReference <int> [10];
            for (int i = 0; i < 10; i++)
            {
                cachedRefs[i] = _cache.Cache(KEYS[i], originalRefs[i]);
                originalRefs[i].Dispose();
            }

            // Cache should keep alive the items until evicted
            Assert.AreEqual(0, _releaseCallCount);

            // Trimming cannot evict shared entries
            _trimRatio = 1.0;
            _cache.Trim(memoryTrimType);
            AssertSharedWithCount(KEYS[0], 100, 1);
            AssertSharedWithCount(KEYS[1], 101, 1);
            AssertSharedWithCount(KEYS[2], 102, 1);
            AssertSharedWithCount(KEYS[3], 103, 1);
            AssertSharedWithCount(KEYS[4], 104, 1);
            AssertSharedWithCount(KEYS[5], 105, 1);
            AssertSharedWithCount(KEYS[6], 106, 1);
            AssertSharedWithCount(KEYS[7], 107, 1);
            AssertSharedWithCount(KEYS[8], 108, 1);
            AssertSharedWithCount(KEYS[9], 109, 1);
            AssertTotalSize(10, 1045);
            AssertExclusivelyOwnedSize(0, 0);

            // Close 7 client references
            cachedRefs[8].Dispose();
            cachedRefs[2].Dispose();
            cachedRefs[7].Dispose();
            cachedRefs[3].Dispose();
            cachedRefs[6].Dispose();
            cachedRefs[4].Dispose();
            cachedRefs[5].Dispose();
            AssertSharedWithCount(KEYS[0], 100, 1);
            AssertSharedWithCount(KEYS[1], 101, 1);
            AssertSharedWithCount(KEYS[9], 109, 1);
            AssertExclusivelyOwned(KEYS[8], 108);
            AssertExclusivelyOwned(KEYS[2], 102);
            AssertExclusivelyOwned(KEYS[7], 107);
            AssertExclusivelyOwned(KEYS[3], 103);
            AssertExclusivelyOwned(KEYS[6], 106);
            AssertExclusivelyOwned(KEYS[4], 104);
            AssertExclusivelyOwned(KEYS[5], 105);
            AssertTotalSize(10, 1045);
            AssertExclusivelyOwnedSize(7, 735);

            // Trim cache by 45%. This means that out of total of 1045 bytes cached, 574 should remain.
            // 310 bytes is used by the clients, which leaves 264 for the exclusively owned items.
            // Only the two most recent exclusively owned items fit, and they occupy 209 bytes.
            _trimRatio = 0.45;
            _cache.Trim(memoryTrimType);
            AssertSharedWithCount(KEYS[0], 100, 1);
            AssertSharedWithCount(KEYS[1], 101, 1);
            AssertSharedWithCount(KEYS[9], 109, 1);
            AssertExclusivelyOwned(KEYS[4], 104);
            AssertExclusivelyOwned(KEYS[5], 105);
            AssertNotCached(KEYS[8], 108);
            AssertNotCached(KEYS[2], 102);
            AssertNotCached(KEYS[7], 107);
            AssertNotCached(KEYS[3], 103);
            AssertNotCached(KEYS[6], 106);
            AssertTotalSize(5, 519);
            AssertExclusivelyOwnedSize(2, 209);
            Assert.IsTrue(_releaseValues.Contains(108));
            Assert.IsTrue(_releaseValues.Contains(102));
            Assert.IsTrue(_releaseValues.Contains(107));
            Assert.IsTrue(_releaseValues.Contains(103));
            Assert.IsTrue(_releaseValues.Contains(106));

            // Full trim. All exclusively owned items should be evicted.
            _trimRatio = 1.0;
            _cache.Trim(memoryTrimType);
            AssertSharedWithCount(KEYS[0], 100, 1);
            AssertSharedWithCount(KEYS[1], 101, 1);
            AssertSharedWithCount(KEYS[9], 109, 1);
            AssertNotCached(KEYS[8], 108);
            AssertNotCached(KEYS[2], 102);
            AssertNotCached(KEYS[7], 107);
            AssertNotCached(KEYS[3], 103);
            AssertNotCached(KEYS[6], 106);
            AssertNotCached(KEYS[6], 104);
            AssertNotCached(KEYS[6], 105);
            AssertTotalSize(3, 310);
            AssertExclusivelyOwnedSize(0, 0);
            Assert.IsTrue(_releaseValues.Contains(104));
            Assert.IsTrue(_releaseValues.Contains(105));
        }