11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2009 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License.
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License.
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.cache;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.cache.TestingCacheLoaders.constantLoader;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.cache.TestingCacheLoaders.identityLoader;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.cache.TestingRemovalListeners.countingRemovalListener;
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.cache.TestingRemovalListeners.nullRemovalListener;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.cache.TestingRemovalListeners.queuingRemovalListener;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.cache.TestingWeighers.constantWeigher;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static java.util.concurrent.TimeUnit.NANOSECONDS;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static java.util.concurrent.TimeUnit.SECONDS;
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible;
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtIncompatible;
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Ticker;
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.cache.TestingRemovalListeners.CountingRemovalListener;
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.cache.TestingRemovalListeners.QueuingRemovalListener;
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Maps;
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Sets;
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.testing.NullPointerTester;
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
370888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport junit.framework.TestCase;
380888a09821a98ac0680fad765217302858e70fa4Paul Duffin
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Map;
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Random;
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Set;
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.CountDownLatch;
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ExecutorService;
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Executors;
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.TimeUnit;
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.atomic.AtomicBoolean;
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.atomic.AtomicInteger;
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unit tests for CacheBuilder.
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible(emulated = true)
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class CacheBuilderTest extends TestCase {
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testNewBuilder() {
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheLoader<Object, Integer> loader = constantLoader(1);
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    LoadingCache<String, Integer> cache = CacheBuilder.newBuilder()
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .removalListener(countingRemovalListener())
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .build(loader);
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(Integer.valueOf(1), cache.getUnchecked("one"));
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(1, cache.size());
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testInitialCapacity_negative() {
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>();
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.initialCapacity(-1);
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalArgumentException expected) {}
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testInitialCapacity_setTwice() {
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>().initialCapacity(16);
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // even to the same value is not allowed
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.initialCapacity(16);
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("CacheTesting")
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testInitialCapacity_small() {
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    LoadingCache<?, ?> cache = CacheBuilder.newBuilder()
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .initialCapacity(5)
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .build(identityLoader());
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    LocalCache<?, ?> map = CacheTesting.toLocalCache(cache);
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(4, map.segments.length);
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(2, map.segments[0].table.length());
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(2, map.segments[1].table.length());
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(2, map.segments[2].table.length());
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(2, map.segments[3].table.length());
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("CacheTesting")
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testInitialCapacity_smallest() {
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    LoadingCache<?, ?> cache = CacheBuilder.newBuilder()
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .initialCapacity(0)
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .build(identityLoader());
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    LocalCache<?, ?> map = CacheTesting.toLocalCache(cache);
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(4, map.segments.length);
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // 1 is as low as it goes, not 0. it feels dirty to know this/test this.
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(1, map.segments[0].table.length());
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(1, map.segments[1].table.length());
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(1, map.segments[2].table.length());
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(1, map.segments[3].table.length());
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testInitialCapacity_large() {
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder.newBuilder().initialCapacity(Integer.MAX_VALUE);
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // that the builder didn't blow up is enough;
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // don't actually create this monster!
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConcurrencyLevel_zero() {
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>();
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.concurrencyLevel(0);
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalArgumentException expected) {}
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConcurrencyLevel_setTwice() {
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>().concurrencyLevel(16);
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // even to the same value is not allowed
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.concurrencyLevel(16);
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("CacheTesting")
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConcurrencyLevel_small() {
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    LoadingCache<?, ?> cache = CacheBuilder.newBuilder()
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .concurrencyLevel(1)
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .build(identityLoader());
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    LocalCache<?, ?> map = CacheTesting.toLocalCache(cache);
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(1, map.segments.length);
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConcurrencyLevel_large() {
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder.newBuilder().concurrencyLevel(Integer.MAX_VALUE);
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // don't actually build this beast
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testMaximumSize_negative() {
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>();
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.maximumSize(-1);
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalArgumentException expected) {}
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testMaximumSize_setTwice() {
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>().maximumSize(16);
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // even to the same value is not allowed
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.maximumSize(16);
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("maximumWeight")
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testMaximumSize_andWeight() {
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>().maximumSize(16);
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.maximumWeight(16);
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("maximumWeight")
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testMaximumWeight_negative() {
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>();
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.maximumWeight(-1);
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalArgumentException expected) {}
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("maximumWeight")
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testMaximumWeight_setTwice() {
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>().maximumWeight(16);
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // even to the same value is not allowed
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.maximumWeight(16);
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.maximumSize(16);
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("maximumWeight")
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testMaximumWeight_withoutWeigher() {
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>()
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .maximumWeight(1);
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.build(identityLoader());
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("weigher")
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testWeigher_withoutMaximumWeight() {
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>()
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .weigher(constantWeigher(42));
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.build(identityLoader());
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("weigher")
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testWeigher_withMaximumSize() {
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>()
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          .weigher(constantWeigher(42))
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          .maximumSize(1);
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>()
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          .maximumSize(1)
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          .weigher(constantWeigher(42));
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("weakKeys")
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testKeyStrengthSetTwice() {
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder1 = new CacheBuilder<Object, Object>().weakKeys();
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder1.weakKeys();
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("weakValues")
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testValueStrengthSetTwice() {
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder1 = new CacheBuilder<Object, Object>().weakValues();
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder1.weakValues();
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder1.softValues();
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder2 = new CacheBuilder<Object, Object>().softValues();
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder2.softValues();
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder2.weakValues();
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testTimeToLive_negative() {
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>();
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.expireAfterWrite(-1, SECONDS);
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalArgumentException expected) {}
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testTimeToLive_small() {
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder.newBuilder()
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .expireAfterWrite(1, NANOSECONDS)
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .build(identityLoader());
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // well, it didn't blow up.
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testTimeToLive_setTwice() {
2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder =
2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new CacheBuilder<Object, Object>().expireAfterWrite(3600, SECONDS);
2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // even to the same value is not allowed
2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.expireAfterWrite(3600, SECONDS);
2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testTimeToIdle_negative() {
2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>();
2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.expireAfterAccess(-1, SECONDS);
2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalArgumentException expected) {}
2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testTimeToIdle_small() {
3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder.newBuilder()
3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .expireAfterAccess(1, NANOSECONDS)
3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .build(identityLoader());
3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // well, it didn't blow up.
3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testTimeToIdle_setTwice() {
3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder =
3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new CacheBuilder<Object, Object>().expireAfterAccess(3600, SECONDS);
3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // even to the same value is not allowed
3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.expireAfterAccess(3600, SECONDS);
3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testTimeToIdleAndToLive() {
3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder.newBuilder()
3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .expireAfterWrite(1, NANOSECONDS)
3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .expireAfterAccess(1, NANOSECONDS)
3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .build(identityLoader());
3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // well, it didn't blow up.
3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("refreshAfterWrite")
3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testRefresh_zero() {
3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>();
3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.refreshAfterWrite(0, SECONDS);
3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalArgumentException expected) {}
3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("refreshAfterWrite")
3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testRefresh_setTwice() {
3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder =
3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new CacheBuilder<Object, Object>().refreshAfterWrite(3600, SECONDS);
3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // even to the same value is not allowed
3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.refreshAfterWrite(3600, SECONDS);
3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testTicker_setTwice() {
3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Ticker testTicker = Ticker.systemTicker();
3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder =
3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new CacheBuilder<Object, Object>().ticker(testTicker);
3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // even to the same instance is not allowed
3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.ticker(testTicker);
3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testRemovalListener_setTwice() {
3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    RemovalListener<Object, Object> testListener = nullRemovalListener();
3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder =
3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new CacheBuilder<Object, Object>().removalListener(testListener);
3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // even to the same instance is not allowed
3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder = builder.removalListener(testListener);
3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail();
3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (IllegalStateException expected) {}
3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3667dd252788645e940eada959bdde927426e2531c9Paul Duffin  @GwtIncompatible("CacheTesting")
3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testNullCache() {
3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CountingRemovalListener<Object, Object> listener = countingRemovalListener();
3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    LoadingCache<Object, Object> nullCache = new CacheBuilder<Object, Object>()
3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .maximumSize(0)
3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .removalListener(listener)
3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .build(identityLoader());
3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(0, nullCache.size());
3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Object key = new Object();
3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertSame(key, nullCache.getUnchecked(key));
3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(1, listener.getCount());
3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(0, nullCache.size());
3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheTesting.checkEmpty(nullCache.asMap());
3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3817dd252788645e940eada959bdde927426e2531c9Paul Duffin  @GwtIncompatible("QueuingRemovalListener")
3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testRemovalNotification_clear() throws InterruptedException {
3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // If a clear() happens while a computation is pending, we should not get a removal
3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // notification.
3861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final AtomicBoolean shouldWait = new AtomicBoolean(false);
3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final CountDownLatch computingLatch = new CountDownLatch(1);
3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheLoader<String, String> computingFunction = new CacheLoader<String, String>() {
3901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public String load(String key) throws InterruptedException {
3911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (shouldWait.get()) {
3921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          computingLatch.await();
3931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
3941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return key;
3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    QueuingRemovalListener<String, String> listener = queuingRemovalListener();
3981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final LoadingCache<String, String> cache = CacheBuilder.newBuilder()
4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .concurrencyLevel(1)
4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .removalListener(listener)
4021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .build(computingFunction);
4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // seed the map, so its segment's count > 0
4051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    cache.getUnchecked("a");
4061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    shouldWait.set(true);
4071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final CountDownLatch computationStarted = new CountDownLatch(1);
4091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final CountDownLatch computationComplete = new CountDownLatch(1);
4101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    new Thread(new Runnable() {
4111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public void run() {
4121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        computationStarted.countDown();
4131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        cache.getUnchecked("b");
4141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        computationComplete.countDown();
4151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }).start();
4171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // wait for the computingEntry to be created
4191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    computationStarted.await();
4201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    cache.invalidateAll();
4211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // let the computation proceed
4221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    computingLatch.countDown();
4231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // don't check cache.size() until we know the get("b") call is complete
4241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    computationComplete.await();
4251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // At this point, the listener should be holding the seed value (a -> a), and the map should
4271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // contain the computed value (b -> b), since the clear() happened before the computation
4281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // completed.
4291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(1, listener.size());
4301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    RemovalNotification<String, String> notification = listener.remove();
4311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals("a", notification.getKey());
4321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals("a", notification.getValue());
4331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(1, cache.size());
4341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals("b", cache.getUnchecked("b"));
4351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
4361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // "Basher tests", where we throw a bunch of stuff at a LoadingCache and check basic invariants.
4381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
4401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * This is a less carefully-controlled version of {@link #testRemovalNotification_clear} - this is
4411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * a black-box test that tries to create lots of different thread-interleavings, and asserts that
4421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * each computation is affected by a call to {@code clear()} (and therefore gets passed to the
4431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * removal listener), or else is not affected by the {@code clear()} (and therefore exists in the
4441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * cache afterward).
4451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
4467dd252788645e940eada959bdde927426e2531c9Paul Duffin  @GwtIncompatible("QueuingRemovalListener")
4471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testRemovalNotification_clear_basher() throws InterruptedException {
4491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // If a clear() happens close to the end of computation, one of two things should happen:
4501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // - computation ends first: the removal listener is called, and the cache does not contain the
4511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    //   key/value pair
4521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // - clear() happens first: the removal listener is not called, and the cache contains the pair
4531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicBoolean computationShouldWait = new AtomicBoolean();
4541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CountDownLatch computationLatch = new CountDownLatch(1);
4551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    QueuingRemovalListener<String, String> listener = queuingRemovalListener();
4561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final LoadingCache <String, String> cache = CacheBuilder.newBuilder()
4571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .removalListener(listener)
4581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .concurrencyLevel(20)
4591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .build(
4601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            new DelayingIdentityLoader<String>(computationShouldWait, computationLatch));
4611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int nThreads = 100;
4631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int nTasks = 1000;
4641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int nSeededEntries = 100;
4651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Set<String> expectedKeys = Sets.newHashSetWithExpectedSize(nTasks + nSeededEntries);
4661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // seed the map, so its segments have a count>0; otherwise, clear() won't visit the in-progress
4671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // entries
4681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < nSeededEntries; i++) {
4691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      String s = "b" + i;
4701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      cache.getUnchecked(s);
4711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      expectedKeys.add(s);
4721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    computationShouldWait.set(true);
4741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final AtomicInteger computedCount = new AtomicInteger();
4761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ExecutorService threadPool = Executors.newFixedThreadPool(nThreads);
4771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final CountDownLatch tasksFinished = new CountDownLatch(nTasks);
4781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < nTasks; i++) {
4791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      final String s = "a" + i;
4801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      threadPool.submit(new Runnable() {
4811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Override public void run() {
4821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          cache.getUnchecked(s);
4831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          computedCount.incrementAndGet();
4841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          tasksFinished.countDown();
4851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
4861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      });
4871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      expectedKeys.add(s);
4881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    computationLatch.countDown();
4911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // let some computations complete
4921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    while (computedCount.get() < nThreads) {
4931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Thread.yield();
4941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
4951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    cache.invalidateAll();
4961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    tasksFinished.await();
4971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Check all of the removal notifications we received: they should have had correctly-associated
4991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // keys and values. (An earlier bug saw removal notifications for in-progress computations,
5001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // which had real keys with null values.)
5011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Map<String, String> removalNotifications = Maps.newHashMap();
5021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (RemovalNotification<String, String> notification : listener) {
5031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      removalNotifications.put(notification.getKey(), notification.getValue());
5041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertEquals("Unexpected key/value pair passed to removalListener",
5051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          notification.getKey(), notification.getValue());
5061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // All of the seed values should have been visible, so we should have gotten removal
5091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // notifications for all of them.
5101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < nSeededEntries; i++) {
5111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertEquals("b" + i, removalNotifications.get("b" + i));
5121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Each of the values added to the map should either still be there, or have seen a removal
5151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // notification.
5161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(expectedKeys, Sets.union(cache.asMap().keySet(), removalNotifications.keySet()));
5171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(Sets.intersection(cache.asMap().keySet(), removalNotifications.keySet()).isEmpty());
5181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
5191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
5211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Calls get() repeatedly from many different threads, and tests that all of the removed entries
5221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * (removed because of size limits or expiration) trigger appropriate removal notifications.
5231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
5247dd252788645e940eada959bdde927426e2531c9Paul Duffin  @GwtIncompatible("QueuingRemovalListener")
5251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testRemovalNotification_get_basher() throws InterruptedException {
5277dd252788645e940eada959bdde927426e2531c9Paul Duffin    int nTasks = 1000;
5281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int nThreads = 100;
5291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final int getsPerTask = 1000;
5301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final int nUniqueKeys = 10000;
5311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Random random = new Random(); // Randoms.insecureRandom();
5321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    QueuingRemovalListener<String, String> removalListener = queuingRemovalListener();
5341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final AtomicInteger computeCount = new AtomicInteger();
5351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final AtomicInteger exceptionCount = new AtomicInteger();
5361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final AtomicInteger computeNullCount = new AtomicInteger();
5371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheLoader<String, String> countingIdentityLoader =
5381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        new CacheLoader<String, String>() {
5391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Override public String load(String key) throws InterruptedException {
5401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            int behavior = random.nextInt(4);
5411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (behavior == 0) { // throw an exception
5421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              exceptionCount.incrementAndGet();
5431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              throw new RuntimeException("fake exception for test");
5441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else if (behavior == 1) { // return null
5451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              computeNullCount.incrementAndGet();
5461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return null;
5471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else if (behavior == 2) { // slight delay before returning
5481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              Thread.sleep(5);
5491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              computeCount.incrementAndGet();
5501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return key;
5511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else {
5521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              computeCount.incrementAndGet();
5531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return key;
5541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
5551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
5561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        };
5571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final LoadingCache<String, String> cache = CacheBuilder.newBuilder()
5587dd252788645e940eada959bdde927426e2531c9Paul Duffin        .recordStats()
5591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .concurrencyLevel(2)
5601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .expireAfterWrite(100, TimeUnit.MILLISECONDS)
5611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .removalListener(removalListener)
5621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .maximumSize(5000)
5631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        .build(countingIdentityLoader);
5641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ExecutorService threadPool = Executors.newFixedThreadPool(nThreads);
5661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < nTasks; i++) {
5671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      threadPool.submit(new Runnable() {
5681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Override public void run() {
5691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          for (int j = 0; j < getsPerTask; j++) {
5701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            try {
5711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              cache.getUnchecked("key" + random.nextInt(nUniqueKeys));
5721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } catch (RuntimeException e) {
5731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
5741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
5751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
5761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      });
5771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    threadPool.shutdown();
5801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    threadPool.awaitTermination(300, TimeUnit.SECONDS);
5811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Since we're not doing any more cache operations, and the cache only expires/evicts when doing
5831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // other operations, the cache and the removal queue won't change from this point on.
5841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Verify that each received removal notification was valid
5861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (RemovalNotification<String, String> notification : removalListener) {
5871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      assertEquals("Invalid removal notification", notification.getKey(), notification.getValue());
5881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheStats stats = cache.stats();
5911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(removalListener.size(), stats.evictionCount());
5921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(computeCount.get(), stats.loadSuccessCount());
5931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(exceptionCount.get() + computeNullCount.get(), stats.loadExceptionCount());
5941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // each computed value is still in the cache, or was passed to the removal listener
5951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(computeCount.get(), cache.size() + removalListener.size());
5961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
5971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("NullPointerTester")
5991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testNullParameters() throws Exception {
6001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    NullPointerTester tester = new NullPointerTester();
6011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    CacheBuilder<Object, Object> builder = new CacheBuilder<Object, Object>();
6021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    tester.testAllPublicInstanceMethods(builder);
6031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("CacheTesting")
6061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testSizingDefaults() {
6071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    LoadingCache<?, ?> cache = CacheBuilder.newBuilder().build(identityLoader());
6081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    LocalCache<?, ?> map = CacheTesting.toLocalCache(cache);
6091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(4, map.segments.length); // concurrency level
6101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(4, map.segments[0].table.length()); // capacity / conc level
6111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("CountDownLatch")
6141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class DelayingIdentityLoader<T> extends CacheLoader<T, T> {
6151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private final AtomicBoolean shouldWait;
6161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private final CountDownLatch delayLatch;
6171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    DelayingIdentityLoader(AtomicBoolean shouldWait, CountDownLatch delayLatch) {
6191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.shouldWait = shouldWait;
6201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.delayLatch = delayLatch;
6211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public T load(T key) throws InterruptedException {
6241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (shouldWait.get()) {
6251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        delayLatch.await();
6261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
6271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return key;
6281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
631