5087f15895f823ae8641f8276b4571c24a8339ec
[yangtools.git] / common / util / src / test / java / org / opendaylight / yangtools / util / concurrent / MappingCheckedFutureTest.java
1 /*
2  * Copyright (c) 2014 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.yangtools.util.concurrent;
10
11
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertNotNull;
14 import static org.junit.Assert.assertNull;
15 import static org.junit.Assert.assertSame;
16 import static org.junit.Assert.fail;
17 import com.google.common.util.concurrent.CheckedFuture;
18 import com.google.common.util.concurrent.SettableFuture;
19 import java.util.concurrent.CancellationException;
20 import java.util.concurrent.CountDownLatch;
21 import java.util.concurrent.ExecutionException;
22 import java.util.concurrent.TimeUnit;
23 import java.util.concurrent.atomic.AtomicReference;
24 import org.junit.Test;
25
26 /**
27  * Unit tests for MappingCheckedFuture.
28  *
29  * @author Thomas Pantelis
30  */
31 public class MappingCheckedFutureTest {
32
33     interface FutureInvoker {
34         void invokeGet( CheckedFuture<?,?> future ) throws Exception;
35         Throwable extractWrappedTestEx( Exception from );
36     }
37
38     @SuppressWarnings("serial")
39     static class TestException extends Exception {
40         TestException( final String message, final Throwable cause ) {
41             super( message, cause );
42         }
43     }
44
45     static final ExceptionMapper<TestException> MAPPER =  new ExceptionMapper<TestException>(
46                                                                       "Test", TestException.class ) {
47
48         @Override
49         protected TestException newWithCause( final String message, final Throwable cause ) {
50             return new TestException( message, cause );
51         }
52     };
53
54     static final FutureInvoker GET = new FutureInvoker() {
55         @Override
56         public void invokeGet( final CheckedFuture<?,?> future ) throws Exception {
57             future.get();
58         }
59
60         @Override
61         public Throwable extractWrappedTestEx( final Exception from ) {
62             if (from instanceof ExecutionException ) {
63                 return ((ExecutionException)from).getCause();
64             }
65
66             return from;
67         }
68     };
69
70     static final FutureInvoker TIMED_GET = new FutureInvoker() {
71         @Override
72         public void invokeGet( final CheckedFuture<?,?> future ) throws Exception {
73             future.get( 1, TimeUnit.HOURS );
74         }
75
76         @Override
77         public Throwable extractWrappedTestEx( final Exception from ) {
78             if (from instanceof ExecutionException ) {
79                 return ((ExecutionException)from).getCause();
80             }
81
82             return from;
83         }
84     };
85
86     static final FutureInvoker CHECKED_GET = new FutureInvoker() {
87         @Override
88         public void invokeGet( final CheckedFuture<?,?> future ) throws Exception {
89             future.checkedGet();
90         }
91
92         @Override
93         public Throwable extractWrappedTestEx( final Exception from ) {
94             return from;
95         }
96     };
97
98     static final FutureInvoker TIMED_CHECKED_GET = new FutureInvoker() {
99         @Override
100         public void invokeGet( final CheckedFuture<?,?> future ) throws Exception {
101             future.checkedGet( 50, TimeUnit.MILLISECONDS );
102         }
103
104         @Override
105         public Throwable extractWrappedTestEx( final Exception from ) {
106             return from;
107         }
108     };
109
110     @Test
111     public void testGet() throws Exception {
112
113         SettableFuture<String> delegate = SettableFuture.create();
114         MappingCheckedFuture<String,TestException> future = MappingCheckedFuture.create( delegate, MAPPER );
115         delegate.set( "test" );
116         assertEquals( "get", "test", future.get() );
117     }
118
119     @Test
120     public void testGetWithExceptions() throws Exception {
121
122         testExecutionException( GET, new RuntimeException() );
123         testExecutionException( GET, new TestException( "mock", null ) );
124         testCancellationException( GET );
125         testInterruptedException( GET );
126     }
127
128     @Test
129     public void testTimedGet() throws Exception {
130
131         SettableFuture<String> delegate = SettableFuture.create();
132         MappingCheckedFuture<String,TestException> future = MappingCheckedFuture.create( delegate, MAPPER );
133         delegate.set( "test" );
134         assertEquals( "get", "test", future.get( 50, TimeUnit.MILLISECONDS ) );
135     }
136
137     @Test
138     public void testTimedGetWithExceptions() throws Exception {
139
140         testExecutionException( TIMED_GET, new RuntimeException() );
141         testCancellationException( TIMED_GET );
142         testInterruptedException( TIMED_GET );
143     }
144
145     @Test
146     public void testCheckedGetWithExceptions() throws Exception {
147
148         testExecutionException( CHECKED_GET, new RuntimeException() );
149         testCancellationException( CHECKED_GET );
150         testInterruptedException( CHECKED_GET );
151     }
152
153     @Test
154     public void testTimedCheckedWithExceptions() throws Exception {
155
156         testExecutionException( TIMED_CHECKED_GET, new RuntimeException() );
157         testCancellationException( TIMED_CHECKED_GET );
158         testInterruptedException( TIMED_CHECKED_GET );
159     }
160
161     private static void testExecutionException( final FutureInvoker invoker, final Throwable cause ) {
162
163         SettableFuture<String> delegate = SettableFuture.create();
164         MappingCheckedFuture<String,TestException> mappingFuture =
165                                                         MappingCheckedFuture.create( delegate, MAPPER );
166
167         delegate.setException( cause );
168
169         try {
170             invoker.invokeGet( mappingFuture );
171             fail( "Expected exception thrown" );
172         } catch( Exception e ) {
173             Throwable expectedTestEx = invoker.extractWrappedTestEx( e );
174             assertNotNull( "Expected returned exception is null", expectedTestEx );
175             assertEquals( "Exception type", TestException.class, expectedTestEx.getClass() );
176
177             if (cause instanceof TestException ) {
178                 assertNull( "Expected null cause", expectedTestEx.getCause() );
179             } else {
180                 assertSame( "TestException cause", cause, expectedTestEx.getCause() );
181             }
182         }
183     }
184
185     private static void testCancellationException( final FutureInvoker invoker ) {
186
187         SettableFuture<String> delegate = SettableFuture.create();
188         MappingCheckedFuture<String,TestException> mappingFuture =
189                                                         MappingCheckedFuture.create( delegate, MAPPER );
190
191         mappingFuture.cancel( false );
192
193         try {
194             invoker.invokeGet( mappingFuture );
195             fail( "Expected exception thrown" );
196         } catch( Exception e ) {
197             Throwable expectedTestEx = invoker.extractWrappedTestEx( e );
198             assertNotNull( "Expected returned exception is null", expectedTestEx );
199             assertEquals( "Exception type", TestException.class, expectedTestEx.getClass() );
200             assertEquals( "TestException cause type", CancellationException.class,
201                           expectedTestEx.getCause().getClass() );
202         }
203     }
204
205     private static void testInterruptedException( final FutureInvoker invoker ) throws Exception {
206
207         SettableFuture<String> delegate = SettableFuture.create();
208         final MappingCheckedFuture<String,TestException> mappingFuture =
209                                                         MappingCheckedFuture.create( delegate, MAPPER );
210
211         final AtomicReference<AssertionError> assertError = new AtomicReference<>();
212         final CountDownLatch doneLatch = new CountDownLatch( 1 );
213         Thread thread = new Thread() {
214
215             @Override
216             public void run() {
217                 try {
218                     doInvoke();
219                 } catch( AssertionError e ) {
220                     assertError.set( e );
221                 } finally {
222                     doneLatch.countDown();
223                 }
224             }
225
226             void doInvoke() {
227                 try {
228                     invoker.invokeGet( mappingFuture );
229                     fail( "Expected exception thrown" );
230                 } catch( Exception e ) {
231                     Throwable expectedTestEx = invoker.extractWrappedTestEx( e );
232                     assertNotNull( "Expected returned exception is null", expectedTestEx );
233                     assertEquals( "Exception type", TestException.class, expectedTestEx.getClass() );
234                     assertEquals( "TestException cause type", InterruptedException.class,
235                                   expectedTestEx.getCause().getClass() );
236                 }
237             }
238         };
239         thread.start();
240
241         thread.interrupt();
242         assertEquals( "get call completed", true, doneLatch.await( 5, TimeUnit.SECONDS ) );
243
244         if (assertError.get() != null ) {
245             throw assertError.get();
246         }
247     }
248 }