d13cd41c85458c63d033e389e88f8f84c0b7daf3
[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
35     @Override
36     protected void setUp() throws Exception {
37         computation = mock(Computation.class);
38     }
39
40     public void testComputeOutOfDate() {
41         initGuard();
42     }
43
44     private void initGuard() {
45         guard = new ComputedValue<Integer>(this, computation);
46
47         assertNull(guard.getCached());
48         
49         when(computation.isOutOfDate()).thenReturn(true);
50         when(computation.compute()).thenReturn(10);
51        
52         int value = guard.get();
53         assertEquals(10, value);
54         verify(computation).compute();
55         reset(computation);
56     }
57     
58     public void testGetCached() { 
59         initGuard();
60         assertEquals(10, (int)guard.getCached());
61         verifyNoMoreInteractions(computation);
62     }
63
64     public void testNoComputationWhenNotOutOfDate() {
65         initGuard();
66         when(computation.isOutOfDate()).thenReturn(false);
67         assertEquals(10, (int) guard.get());
68         verify(computation, never()).compute();
69     }
70
71     public void testOnlyOneConcurrentComputation() throws Exception {
72         initGuard();
73         final int computeTime = 500;
74         when(computation.isOutOfDate()).thenReturn(true);
75         when(computation.compute()).thenAnswer(new Answer<Integer>() {
76             @Override
77             public Integer answer(InvocationOnMock aInvocation)
78                 throws Throwable {
79                 Thread.sleep(computeTime);
80                 return 100;
81             }
82         });
83
84         final List<Integer> results = new ArrayList<Integer>();
85
86         Runnable task = new Runnable() {
87             @Override
88             public void run() {
89                 int res = guard.get();
90                 results.add(res);
91             }
92         };
93
94         // concurrent computation in two threads.
95         Thread t1 = new Thread(task);
96         Thread t2 = new Thread(task);
97         t1.start();
98         Thread.sleep(computeTime / 2);
99         // second task will return old value 10 because first one is still busy.
100         t2.start();
101         t1.join();
102         t2.join();
103         assertEquals(2, results.size());
104         assertEquals(10, (int) results.get(0));
105         assertEquals(100, (int) results.get(1));
106         verify(computation, times(2)).isOutOfDate();
107     }
108
109     public void testExceptionWhileComputing() {
110         initGuard();
111         when(computation.isOutOfDate()).thenReturn(true);
112         when(computation.compute()).thenThrow(new RuntimeException("xx"));
113         try {
114             guard.get();
115             fail();
116         } catch (RuntimeException e) {
117             assertEquals("xx", e.getMessage());
118         }
119     }
120
121     public void testExceptionWhileCheckingOutOfDate() {
122         initGuard();
123         when(computation.isOutOfDate()).thenThrow(new RuntimeException("xx"));
124         try {
125             guard.get();
126             fail();
127         } catch (RuntimeException e) {
128             assertEquals("xx", e.getMessage());
129         }
130     }
131 }