(no commit message)
[utils] / support / general / src / test / java / org / wamblee / cache / ComputedValueTest.java
1 /*
2  * Copyright 2005-2010 the original author or 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 package org.wamblee.cache;
17
18 import static org.mockito.Mockito.*;
19
20 import java.util.ArrayList;
21 import java.util.List;
22
23 import junit.framework.TestCase;
24
25 import org.mockito.invocation.InvocationOnMock;
26 import org.mockito.stubbing.Answer;
27 import org.wamblee.cache.ComputedValue.Computation;
28
29 public class ComputedValueTest extends TestCase {
30
31     private Computation<Integer> computation;
32     private ComputedValue<Integer> guard;
33
34     @Override
35     protected void setUp() throws Exception {
36         computation = mock(Computation.class);
37     }
38
39     public void testComputeOutOfDate() {
40         initGuard();
41     }
42
43     private void initGuard() {
44         guard = new ComputedValue<Integer>(this, computation);
45
46         assertNull(guard.getCached());
47
48         when(computation.isOutOfDate()).thenReturn(true);
49         when(computation.compute()).thenReturn(10);
50
51         int value = guard.get();
52         assertEquals(10, value);
53         verify(computation).compute();
54         reset(computation);
55     }
56
57     public void testGetCached() {
58         initGuard();
59         assertEquals(10, (int) guard.getCached());
60         verifyNoMoreInteractions(computation);
61     }
62
63     public void testNoComputationWhenNotOutOfDate() {
64         initGuard();
65         when(computation.isOutOfDate()).thenReturn(false);
66         assertEquals(10, (int) guard.get());
67         verify(computation, never()).compute();
68     }
69
70     public void testOnlyOneConcurrentComputation() throws Exception {
71         initGuard();
72         final int computeTime = 500;
73         when(computation.isOutOfDate()).thenReturn(true);
74         when(computation.compute()).thenAnswer(new Answer<Integer>() {
75             @Override
76             public Integer answer(InvocationOnMock aInvocation)
77                 throws Throwable {
78                 Thread.sleep(computeTime);
79                 return 100;
80             }
81         });
82
83         final List<Integer> results = new ArrayList<Integer>();
84
85         Runnable task = new Runnable() {
86             @Override
87             public void run() {
88                 int res = guard.get();
89                 results.add(res);
90             }
91         };
92
93         // concurrent computation in two threads.
94         Thread t1 = new Thread(task);
95         Thread t2 = new Thread(task);
96         t1.start();
97         Thread.sleep(computeTime / 2);
98         // second task will return old value 10 because first one is still busy.
99         t2.start();
100         t1.join();
101         t2.join();
102         assertEquals(2, results.size());
103         assertEquals(10, (int) results.get(0));
104         assertEquals(100, (int) results.get(1));
105         verify(computation, times(2)).isOutOfDate();
106     }
107
108     public void testExceptionWhileComputing() {
109         initGuard();
110         when(computation.isOutOfDate()).thenReturn(true);
111         when(computation.compute()).thenThrow(new RuntimeException("xx"));
112         try {
113             guard.get();
114             fail();
115         } catch (RuntimeException e) {
116             assertEquals("xx", e.getMessage());
117         }
118     }
119
120     public void testExceptionWhileCheckingOutOfDate() {
121         initGuard();
122         when(computation.isOutOfDate()).thenThrow(new RuntimeException("xx"));
123         try {
124             guard.get();
125             fail();
126         } catch (RuntimeException e) {
127             assertEquals("xx", e.getMessage());
128         }
129     }
130 }