View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.mina.util;
20  
21  import static org.junit.Assert.assertFalse;
22  import static org.junit.Assert.assertTrue;
23  import static org.junit.Assert.fail;
24  import static org.mockito.Matchers.anyBoolean;
25  import static org.mockito.Matchers.argThat;
26  import static org.mockito.Mockito.doReturn;
27  import static org.mockito.Mockito.mock;
28  import static org.mockito.Mockito.never;
29  import static org.mockito.Mockito.spy;
30  import static org.mockito.Mockito.verify;
31  
32  import java.util.concurrent.CancellationException;
33  import java.util.concurrent.ExecutionException;
34  import java.util.concurrent.TimeUnit;
35  import java.util.concurrent.TimeoutException;
36  
37  import org.apache.mina.api.IoFutureListener;
38  import org.hamcrest.BaseMatcher;
39  import org.hamcrest.Description;
40  import org.hamcrest.Matcher;
41  import org.junit.Test;
42  import org.mockito.Matchers;
43  
44  /**
45   * @author <a href="http://mina.apache.org">Apache MINA Project</a>
46   */
47  public class AbstractIoFutureTest {
48  
49      @Test
50      public void testSet() {
51          final MockAbstractIoFuture<Boolean> future = spy(new MockAbstractIoFuture<Boolean>());
52  
53          assertFalse(future.isCancelled());
54          assertFalse(future.isDone());
55  
56          future.setResult(true);
57  
58          assertFalse(future.isCancelled());
59          assertTrue(future.isDone());
60      }
61  
62      @Test
63      @SuppressWarnings({ "unchecked" })
64      public void testSetListeners() {
65          final MockAbstractIoFuture<Boolean> future = spy(new MockAbstractIoFuture<Boolean>());
66          final IoFutureListener<Boolean> listener = mock(IoFutureListener.class);
67  
68          future.register(listener);
69  
70          assertFalse(future.isCancelled());
71          assertFalse(future.isDone());
72  
73          future.setResult(true);
74  
75          assertFalse(future.isCancelled());
76          assertTrue(future.isDone());
77  
78          verify(listener).completed(true);
79          verify(listener, never()).exception(Matchers.<Throwable> any());
80      }
81  
82      @Test
83      @SuppressWarnings({ "unchecked" })
84      public void testSetListenersAlreadySet() {
85          final MockAbstractIoFuture<Boolean> future = spy(new MockAbstractIoFuture<Boolean>());
86          final IoFutureListener<Boolean> listener = mock(IoFutureListener.class);
87  
88          assertFalse(future.isCancelled());
89          assertFalse(future.isDone());
90  
91          future.setResult(true);
92          future.register(listener);
93  
94          assertFalse(future.isCancelled());
95          assertTrue(future.isDone());
96  
97          verify(listener).completed(true);
98          verify(listener, never()).exception(Matchers.<Throwable> any());
99      }
100 
101     @Test
102     public void testTimedGet() {
103         final MockAbstractIoFuture<Boolean> future = spy(new MockAbstractIoFuture<Boolean>());
104 
105         assertFalse(future.isCancelled());
106         assertFalse(future.isDone());
107 
108         new Thread(new Runnable() {
109             @Override
110             public void run() {
111                 try {
112                     Thread.sleep(1000);
113                     future.setResult(true);
114                 } catch (final InterruptedException ignored) {
115                 }
116             }
117         }).start();
118 
119         try {
120             assertTrue(future.get(1, TimeUnit.DAYS));
121             assertFalse(future.isCancelled());
122             assertTrue(future.isDone());
123         } catch (final InterruptedException e) {
124             fail("This future was not interrupted");
125         } catch (final ExecutionException ee) {
126             fail("This future did not have an execution exception");
127         } catch (final TimeoutException e) {
128             fail("This future was not interrupted");
129         }
130     }
131 
132     @Test
133     public void testException() {
134         final MockAbstractIoFuture<Boolean> future = spy(new MockAbstractIoFuture<Boolean>());
135 
136         assertFalse(future.isCancelled());
137         assertFalse(future.isDone());
138 
139         future.setException(new NullPointerException());
140 
141         assertFalse(future.isCancelled());
142         assertTrue(future.isDone());
143 
144         try {
145             future.get();
146             fail("This future had an execution exception");
147         } catch (final InterruptedException e) {
148             fail("This future was not interrupted");
149         } catch (final ExecutionException ee) {
150             assertTrue(ee.getCause() instanceof NullPointerException);
151         }
152 
153         assertFalse(future.isCancelled());
154         assertTrue(future.isDone());
155     }
156 
157     @Test
158     @SuppressWarnings({ "unchecked" })
159     public void testExceptionListeners() {
160         final MockAbstractIoFuture<Boolean> future = spy(new MockAbstractIoFuture<Boolean>());
161         final IoFutureListener<Boolean> listener = mock(IoFutureListener.class);
162 
163         future.register(listener);
164 
165         assertFalse(future.isCancelled());
166         assertFalse(future.isDone());
167 
168         future.setException(new NullPointerException());
169 
170         assertFalse(future.isCancelled());
171         assertTrue(future.isDone());
172 
173         verify(listener).exception(argThat(matchesExecutionException()));
174         verify(listener, never()).completed(Matchers.<Boolean> any());
175     }
176 
177     @Test
178     @SuppressWarnings({ "unchecked" })
179     public void testExceptionListenersExceptionAlreadySet() {
180         final MockAbstractIoFuture<Boolean> future = spy(new MockAbstractIoFuture<Boolean>());
181         final IoFutureListener<Boolean> listener = mock(IoFutureListener.class);
182 
183         assertFalse(future.isCancelled());
184         assertFalse(future.isDone());
185 
186         future.setException(new NullPointerException());
187         future.register(listener);
188 
189         assertFalse(future.isCancelled());
190         assertTrue(future.isDone());
191 
192         verify(listener).exception(argThat(matchesExecutionException()));
193         verify(listener, never()).completed(Matchers.<Boolean> any());
194     }
195 
196     @Test
197     public void testImmediateExceptionForTimedGet() {
198         final MockAbstractIoFuture<Boolean> future = spy(new MockAbstractIoFuture<Boolean>());
199 
200         assertFalse(future.isCancelled());
201         assertFalse(future.isDone());
202 
203         future.setException(new NullPointerException());
204 
205         assertFalse(future.isCancelled());
206         assertTrue(future.isDone());
207 
208         try {
209             future.get(1, TimeUnit.DAYS);
210             fail("This future had an execution exception");
211         } catch (final InterruptedException e) {
212             fail("This future was not interrupted");
213         } catch (final ExecutionException ee) {
214             assertTrue(ee.getCause() instanceof NullPointerException);
215         } catch (final TimeoutException e) {
216             fail("This future was not interrupted");
217         }
218 
219         assertFalse(future.isCancelled());
220         assertTrue(future.isDone());
221     }
222 
223     @Test
224     public void testTimedExceptionForTimedGet() {
225         final MockAbstractIoFuture<Boolean> future = spy(new MockAbstractIoFuture<Boolean>());
226 
227         assertFalse(future.isCancelled());
228         assertFalse(future.isDone());
229 
230         new Thread(new Runnable() {
231             @Override
232             public void run() {
233                 try {
234                     Thread.sleep(1000);
235                     future.setException(new NullPointerException());
236                 } catch (final InterruptedException ignored) {
237                 }
238             }
239         }).start();
240 
241         try {
242             assertTrue(future.get(1, TimeUnit.DAYS));
243         } catch (final InterruptedException e) {
244             fail("This future was not interrupted");
245         } catch (final ExecutionException ee) {
246         } catch (final TimeoutException e) {
247             fail("This future was not interrupted");
248         }
249 
250         assertFalse(future.isCancelled());
251         assertTrue(future.isDone());
252     }
253 
254     @Test
255     public void testCancel() throws Exception {
256         final MockAbstractIoFuture<Boolean> future = spy(new MockAbstractIoFuture<Boolean>());
257         doReturn(true).when(future).cancelOwner(anyBoolean());
258 
259         assertFalse(future.isCancelled());
260         assertFalse(future.isDone());
261         assertTrue(future.cancel(false));
262         assertTrue(future.isCancelled());
263         assertTrue(future.isDone());
264         assertFalse(future.cancel(false));
265         assertTrue(future.isCancelled());
266         assertTrue(future.isDone());
267 
268         try {
269             future.get();
270             fail("This future was canceled");
271         } catch (final CancellationException ignore) {
272         }
273     }
274 
275     @Test
276     public void testCancelUncancelableOwner() throws Exception {
277         final MockAbstractIoFuture<Boolean> future = spy(new MockAbstractIoFuture<Boolean>());
278         doReturn(false).when(future).cancelOwner(anyBoolean());
279 
280         assertFalse(future.isCancelled());
281         assertFalse(future.isDone());
282         assertFalse(future.cancel(false));
283         assertFalse(future.isCancelled());
284         assertTrue(future.isDone());
285     }
286 
287     @Test
288     public void testCancelFinishedFuture() throws Exception {
289         final MockAbstractIoFuture<Boolean> future = spy(new MockAbstractIoFuture<Boolean>());
290         doReturn(true).when(future).cancelOwner(anyBoolean());
291 
292         future.setResult(true);
293 
294         assertFalse(future.isCancelled());
295         assertTrue(future.isDone());
296         assertFalse(future.cancel(false));
297         assertFalse(future.isCancelled());
298         assertTrue(future.isDone());
299 
300         assertTrue(future.get());
301     }
302 
303     @Test
304     @SuppressWarnings({ "unchecked" })
305     public void testCanceledListeners() {
306         final MockAbstractIoFuture<Boolean> future = spy(new MockAbstractIoFuture<Boolean>());
307         doReturn(true).when(future).cancelOwner(anyBoolean());
308         final IoFutureListener<Boolean> listener = mock(IoFutureListener.class);
309 
310         future.register(listener);
311 
312         assertFalse(future.isCancelled());
313         assertFalse(future.isDone());
314 
315         future.cancel(true);
316 
317         assertTrue(future.isCancelled());
318         assertTrue(future.isDone());
319 
320         verify(listener).exception(Matchers.<CancellationException> any());
321         verify(listener, never()).completed(Matchers.<Boolean> any());
322     }
323 
324     @Test
325     @SuppressWarnings({ "unchecked" })
326     public void testCanceledListenersAlreadySet() {
327         final MockAbstractIoFuture<Boolean> future = spy(new MockAbstractIoFuture<Boolean>());
328         doReturn(true).when(future).cancelOwner(anyBoolean());
329         final IoFutureListener<Boolean> listener = mock(IoFutureListener.class);
330 
331         assertFalse(future.isCancelled());
332         assertFalse(future.isDone());
333 
334         future.cancel(true);
335         future.register(listener);
336 
337         assertTrue(future.isCancelled());
338         assertTrue(future.isDone());
339 
340         verify(listener).exception(Matchers.<CancellationException> any());
341         verify(listener, never()).completed(Matchers.<Boolean> any());
342     }
343 
344     @Test
345     public void testTimeout() {
346         final MockAbstractIoFuture<Boolean> future = spy(new MockAbstractIoFuture<Boolean>());
347 
348         assertFalse(future.isCancelled());
349         assertFalse(future.isDone());
350 
351         try {
352             future.get(10, TimeUnit.MILLISECONDS);
353             fail("This future has timed out");
354         } catch (final InterruptedException e) {
355             fail("This future was not interrupted");
356         } catch (final ExecutionException ee) {
357             fail("This future did not have an execution exception");
358         } catch (final TimeoutException e) {
359         }
360     }
361 
362     private static Matcher<Throwable> matchesExecutionException() {
363         return new BaseMatcher<Throwable>() {
364             @Override
365             public boolean matches(final Object item) {
366                 return item instanceof ExecutionException
367                         && ((ExecutionException) item).getCause() instanceof NullPointerException;
368             }
369 
370             @Override
371             public void describeTo(final Description description) {
372                 description.appendText("ExecutionException(NullPointerException)");
373             }
374         };
375     }
376 
377     public static class MockAbstractIoFuture<V> extends AbstractIoFuture<V> {
378 
379         @Override
380         protected boolean cancelOwner(final boolean mayInterruptIfRunning) {
381             throw new UnsupportedOperationException();
382         }
383     }
384 }