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  package org.apache.commons.lang3;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertInstanceOf;
21  import static org.junit.jupiter.api.Assertions.assertNotNull;
22  import static org.junit.jupiter.api.Assertions.assertNull;
23  import static org.junit.jupiter.api.Assertions.assertSame;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  
27  import java.io.IOException;
28  import java.io.UncheckedIOException;
29  import java.lang.reflect.UndeclaredThrowableException;
30  import java.util.concurrent.Callable;
31  import java.util.function.BiConsumer;
32  import java.util.function.BiFunction;
33  import java.util.function.BiPredicate;
34  import java.util.function.Consumer;
35  import java.util.function.Function;
36  import java.util.function.Predicate;
37  import java.util.function.Supplier;
38  
39  import org.apache.commons.lang3.Functions.FailableBiConsumer;
40  import org.apache.commons.lang3.Functions.FailableBiFunction;
41  import org.apache.commons.lang3.Functions.FailableCallable;
42  import org.apache.commons.lang3.Functions.FailableConsumer;
43  import org.apache.commons.lang3.Functions.FailableFunction;
44  import org.apache.commons.lang3.Functions.FailableSupplier;
45  import org.junit.jupiter.api.Test;
46  
47  /**
48   * Tests Functions.
49   *
50   * @deprecated this test can be removed once the deprecated source class {@link org.apache.commons.lang3.Functions} is removed.
51   */
52  @Deprecated
53  class FunctionsTest extends AbstractLangTest {
54  
55      public static class CloseableObject {
56          private boolean closed;
57  
58          public void close() {
59              closed = true;
60          }
61  
62          public boolean isClosed() {
63              return closed;
64          }
65  
66          public void reset() {
67              closed = false;
68          }
69  
70          public void run(final Throwable throwable) throws Throwable {
71              if (throwable != null) {
72                  throw throwable;
73              }
74          }
75      }
76  
77      public static class FailureOnOddInvocations {
78          private static int invocations;
79  
80          static boolean failingBool() throws SomeException {
81              throwOnOdd();
82              return true;
83          }
84  
85          static boolean testDouble(final double value) throws SomeException {
86              throwOnOdd();
87              return true;
88          }
89  
90          static boolean testInt(final int value) throws SomeException {
91              throwOnOdd();
92              return true;
93          }
94  
95          static boolean testLong(final long value) throws SomeException {
96              throwOnOdd();
97              return true;
98          }
99  
100         private static void throwOnOdd() throws SomeException {
101             final int i = ++invocations;
102             if (i % 2 == 1) {
103                 throw new SomeException("Odd Invocation: " + i);
104             }
105         }
106 
107         FailureOnOddInvocations() throws SomeException {
108             throwOnOdd();
109         }
110 
111         boolean getAsBoolean() throws SomeException {
112             throwOnOdd();
113             return true;
114         }
115     }
116 
117     public static class SomeException extends Exception {
118 
119         private static final long serialVersionUID = -4965704778119283411L;
120 
121         private Throwable t;
122 
123         SomeException(final String message) {
124             super(message);
125         }
126 
127         public void setThrowable(final Throwable throwable) {
128             t = throwable;
129         }
130 
131         void test() throws Throwable {
132             if (t != null) {
133                 throw t;
134             }
135         }
136     }
137 
138     public static class Testable<T, P> {
139         private T acceptedObject;
140         private P acceptedPrimitiveObject1;
141         private P acceptedPrimitiveObject2;
142         private Throwable throwable;
143 
144         Testable(final Throwable throwable) {
145             this.throwable = throwable;
146         }
147 
148         public T getAcceptedObject() {
149             return acceptedObject;
150         }
151 
152         public P getAcceptedPrimitiveObject1() {
153             return acceptedPrimitiveObject1;
154         }
155 
156         public P getAcceptedPrimitiveObject2() {
157             return acceptedPrimitiveObject2;
158         }
159 
160         public void setThrowable(final Throwable throwable) {
161             this.throwable = throwable;
162         }
163 
164         void test() throws Throwable {
165             test(throwable);
166         }
167 
168         public Object test(final Object input1, final Object input2) throws Throwable {
169             test(throwable);
170             return acceptedObject;
171         }
172 
173         void test(final Throwable throwable) throws Throwable {
174             if (throwable != null) {
175                 throw throwable;
176             }
177         }
178 
179         public boolean testAsBooleanPrimitive() throws Throwable {
180             return testAsBooleanPrimitive(throwable);
181         }
182 
183         public boolean testAsBooleanPrimitive(final Throwable throwable) throws Throwable {
184             if (throwable != null) {
185                 throw throwable;
186             }
187             return false;
188         }
189 
190         public double testAsDoublePrimitive() throws Throwable {
191             return testAsDoublePrimitive(throwable);
192         }
193 
194         public double testAsDoublePrimitive(final Throwable throwable) throws Throwable {
195             if (throwable != null) {
196                 throw throwable;
197             }
198             return 0;
199         }
200 
201         public Integer testAsInteger() throws Throwable {
202             return testAsInteger(throwable);
203         }
204 
205         public Integer testAsInteger(final Throwable throwable) throws Throwable {
206             if (throwable != null) {
207                 throw throwable;
208             }
209             return 0;
210         }
211 
212         public int testAsIntPrimitive() throws Throwable {
213             return testAsIntPrimitive(throwable);
214         }
215 
216         public int testAsIntPrimitive(final Throwable throwable) throws Throwable {
217             if (throwable != null) {
218                 throw throwable;
219             }
220             return 0;
221         }
222 
223         public long testAsLongPrimitive() throws Throwable {
224             return testAsLongPrimitive(throwable);
225         }
226 
227         public long testAsLongPrimitive(final Throwable throwable) throws Throwable {
228             if (throwable != null) {
229                 throw throwable;
230             }
231             return 0;
232         }
233 
234         void testDouble(final double i) throws Throwable {
235             test(throwable);
236             acceptedPrimitiveObject1 = (P) (Double) i;
237         }
238 
239         public double testDoubleDouble(final double i, final double j) throws Throwable {
240             test(throwable);
241             acceptedPrimitiveObject1 = (P) (Double) i;
242             acceptedPrimitiveObject2 = (P) (Double) j;
243             return 3d;
244         }
245 
246         void testInt(final int i) throws Throwable {
247             test(throwable);
248             acceptedPrimitiveObject1 = (P) (Integer) i;
249         }
250 
251         void testLong(final long i) throws Throwable {
252             test(throwable);
253             acceptedPrimitiveObject1 = (P) (Long) i;
254         }
255 
256         void testObjDouble(final T object, final double i) throws Throwable {
257             test(throwable);
258             acceptedObject = object;
259             acceptedPrimitiveObject1 = (P) (Double) i;
260         }
261 
262         void testObjInt(final T object, final int i) throws Throwable {
263             test(throwable);
264             acceptedObject = object;
265             acceptedPrimitiveObject1 = (P) (Integer) i;
266         }
267 
268         void testObjLong(final T object, final long i) throws Throwable {
269             test(throwable);
270             acceptedObject = object;
271             acceptedPrimitiveObject1 = (P) (Long) i;
272         }
273     }
274 
275     @Test
276     void testAcceptBiConsumer() {
277         final IllegalStateException ise = new IllegalStateException();
278         final Testable<?, ?> testable = new Testable<>(null);
279         Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(Testable::test, testable, ise));
280         assertSame(ise, e);
281 
282         final Error error = new OutOfMemoryError();
283         e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(Testable::test, testable, error));
284         assertSame(error, e);
285 
286         final IOException ioe = new IOException("Unknown I/O error");
287         testable.setThrowable(ioe);
288         e = assertThrows(UncheckedIOException.class, () -> Functions.accept(Testable::test, testable, ioe));
289         final Throwable t = e.getCause();
290         assertNotNull(t);
291         assertSame(ioe, t);
292 
293         testable.setThrowable(null);
294         Functions.accept(Testable::test, testable, (Throwable) null);
295     }
296 
297     @Test
298     void testAcceptConsumer() {
299         final IllegalStateException ise = new IllegalStateException();
300         final Testable<?, ?> testable = new Testable<>(ise);
301         Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(Testable::test, testable));
302         assertSame(ise, e);
303 
304         final Error error = new OutOfMemoryError();
305         testable.setThrowable(error);
306         e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(Testable::test, testable));
307         assertSame(error, e);
308 
309         final IOException ioe = new IOException("Unknown I/O error");
310         testable.setThrowable(ioe);
311         e = assertThrows(UncheckedIOException.class, () -> Functions.accept(Testable::test, testable));
312         final Throwable t = e.getCause();
313         assertNotNull(t);
314         assertSame(ioe, t);
315 
316         testable.setThrowable(null);
317         Functions.accept(Testable::test, testable);
318     }
319 
320     @Test
321     void testAcceptDoubleConsumer() {
322         final IllegalStateException ise = new IllegalStateException();
323         final Testable<?, Double> testable = new Testable<>(ise);
324         Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testDouble, 1d));
325         assertSame(ise, e);
326         assertNull(testable.getAcceptedPrimitiveObject1());
327 
328         final Error error = new OutOfMemoryError();
329         testable.setThrowable(error);
330         e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testDouble, 1d));
331         assertSame(error, e);
332         assertNull(testable.getAcceptedPrimitiveObject1());
333 
334         final IOException ioe = new IOException("Unknown I/O error");
335         testable.setThrowable(ioe);
336         e = assertThrows(UncheckedIOException.class, () -> Functions.accept(testable::testDouble, 1d));
337         final Throwable t = e.getCause();
338         assertNotNull(t);
339         assertSame(ioe, t);
340         assertNull(testable.getAcceptedPrimitiveObject1());
341 
342         testable.setThrowable(null);
343         Functions.accept(testable::testDouble, 1d);
344         assertEquals(1, testable.getAcceptedPrimitiveObject1());
345     }
346 
347     @Test
348     void testAcceptIntConsumer() {
349         final IllegalStateException ise = new IllegalStateException();
350         final Testable<?, Integer> testable = new Testable<>(ise);
351         Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testInt, 1));
352         assertSame(ise, e);
353         assertNull(testable.getAcceptedPrimitiveObject1());
354 
355         final Error error = new OutOfMemoryError();
356         testable.setThrowable(error);
357         e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testInt, 1));
358         assertSame(error, e);
359         assertNull(testable.getAcceptedPrimitiveObject1());
360 
361         final IOException ioe = new IOException("Unknown I/O error");
362         testable.setThrowable(ioe);
363         e = assertThrows(UncheckedIOException.class, () -> Functions.accept(testable::testInt, 1));
364         final Throwable t = e.getCause();
365         assertNotNull(t);
366         assertSame(ioe, t);
367         assertNull(testable.getAcceptedPrimitiveObject1());
368 
369         testable.setThrowable(null);
370         Functions.accept(testable::testInt, 1);
371         assertEquals(1, testable.getAcceptedPrimitiveObject1());
372     }
373 
374     @Test
375     void testAcceptLongConsumer() {
376         final IllegalStateException ise = new IllegalStateException();
377         final Testable<?, Long> testable = new Testable<>(ise);
378         Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testLong, 1L));
379         assertSame(ise, e);
380         assertNull(testable.getAcceptedPrimitiveObject1());
381 
382         final Error error = new OutOfMemoryError();
383         testable.setThrowable(error);
384         e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testLong, 1L));
385         assertSame(error, e);
386         assertNull(testable.getAcceptedPrimitiveObject1());
387 
388         final IOException ioe = new IOException("Unknown I/O error");
389         testable.setThrowable(ioe);
390         e = assertThrows(UncheckedIOException.class, () -> Functions.accept(testable::testLong, 1L));
391         final Throwable t = e.getCause();
392         assertNotNull(t);
393         assertSame(ioe, t);
394         assertNull(testable.getAcceptedPrimitiveObject1());
395 
396         testable.setThrowable(null);
397         Functions.accept(testable::testLong, 1L);
398         assertEquals(1, testable.getAcceptedPrimitiveObject1());
399     }
400 
401     @Test
402     void testAcceptObjDoubleConsumer() {
403         final IllegalStateException ise = new IllegalStateException();
404         final Testable<String, Double> testable = new Testable<>(ise);
405         Throwable e = assertThrows(IllegalStateException.class,
406             () -> Functions.accept(testable::testObjDouble, "X", 1d));
407         assertSame(ise, e);
408         assertNull(testable.getAcceptedObject());
409         assertNull(testable.getAcceptedPrimitiveObject1());
410 
411         final Error error = new OutOfMemoryError();
412         testable.setThrowable(error);
413         e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testObjDouble, "X", 1d));
414         assertSame(error, e);
415         assertNull(testable.getAcceptedObject());
416         assertNull(testable.getAcceptedPrimitiveObject1());
417 
418         final IOException ioe = new IOException("Unknown I/O error");
419         testable.setThrowable(ioe);
420         e = assertThrows(UncheckedIOException.class, () -> Functions.accept(testable::testObjDouble, "X", 1d));
421         final Throwable t = e.getCause();
422         assertNotNull(t);
423         assertSame(ioe, t);
424         assertNull(testable.getAcceptedObject());
425         assertNull(testable.getAcceptedPrimitiveObject1());
426 
427         testable.setThrowable(null);
428         Functions.accept(testable::testObjDouble, "X", 1d);
429         assertEquals("X", testable.getAcceptedObject());
430         assertEquals(1d, testable.getAcceptedPrimitiveObject1());
431     }
432 
433     @Test
434     void testAcceptObjIntConsumer() {
435         final IllegalStateException ise = new IllegalStateException();
436         final Testable<String, Integer> testable = new Testable<>(ise);
437         Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testObjInt, "X", 1));
438         assertSame(ise, e);
439         assertNull(testable.getAcceptedObject());
440         assertNull(testable.getAcceptedPrimitiveObject1());
441 
442         final Error error = new OutOfMemoryError();
443         testable.setThrowable(error);
444         e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testObjInt, "X", 1));
445         assertSame(error, e);
446         assertNull(testable.getAcceptedObject());
447         assertNull(testable.getAcceptedPrimitiveObject1());
448 
449         final IOException ioe = new IOException("Unknown I/O error");
450         testable.setThrowable(ioe);
451         e = assertThrows(UncheckedIOException.class, () -> Functions.accept(testable::testObjInt, "X", 1));
452         final Throwable t = e.getCause();
453         assertNotNull(t);
454         assertSame(ioe, t);
455         assertNull(testable.getAcceptedObject());
456         assertNull(testable.getAcceptedPrimitiveObject1());
457 
458         testable.setThrowable(null);
459         Functions.accept(testable::testObjInt, "X", 1);
460         assertEquals("X", testable.getAcceptedObject());
461         assertEquals(1, testable.getAcceptedPrimitiveObject1());
462     }
463 
464     @Test
465     void testAcceptObjLongConsumer() {
466         final IllegalStateException ise = new IllegalStateException();
467         final Testable<String, Long> testable = new Testable<>(ise);
468         Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testObjLong, "X", 1L));
469         assertSame(ise, e);
470         assertNull(testable.getAcceptedObject());
471         assertNull(testable.getAcceptedPrimitiveObject1());
472 
473         final Error error = new OutOfMemoryError();
474         testable.setThrowable(error);
475         e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testObjLong, "X", 1L));
476         assertSame(error, e);
477         assertNull(testable.getAcceptedObject());
478         assertNull(testable.getAcceptedPrimitiveObject1());
479 
480         final IOException ioe = new IOException("Unknown I/O error");
481         testable.setThrowable(ioe);
482         e = assertThrows(UncheckedIOException.class, () -> Functions.accept(testable::testObjLong, "X", 1L));
483         final Throwable t = e.getCause();
484         assertNotNull(t);
485         assertSame(ioe, t);
486         assertNull(testable.getAcceptedObject());
487         assertNull(testable.getAcceptedPrimitiveObject1());
488 
489         testable.setThrowable(null);
490         Functions.accept(testable::testObjLong, "X", 1L);
491         assertEquals("X", testable.getAcceptedObject());
492         assertEquals(1L, testable.getAcceptedPrimitiveObject1());
493     }
494 
495     @Test
496     void testApplyBiFunction() {
497         final IllegalStateException ise = new IllegalStateException();
498         final Testable<?, ?> testable = new Testable<>(null);
499         Throwable e = assertThrows(IllegalStateException.class,
500             () -> Functions.apply(Testable::testAsInteger, testable, ise));
501         assertSame(ise, e);
502 
503         final Error error = new OutOfMemoryError();
504         e = assertThrows(OutOfMemoryError.class, () -> Functions.apply(Testable::testAsInteger, testable, error));
505         assertSame(error, e);
506 
507         final IOException ioe = new IOException("Unknown I/O error");
508         e = assertThrows(UncheckedIOException.class, () -> Functions.apply(Testable::testAsInteger, testable, ioe));
509         final Throwable t = e.getCause();
510         assertNotNull(t);
511         assertSame(ioe, t);
512 
513         final Integer i = Functions.apply(Testable::testAsInteger, testable, (Throwable) null);
514         assertNotNull(i);
515         assertEquals(0, i.intValue());
516     }
517 
518     @Test
519     void testApplyFunction() {
520         final IllegalStateException ise = new IllegalStateException();
521         final Testable<?, ?> testable = new Testable<>(ise);
522         Throwable e = assertThrows(IllegalStateException.class,
523             () -> Functions.apply(Testable::testAsInteger, testable));
524         assertSame(ise, e);
525 
526         final Error error = new OutOfMemoryError();
527         testable.setThrowable(error);
528         e = assertThrows(OutOfMemoryError.class, () -> Functions.apply(Testable::testAsInteger, testable));
529         assertSame(error, e);
530 
531         final IOException ioe = new IOException("Unknown I/O error");
532         testable.setThrowable(ioe);
533         e = assertThrows(UncheckedIOException.class, () -> Functions.apply(Testable::testAsInteger, testable));
534         final Throwable t = e.getCause();
535         assertNotNull(t);
536         assertSame(ioe, t);
537 
538         testable.setThrowable(null);
539         final Integer i = Functions.apply(Testable::testAsInteger, testable);
540         assertNotNull(i);
541         assertEquals(0, i.intValue());
542     }
543 
544     @Test
545     void testAsCallable() {
546         FailureOnOddInvocations.invocations = 0;
547         final FailableCallable<FailureOnOddInvocations, SomeException> failableCallable = FailureOnOddInvocations::new;
548         final Callable<FailureOnOddInvocations> callable = Functions.asCallable(failableCallable);
549         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, callable::call);
550         final Throwable cause = e.getCause();
551         assertNotNull(cause);
552         assertInstanceOf(SomeException.class, cause);
553         assertEquals("Odd Invocation: 1", cause.getMessage());
554         final FailureOnOddInvocations instance;
555         try {
556             instance = callable.call();
557         } catch (final Exception ex) {
558             throw Functions.rethrow(ex);
559         }
560         assertNotNull(instance);
561     }
562 
563     @Test
564     void testAsConsumer() {
565         final IllegalStateException ise = new IllegalStateException();
566         final Testable<?, ?> testable = new Testable<>(ise);
567         final Consumer<Testable<?, ?>> consumer = Functions.asConsumer(Testable::test);
568         Throwable e = assertThrows(IllegalStateException.class, () -> consumer.accept(testable));
569         assertSame(ise, e);
570 
571         final Error error = new OutOfMemoryError();
572         testable.setThrowable(error);
573         e = assertThrows(OutOfMemoryError.class, () -> consumer.accept(testable));
574         assertSame(error, e);
575 
576         final IOException ioe = new IOException("Unknown I/O error");
577         testable.setThrowable(ioe);
578         e = assertThrows(UncheckedIOException.class, () -> consumer.accept(testable));
579         final Throwable t = e.getCause();
580         assertNotNull(t);
581         assertSame(ioe, t);
582 
583         testable.setThrowable(null);
584         Functions.accept(Testable::test, testable);
585     }
586 
587     @Test
588     void testAsRunnable() {
589         FailureOnOddInvocations.invocations = 0;
590         final Runnable runnable = Functions.asRunnable(FailureOnOddInvocations::new);
591         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, runnable::run);
592         final Throwable cause = e.getCause();
593         assertNotNull(cause);
594         assertInstanceOf(SomeException.class, cause);
595         assertEquals("Odd Invocation: 1", cause.getMessage());
596 
597         // Even invocations, should not throw an exception
598         runnable.run();
599     }
600 
601     @Test
602     void testAsSupplier() {
603         FailureOnOddInvocations.invocations = 0;
604         final FailableSupplier<FailureOnOddInvocations, Throwable> failableSupplier = FailureOnOddInvocations::new;
605         final Supplier<FailureOnOddInvocations> supplier = Functions.asSupplier(failableSupplier);
606         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, supplier::get);
607         final Throwable cause = e.getCause();
608         assertNotNull(cause);
609         assertInstanceOf(SomeException.class, cause);
610         assertEquals("Odd Invocation: 1", cause.getMessage());
611         assertNotNull(supplier.get());
612     }
613 
614     @Test
615     void testBiConsumer() {
616         final IllegalStateException ise = new IllegalStateException();
617         final Testable<?, ?> testable = new Testable<>(null);
618         final FailableBiConsumer<Testable<?, ?>, Throwable, Throwable> failableBiConsumer = (t, th) -> {
619             t.setThrowable(th);
620             t.test();
621         };
622         final BiConsumer<Testable<?, ?>, Throwable> consumer = Functions.asBiConsumer(failableBiConsumer);
623         Throwable e = assertThrows(IllegalStateException.class, () -> consumer.accept(testable, ise));
624         assertSame(ise, e);
625 
626         final Error error = new OutOfMemoryError();
627         e = assertThrows(OutOfMemoryError.class, () -> consumer.accept(testable, error));
628         assertSame(error, e);
629 
630         final IOException ioe = new IOException("Unknown I/O error");
631         testable.setThrowable(ioe);
632         e = assertThrows(UncheckedIOException.class, () -> consumer.accept(testable, ioe));
633         final Throwable t = e.getCause();
634         assertNotNull(t);
635         assertSame(ioe, t);
636 
637         consumer.accept(testable, null);
638     }
639 
640     @Test
641     void testBiFunction() {
642         final IllegalStateException ise = new IllegalStateException();
643         final Testable<?, ?> testable = new Testable<>(ise);
644         final FailableBiFunction<Testable<?, ?>, Throwable, Integer, Throwable> failableBiFunction = (t, th) -> {
645             t.setThrowable(th);
646             return Integer.valueOf(t.testAsInteger());
647         };
648         final BiFunction<Testable<?, ?>, Throwable, Integer> biFunction = Functions.asBiFunction(failableBiFunction);
649         Throwable e = assertThrows(IllegalStateException.class, () -> biFunction.apply(testable, ise));
650         assertSame(ise, e);
651 
652         final Error error = new OutOfMemoryError();
653         testable.setThrowable(error);
654         e = assertThrows(OutOfMemoryError.class, () -> biFunction.apply(testable, error));
655         assertSame(error, e);
656 
657         final IOException ioe = new IOException("Unknown I/O error");
658         testable.setThrowable(ioe);
659         e = assertThrows(UncheckedIOException.class, () -> biFunction.apply(testable, ioe));
660         final Throwable t = e.getCause();
661         assertNotNull(t);
662         assertSame(ioe, t);
663 
664         assertEquals(0, biFunction.apply(testable, null).intValue());
665     }
666 
667     @Test
668     /** Test that asPredicate(FailableBiPredicate) is converted to -> BiPredicate  */
669     void testBiPredicate() {
670         FailureOnOddInvocations.invocations = 0;
671         final Functions.FailableBiPredicate<Object, Object, Throwable> failableBiPredicate = (t1,
672             t2) -> FailureOnOddInvocations.failingBool();
673         final BiPredicate<?, ?> predicate = Functions.asBiPredicate(failableBiPredicate);
674         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class,
675             () -> predicate.test(null, null));
676         final Throwable cause = e.getCause();
677         assertNotNull(cause);
678         assertInstanceOf(SomeException.class, cause);
679         assertEquals("Odd Invocation: 1", cause.getMessage());
680         final boolean instance = predicate.test(null, null);
681         assertNotNull(instance);
682     }
683 
684     @Test
685     void testCallable() {
686         FailureOnOddInvocations.invocations = 0;
687         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class,
688             () -> Functions.run(FailureOnOddInvocations::new));
689         final Throwable cause = e.getCause();
690         assertNotNull(cause);
691         assertInstanceOf(SomeException.class, cause);
692         assertEquals("Odd Invocation: 1", cause.getMessage());
693         final FailureOnOddInvocations instance = Functions.call(FailureOnOddInvocations::new);
694         assertNotNull(instance);
695     }
696 
697     @Test
698     void testConstructor() {
699         // We allow this, which must have been an omission to make the ctor private.
700         // We could make the ctor private in 4.0.
701         new Functions();
702     }
703 
704     @Test
705     void testFunction() {
706         final IllegalStateException ise = new IllegalStateException();
707         final Testable<?, ?> testable = new Testable<>(ise);
708         final FailableFunction<Throwable, Integer, Throwable> failableFunction = th -> {
709             testable.setThrowable(th);
710             return Integer.valueOf(testable.testAsInteger());
711         };
712         final Function<Throwable, Integer> function = Functions.asFunction(failableFunction);
713         Throwable e = assertThrows(IllegalStateException.class, () -> function.apply(ise));
714         assertSame(ise, e);
715 
716         final Error error = new OutOfMemoryError();
717         testable.setThrowable(error);
718         e = assertThrows(OutOfMemoryError.class, () -> function.apply(error));
719         assertSame(error, e);
720 
721         final IOException ioe = new IOException("Unknown I/O error");
722         testable.setThrowable(ioe);
723         e = assertThrows(UncheckedIOException.class, () -> function.apply(ioe));
724         final Throwable t = e.getCause();
725         assertNotNull(t);
726         assertSame(ioe, t);
727 
728         assertEquals(0, function.apply(null).intValue());
729     }
730 
731     @Test
732     void testGetFromSupplier() {
733         FailureOnOddInvocations.invocations = 0;
734         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class,
735             () -> Functions.run(FailureOnOddInvocations::new));
736         final Throwable cause = e.getCause();
737         assertNotNull(cause);
738         assertInstanceOf(SomeException.class, cause);
739         assertEquals("Odd Invocation: 1", cause.getMessage());
740         final FailureOnOddInvocations instance = Functions.call(FailureOnOddInvocations::new);
741         assertNotNull(instance);
742     }
743 
744     @Test
745     void testGetSupplier() {
746         final IllegalStateException ise = new IllegalStateException();
747         final Testable<?, ?> testable = new Testable<>(ise);
748         Throwable e = assertThrows(IllegalStateException.class, () -> Functions.get(testable::testAsInteger));
749         assertSame(ise, e);
750 
751         final Error error = new OutOfMemoryError();
752         testable.setThrowable(error);
753         e = assertThrows(OutOfMemoryError.class, () -> Functions.get(testable::testAsInteger));
754         assertSame(error, e);
755 
756         final IOException ioe = new IOException("Unknown I/O error");
757         testable.setThrowable(ioe);
758         e = assertThrows(UncheckedIOException.class, () -> Functions.get(testable::testAsInteger));
759         final Throwable t = e.getCause();
760         assertNotNull(t);
761         assertSame(ioe, t);
762 
763         testable.setThrowable(null);
764         final Integer i = Functions.apply(Testable::testAsInteger, testable);
765         assertNotNull(i);
766         assertEquals(0, i.intValue());
767     }
768 
769     @Test
770     /** Test that asPredicate(FailablePredicate) is converted to -> Predicate  */
771     void testPredicate() {
772         FailureOnOddInvocations.invocations = 0;
773         final Functions.FailablePredicate<Object, Throwable> failablePredicate = t -> FailureOnOddInvocations
774             .failingBool();
775         final Predicate<?> predicate = Functions.asPredicate(failablePredicate);
776         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class,
777             () -> predicate.test(null));
778         final Throwable cause = e.getCause();
779         assertNotNull(cause);
780         assertInstanceOf(SomeException.class, cause);
781         assertEquals("Odd Invocation: 1", cause.getMessage());
782         final boolean instance = predicate.test(null);
783         assertNotNull(instance);
784     }
785 
786     @Test
787     void testRunnable() {
788         FailureOnOddInvocations.invocations = 0;
789         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class,
790             () -> Functions.run(FailureOnOddInvocations::new));
791         final Throwable cause = e.getCause();
792         assertNotNull(cause);
793         assertInstanceOf(SomeException.class, cause);
794         assertEquals("Odd Invocation: 1", cause.getMessage());
795 
796         // Even invocations, should not throw an exception
797         Functions.run(FailureOnOddInvocations::new);
798     }
799 
800     /**
801      * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
802      * Object and Throwable.
803      */
804     @Test
805     void testThrows_FailableBiConsumer_Object_Throwable() {
806         new Functions.FailableBiConsumer<Object, Object, Throwable>() {
807 
808             @Override
809             public void accept(final Object object1, final Object object2) throws Throwable {
810                 throw new IOException("test");
811             }
812         };
813     }
814 
815     /**
816      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
817      * generic test types.
818      */
819     @Test
820     void testThrows_FailableBiConsumer_String_IOException() {
821         new Functions.FailableBiConsumer<String, String, IOException>() {
822 
823             @Override
824             public void accept(final String object1, final String object2) throws IOException {
825                 throw new IOException("test");
826 
827             }
828         };
829     }
830 
831     /**
832      * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
833      * Object and Throwable.
834      */
835     @Test
836     void testThrows_FailableBiFunction_Object_Throwable() {
837         new Functions.FailableBiFunction<Object, Object, Object, Throwable>() {
838 
839             @Override
840             public Object apply(final Object input1, final Object input2) throws Throwable {
841                 throw new IOException("test");
842             }
843         };
844     }
845 
846     /**
847      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
848      * generic test types.
849      */
850     @Test
851     void testThrows_FailableBiFunction_String_IOException() {
852         new Functions.FailableBiFunction<String, String, String, IOException>() {
853 
854             @Override
855             public String apply(final String input1, final String input2) throws IOException {
856                 throw new IOException("test");
857             }
858         };
859     }
860 
861     /**
862      * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
863      * Object and Throwable.
864      */
865     @Test
866     void testThrows_FailableBiPredicate_Object_Throwable() {
867         new Functions.FailableBiPredicate<Object, Object, Throwable>() {
868 
869             @Override
870             public boolean test(final Object object1, final Object object2) throws Throwable {
871                 throw new IOException("test");
872             }
873         };
874     }
875 
876     /**
877      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
878      * generic test types.
879      */
880     @Test
881     void testThrows_FailableBiPredicate_String_IOException() {
882         new Functions.FailableBiPredicate<String, String, IOException>() {
883 
884             @Override
885             public boolean test(final String object1, final String object2) throws IOException {
886                 throw new IOException("test");
887             }
888         };
889     }
890 
891     /**
892      * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
893      * Object and Throwable.
894      */
895     @Test
896     void testThrows_FailableCallable_Object_Throwable() {
897         new Functions.FailableCallable<Object, Throwable>() {
898 
899             @Override
900             public Object call() throws Throwable {
901                 throw new IOException("test");
902             }
903         };
904     }
905 
906     /**
907      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
908      * generic test types.
909      */
910     @Test
911     void testThrows_FailableCallable_String_IOException() {
912         new Functions.FailableCallable<String, IOException>() {
913 
914             @Override
915             public String call() throws IOException {
916                 throw new IOException("test");
917             }
918         };
919     }
920 
921     /**
922      * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
923      * Object and Throwable.
924      */
925     @Test
926     void testThrows_FailableConsumer_Object_Throwable() {
927         new Functions.FailableConsumer<Object, Throwable>() {
928 
929             @Override
930             public void accept(final Object object) throws Throwable {
931                 throw new IOException("test");
932 
933             }
934         };
935     }
936 
937     /**
938      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
939      * generic test types.
940      */
941     @Test
942     void testThrows_FailableConsumer_String_IOException() {
943         new Functions.FailableConsumer<String, IOException>() {
944 
945             @Override
946             public void accept(final String object) throws IOException {
947                 throw new IOException("test");
948 
949             }
950         };
951     }
952 
953     /**
954      * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
955      * Object and Throwable.
956      */
957     @Test
958     void testThrows_FailableFunction_Object_Throwable() {
959         new Functions.FailableFunction<Object, Object, Throwable>() {
960 
961             @Override
962             public Object apply(final Object input) throws Throwable {
963                 throw new IOException("test");
964             }
965         };
966     }
967 
968     /**
969      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
970      * generic test types.
971      */
972     @Test
973     void testThrows_FailableFunction_String_IOException() {
974         new Functions.FailableFunction<String, String, IOException>() {
975 
976             @Override
977             public String apply(final String input) throws IOException {
978                 throw new IOException("test");
979             }
980         };
981     }
982 
983     /**
984      * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
985      * Object and Throwable.
986      */
987     @Test
988     void testThrows_FailablePredicate_Object_Throwable() {
989         new Functions.FailablePredicate<Object, Throwable>() {
990 
991             @Override
992             public boolean test(final Object object) throws Throwable {
993                 throw new IOException("test");
994             }
995         };
996     }
997 
998     /**
999      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
1000      * generic test types.
1001      */
1002     @Test
1003     void testThrows_FailablePredicate_String_IOException() {
1004         new Functions.FailablePredicate<String, IOException>() {
1005 
1006             @Override
1007             public boolean test(final String object) throws IOException {
1008                 throw new IOException("test");
1009             }
1010         };
1011     }
1012 
1013     /**
1014      * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
1015      * Object and Throwable.
1016      */
1017     @Test
1018     void testThrows_FailableRunnable_Object_Throwable() {
1019         new Functions.FailableRunnable<Throwable>() {
1020 
1021             @Override
1022             public void run() throws Throwable {
1023                 throw new IOException("test");
1024 
1025             }
1026         };
1027     }
1028 
1029     /**
1030      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
1031      * generic test types.
1032      */
1033     @Test
1034     void testThrows_FailableRunnable_String_IOException() {
1035         new Functions.FailableRunnable<IOException>() {
1036 
1037             @Override
1038             public void run() throws IOException {
1039                 throw new IOException("test");
1040             }
1041         };
1042     }
1043 
1044     /**
1045      * Tests that our failable interface is properly defined to throw any exception. using the top level generic types
1046      * Object and Throwable.
1047      */
1048     @Test
1049     void testThrows_FailableSupplier_Object_Throwable() {
1050         new Functions.FailableSupplier<Object, Throwable>() {
1051 
1052             @Override
1053             public Object get() throws Throwable {
1054                 throw new IOException("test");
1055             }
1056         };
1057     }
1058 
1059     /**
1060      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
1061      * generic test types.
1062      */
1063     @Test
1064     void testThrows_FailableSupplier_String_IOException() {
1065         new Functions.FailableSupplier<String, IOException>() {
1066 
1067             @Override
1068             public String get() throws IOException {
1069                 throw new IOException("test");
1070             }
1071         };
1072     }
1073 
1074     @Test
1075     void testTryWithResources() {
1076         final CloseableObject co = new CloseableObject();
1077         final FailableConsumer<Throwable, ? extends Throwable> consumer = co::run;
1078         final IllegalStateException ise = new IllegalStateException();
1079         Throwable e = assertThrows(IllegalStateException.class,
1080             () -> Functions.tryWithResources(() -> consumer.accept(ise), co::close));
1081         assertSame(ise, e);
1082 
1083         assertTrue(co.isClosed());
1084         co.reset();
1085         final Error error = new OutOfMemoryError();
1086         e = assertThrows(OutOfMemoryError.class,
1087             () -> Functions.tryWithResources(() -> consumer.accept(error), co::close));
1088         assertSame(error, e);
1089 
1090         assertTrue(co.isClosed());
1091         co.reset();
1092         final IOException ioe = new IOException("Unknown I/O error");
1093         final UncheckedIOException uioe = assertThrows(UncheckedIOException.class,
1094             () -> Functions.tryWithResources(() -> consumer.accept(ioe), co::close));
1095         final IOException cause = uioe.getCause();
1096         assertSame(ioe, cause);
1097 
1098         assertTrue(co.isClosed());
1099         co.reset();
1100         Functions.tryWithResources(() -> consumer.accept(null), co::close);
1101         assertTrue(co.isClosed());
1102     }
1103 }