@Test
  public void testPositionUpdateInGhostList() {
    // Cache has 4 entries; 2 for LFU and 2 for MFU
    // key is considered as MFU, if its accessCount > 1
    mCache =
        createDummyAdaptiveCountingMemoryCache(
            mParamsSupplier,
            mCacheTrimStrategy,
            mValueDescriptor,
            100,
            1,
            2,
            initialLFUCacheFractionPromil);

    // insert item1 to LFU
    CloseableReference<Integer> originalRef1 = newReference(10);
    CloseableReference<Integer> valueRef1a = mCache.cache(KEYS[1], originalRef1);
    originalRef1.close();
    valueRef1a.close();
    assertLFUExclusivelyOwned(KEYS[1], 10);
    assertGhostListsValidSize();

    // insert item2 to LFU
    CloseableReference<Integer> originalRef2 = newReference(20);
    CloseableReference<Integer> valueRef2a = mCache.cache(KEYS[2], originalRef2);
    originalRef2.close();
    valueRef2a.close();
    assertLFUExclusivelyOwned(KEYS[1], 10);
    assertLFUExclusivelyOwned(KEYS[2], 20);
    assertGhostListsValidSize();

    // insert item3 to ghost list, this will result in evicting item1 from the LFU and insert it to
    // the LFU ghost list.
    CloseableReference<Integer> originalRef3 = newReference(30);
    CloseableReference<Integer> valueRef3a = mCache.cache(KEYS[3], originalRef3);
    originalRef3.close();
    valueRef3a.close();
    assertLFUExclusivelyOwned(KEYS[2], 20);
    assertLFUExclusivelyOwned(KEYS[3], 30);
    assertKeyIsInLFUGhostList(KEYS[1], 1);
    assertGhostListsValidSize();

    // insert item4 to LFU, this will result in evicting item2 from the LFU and inset it to the LFU
    // ghost list.
    CloseableReference<Integer> originalRef4 = newReference(40);
    CloseableReference<Integer> valueRef4a = mCache.cache(KEYS[4], originalRef4);
    originalRef4.close();
    valueRef4a.close();
    assertLFUExclusivelyOwned(KEYS[3], 30);
    assertLFUExclusivelyOwned(KEYS[4], 40);
    assertKeyIsInLFUGhostList(KEYS[1], 1);
    assertKeyIsInLFUGhostList(KEYS[2], 1);
    assertGhostListsValidSize();

    // try to access item1 (which is already evicted).
    CloseableReference<Integer> valueRef1b = mCache.get(KEYS[1]);
    assertNull(valueRef1b);
    assertKeyIsInLFUGhostList(KEYS[1], 2);
    assertGhostListsValidSize();

    // insert item5 to LFU, this will result in evicting item3 from LFU and insert it to the LFU
    // ghost list
    CloseableReference<Integer> originalRef5 = newReference(50);
    CloseableReference<Integer> valueRef5a = mCache.cache(KEYS[5], originalRef5);
    originalRef5.close();
    valueRef5a.close();

    // make sure item2 is removed from LFU ghost list and not item1 (since they have replaced
    // their positions in the ghost list)
    assertGhostListsValidSize();
    assertLFUExclusivelyOwned(KEYS[4], 40);
    assertLFUExclusivelyOwned(KEYS[5], 50);
    assertKeyIsInLFUGhostList(KEYS[1], 2);
    assertKeyIsInLFUGhostList(KEYS[3], 1);
    assertKeyIsNotInLFUGhostList(KEYS[2]);
  }
This test checks that the ghost list is actually an LRU list. It checks if the position of the
keys in the LFU ghost list is updated when trying to access them after being evicted (but they
were found it in the ghost list). ExpectedL the accessed key will be moved to the youngest
position in the ghost list.
imagepipeline-base/src/test/java/com/facebook/imagepipeline/cache/AbstractAdaptiveCountingMemoryCacheTest.java