View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.lang3.concurrent;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertFalse;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertNull;
24  import static org.junit.jupiter.api.Assertions.assertSame;
25  import static org.junit.jupiter.api.Assertions.assertThrows;
26  import static org.junit.jupiter.api.Assertions.assertTrue;
27  
28  import java.util.concurrent.ConcurrentHashMap;
29  import java.util.concurrent.ConcurrentMap;
30  import java.util.concurrent.ExecutionException;
31  import java.util.concurrent.Future;
32  import java.util.concurrent.TimeUnit;
33  
34  import org.apache.commons.lang3.AbstractLangTest;
35  import org.easymock.EasyMock;
36  import org.junit.jupiter.api.Test;
37  
38  /**
39   * Test class for {@link ConcurrentUtils}.
40   */
41  class ConcurrentUtilsTest extends AbstractLangTest {
42      /**
43       * Tests constant future.
44       *
45       * @throws Exception so we don't have to catch it
46       */
47      @Test
48      void testConstantFuture_Integer() throws Exception {
49          final Integer value = Integer.valueOf(5);
50          final Future<Integer> test = ConcurrentUtils.constantFuture(value);
51          assertTrue(test.isDone());
52          assertSame(value, test.get());
53          assertSame(value, test.get(1000, TimeUnit.SECONDS));
54          assertSame(value, test.get(1000, null));
55          assertFalse(test.isCancelled());
56          assertFalse(test.cancel(true));
57          assertFalse(test.cancel(false));
58      }
59  
60      /**
61       * Tests constant future.
62       *
63       * @throws Exception so we don't have to catch it
64       */
65      @Test
66      void testConstantFuture_null() throws Exception {
67          final Integer value = null;
68          final Future<Integer> test = ConcurrentUtils.constantFuture(value);
69          assertTrue(test.isDone());
70          assertSame(value, test.get());
71          assertSame(value, test.get(1000, TimeUnit.SECONDS));
72          assertSame(value, test.get(1000, null));
73          assertFalse(test.isCancelled());
74          assertFalse(test.cancel(true));
75          assertFalse(test.cancel(false));
76      }
77  
78      /**
79       * Tests createIfAbsent() if the map does not contain the key in question.
80       *
81       * @throws org.apache.commons.lang3.concurrent.ConcurrentException so we don't have to catch it
82       */
83      @Test
84      void testCreateIfAbsentKeyNotPresent() throws ConcurrentException {
85          final ConcurrentInitializer<Integer> init = EasyMock.createMock(ConcurrentInitializer.class);
86          final String key = "testKey";
87          final Integer value = 42;
88          EasyMock.expect(init.get()).andReturn(value);
89          EasyMock.replay(init);
90          final ConcurrentMap<String, Integer> map = new ConcurrentHashMap<>();
91          assertEquals(value, ConcurrentUtils.createIfAbsent(map, key, init), "Wrong result");
92          assertEquals(value, map.get(key), "Wrong value in map");
93          EasyMock.verify(init);
94      }
95  
96      /**
97       * Tests createIfAbsent() if the key is found in the map.
98       *
99       * @throws org.apache.commons.lang3.concurrent.ConcurrentException so we don't have to catch it
100      */
101     @Test
102     void testCreateIfAbsentKeyPresent() throws ConcurrentException {
103         final ConcurrentInitializer<Integer> init = EasyMock.createMock(ConcurrentInitializer.class);
104         EasyMock.replay(init);
105         final String key = "testKey";
106         final Integer value = 42;
107         final ConcurrentMap<String, Integer> map = new ConcurrentHashMap<>();
108         map.put(key, value);
109         assertEquals(value, ConcurrentUtils.createIfAbsent(map, key, init), "Wrong result");
110         assertEquals(value, map.get(key), "Wrong value in map");
111         EasyMock.verify(init);
112     }
113 
114     /**
115      * Tests createIfAbsent() if a null initializer is passed in.
116      *
117      * @throws org.apache.commons.lang3.concurrent.ConcurrentException so we don't have to catch it
118      */
119     @Test
120     void testCreateIfAbsentNullInit() throws ConcurrentException {
121         final ConcurrentMap<String, Integer> map = new ConcurrentHashMap<>();
122         final String key = "testKey";
123         final Integer value = 42;
124         map.put(key, value);
125         assertNull(ConcurrentUtils.createIfAbsent(map, key, null), "Wrong result");
126         assertEquals(value, map.get(key), "Map was changed");
127     }
128 
129     /**
130      * Tests createIfAbsent() if a null map is passed in.
131      *
132      * @throws org.apache.commons.lang3.concurrent.ConcurrentException so we don't have to catch it
133      */
134     @Test
135     void testCreateIfAbsentNullMap() throws ConcurrentException {
136         final ConcurrentInitializer<Integer> init = EasyMock.createMock(ConcurrentInitializer.class);
137         EasyMock.replay(init);
138         assertNull(ConcurrentUtils.createIfAbsent(null, "test", init), "Wrong result");
139         EasyMock.verify(init);
140     }
141 
142     /**
143      * Tests createIfAbsentUnchecked() if an exception is thrown.
144      *
145      * @throws org.apache.commons.lang3.concurrent.ConcurrentException so we don't have to catch it
146      */
147     @Test
148     void testCreateIfAbsentUncheckedException() throws ConcurrentException {
149         final ConcurrentInitializer<Integer> init = EasyMock.createMock(ConcurrentInitializer.class);
150         final Exception ex = new Exception();
151         EasyMock.expect(init.get()).andThrow(new ConcurrentException(ex));
152         EasyMock.replay(init);
153         final ConcurrentRuntimeException crex = assertThrows(ConcurrentRuntimeException.class,
154             () -> ConcurrentUtils.createIfAbsentUnchecked(new ConcurrentHashMap<>(), "test", init));
155         assertEquals(ex, crex.getCause(), "Wrong cause");
156         EasyMock.verify(init);
157     }
158 
159     /**
160      * Tests createIfAbsentUnchecked() if no exception is thrown.
161      */
162     @Test
163     void testCreateIfAbsentUncheckedSuccess() {
164         final String key = "testKey";
165         final Integer value = 42;
166         final ConcurrentMap<String, Integer> map = new ConcurrentHashMap<>();
167         assertEquals(value, ConcurrentUtils.createIfAbsentUnchecked(map, key, new ConstantInitializer<>(value)), "Wrong result");
168         assertEquals(value, map.get(key), "Wrong value in map");
169     }
170 
171     /**
172      * Tests extractCause() if the cause is a checked exception.
173      */
174     @Test
175     void testExtractCauseChecked() {
176         final Exception ex = new Exception("Test");
177         final ConcurrentException cex = ConcurrentUtils.extractCause(new ExecutionException(ex));
178         assertSame(ex, cex.getCause(), "Wrong cause");
179     }
180 
181     /**
182      * Tests extractCause() if the cause is an error.
183      */
184     @Test
185     void testExtractCauseError() {
186         final Error err = new AssertionError("Test");
187         final AssertionError e = assertThrows(AssertionError.class, () -> ConcurrentUtils.extractCause(new ExecutionException(err)));
188         assertEquals(err, e, "Wrong error");
189     }
190 
191     /**
192      * Tests extractCause() for a null exception.
193      */
194     @Test
195     void testExtractCauseNull() {
196         assertNull(ConcurrentUtils.extractCause(null), "Non null result");
197     }
198 
199     /**
200      * Tests extractCause() if the cause of the passed in exception is null.
201      */
202     @Test
203     void testExtractCauseNullCause() {
204         assertNull(ConcurrentUtils.extractCause(new ExecutionException("Test", null)), "Non null result");
205     }
206 
207     /**
208      * Tests extractCauseUnchecked() if the cause is a checked exception.
209      */
210     @Test
211     void testExtractCauseUncheckedChecked() {
212         final Exception ex = new Exception("Test");
213         final ConcurrentRuntimeException cex = ConcurrentUtils.extractCauseUnchecked(new ExecutionException(ex));
214         assertSame(ex, cex.getCause(), "Wrong cause");
215     }
216 
217     /**
218      * Tests extractCauseUnchecked() if the cause is an error.
219      */
220     @Test
221     void testExtractCauseUncheckedError() {
222         final Error err = new AssertionError("Test");
223         final Error e = assertThrows(Error.class, () -> ConcurrentUtils.extractCauseUnchecked(new ExecutionException(err)));
224         assertEquals(err, e, "Wrong error");
225     }
226 
227     /**
228      * Tests extractCause() if the cause is an unchecked exception.
229      */
230     @Test
231     void testExtractCauseUncheckedException() {
232         final RuntimeException rex = new RuntimeException("Test");
233         assertThrows(RuntimeException.class, () -> ConcurrentUtils.extractCause(new ExecutionException(rex)));
234     }
235 
236     /**
237      * Tests extractCauseUnchecked() for a null exception.
238      */
239     @Test
240     void testExtractCauseUncheckedNull() {
241         assertNull(ConcurrentUtils.extractCauseUnchecked(null), "Non null result");
242     }
243 
244     /**
245      * Tests extractCauseUnchecked() if the cause of the passed in exception is null.
246      */
247     @Test
248     void testExtractCauseUncheckedNullCause() {
249         assertNull(ConcurrentUtils.extractCauseUnchecked(new ExecutionException("Test", null)), "Non null result");
250     }
251 
252     /**
253      * Tests extractCauseUnchecked() if the cause is an unchecked exception.
254      */
255     @Test
256     void testExtractCauseUncheckedUncheckedException() {
257         final RuntimeException rex = new RuntimeException("Test");
258         final RuntimeException r = assertThrows(RuntimeException.class, () -> ConcurrentUtils.extractCauseUnchecked(new ExecutionException(rex)));
259         assertEquals(rex, r, "Wrong exception");
260     }
261 
262     /**
263      * Tests handleCause() if the cause is a checked exception.
264      */
265     @Test
266     void testHandleCauseChecked() {
267         final Exception ex = new Exception("Test");
268         final ConcurrentException cex = assertThrows(ConcurrentException.class, () -> ConcurrentUtils.handleCause(new ExecutionException(ex)));
269         assertEquals(ex, cex.getCause(), "Wrong cause");
270     }
271 
272     /**
273      * Tests handleCause() if the cause is an error.
274      */
275     @Test
276     void testHandleCauseError() {
277         final Error err = new AssertionError("Test");
278         final Error e = assertThrows(Error.class, () -> ConcurrentUtils.handleCause(new ExecutionException(err)));
279         assertEquals(err, e, "Wrong error");
280     }
281 
282     /**
283      * Tests handleCause() for a null parameter or a null cause. In this case the method should do nothing. We can only test
284      * that no exception is thrown.
285      *
286      * @throws org.apache.commons.lang3.concurrent.ConcurrentException so we don't have to catch it
287      */
288     @Test
289     void testHandleCauseNull() throws ConcurrentException {
290         ConcurrentUtils.handleCause(null);
291         ConcurrentUtils.handleCause(new ExecutionException("Test", null));
292     }
293 
294     /**
295      * Tests handleCauseUnchecked() if the cause is a checked exception.
296      */
297     @Test
298     void testHandleCauseUncheckedChecked() {
299         final Exception ex = new Exception("Test");
300         final ConcurrentRuntimeException crex = assertThrows(ConcurrentRuntimeException.class,
301             () -> ConcurrentUtils.handleCauseUnchecked(new ExecutionException(ex)));
302         assertEquals(ex, crex.getCause(), "Wrong cause");
303     }
304 
305     /**
306      * Tests handleCauseUnchecked() if the cause is an error.
307      */
308     @Test
309     void testHandleCauseUncheckedError() {
310         final Error err = new AssertionError("Test");
311         final Error e = assertThrows(Error.class, () -> ConcurrentUtils.handleCauseUnchecked(new ExecutionException(err)));
312         assertEquals(err, e, "Wrong error");
313     }
314 
315     /**
316      * Tests handleCause() if the cause is an unchecked exception.
317      */
318     @Test
319     void testHandleCauseUncheckedException() {
320         final RuntimeException rex = new RuntimeException("Test");
321         final RuntimeException r = assertThrows(RuntimeException.class, () -> ConcurrentUtils.handleCause(new ExecutionException(rex)));
322         assertEquals(rex, r, "Wrong exception");
323     }
324 
325     /**
326      * Tests handleCauseUnchecked() for a null parameter or a null cause. In this case the method should do nothing. We can
327      * only test that no exception is thrown.
328      */
329     @Test
330     void testHandleCauseUncheckedNull() {
331         ConcurrentUtils.handleCauseUnchecked(null);
332         ConcurrentUtils.handleCauseUnchecked(new ExecutionException("Test", null));
333     }
334 
335     /**
336      * Tests handleCauseUnchecked() if the cause is an unchecked exception.
337      */
338     @Test
339     void testHandleCauseUncheckedUncheckedException() {
340         final RuntimeException rex = new RuntimeException("Test");
341         final RuntimeException r = assertThrows(RuntimeException.class, () -> ConcurrentUtils.handleCauseUnchecked(new ExecutionException(rex)));
342         assertEquals(rex, r, "Wrong exception");
343     }
344 
345     /**
346      * Tests a successful initialize() operation.
347      *
348      * @throws org.apache.commons.lang3.concurrent.ConcurrentException so we don't have to catch it
349      */
350     @Test
351     void testInitialize() throws ConcurrentException {
352         final ConcurrentInitializer<Object> init = EasyMock.createMock(ConcurrentInitializer.class);
353         final Object result = new Object();
354         EasyMock.expect(init.get()).andReturn(result);
355         EasyMock.replay(init);
356         assertSame(result, ConcurrentUtils.initialize(init), "Wrong result object");
357         EasyMock.verify(init);
358     }
359 
360     /**
361      * Tests initialize() for a null argument.
362      *
363      * @throws org.apache.commons.lang3.concurrent.ConcurrentException so we don't have to catch it
364      */
365     @Test
366     void testInitializeNull() throws ConcurrentException {
367         assertNull(ConcurrentUtils.initialize(null), "Got a result");
368     }
369 
370     /**
371      * Tests a successful initializeUnchecked() operation.
372      *
373      * @throws org.apache.commons.lang3.concurrent.ConcurrentException so we don't have to catch it
374      */
375     @Test
376     void testInitializeUnchecked() throws ConcurrentException {
377         final ConcurrentInitializer<Object> init = EasyMock.createMock(ConcurrentInitializer.class);
378         final Object result = new Object();
379         EasyMock.expect(init.get()).andReturn(result);
380         EasyMock.replay(init);
381         assertSame(result, ConcurrentUtils.initializeUnchecked(init), "Wrong result object");
382         EasyMock.verify(init);
383     }
384 
385     /**
386      * Tests whether exceptions are correctly handled by initializeUnchecked().
387      *
388      * @throws org.apache.commons.lang3.concurrent.ConcurrentException so we don't have to catch it
389      */
390     @Test
391     void testInitializeUncheckedEx() throws ConcurrentException {
392         final ConcurrentInitializer<Object> init = EasyMock.createMock(ConcurrentInitializer.class);
393         final Exception cause = new Exception();
394         EasyMock.expect(init.get()).andThrow(new ConcurrentException(cause));
395         EasyMock.replay(init);
396         final ConcurrentRuntimeException crex = assertThrows(ConcurrentRuntimeException.class, () -> ConcurrentUtils.initializeUnchecked(init));
397         assertSame(cause, crex.getCause(), "Wrong cause");
398         EasyMock.verify(init);
399     }
400 
401     /**
402      * Tests initializeUnchecked() for a null argument.
403      */
404     @Test
405     void testInitializeUncheckedNull() {
406         assertNull(ConcurrentUtils.initializeUnchecked(null), "Got a result");
407     }
408 
409     /**
410      * Tests putIfAbsent() if the map does not contain the key in question.
411      */
412     @Test
413     void testPutIfAbsentKeyNotPresent() {
414         final String key = "testKey";
415         final Integer value = 42;
416         final ConcurrentMap<String, Integer> map = new ConcurrentHashMap<>();
417         assertEquals(value, ConcurrentUtils.putIfAbsent(map, key, value), "Wrong result");
418         assertEquals(value, map.get(key), "Wrong value in map");
419     }
420 
421     /**
422      * Tests putIfAbsent() if the map contains the key in question.
423      */
424     @Test
425     void testPutIfAbsentKeyPresent() {
426         final String key = "testKey";
427         final Integer value = 42;
428         final ConcurrentMap<String, Integer> map = new ConcurrentHashMap<>();
429         map.put(key, value);
430         assertEquals(value, ConcurrentUtils.putIfAbsent(map, key, 0), "Wrong result");
431         assertEquals(value, map.get(key), "Wrong value in map");
432     }
433 
434     /**
435      * Tests putIfAbsent() if a null map is passed in.
436      */
437     @Test
438     void testPutIfAbsentNullMap() {
439         assertNull(ConcurrentUtils.putIfAbsent(null, "test", 100), "Wrong result");
440     }
441 
442     /**
443      * Tests creating ConcurrentRuntimeException with no arguments.
444      */
445     @Test
446     void testUninitializedConcurrentRuntimeException() {
447         assertNotNull(new ConcurrentRuntimeException(), "Error creating empty ConcurrentRuntimeException");
448     }
449 }