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