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