1 /*
2  * Copyright (C) 2011 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.collect.ImmutableList;
20 import com.google.common.collect.ImmutableMap;
21 import com.google.common.collect.Lists;
22 import com.google.common.util.concurrent.Futures;
23 import com.google.common.util.concurrent.ListenableFuture;
24 
25 import junit.framework.TestCase;
26 
27 import java.util.LinkedList;
28 import java.util.Map;
29 import java.util.concurrent.Executor;
30 import java.util.concurrent.atomic.AtomicInteger;
31 
32 /**
33  * Unit tests for {@link CacheLoader}.
34  *
35  * @author Charles Fry
36  */
37 public class CacheLoaderTest extends TestCase {
38 
39   private static class QueuingExecutor implements Executor {
40     private LinkedList<Runnable> tasks = Lists.newLinkedList();
41 
42     @Override
execute(Runnable task)43     public void execute(Runnable task) {
44       tasks.add(task);
45     }
46 
runNext()47     private void runNext() {
48       tasks.removeFirst().run();
49     }
50   }
51 
testAsyncReload()52   public void testAsyncReload() throws Exception {
53     final AtomicInteger loadCount = new AtomicInteger();
54     final AtomicInteger reloadCount = new AtomicInteger();
55     final AtomicInteger loadAllCount = new AtomicInteger();
56 
57     CacheLoader<Object, Object> baseLoader = new CacheLoader<Object, Object>() {
58       @Override
59       public Object load(Object key) {
60         loadCount.incrementAndGet();
61         return new Object();
62       }
63 
64       @Override
65       public ListenableFuture<Object> reload(Object key, Object oldValue) {
66         reloadCount.incrementAndGet();
67         return Futures.immediateFuture(new Object());
68       }
69 
70       @Override
71       public Map<Object, Object> loadAll(Iterable<? extends Object> keys) {
72         loadAllCount.incrementAndGet();
73         return ImmutableMap.of();
74       }
75     };
76 
77     assertEquals(0, loadCount.get());
78     assertEquals(0, reloadCount.get());
79     assertEquals(0, loadAllCount.get());
80 
81     baseLoader.load(new Object());
82     baseLoader.reload(new Object(), new Object());
83     baseLoader.loadAll(ImmutableList.of(new Object()));
84     assertEquals(1, loadCount.get());
85     assertEquals(1, reloadCount.get());
86     assertEquals(1, loadAllCount.get());
87 
88     QueuingExecutor executor = new QueuingExecutor();
89     CacheLoader<Object, Object> asyncReloader =
90         CacheLoader.asyncReloading(baseLoader, executor);
91 
92     asyncReloader.load(new Object());
93     asyncReloader.reload(new Object(), new Object());
94     asyncReloader.loadAll(ImmutableList.of(new Object()));
95     assertEquals(2, loadCount.get());
96     assertEquals(1, reloadCount.get());
97     assertEquals(2, loadAllCount.get());
98 
99     executor.runNext();
100     assertEquals(2, loadCount.get());
101     assertEquals(2, reloadCount.get());
102     assertEquals(2, loadAllCount.get());
103   }
104 }
105