1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
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 }