public void testNewEntry() { for (CacheBuilder<Object, Object> builder : allEntryTypeMakers()) { LocalCache<Object, Object> map = makeLocalCache(builder); Object keyOne = new Object(); Object valueOne = new Object(); int hashOne = map.hash(keyOne); ReferenceEntry<Object, Object> entryOne = map.newEntry(keyOne, hashOne, null); ValueReference<Object, Object> valueRefOne = map.newValueReference(entryOne, valueOne, 1); assertSame(valueOne, valueRefOne.get()); entryOne.setValueReference(valueRefOne); assertSame(keyOne, entryOne.getKey()); assertEquals(hashOne, entryOne.getHash()); assertNull(entryOne.getNext()); assertSame(valueRefOne, entryOne.getValueReference()); Object keyTwo = new Object(); Object valueTwo = new Object(); int hashTwo = map.hash(keyTwo); ReferenceEntry<Object, Object> entryTwo = map.newEntry(keyTwo, hashTwo, entryOne); ValueReference<Object, Object> valueRefTwo = map.newValueReference(entryTwo, valueTwo, 1); assertSame(valueTwo, valueRefTwo.get()); entryTwo.setValueReference(valueRefTwo); assertSame(keyTwo, entryTwo.getKey()); assertEquals(hashTwo, entryTwo.getHash()); assertSame(entryOne, entryTwo.getNext()); assertSame(valueRefTwo, entryTwo.getValueReference()); } }
public void testRecordWrite() { for (CacheBuilder<Object, Object> builder : allEvictingMakers()) { LocalCache<Object, Object> map = makeLocalCache(builder.concurrencyLevel(1)); Segment<Object, Object> segment = map.segments[0]; List<ReferenceEntry<Object, Object>> writeOrder = Lists.newLinkedList(); Object value = new Object(); ReferenceEntry<Object, Object> entry = createDummyEntry(key, hash, value, null); checkEvictionQueues(map, segment, writeOrder, writeOrder); checkExpirationTimes(map); checkEvictionQueues(map, segment, writeOrder, writeOrder); checkExpirationTimes(map);
public void testDrainKeyReferenceQueueOnWrite() { for (CacheBuilder<Object, Object> builder : allKeyValueStrengthMakers()) { LocalCache<Object, Object> map = makeLocalCache(builder.concurrencyLevel(1)); if (map.usesKeyReferences()) { Segment<Object, Object> segment = map.segments[0]; Object keyOne = new Object(); int hashOne = map.hash(keyOne); Object valueOne = new Object(); Object keyTwo = new Object(); Object valueTwo = new Object(); map.put(keyOne, valueOne); ReferenceEntry<Object, Object> entry = segment.getEntry(keyOne, hashOne); @SuppressWarnings("unchecked") Reference<Object> reference = (Reference) entry; reference.enqueue(); map.put(keyTwo, valueTwo); assertFalse(map.containsKey(keyOne)); assertFalse(map.containsValue(valueOne)); assertNull(map.get(keyOne)); assertEquals(1, map.size()); assertNull(segment.keyReferenceQueue.poll()); } } }
public void testSetExpireAfterAccess() { long duration = 42; TimeUnit unit = TimeUnit.SECONDS; LocalCache<Object, Object> map = makeLocalCache(createCacheBuilder().expireAfterAccess(duration, unit)); assertEquals(unit.toNanos(duration), map.expireAfterAccessNanos); }
public void testDefaults() { LocalCache<Object, Object> map = makeLocalCache(createCacheBuilder()); assertSame(Strength.STRONG, map.keyStrength); assertSame(Strength.STRONG, map.valueStrength); assertSame(map.keyStrength.defaultEquivalence(), map.keyEquivalence); assertSame(map.valueStrength.defaultEquivalence(), map.valueEquivalence); assertEquals(0, map.expireAfterAccessNanos); assertEquals(0, map.expireAfterWriteNanos); assertEquals(0, map.refreshNanos); assertEquals(CacheBuilder.UNSET_INT, map.maxWeight); assertSame(EntryFactory.STRONG, map.entryFactory); assertSame(CacheBuilder.NullListener.INSTANCE, map.removalListener); assertSame(DISCARDING_QUEUE, map.removalNotificationQueue); assertSame(NULL_TICKER, map.ticker); assertEquals(4, map.concurrencyLevel); // concurrency level assertThat(map.segments).hasLength(4); // initial capacity / concurrency level assertEquals(16 / map.segments.length, map.segments[0].table.length()); assertFalse(map.evictsBySize()); assertFalse(map.expires()); assertFalse(map.expiresAfterWrite()); assertFalse(map.expiresAfterAccess()); assertFalse(map.refreshes()); }
@AndroidIncompatible // Perhaps emulator clock does not update between the two get() calls? public void testComputeExpiredEntry() throws ExecutionException { CacheBuilder<Object, Object> builder = createCacheBuilder().expireAfterWrite(1, TimeUnit.NANOSECONDS); CountingLoader loader = new CountingLoader(); LocalCache<Object, Object> map = makeLocalCache(builder); assertEquals(0, loader.getCount()); Object key = new Object(); Object one = map.get(key, loader); assertEquals(1, loader.getCount()); Object two = map.get(key, loader); assertNotSame(one, two); assertEquals(2, loader.getCount()); }
public void testRemovalListener_replaced() { QueuingRemovalListener<Object, Object> listener = queuingRemovalListener(); LocalCache<Object, Object> map = makeLocalCache(createCacheBuilder().removalListener(listener)); assertTrue(listener.isEmpty()); Object one = new Object(); Object two = new Object(); Object three = new Object(); Object four = new Object(); Object five = new Object(); Object six = new Object(); map.put(one, two); map.put(one, three); assertNotified(listener, one, two, RemovalCause.REPLACED); Map<Object, Object> newMap = ImmutableMap.of(one, four); map.putAll(newMap); assertNotified(listener, one, three, RemovalCause.REPLACED); map.replace(one, five); assertNotified(listener, one, four, RemovalCause.REPLACED); map.replace(one, five, six); assertNotified(listener, one, five, RemovalCause.REPLACED); }
public void testRecordReadOnGet() { for (CacheBuilder<Object, Object> builder : allEvictingMakers()) { LocalCache<Object, Object> map = makeLocalCache(builder.concurrencyLevel(1)); Segment<Object, Object> segment = map.segments[0]; List<ReferenceEntry<Object, Object>> writeOrder = Lists.newLinkedList(); checkEvictionQueues(map, segment, readOrder, writeOrder); checkExpirationTimes(map); assertTrue(segment.recencyQueue.isEmpty()); reads.add(entry); i.remove(); assertTrue(segment.recencyQueue.size() <= DRAIN_THRESHOLD); checkAndDrainRecencyQueue(map, segment, reads.subList(undrainedIndex, reads.size())); readOrder.addAll(reads); checkEvictionQueues(map, segment, readOrder, writeOrder); checkExpirationTimes(map);
public void testRemoveEntry() { LocalCache<Object, Object> map = makeLocalCache( createCacheBuilder() .concurrencyLevel(1) .initialCapacity(1) .maximumSize(SMALL_MAX_SIZE) .expireAfterWrite(99999, SECONDS) .removalListener(countingRemovalListener())); Segment<Object, Object> segment = map.segments[0]; AtomicReferenceArray<ReferenceEntry<Object, Object>> table = segment.table; assertEquals(1, table.length()); Object key = new Object(); Object value = new Object(); int hash = map.hash(key); DummyEntry<Object, Object> entry = createDummyEntry(key, hash, value, null); // remove absent assertFalse(segment.removeEntry(entry, hash, RemovalCause.COLLECTED)); // remove live segment.recordWrite(entry, 1, map.ticker.read()); table.set(0, entry); segment.count = 1; assertTrue(segment.removeEntry(entry, hash, RemovalCause.COLLECTED)); assertNotificationEnqueued(map, key, value, hash); assertTrue(map.removalNotificationQueue.isEmpty()); assertFalse(segment.accessQueue.contains(entry)); assertFalse(segment.writeQueue.contains(entry)); assertEquals(0, segment.count); assertNull(table.get(0)); }
public void testDrainRecencyQueueOnWrite() { for (CacheBuilder<Object, Object> builder : allEvictingMakers()) { LocalCache<Object, Object> map = makeLocalCache(builder.concurrencyLevel(1)); Segment<Object, Object> segment = map.segments[0]; if (segment.recencyQueue != DISCARDING_QUEUE) { Object keyOne = new Object(); Object valueOne = new Object(); Object keyTwo = new Object(); Object valueTwo = new Object(); map.put(keyOne, valueOne); assertTrue(segment.recencyQueue.isEmpty()); for (int i = 0; i < DRAIN_THRESHOLD / 2; i++) { map.get(keyOne); } assertFalse(segment.recencyQueue.isEmpty()); map.put(keyTwo, valueTwo); assertTrue(segment.recencyQueue.isEmpty()); } } }
public void testExpand() { LocalCache<Object, Object> map = makeLocalCache(createCacheBuilder().concurrencyLevel(1).initialCapacity(1)); Segment<Object, Object> segment = map.segments[0]; assertEquals(1, segment.table.length()); segment.count = originalCount; ImmutableMap<Object, Object> originalMap = ImmutableMap.copyOf(map); assertEquals(originalCount, originalMap.size()); assertEquals(originalMap, map); segment.expand(); assertEquals(i, segment.table.length()); assertEquals(originalCount, countLiveEntries(map, 0)); assertEquals(originalCount, segment.count); assertEquals(originalMap, map);
assertEquals(1, one.size()); assertFalse(one.asMap().isEmpty()); LocalManualCache<Object, Object> two = SerializableTester.reserialize(one); assertEquals(0, two.size()); assertTrue(two.asMap().isEmpty()); assertEquals(localCacheOne.keyStrength, localCacheTwo.keyStrength); assertEquals(localCacheOne.keyStrength, localCacheTwo.keyStrength); assertEquals(localCacheOne.valueEquivalence, localCacheTwo.valueEquivalence); assertEquals(localCacheOne.valueEquivalence, localCacheTwo.valueEquivalence); assertEquals(localCacheOne.maxWeight, localCacheTwo.maxWeight); assertEquals(localCacheOne.weigher, localCacheTwo.weigher); assertEquals(localCacheOne.expireAfterAccessNanos, localCacheTwo.expireAfterAccessNanos); assertEquals(localCacheOne.expireAfterWriteNanos, localCacheTwo.expireAfterWriteNanos); assertEquals(localCacheOne.removalListener, localCacheTwo.removalListener); assertEquals(localCacheOne.ticker, localCacheTwo.ticker); assertEquals(localCacheTwo.keyStrength, localCacheThree.keyStrength); assertEquals(localCacheTwo.keyStrength, localCacheThree.keyStrength); assertEquals(localCacheTwo.valueEquivalence, localCacheThree.valueEquivalence); assertEquals(localCacheTwo.valueEquivalence, localCacheThree.valueEquivalence); assertEquals(localCacheTwo.maxWeight, localCacheThree.maxWeight); assertEquals(localCacheTwo.weigher, localCacheThree.weigher); assertEquals(localCacheTwo.expireAfterAccessNanos, localCacheThree.expireAfterAccessNanos); assertEquals(localCacheTwo.expireAfterWriteNanos, localCacheThree.expireAfterWriteNanos); assertEquals(localCacheTwo.removalListener, localCacheThree.removalListener); assertEquals(localCacheTwo.ticker, localCacheThree.ticker);
public void testSegmentRefresh_duplicate() throws ExecutionException { LocalCache<Object, Object> map = makeLocalCache(createCacheBuilder().concurrencyLevel(1)); Segment<Object, Object> segment = map.segments[0]; Object key = new Object(); int hash = map.hash(key); AtomicReferenceArray<ReferenceEntry<Object, Object>> table = segment.table; int index = hash & (table.length() - 1); // already loading DummyEntry<Object, Object> entry = DummyEntry.create(key, hash, null); DummyValueReference<Object, Object> valueRef = DummyValueReference.create(null); valueRef.setLoading(true); entry.setValueReference(valueRef); table.set(index, entry); assertNull(segment.refresh(key, hash, identityLoader(), false)); }
private static <K, V> void assertSameEntries( List<ReferenceEntry<K, V>> expectedEntries, List<ReferenceEntry<K, V>> actualEntries) { int size = expectedEntries.size(); assertEquals(size, actualEntries.size()); for (int i = 0; i < size; i++) { ReferenceEntry<K, V> expectedEntry = expectedEntries.get(i); ReferenceEntry<K, V> actualEntry = actualEntries.get(i); assertSame(expectedEntry.getKey(), actualEntry.getKey()); assertSame(expectedEntry.getValueReference().get(), actualEntry.getValueReference().get()); } }
/** * Returns an iterable containing all combinations of maximumSize, expireAfterAccess/Write, * weakKeys and weak/softValues. */ @SuppressWarnings("unchecked") // varargs private static Iterable<CacheBuilder<Object, Object>> allEntryTypeMakers() { List<CacheBuilder<Object, Object>> result = newArrayList(allKeyValueStrengthMakers()); for (CacheBuilder<Object, Object> builder : allKeyValueStrengthMakers()) { result.add(builder.maximumSize(SMALL_MAX_SIZE)); } for (CacheBuilder<Object, Object> builder : allKeyValueStrengthMakers()) { result.add(builder.expireAfterAccess(99999, SECONDS)); } for (CacheBuilder<Object, Object> builder : allKeyValueStrengthMakers()) { result.add(builder.expireAfterWrite(99999, SECONDS)); } for (CacheBuilder<Object, Object> builder : allKeyValueStrengthMakers()) { result.add(builder.maximumSize(SMALL_MAX_SIZE).expireAfterAccess(99999, SECONDS)); } for (CacheBuilder<Object, Object> builder : allKeyValueStrengthMakers()) { result.add(builder.maximumSize(SMALL_MAX_SIZE).expireAfterWrite(99999, SECONDS)); } return result; }
public void testPutCausesExpansion() { for (int count = 1; count <= 100; count++) { LocalCache<Object, Object> map = makeLocalCache(createCacheBuilder().concurrencyLevel(1).initialCapacity(1)); Segment<Object, Object> segment = map.segments[0]; assertEquals(1, segment.table.length()); for (int i = 0; i < count; i++) { Object key = new Object(); Object value = new Object(); segment.put(key, key.hashCode(), value, true); } assertEquals(count, segment.count); assertTrue(count <= segment.threshold); assertTrue(count <= (segment.table.length() * 3 / 4)); assertTrue(count > (segment.table.length() * 3 / 8)); } }
public void testRemovalListener_size() { QueuingRemovalListener<Object, Object> listener = queuingRemovalListener(); LocalCache<Object, Object> map = makeLocalCache( createCacheBuilder().concurrencyLevel(1).maximumSize(2).removalListener(listener)); assertTrue(listener.isEmpty()); Object one = new Object(); Object two = new Object(); Object three = new Object(); Object four = new Object(); map.put(one, two); map.put(two, three); assertTrue(listener.isEmpty()); map.put(three, four); assertNotified(listener, one, two, RemovalCause.SIZE); assertTrue(listener.isEmpty()); }
public void testComputePartiallyCollectedKey() throws ExecutionException { CacheBuilder<Object, Object> builder = createCacheBuilder().concurrencyLevel(1); CountingLoader loader = new CountingLoader(); LocalCache<Object, Object> map = makeLocalCache(builder); Segment<Object, Object> segment = map.segments[0]; AtomicReferenceArray<ReferenceEntry<Object, Object>> table = segment.table; assertEquals(0, loader.getCount()); Object key = new Object(); int hash = map.hash(key); Object value = new Object(); int index = hash & (table.length() - 1); DummyEntry<Object, Object> entry = DummyEntry.create(key, hash, null); DummyValueReference<Object, Object> valueRef = DummyValueReference.create(value); entry.setValueReference(valueRef); table.set(index, entry); segment.count++; assertSame(value, map.get(key, loader)); assertEquals(0, loader.getCount()); assertEquals(1, segment.count); entry.clearKey(); assertNotSame(value, map.get(key, loader)); assertEquals(1, loader.getCount()); assertEquals(2, segment.count); }
public void testRecordReadOnCompute() throws ExecutionException { CountingLoader loader = new CountingLoader(); for (CacheBuilder<Object, Object> builder : allEvictingMakers()) { LocalCache<Object, Object> map = makeLocalCache(builder.concurrencyLevel(1)); Segment<Object, Object> segment = map.segments[0]; List<ReferenceEntry<Object, Object>> writeOrder = Lists.newLinkedList(); checkEvictionQueues(map, segment, readOrder, writeOrder); checkExpirationTimes(map); assertTrue(segment.recencyQueue.isEmpty()); reads.add(entry); i.remove(); assertTrue(segment.recencyQueue.size() <= DRAIN_THRESHOLD); checkAndDrainRecencyQueue(map, segment, reads.subList(undrainedIndex, reads.size())); readOrder.addAll(reads); checkEvictionQueues(map, segment, readOrder, writeOrder); checkExpirationTimes(map);
public void testRemoveEntry() { LocalCache<Object, Object> map = makeLocalCache(createCacheBuilder() .concurrencyLevel(1) .initialCapacity(1) .maximumSize(SMALL_MAX_SIZE) .expireAfterWrite(99999, SECONDS) .removalListener(countingRemovalListener())); Segment<Object, Object> segment = map.segments[0]; AtomicReferenceArray<ReferenceEntry<Object, Object>> table = segment.table; assertEquals(1, table.length()); Object key = new Object(); Object value = new Object(); int hash = map.hash(key); DummyEntry<Object, Object> entry = createDummyEntry(key, hash, value, null); // remove absent assertFalse(segment.removeEntry(entry, hash, RemovalCause.COLLECTED)); // remove live segment.recordWrite(entry, 1, map.ticker.read()); table.set(0, entry); segment.count = 1; assertTrue(segment.removeEntry(entry, hash, RemovalCause.COLLECTED)); assertNotificationEnqueued(map, key, value, hash); assertTrue(map.removalNotificationQueue.isEmpty()); assertFalse(segment.accessQueue.contains(entry)); assertFalse(segment.writeQueue.contains(entry)); assertEquals(0, segment.count); assertNull(table.get(0)); }