Home | History | Annotate | Download | only in cache
      1 /*
      2  * Copyright (C) 2012 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.common.cache;
     18 
     19 import com.google.common.annotations.GwtCompatible;
     20 import com.google.common.collect.ImmutableList;
     21 import com.google.common.collect.ImmutableMap;
     22 import com.google.common.collect.ImmutableSet;
     23 import com.google.common.collect.Sets;
     24 import com.google.common.testing.FakeTicker;
     25 
     26 import junit.framework.TestCase;
     27 
     28 import java.util.Iterator;
     29 import java.util.Map;
     30 import java.util.Map.Entry;
     31 import java.util.Set;
     32 import java.util.concurrent.Callable;
     33 import java.util.concurrent.ConcurrentMap;
     34 import java.util.concurrent.ExecutionException;
     35 import java.util.concurrent.TimeUnit;
     36 
     37 /**
     38  * Test suite for {@link CacheBuilder}.
     39  * TODO(cpovirk): merge into CacheBuilderTest?
     40  *
     41  * @author Jon Donovan
     42  */
     43 @GwtCompatible
     44 public class CacheBuilderGwtTest extends TestCase {
     45 
     46   private FakeTicker fakeTicker;
     47 
     48   @Override
     49   protected void setUp() throws Exception {
     50     super.setUp();
     51 
     52     fakeTicker = new FakeTicker();
     53   }
     54 
     55   public void testLoader() throws ExecutionException {
     56 
     57     final Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
     58         .build();
     59 
     60     Callable<Integer> loader = new Callable<Integer>() {
     61       private int i = 0;
     62 
     63       @Override
     64       public Integer call() throws Exception {
     65         return ++i;
     66       }
     67     };
     68 
     69     cache.put(0, 10);
     70 
     71     assertEquals(Integer.valueOf(10), cache.get(0, loader));
     72     assertEquals(Integer.valueOf(1), cache.get(20, loader));
     73     assertEquals(Integer.valueOf(2), cache.get(34, loader));
     74 
     75     cache.invalidate(0);
     76     assertEquals(Integer.valueOf(3), cache.get(0, loader));
     77 
     78     cache.put(0, 10);
     79     cache.invalidateAll();
     80     assertEquals(Integer.valueOf(4), cache.get(0, loader));
     81   }
     82 
     83   public void testSizeConstraint() {
     84     final Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
     85         .maximumSize(4)
     86         .build();
     87 
     88     cache.put(1, 10);
     89     cache.put(2, 20);
     90     cache.put(3, 30);
     91     cache.put(4, 40);
     92     cache.put(5, 50);
     93 
     94     assertEquals(null, cache.getIfPresent(10));
     95     // Order required to remove dependence on acces order / write order constraint.
     96     assertEquals(Integer.valueOf(20), cache.getIfPresent(2));
     97     assertEquals(Integer.valueOf(30), cache.getIfPresent(3));
     98     assertEquals(Integer.valueOf(40), cache.getIfPresent(4));
     99     assertEquals(Integer.valueOf(50), cache.getIfPresent(5));
    100 
    101     cache.put(1, 10);
    102     assertEquals(Integer.valueOf(10), cache.getIfPresent(1));
    103     assertEquals(Integer.valueOf(30), cache.getIfPresent(3));
    104     assertEquals(Integer.valueOf(40), cache.getIfPresent(4));
    105     assertEquals(Integer.valueOf(50), cache.getIfPresent(5));
    106     assertEquals(null, cache.getIfPresent(2));
    107   }
    108 
    109   public void testLoadingCache() throws ExecutionException {
    110     CacheLoader<Integer, Integer> loader = new CacheLoader<Integer, Integer>() {
    111       int i = 0;
    112       @Override
    113       public Integer load(Integer key) throws Exception {
    114         return i++;
    115       }
    116 
    117     };
    118 
    119     LoadingCache<Integer, Integer> cache = CacheBuilder.newBuilder()
    120         .build(loader);
    121 
    122     cache.put(10, 20);
    123 
    124     Map<Integer, Integer> map = cache.getAll(ImmutableList.of(10, 20, 30, 54, 443, 1));
    125 
    126     assertEquals(Integer.valueOf(20), map.get(10));
    127     assertEquals(Integer.valueOf(0), map.get(20));
    128     assertEquals(Integer.valueOf(1), map.get(30));
    129     assertEquals(Integer.valueOf(2), map.get(54));
    130     assertEquals(Integer.valueOf(3), map.get(443));
    131     assertEquals(Integer.valueOf(4), map.get(1));
    132     assertEquals(Integer.valueOf(5), cache.get(6));
    133     assertEquals(Integer.valueOf(6), cache.apply(7));
    134   }
    135 
    136   public void testExpireAfterAccess() {
    137     final Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
    138         .expireAfterAccess(1000, TimeUnit.MILLISECONDS)
    139         .ticker(fakeTicker)
    140         .build();
    141 
    142     cache.put(0, 10);
    143     cache.put(2, 30);
    144 
    145     fakeTicker.advance(999, TimeUnit.MILLISECONDS);
    146     assertEquals(Integer.valueOf(30), cache.getIfPresent(2));
    147     fakeTicker.advance(1, TimeUnit.MILLISECONDS);
    148     assertEquals(Integer.valueOf(30), cache.getIfPresent(2));
    149     fakeTicker.advance(1000, TimeUnit.MILLISECONDS);
    150     assertEquals(null, cache.getIfPresent(0));
    151   }
    152 
    153   public void testExpireAfterWrite() {
    154     final Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
    155         .expireAfterWrite(1000, TimeUnit.MILLISECONDS)
    156         .ticker(fakeTicker)
    157         .build();
    158 
    159     cache.put(10, 100);
    160     cache.put(20, 200);
    161     cache.put(4, 2);
    162 
    163     fakeTicker.advance(999, TimeUnit.MILLISECONDS);
    164     assertEquals(Integer.valueOf(100), cache.getIfPresent(10));
    165     assertEquals(Integer.valueOf(200), cache.getIfPresent(20));
    166     assertEquals(Integer.valueOf(2), cache.getIfPresent(4));
    167 
    168     fakeTicker.advance(2, TimeUnit.MILLISECONDS);
    169     assertEquals(null, cache.getIfPresent(10));
    170     assertEquals(null, cache.getIfPresent(20));
    171     assertEquals(null, cache.getIfPresent(4));
    172 
    173     cache.put(10, 20);
    174     assertEquals(Integer.valueOf(20), cache.getIfPresent(10));
    175 
    176     fakeTicker.advance(1000, TimeUnit.MILLISECONDS);
    177     assertEquals(null, cache.getIfPresent(10));
    178   }
    179 
    180   public void testExpireAfterWriteAndAccess() {
    181     final Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
    182         .expireAfterWrite(1000, TimeUnit.MILLISECONDS)
    183         .expireAfterAccess(500, TimeUnit.MILLISECONDS)
    184         .ticker(fakeTicker)
    185         .build();
    186 
    187     cache.put(10, 100);
    188     cache.put(20, 200);
    189     cache.put(4, 2);
    190 
    191     fakeTicker.advance(499, TimeUnit.MILLISECONDS);
    192     assertEquals(Integer.valueOf(100), cache.getIfPresent(10));
    193     assertEquals(Integer.valueOf(200), cache.getIfPresent(20));
    194 
    195     fakeTicker.advance(2, TimeUnit.MILLISECONDS);
    196     assertEquals(Integer.valueOf(100), cache.getIfPresent(10));
    197     assertEquals(Integer.valueOf(200), cache.getIfPresent(20));
    198     assertEquals(null, cache.getIfPresent(4));
    199 
    200     fakeTicker.advance(499, TimeUnit.MILLISECONDS);
    201     assertEquals(null, cache.getIfPresent(10));
    202     assertEquals(null, cache.getIfPresent(20));
    203 
    204     cache.put(10, 20);
    205     assertEquals(Integer.valueOf(20), cache.getIfPresent(10));
    206 
    207     fakeTicker.advance(500, TimeUnit.MILLISECONDS);
    208     assertEquals(null, cache.getIfPresent(10));
    209   }
    210 
    211   public void testMapMethods() {
    212     Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
    213         .build();
    214 
    215     ConcurrentMap<Integer, Integer> asMap = cache.asMap();
    216 
    217     cache.put(10, 100);
    218     cache.put(2, 52);
    219 
    220     asMap.replace(2, 79);
    221     asMap.replace(3, 60);
    222 
    223     assertEquals(null, cache.getIfPresent(3));
    224     assertEquals(null, asMap.get(3));
    225 
    226     assertEquals(Integer.valueOf(79), cache.getIfPresent(2));
    227     assertEquals(Integer.valueOf(79), asMap.get(2));
    228 
    229     asMap.replace(10, 100, 50);
    230     asMap.replace(2, 52, 99);
    231 
    232     assertEquals(Integer.valueOf(50), cache.getIfPresent(10));
    233     assertEquals(Integer.valueOf(50), asMap.get(10));
    234     assertEquals(Integer.valueOf(79), cache.getIfPresent(2));
    235     assertEquals(Integer.valueOf(79), asMap.get(2));
    236 
    237     asMap.remove(10, 100);
    238     asMap.remove(2, 79);
    239 
    240     assertEquals(Integer.valueOf(50), cache.getIfPresent(10));
    241     assertEquals(Integer.valueOf(50), asMap.get(10));
    242     assertEquals(null, cache.getIfPresent(2));
    243     assertEquals(null, asMap.get(2));
    244 
    245     asMap.putIfAbsent(2, 20);
    246     asMap.putIfAbsent(10, 20);
    247 
    248     assertEquals(Integer.valueOf(20), cache.getIfPresent(2));
    249     assertEquals(Integer.valueOf(20), asMap.get(2));
    250     assertEquals(Integer.valueOf(50), cache.getIfPresent(10));
    251     assertEquals(Integer.valueOf(50), asMap.get(10));
    252   }
    253 
    254   public void testRemovalListener() {
    255     final int[] stats = new int[4];
    256 
    257     RemovalListener<Integer, Integer> countingListener = new RemovalListener<Integer, Integer>() {
    258       @Override
    259       public void onRemoval(RemovalNotification<Integer, Integer> notification) {
    260         switch (notification.getCause()) {
    261           case EXPIRED:
    262             stats[0]++;
    263             break;
    264           case EXPLICIT:
    265             stats[1]++;
    266             break;
    267           case REPLACED:
    268             stats[2]++;
    269             break;
    270           case SIZE:
    271             stats[3]++;
    272             break;
    273           default:
    274             throw new IllegalStateException("No collected exceptions in GWT CacheBuilder.");
    275         }
    276       }
    277     };
    278 
    279     Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
    280         .expireAfterWrite(1000, TimeUnit.MILLISECONDS)
    281         .removalListener(countingListener)
    282         .ticker(fakeTicker)
    283         .maximumSize(2)
    284         .build();
    285 
    286     // Add more than two elements to increment size removals.
    287     cache.put(3, 20);
    288     cache.put(6, 2);
    289     cache.put(98, 45);
    290     cache.put(56, 76);
    291     cache.put(23, 84);
    292 
    293     // Replace the two present elements.
    294     cache.put(23, 20);
    295     cache.put(56, 49);
    296     cache.put(23, 2);
    297     cache.put(56, 4);
    298 
    299     // Expire the two present elements.
    300     fakeTicker.advance(1001, TimeUnit.MILLISECONDS);
    301 
    302     cache.getIfPresent(23);
    303     cache.getIfPresent(56);
    304 
    305     // Add two elements and invalidate them.
    306     cache.put(1, 4);
    307     cache.put(2, 8);
    308 
    309     cache.invalidateAll();
    310 
    311     assertEquals(2, stats[0]);
    312     assertEquals(2, stats[1]);
    313     assertEquals(4, stats[2]);
    314     assertEquals(3, stats[3]);
    315   }
    316 
    317   public void testPutAll() {
    318     Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
    319         .build();
    320 
    321     cache.putAll(ImmutableMap.of(10, 20, 30, 50, 60, 90));
    322 
    323     assertEquals(Integer.valueOf(20), cache.getIfPresent(10));
    324     assertEquals(Integer.valueOf(50), cache.getIfPresent(30));
    325     assertEquals(Integer.valueOf(90), cache.getIfPresent(60));
    326 
    327     cache.asMap().putAll(ImmutableMap.of(10, 50, 30, 20, 60, 70, 5, 5));
    328 
    329     assertEquals(Integer.valueOf(50), cache.getIfPresent(10));
    330     assertEquals(Integer.valueOf(20), cache.getIfPresent(30));
    331     assertEquals(Integer.valueOf(70), cache.getIfPresent(60));
    332     assertEquals(Integer.valueOf(5), cache.getIfPresent(5));
    333   }
    334 
    335   public void testInvalidate() {
    336     Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
    337         .build();
    338 
    339     cache.put(654, 2675);
    340     cache.put(2456, 56);
    341     cache.put(2, 15);
    342 
    343     cache.invalidate(654);
    344 
    345     assertFalse(cache.asMap().containsKey(654));
    346     assertTrue(cache.asMap().containsKey(2456));
    347     assertTrue(cache.asMap().containsKey(2));
    348   }
    349 
    350   public void testInvalidateAll() {
    351     Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
    352         .build();
    353 
    354     cache.put(654, 2675);
    355     cache.put(2456, 56);
    356     cache.put(2, 15);
    357 
    358     cache.invalidateAll();
    359     assertFalse(cache.asMap().containsKey(654));
    360     assertFalse(cache.asMap().containsKey(2456));
    361     assertFalse(cache.asMap().containsKey(2));
    362 
    363     cache.put(654, 2675);
    364     cache.put(2456, 56);
    365     cache.put(2, 15);
    366     cache.put(1, 3);
    367 
    368     cache.invalidateAll(ImmutableSet.of(1, 2));
    369 
    370     assertFalse(cache.asMap().containsKey(1));
    371     assertFalse(cache.asMap().containsKey(2));
    372     assertTrue(cache.asMap().containsKey(654));
    373     assertTrue(cache.asMap().containsKey(2456));
    374   }
    375 
    376   public void testAsMap_containsValue() {
    377     Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
    378         .expireAfterWrite(20000, TimeUnit.MILLISECONDS)
    379         .ticker(fakeTicker)
    380         .build();
    381 
    382     cache.put(654, 2675);
    383     fakeTicker.advance(10000, TimeUnit.MILLISECONDS);
    384     cache.put(2456, 56);
    385     cache.put(2, 15);
    386 
    387     fakeTicker.advance(10001, TimeUnit.MILLISECONDS);
    388 
    389     assertTrue(cache.asMap().containsValue(15));
    390     assertTrue(cache.asMap().containsValue(56));
    391     assertFalse(cache.asMap().containsValue(2675));
    392   }
    393 
    394   public void testAsMap_containsKey() {
    395     Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
    396         .expireAfterWrite(20000, TimeUnit.MILLISECONDS)
    397         .ticker(fakeTicker)
    398         .build();
    399 
    400     cache.put(654, 2675);
    401     fakeTicker.advance(10000, TimeUnit.MILLISECONDS);
    402     cache.put(2456, 56);
    403     cache.put(2, 15);
    404 
    405     fakeTicker.advance(10001, TimeUnit.MILLISECONDS);
    406 
    407     assertTrue(cache.asMap().containsKey(2));
    408     assertTrue(cache.asMap().containsKey(2456));
    409     assertFalse(cache.asMap().containsKey(654));
    410   }
    411 
    412   public void testAsMapValues_contains() {
    413     Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
    414         .expireAfterWrite(1000, TimeUnit.MILLISECONDS)
    415         .ticker(fakeTicker)
    416         .build();
    417 
    418     cache.put(10, 20);
    419     fakeTicker.advance(500, TimeUnit.MILLISECONDS);
    420     cache.put(20, 22);
    421     cache.put(5, 10);
    422 
    423     fakeTicker.advance(501, TimeUnit.MILLISECONDS);
    424 
    425     assertTrue(cache.asMap().values().contains(22));
    426     assertTrue(cache.asMap().values().contains(10));
    427     assertFalse(cache.asMap().values().contains(20));
    428   }
    429 
    430   public void testAsMapKeySet() {
    431     Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
    432         .expireAfterWrite(1000, TimeUnit.MILLISECONDS)
    433         .ticker(fakeTicker)
    434         .build();
    435 
    436     cache.put(10, 20);
    437     fakeTicker.advance(500, TimeUnit.MILLISECONDS);
    438     cache.put(20, 22);
    439     cache.put(5, 10);
    440 
    441     fakeTicker.advance(501, TimeUnit.MILLISECONDS);
    442 
    443     Set<Integer> foundKeys = Sets.newHashSet();
    444     for (Integer current : cache.asMap().keySet()) {
    445       foundKeys.add(current);
    446     }
    447 
    448     assertEquals(ImmutableSet.of(20, 5), foundKeys);
    449   }
    450 
    451 
    452   public void testAsMapKeySet_contains() {
    453     Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
    454         .expireAfterWrite(1000, TimeUnit.MILLISECONDS)
    455         .ticker(fakeTicker)
    456         .build();
    457 
    458     cache.put(10, 20);
    459     fakeTicker.advance(500, TimeUnit.MILLISECONDS);
    460     cache.put(20, 22);
    461     cache.put(5, 10);
    462 
    463     fakeTicker.advance(501, TimeUnit.MILLISECONDS);
    464 
    465     assertTrue(cache.asMap().keySet().contains(20));
    466     assertTrue(cache.asMap().keySet().contains(5));
    467     assertFalse(cache.asMap().keySet().contains(10));
    468   }
    469 
    470   public void testAsMapEntrySet() {
    471     Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
    472         .expireAfterWrite(1000, TimeUnit.MILLISECONDS)
    473         .ticker(fakeTicker)
    474         .build();
    475 
    476     cache.put(10, 20);
    477     fakeTicker.advance(500, TimeUnit.MILLISECONDS);
    478     cache.put(20, 22);
    479     cache.put(5, 10);
    480 
    481     fakeTicker.advance(501, TimeUnit.MILLISECONDS);
    482 
    483     int sum = 0;
    484     for (Entry<Integer, Integer> current : cache.asMap().entrySet()) {
    485       sum += current.getKey() + current.getValue();
    486     }
    487     assertEquals(57, sum);
    488   }
    489 
    490   public void testAsMapValues_iteratorRemove() {
    491     Cache<Integer, Integer> cache = CacheBuilder.newBuilder()
    492         .expireAfterWrite(1000, TimeUnit.MILLISECONDS)
    493         .ticker(fakeTicker)
    494         .build();
    495 
    496     cache.put(10, 20);
    497     Iterator<Integer> iterator = cache.asMap().values().iterator();
    498     iterator.next();
    499     iterator.remove();
    500 
    501     assertEquals(0, cache.size());
    502   }
    503 }
    504