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.function;
18  
19  import static org.apache.commons.lang3.LangAssertions.assertNullPointerException;
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.assertInstanceOf;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertNull;
25  import static org.junit.jupiter.api.Assertions.assertSame;
26  import static org.junit.jupiter.api.Assertions.assertThrows;
27  import static org.junit.jupiter.api.Assertions.assertTrue;
28  
29  import java.io.IOException;
30  import java.io.UncheckedIOException;
31  import java.lang.reflect.UndeclaredThrowableException;
32  import java.util.concurrent.Callable;
33  import java.util.function.BiConsumer;
34  import java.util.function.BiFunction;
35  import java.util.function.BiPredicate;
36  import java.util.function.Consumer;
37  import java.util.function.Function;
38  import java.util.function.Predicate;
39  import java.util.function.Supplier;
40  
41  import org.apache.commons.lang3.AbstractLangTest;
42  import org.apache.commons.lang3.StringUtils;
43  import org.junit.jupiter.api.BeforeEach;
44  import org.junit.jupiter.api.Test;
45  
46  /**
47   * Tests "failable" interfaces defined in this package.
48   */
49  class FailableTest extends AbstractLangTest {
50  
51      public static class CloseableObject {
52          private boolean closed;
53  
54          public void close() {
55              closed = true;
56          }
57  
58          public boolean isClosed() {
59              return closed;
60          }
61  
62          public void reset() {
63              closed = false;
64          }
65  
66          public void run(final Throwable throwable) throws Throwable {
67              if (throwable != null) {
68                  throw throwable;
69              }
70          }
71      }
72  
73      public static class FailureOnInvocationCount {
74          private int current;
75          private final int throwOn;
76  
77          FailureOnInvocationCount(final int throwOn) throws SomeException {
78              this.throwOn = throwOn;
79          }
80  
81          int inc(final int value) throws SomeException {
82              throwSeOn();
83              return value + 1;
84          }
85  
86          int incCnfe(final int value) throws ClassNotFoundException {
87              throwCnfeOn();
88              return value + 1;
89          }
90  
91          int incIo(final int value) throws IOException {
92              throwIoOn();
93              return value + 1;
94          }
95  
96          void reset() {
97              current = 0;
98          }
99  
100         private void throwCnfeOn() throws ClassNotFoundException {
101             if (++current == throwOn) {
102                 final String message = "Count: " + current;
103                 throw new ClassNotFoundException(message, new SomeException(message, current));
104             }
105         }
106 
107         private void throwIoOn() throws IOException {
108             if (++current == throwOn) {
109                 throw new IOException(new SomeException("Count: " + current, current));
110             }
111         }
112 
113         private void throwSeOn() throws SomeException {
114             if (++current == throwOn) {
115                 throw new SomeException("Count: " + current, current);
116             }
117         }
118 
119     }
120 
121     public static class FailureOnOddInvocations {
122         private static int invocations;
123 
124         static void reset() {
125             invocations = 0;
126         }
127 
128         static boolean testDouble(final double value) throws SomeException {
129             throwOnOdd();
130             return true;
131         }
132 
133         static boolean testGetBool() throws SomeException {
134             throwOnOdd();
135             return true;
136         }
137 
138         static int testInc(final int value) throws SomeException {
139             throwOnOdd();
140             return value + 1;
141         }
142 
143         static boolean testInt(final int value) throws SomeException {
144             throwOnOdd();
145             return true;
146         }
147 
148         static boolean testLong(final long value) throws SomeException {
149             throwOnOdd();
150             return true;
151         }
152 
153         private static void throwOnOdd() throws SomeException {
154             final int i = ++invocations;
155             if (i % 2 == 1) {
156                 throw new SomeException("Odd Invocation: " + i, i);
157             }
158         }
159 
160         FailureOnOddInvocations() throws SomeException {
161             throwOnOdd();
162         }
163 
164         boolean getAsBoolean() throws SomeException {
165             throwOnOdd();
166             return true;
167         }
168     }
169 
170     public static class SomeException extends Exception {
171 
172         private static final long serialVersionUID = -4965704778119283411L;
173 
174         private Throwable t;
175 
176         final int value;
177 
178         SomeException(final String message) {
179             this(message, 0);
180         }
181 
182         SomeException(final String message, final int value) {
183             super(message);
184             this.value = value;
185         }
186 
187         public void setThrowable(final Throwable throwable) {
188             t = throwable;
189         }
190 
191         void test() throws Throwable {
192             if (t != null) {
193                 throw t;
194             }
195         }
196     }
197 
198     public static class Testable<T, P> {
199         private T acceptedObject;
200         private P acceptedPrimitiveObject1;
201         private P acceptedPrimitiveObject2;
202         private Throwable throwable;
203 
204         Testable(final Throwable throwable) {
205             this.throwable = throwable;
206         }
207 
208         public T getAcceptedObject() {
209             return acceptedObject;
210         }
211 
212         public P getAcceptedPrimitiveObject1() {
213             return acceptedPrimitiveObject1;
214         }
215 
216         public P getAcceptedPrimitiveObject2() {
217             return acceptedPrimitiveObject2;
218         }
219 
220         public void setThrowable(final Throwable throwable) {
221             this.throwable = throwable;
222         }
223 
224         void test() throws Throwable {
225             test(throwable);
226         }
227 
228         public Object test(final Object input1, final Object input2) throws Throwable {
229             test(throwable);
230             return acceptedObject;
231         }
232 
233         void test(final Throwable throwable) throws Throwable {
234             if (throwable != null) {
235                 throw throwable;
236             }
237         }
238 
239         public boolean testAsBooleanPrimitive() throws Throwable {
240             return testAsBooleanPrimitive(throwable);
241         }
242 
243         public boolean testAsBooleanPrimitive(final Throwable throwable) throws Throwable {
244             if (throwable != null) {
245                 throw throwable;
246             }
247             return false;
248         }
249 
250         public double testAsDoublePrimitive() throws Throwable {
251             return testAsDoublePrimitive(throwable);
252         }
253 
254         public double testAsDoublePrimitive(final Throwable throwable) throws Throwable {
255             if (throwable != null) {
256                 throw throwable;
257             }
258             return 0;
259         }
260 
261         public Integer testAsInteger() throws Throwable {
262             return testAsInteger(throwable);
263         }
264 
265         public Integer testAsInteger(final Throwable throwable) throws Throwable {
266             if (throwable != null) {
267                 throw throwable;
268             }
269             return 0;
270         }
271 
272         public int testAsIntPrimitive() throws Throwable {
273             return testAsIntPrimitive(throwable);
274         }
275 
276         public int testAsIntPrimitive(final Throwable throwable) throws Throwable {
277             if (throwable != null) {
278                 throw throwable;
279             }
280             return 0;
281         }
282 
283         public long testAsLongPrimitive() throws Throwable {
284             return testAsLongPrimitive(throwable);
285         }
286 
287         public long testAsLongPrimitive(final Throwable throwable) throws Throwable {
288             if (throwable != null) {
289                 throw throwable;
290             }
291             return 0;
292         }
293 
294         public short testAsShortPrimitive() throws Throwable {
295             return testAsShortPrimitive(throwable);
296         }
297 
298         public short testAsShortPrimitive(final Throwable throwable) throws Throwable {
299             if (throwable != null) {
300                 throw throwable;
301             }
302             return 0;
303         }
304 
305         void testDouble(final double i) throws Throwable {
306             test(throwable);
307             acceptedPrimitiveObject1 = (P) (Double) i;
308         }
309 
310         public double testDoubleDouble(final double i, final double j) throws Throwable {
311             test(throwable);
312             acceptedPrimitiveObject1 = (P) (Double) i;
313             acceptedPrimitiveObject2 = (P) (Double) j;
314             return 3d;
315         }
316 
317         void testInt(final int i) throws Throwable {
318             test(throwable);
319             acceptedPrimitiveObject1 = (P) (Integer) i;
320         }
321 
322         void testLong(final long i) throws Throwable {
323             test(throwable);
324             acceptedPrimitiveObject1 = (P) (Long) i;
325         }
326 
327         void testObjDouble(final T object, final double i) throws Throwable {
328             test(throwable);
329             acceptedObject = object;
330             acceptedPrimitiveObject1 = (P) (Double) i;
331         }
332 
333         void testObjInt(final T object, final int i) throws Throwable {
334             test(throwable);
335             acceptedObject = object;
336             acceptedPrimitiveObject1 = (P) (Integer) i;
337         }
338 
339         void testObjLong(final T object, final long i) throws Throwable {
340             test(throwable);
341             acceptedObject = object;
342             acceptedPrimitiveObject1 = (P) (Long) i;
343         }
344     }
345 
346     private static final OutOfMemoryError ERROR = new OutOfMemoryError();
347 
348     private static final IllegalStateException ILLEGAL_STATE_EXCEPTION = new IllegalStateException();
349 
350     @BeforeEach
351     void beforeEach() {
352         FailureOnOddInvocations.reset();
353     }
354 
355     @Test
356     void testAcceptBiConsumer() {
357         final Testable<?, ?> testable = new Testable<>(null);
358         Throwable e = assertThrows(IllegalStateException.class,
359             () -> Failable.accept(Testable::test, testable, ILLEGAL_STATE_EXCEPTION));
360         assertSame(ILLEGAL_STATE_EXCEPTION, e);
361 
362         e = assertThrows(OutOfMemoryError.class, () -> Failable.accept(Testable::test, testable, ERROR));
363         assertSame(ERROR, e);
364 
365         final IOException ioe = new IOException("Unknown I/O error");
366         testable.setThrowable(ioe);
367         e = assertThrows(UncheckedIOException.class, () -> Failable.accept(Testable::test, testable, ioe));
368         final Throwable t = e.getCause();
369         assertNotNull(t);
370         assertSame(ioe, t);
371 
372         testable.setThrowable(null);
373         Failable.accept(Testable::test, testable, (Throwable) null);
374     }
375 
376     @Test
377     void testAcceptConsumer() {
378         final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
379         Throwable e = assertThrows(IllegalStateException.class, () -> Failable.accept(Testable::test, testable));
380         assertSame(ILLEGAL_STATE_EXCEPTION, e);
381 
382         testable.setThrowable(ERROR);
383         e = assertThrows(OutOfMemoryError.class, () -> Failable.accept(Testable::test, testable));
384         assertSame(ERROR, e);
385 
386         final IOException ioe = new IOException("Unknown I/O error");
387         testable.setThrowable(ioe);
388         e = assertThrows(UncheckedIOException.class, () -> Failable.accept(Testable::test, testable));
389         final Throwable t = e.getCause();
390         assertNotNull(t);
391         assertSame(ioe, t);
392 
393         testable.setThrowable(null);
394         Failable.accept(Testable::test, testable);
395     }
396 
397     @Test
398     void testAcceptDoubleConsumer() {
399         final Testable<?, Double> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
400         Throwable e = assertThrows(IllegalStateException.class, () -> Failable.accept(testable::testDouble, 1d));
401         assertSame(ILLEGAL_STATE_EXCEPTION, e);
402         assertNull(testable.getAcceptedPrimitiveObject1());
403 
404         testable.setThrowable(ERROR);
405         e = assertThrows(OutOfMemoryError.class, () -> Failable.accept(testable::testDouble, 1d));
406         assertSame(ERROR, e);
407         assertNull(testable.getAcceptedPrimitiveObject1());
408 
409         final IOException ioe = new IOException("Unknown I/O error");
410         testable.setThrowable(ioe);
411         e = assertThrows(UncheckedIOException.class, () -> Failable.accept(testable::testDouble, 1d));
412         final Throwable t = e.getCause();
413         assertNotNull(t);
414         assertSame(ioe, t);
415         assertNull(testable.getAcceptedPrimitiveObject1());
416 
417         testable.setThrowable(null);
418         Failable.accept(testable::testDouble, 1d);
419         assertEquals(1, testable.getAcceptedPrimitiveObject1());
420     }
421 
422     @Test
423     void testAcceptIntConsumer() {
424         final Testable<?, Integer> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
425         Throwable e = assertThrows(IllegalStateException.class, () -> Failable.accept(testable::testInt, 1));
426         assertSame(ILLEGAL_STATE_EXCEPTION, e);
427         assertNull(testable.getAcceptedPrimitiveObject1());
428 
429         testable.setThrowable(ERROR);
430         e = assertThrows(OutOfMemoryError.class, () -> Failable.accept(testable::testInt, 1));
431         assertSame(ERROR, e);
432         assertNull(testable.getAcceptedPrimitiveObject1());
433 
434         final IOException ioe = new IOException("Unknown I/O error");
435         testable.setThrowable(ioe);
436         e = assertThrows(UncheckedIOException.class, () -> Failable.accept(testable::testInt, 1));
437         final Throwable t = e.getCause();
438         assertNotNull(t);
439         assertSame(ioe, t);
440         assertNull(testable.getAcceptedPrimitiveObject1());
441 
442         testable.setThrowable(null);
443         Failable.accept(testable::testInt, 1);
444         assertEquals(1, testable.getAcceptedPrimitiveObject1());
445     }
446 
447     @Test
448     void testAcceptLongConsumer() {
449         final Testable<?, Long> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
450         Throwable e = assertThrows(IllegalStateException.class, () -> Failable.accept(testable::testLong, 1L));
451         assertSame(ILLEGAL_STATE_EXCEPTION, e);
452         assertNull(testable.getAcceptedPrimitiveObject1());
453 
454         testable.setThrowable(ERROR);
455         e = assertThrows(OutOfMemoryError.class, () -> Failable.accept(testable::testLong, 1L));
456         assertSame(ERROR, e);
457         assertNull(testable.getAcceptedPrimitiveObject1());
458 
459         final IOException ioe = new IOException("Unknown I/O error");
460         testable.setThrowable(ioe);
461         e = assertThrows(UncheckedIOException.class, () -> Failable.accept(testable::testLong, 1L));
462         final Throwable t = e.getCause();
463         assertNotNull(t);
464         assertSame(ioe, t);
465         assertNull(testable.getAcceptedPrimitiveObject1());
466 
467         testable.setThrowable(null);
468         Failable.accept(testable::testLong, 1L);
469         assertEquals(1, testable.getAcceptedPrimitiveObject1());
470     }
471 
472     @Test
473     void testAcceptObjDoubleConsumer() {
474         final Testable<String, Double> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
475         Throwable e = assertThrows(IllegalStateException.class,
476             () -> Failable.accept(testable::testObjDouble, "X", 1d));
477         assertSame(ILLEGAL_STATE_EXCEPTION, e);
478         assertNull(testable.getAcceptedObject());
479         assertNull(testable.getAcceptedPrimitiveObject1());
480 
481         testable.setThrowable(ERROR);
482         e = assertThrows(OutOfMemoryError.class, () -> Failable.accept(testable::testObjDouble, "X", 1d));
483         assertSame(ERROR, e);
484         assertNull(testable.getAcceptedObject());
485         assertNull(testable.getAcceptedPrimitiveObject1());
486 
487         final IOException ioe = new IOException("Unknown I/O error");
488         testable.setThrowable(ioe);
489         e = assertThrows(UncheckedIOException.class, () -> Failable.accept(testable::testObjDouble, "X", 1d));
490         final Throwable t = e.getCause();
491         assertNotNull(t);
492         assertSame(ioe, t);
493         assertNull(testable.getAcceptedObject());
494         assertNull(testable.getAcceptedPrimitiveObject1());
495 
496         testable.setThrowable(null);
497         Failable.accept(testable::testObjDouble, "X", 1d);
498         assertEquals("X", testable.getAcceptedObject());
499         assertEquals(1d, testable.getAcceptedPrimitiveObject1());
500     }
501 
502     @Test
503     void testAcceptObjIntConsumer() {
504         final Testable<String, Integer> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
505         Throwable e = assertThrows(IllegalStateException.class, () -> Failable.accept(testable::testObjInt, "X", 1));
506         assertSame(ILLEGAL_STATE_EXCEPTION, e);
507         assertNull(testable.getAcceptedObject());
508         assertNull(testable.getAcceptedPrimitiveObject1());
509 
510         testable.setThrowable(ERROR);
511         e = assertThrows(OutOfMemoryError.class, () -> Failable.accept(testable::testObjInt, "X", 1));
512         assertSame(ERROR, e);
513         assertNull(testable.getAcceptedObject());
514         assertNull(testable.getAcceptedPrimitiveObject1());
515 
516         final IOException ioe = new IOException("Unknown I/O error");
517         testable.setThrowable(ioe);
518         e = assertThrows(UncheckedIOException.class, () -> Failable.accept(testable::testObjInt, "X", 1));
519         final Throwable t = e.getCause();
520         assertNotNull(t);
521         assertSame(ioe, t);
522         assertNull(testable.getAcceptedObject());
523         assertNull(testable.getAcceptedPrimitiveObject1());
524 
525         testable.setThrowable(null);
526         Failable.accept(testable::testObjInt, "X", 1);
527         assertEquals("X", testable.getAcceptedObject());
528         assertEquals(1, testable.getAcceptedPrimitiveObject1());
529     }
530 
531     @Test
532     void testAcceptObjLongConsumer() {
533         final Testable<String, Long> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
534         Throwable e = assertThrows(IllegalStateException.class, () -> Failable.accept(testable::testObjLong, "X", 1L));
535         assertSame(ILLEGAL_STATE_EXCEPTION, e);
536         assertNull(testable.getAcceptedObject());
537         assertNull(testable.getAcceptedPrimitiveObject1());
538 
539         testable.setThrowable(ERROR);
540         e = assertThrows(OutOfMemoryError.class, () -> Failable.accept(testable::testObjLong, "X", 1L));
541         assertSame(ERROR, e);
542         assertNull(testable.getAcceptedObject());
543         assertNull(testable.getAcceptedPrimitiveObject1());
544 
545         final IOException ioe = new IOException("Unknown I/O error");
546         testable.setThrowable(ioe);
547         e = assertThrows(UncheckedIOException.class, () -> Failable.accept(testable::testObjLong, "X", 1L));
548         final Throwable t = e.getCause();
549         assertNotNull(t);
550         assertSame(ioe, t);
551         assertNull(testable.getAcceptedObject());
552         assertNull(testable.getAcceptedPrimitiveObject1());
553 
554         testable.setThrowable(null);
555         Failable.accept(testable::testObjLong, "X", 1L);
556         assertEquals("X", testable.getAcceptedObject());
557         assertEquals(1L, testable.getAcceptedPrimitiveObject1());
558     }
559 
560     @Test
561     void testApplyBiFunction() {
562         final Testable<?, ?> testable = new Testable<>(null);
563         Throwable e = assertThrows(IllegalStateException.class,
564             () -> Failable.apply(Testable::testAsInteger, testable, ILLEGAL_STATE_EXCEPTION));
565         assertSame(ILLEGAL_STATE_EXCEPTION, e);
566 
567         e = assertThrows(OutOfMemoryError.class, () -> Failable.apply(Testable::testAsInteger, testable, ERROR));
568         assertSame(ERROR, e);
569 
570         final IOException ioe = new IOException("Unknown I/O error");
571         e = assertThrows(UncheckedIOException.class, () -> Failable.apply(Testable::testAsInteger, testable, ioe));
572         final Throwable t = e.getCause();
573         assertNotNull(t);
574         assertSame(ioe, t);
575 
576         final Integer i = Failable.apply(Testable::testAsInteger, testable, (Throwable) null);
577         assertNotNull(i);
578         assertEquals(0, i.intValue());
579     }
580 
581     @Test
582     void testApplyDoubleBinaryOperator() {
583         final Testable<?, Double> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
584         final Throwable e = assertThrows(IllegalStateException.class,
585             () -> Failable.applyAsDouble(testable::testDoubleDouble, 1d, 2d));
586         assertSame(ILLEGAL_STATE_EXCEPTION, e);
587 
588         final Testable<?, Double> testable2 = new Testable<>(null);
589         final double i = Failable.applyAsDouble(testable2::testDoubleDouble, 1d, 2d);
590         assertEquals(3d, i);
591     }
592 
593     @Test
594     void testApplyFunction() {
595         final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
596         Throwable e = assertThrows(IllegalStateException.class,
597             () -> Failable.apply(Testable::testAsInteger, testable));
598         assertSame(ILLEGAL_STATE_EXCEPTION, e);
599 
600         testable.setThrowable(ERROR);
601         e = assertThrows(OutOfMemoryError.class, () -> Failable.apply(Testable::testAsInteger, testable));
602         assertSame(ERROR, e);
603 
604         final IOException ioe = new IOException("Unknown I/O error");
605         testable.setThrowable(ioe);
606         e = assertThrows(UncheckedIOException.class, () -> Failable.apply(Testable::testAsInteger, testable));
607         final Throwable t = e.getCause();
608         assertNotNull(t);
609         assertSame(ioe, t);
610 
611         testable.setThrowable(null);
612         final Integer i = Failable.apply(Testable::testAsInteger, testable);
613         assertNotNull(i);
614         assertEquals(0, i.intValue());
615     }
616 
617     @Test
618     void testApplyNonNull() throws SomeException {
619         // No checked exceptions in signatures
620         assertEquals("A", Failable.applyNonNull("a", String::toUpperCase));
621         assertNull(Failable.applyNonNull((String) null, String::toUpperCase));
622         assertNull(Failable.applyNonNull("a", s -> null));
623         assertThrows(NullPointerException.class, () -> Failable.applyNonNull("a", null));
624         // Checked exceptions in signatures
625         final FailureOnInvocationCount obj1 = new FailureOnInvocationCount(1);
626         assertEquals(1, assertThrows(SomeException.class, () -> Failable.applyNonNull(1, obj1::inc)).value);
627         assertEquals(2, Failable.applyNonNull(1, obj1::inc));
628     }
629 
630     @Test
631     void testApplyNonNull2() throws SomeException, IOException {
632         // No checked exceptions in signatures
633         assertEquals("A", Failable.applyNonNull(" a ", String::toUpperCase, String::trim));
634         assertNull(Failable.applyNonNull((String) null, String::toUpperCase, String::trim));
635         assertNull(Failable.applyNonNull(" a ", s -> null, String::trim));
636         assertNull(Failable.applyNonNull(" a ", String::toUpperCase, s -> null));
637         assertThrows(NullPointerException.class, () -> Failable.applyNonNull(" a ", null, String::trim));
638         assertThrows(NullPointerException.class, () -> Failable.applyNonNull(" a ", String::toUpperCase, null));
639         // Same checked exceptions in signatures
640         final FailureOnInvocationCount obj1 = new FailureOnInvocationCount(1);
641         final FailureOnInvocationCount obj2 = new FailureOnInvocationCount(2);
642         assertEquals(1, assertThrows(SomeException.class, () -> Failable.applyNonNull(1, obj1::inc, obj1::inc)).value);
643         assertEquals(2, assertThrows(SomeException.class, () -> Failable.applyNonNull(1, obj2::inc, obj2::inc)).value);
644         assertEquals(3, Failable.applyNonNull(1, obj1::inc, obj1::inc));
645         assertEquals(3, Failable.applyNonNull(1, obj2::inc, obj2::inc));
646         // Different checked exceptions in signatures
647         obj1.reset();
648         obj2.reset();
649         assertEquals(1, assertThrows(SomeException.class, () -> Failable.applyNonNull(1, obj1::inc, obj1::incIo)).value);
650         assertEquals(2, ((SomeException) assertThrows(IOException.class, () -> Failable.applyNonNull(1, obj2::inc, obj2::incIo)).getCause()).value);
651         assertEquals(3, Failable.applyNonNull(1, obj1::inc, obj1::incIo));
652         assertEquals(3, Failable.applyNonNull(1, obj2::inc, obj2::incIo));
653     }
654 
655     @Test
656     void testApplyNonNull3() throws SomeException, IOException, ClassNotFoundException {
657         // No checked exceptions in signatures
658         assertEquals("CBA", Failable.applyNonNull(" abc ", String::toUpperCase, String::trim, StringUtils::reverse));
659         assertNull(Failable.applyNonNull((String) null, String::toUpperCase, String::trim, StringUtils::reverse));
660         assertNull(Failable.applyNonNull(" abc ", s -> null, String::trim, StringUtils::reverse));
661         assertNull(Failable.applyNonNull(" abc ", String::toUpperCase, s -> null, StringUtils::reverse));
662         assertNull(Failable.applyNonNull(" abc ", String::toUpperCase, String::trim, s -> null));
663         assertThrows(NullPointerException.class, () -> Failable.applyNonNull(" abc ", null, String::trim, StringUtils::reverse));
664         assertThrows(NullPointerException.class, () -> Failable.applyNonNull(" abc ", String::toUpperCase, null, StringUtils::reverse));
665         assertThrows(NullPointerException.class, () -> Failable.applyNonNull(" abc ", String::toUpperCase, String::trim, null));
666         // Same checked exceptions in signatures
667         final FailureOnInvocationCount obj1 = new FailureOnInvocationCount(1);
668         final FailureOnInvocationCount obj2 = new FailureOnInvocationCount(2);
669         final FailureOnInvocationCount obj3 = new FailureOnInvocationCount(3);
670         assertEquals(1, assertThrows(SomeException.class, () -> Failable.applyNonNull(1, obj1::inc, obj1::inc, obj1::inc)).value);
671         assertEquals(2, assertThrows(SomeException.class, () -> Failable.applyNonNull(1, obj2::inc, obj2::inc, obj2::inc)).value);
672         assertEquals(3, assertThrows(SomeException.class, () -> Failable.applyNonNull(1, obj3::inc, obj3::inc, obj3::inc)).value);
673         assertEquals(4, Failable.applyNonNull(1, obj1::inc, obj1::inc, obj1::inc));
674         assertEquals(4, Failable.applyNonNull(1, obj2::inc, obj2::inc, obj2::inc));
675         assertEquals(4, Failable.applyNonNull(1, obj3::inc, obj3::inc, obj3::inc));
676         // Different checked exceptions in signatures
677         obj1.reset();
678         obj2.reset();
679         obj3.reset();
680         assertEquals(1, assertThrows(SomeException.class, () -> Failable.applyNonNull(1, obj1::inc, obj1::incIo, obj1::incIo)).value);
681         assertEquals(2, ((SomeException) assertThrows(IOException.class, () -> Failable.applyNonNull(1, obj2::inc, obj2::incIo, obj2::incIo)).getCause()).value);
682         assertEquals(3, ((SomeException) assertThrows(IOException.class, () -> Failable.applyNonNull(1, obj3::inc, obj3::incIo, obj3::incIo)).getCause()).value);
683         assertEquals(4, Failable.applyNonNull(1, obj1::inc, obj1::incIo, obj1::incIo));
684         assertEquals(4, Failable.applyNonNull(1, obj2::inc, obj2::incIo, obj2::incIo));
685         assertEquals(4, Failable.applyNonNull(1, obj3::inc, obj3::incIo, obj3::incIo));
686     }
687 
688     @Test
689     void testAsCallable() {
690         FailureOnOddInvocations.invocations = 0;
691         final FailableCallable<FailureOnOddInvocations, SomeException> failableCallable = FailureOnOddInvocations::new;
692         final Callable<FailureOnOddInvocations> callable = Failable.asCallable(failableCallable);
693         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, callable::call);
694         final Throwable cause = e.getCause();
695         assertNotNull(cause);
696         assertInstanceOf(SomeException.class, cause);
697         assertEquals("Odd Invocation: 1", cause.getMessage());
698         final FailureOnOddInvocations instance;
699         try {
700             instance = callable.call();
701         } catch (final Exception ex) {
702             throw Failable.rethrow(ex);
703         }
704         assertNotNull(instance);
705     }
706 
707     @Test
708     void testAsConsumer() {
709         final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
710         final Consumer<Testable<?, ?>> consumer = Failable.asConsumer(Testable::test);
711         Throwable e = assertThrows(IllegalStateException.class, () -> consumer.accept(testable));
712         assertSame(ILLEGAL_STATE_EXCEPTION, e);
713 
714         testable.setThrowable(ERROR);
715         e = assertThrows(OutOfMemoryError.class, () -> consumer.accept(testable));
716         assertSame(ERROR, e);
717 
718         final IOException ioe = new IOException("Unknown I/O error");
719         testable.setThrowable(ioe);
720         e = assertThrows(UncheckedIOException.class, () -> consumer.accept(testable));
721         final Throwable t = e.getCause();
722         assertNotNull(t);
723         assertSame(ioe, t);
724 
725         testable.setThrowable(null);
726         Failable.accept(Testable::test, testable);
727     }
728 
729     @Test
730     void testAsRunnable() {
731         FailureOnOddInvocations.invocations = 0;
732         final Runnable runnable = Failable.asRunnable(FailureOnOddInvocations::new);
733         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, runnable::run);
734         final Throwable cause = e.getCause();
735         assertNotNull(cause);
736         assertInstanceOf(SomeException.class, cause);
737         assertEquals("Odd Invocation: 1", cause.getMessage());
738 
739         // Even invocations, should not throw an exception
740         runnable.run();
741     }
742 
743     @Test
744     void testAsSupplier() {
745         FailureOnOddInvocations.invocations = 0;
746         final FailableSupplier<FailureOnOddInvocations, Throwable> failableSupplier = FailureOnOddInvocations::new;
747         final Supplier<FailureOnOddInvocations> supplier = Failable.asSupplier(failableSupplier);
748         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, supplier::get);
749         final Throwable cause = e.getCause();
750         assertNotNull(cause);
751         assertInstanceOf(SomeException.class, cause);
752         assertEquals("Odd Invocation: 1", cause.getMessage());
753         assertNotNull(supplier.get());
754     }
755 
756     @Test
757     void testBiConsumer() throws Throwable {
758         final Testable<?, ?> testable = new Testable<>(null);
759         final FailableBiConsumer<Testable<?, ?>, Throwable, Throwable> failableBiConsumer = (t, th) -> {
760             t.setThrowable(th);
761             t.test();
762         };
763         final BiConsumer<Testable<?, ?>, Throwable> consumer = Failable.asBiConsumer(failableBiConsumer);
764         Throwable e = assertThrows(IllegalStateException.class,
765             () -> consumer.accept(testable, ILLEGAL_STATE_EXCEPTION));
766         assertSame(ILLEGAL_STATE_EXCEPTION, e);
767 
768         e = assertThrows(OutOfMemoryError.class, () -> consumer.accept(testable, ERROR));
769         assertSame(ERROR, e);
770 
771         e = assertThrows(OutOfMemoryError.class, () -> failableBiConsumer.accept(testable, ERROR));
772         assertSame(ERROR, e);
773 
774         final IOException ioe = new IOException("Unknown I/O error");
775         testable.setThrowable(ioe);
776         e = assertThrows(UncheckedIOException.class, () -> consumer.accept(testable, ioe));
777         final Throwable t = e.getCause();
778         assertNotNull(t);
779         assertSame(ioe, t);
780 
781         consumer.accept(testable, null);
782     }
783 
784     @Test
785     void testBiConsumerAndThen() throws Throwable {
786         final Testable<?, ?> testable = new Testable<>(null);
787         final FailableBiConsumer<Testable<?, ?>, Throwable, Throwable> failing = (t, th) -> {
788             t.setThrowable(th);
789             t.test();
790         };
791         final FailableBiConsumer<Testable<?, ?>, Throwable, Throwable> nop = FailableBiConsumer.nop();
792         Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).accept(testable, ERROR));
793         assertSame(ERROR, e);
794         e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).accept(testable, ERROR));
795         assertSame(ERROR, e);
796         // Does not throw
797         nop.andThen(nop);
798         // Documented in Javadoc edge-case.
799         assertNullPointerException(() -> failing.andThen(null));
800     }
801 
802     @Test
803     void testBiFunction() {
804         final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
805         final FailableBiFunction<Testable<?, ?>, Throwable, Integer, Throwable> failableBiFunction = (t, th) -> {
806             t.setThrowable(th);
807             return t.testAsInteger();
808         };
809         final BiFunction<Testable<?, ?>, Throwable, Integer> biFunction = Failable.asBiFunction(failableBiFunction);
810         Throwable e = assertThrows(IllegalStateException.class,
811             () -> biFunction.apply(testable, ILLEGAL_STATE_EXCEPTION));
812         assertSame(ILLEGAL_STATE_EXCEPTION, e);
813 
814         testable.setThrowable(ERROR);
815         e = assertThrows(OutOfMemoryError.class, () -> biFunction.apply(testable, ERROR));
816         assertSame(ERROR, e);
817 
818         final IOException ioe = new IOException("Unknown I/O error");
819         testable.setThrowable(ioe);
820         e = assertThrows(UncheckedIOException.class, () -> biFunction.apply(testable, ioe));
821         final Throwable t = e.getCause();
822         assertNotNull(t);
823         assertSame(ioe, t);
824 
825         assertEquals(0, biFunction.apply(testable, null).intValue());
826     }
827 
828     @Test
829     void testBiFunctionAndThen() throws IOException {
830         // Unchecked usage pattern in JRE
831         final BiFunction<Object, Integer, Integer> nopBiFunction = (t, u) -> null;
832         final Function<Object, Integer> nopFunction = t -> null;
833         nopBiFunction.andThen(nopFunction);
834         // Checked usage pattern
835         final FailableBiFunction<Object, Integer, Integer, IOException> failingBiFunctionTest = (t, u) -> {
836             throw new IOException();
837         };
838         final FailableFunction<Object, Integer, IOException> failingFunction = t -> {
839             throw new IOException();
840         };
841         final FailableBiFunction<Object, Integer, Integer, IOException> nopFailableBiFunction = FailableBiFunction
842             .nop();
843         final FailableFunction<Object, Integer, IOException> nopFailableFunction = FailableFunction.nop();
844         //
845         assertThrows(IOException.class, () -> failingBiFunctionTest.andThen(failingFunction).apply(null, null));
846         assertThrows(IOException.class, () -> failingBiFunctionTest.andThen(nopFailableFunction).apply(null, null));
847         //
848         assertThrows(IOException.class, () -> nopFailableBiFunction.andThen(failingFunction).apply(null, null));
849         nopFailableBiFunction.andThen(nopFailableFunction).apply(null, null);
850         // Documented in Javadoc edge-case.
851         assertNullPointerException(() -> failingBiFunctionTest.andThen(null));
852     }
853 
854     @Test
855     /** Test that asPredicate(FailableBiPredicate) is converted to -> BiPredicate  */
856     void testBiPredicate() {
857         FailureOnOddInvocations.invocations = 0;
858         final FailableBiPredicate<Object, Object, Throwable> failableBiPredicate = (t1, t2) -> FailureOnOddInvocations
859             .testGetBool();
860         final BiPredicate<?, ?> predicate = Failable.asBiPredicate(failableBiPredicate);
861         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class,
862             () -> predicate.test(null, null));
863         final Throwable cause = e.getCause();
864         assertNotNull(cause);
865         assertInstanceOf(SomeException.class, cause);
866         assertEquals("Odd Invocation: 1", cause.getMessage());
867         assertTrue(predicate.test(null, null));
868     }
869 
870     @Test
871     void testBiPredicateAnd() throws Throwable {
872         assertTrue(FailableBiPredicate.TRUE.and(FailableBiPredicate.TRUE).test(null, null));
873         assertFalse(FailableBiPredicate.TRUE.and(FailableBiPredicate.FALSE).test(null, null));
874         assertFalse(FailableBiPredicate.FALSE.and(FailableBiPredicate.TRUE).test(null, null));
875         assertFalse(FailableBiPredicate.FALSE.and(FailableBiPredicate.FALSE).test(null, null));
876         // null tests
877         assertNullPointerException(
878             () -> assertFalse(FailableBiPredicate.falsePredicate().and(null).test(null, null)));
879         assertNullPointerException(
880             () -> assertTrue(FailableBiPredicate.truePredicate().and(null).test(null, null)));
881     }
882 
883     @Test
884     void testBiPredicateNegate() throws Throwable {
885         assertFalse(FailableBiPredicate.TRUE.negate().test(null, null));
886         assertFalse(FailableBiPredicate.truePredicate().negate().test(null, null));
887         assertTrue(FailableBiPredicate.FALSE.negate().test(null, null));
888         assertTrue(FailableBiPredicate.falsePredicate().negate().test(null, null));
889     }
890 
891     @Test
892     void testBiPredicateOr() throws Throwable {
893         assertTrue(FailableBiPredicate.TRUE.or(FailableBiPredicate.TRUE).test(null, null));
894         assertTrue(FailableBiPredicate.TRUE.or(FailableBiPredicate.FALSE).test(null, null));
895         assertTrue(FailableBiPredicate.FALSE.or(FailableBiPredicate.TRUE).test(null, null));
896         assertFalse(FailableBiPredicate.FALSE.or(FailableBiPredicate.FALSE).test(null, null));
897         // null tests
898         assertNullPointerException(
899             () -> assertFalse(FailableBiPredicate.falsePredicate().or(null).test(null, null)));
900         assertNullPointerException(
901             () -> assertTrue(FailableBiPredicate.truePredicate().or(null).test(null, null)));
902     }
903 
904     @Test
905     void testByteConsumerAndThen() throws Throwable {
906         final Testable<?, ?> testable = new Testable<>(null);
907         final FailableByteConsumer<Throwable> failing = t -> {
908             testable.setThrowable(ERROR);
909             testable.test();
910         };
911         final FailableByteConsumer<Throwable> nop = FailableByteConsumer.nop();
912         Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).accept((byte) 0));
913         assertSame(ERROR, e);
914         e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).accept((byte) 0));
915         assertSame(ERROR, e);
916         // Does not throw
917         nop.andThen(nop);
918         // Documented in Javadoc edge-case.
919         assertNullPointerException(() -> failing.andThen(null));
920     }
921 
922     @Test
923     void testCallable() {
924         FailureOnOddInvocations.invocations = 0;
925         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class,
926             () -> Failable.run(FailureOnOddInvocations::new));
927         final Throwable cause = e.getCause();
928         assertNotNull(cause);
929         assertInstanceOf(SomeException.class, cause);
930         assertEquals("Odd Invocation: 1", cause.getMessage());
931         final FailureOnOddInvocations instance = Failable.call(FailureOnOddInvocations::new);
932         assertNotNull(instance);
933     }
934 
935     @Test
936     void testConsumerAndThen() throws Throwable {
937         final Testable<?, ?> testable = new Testable<>(null);
938         final FailableConsumer<Throwable, Throwable> failableConsumer = th -> {
939             testable.setThrowable(th);
940             testable.test();
941         };
942         final FailableConsumer<Throwable, Throwable> nop = FailableConsumer.nop();
943         final Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failableConsumer).accept(ERROR));
944         assertSame(ERROR, e);
945         // Does not throw
946         nop.andThen(nop);
947         // Documented in Javadoc edge-case.
948         assertNullPointerException(() -> failableConsumer.andThen(null));
949     }
950 
951     @Test
952     void testDoubleConsumerAndThen() throws Throwable {
953         final Testable<?, ?> testable = new Testable<>(null);
954         final FailableDoubleConsumer<Throwable> failing = t -> {
955             testable.setThrowable(ERROR);
956             testable.test();
957         };
958         final FailableDoubleConsumer<Throwable> nop = FailableDoubleConsumer.nop();
959         Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).accept(0d));
960         assertSame(ERROR, e);
961         e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).accept(0d));
962         assertSame(ERROR, e);
963         // Does not throw
964         nop.andThen(nop);
965         // Documented in Javadoc edge-case.
966         assertNullPointerException(() -> failing.andThen(null));
967     }
968 
969     @Test
970     void testDoublePredicate() throws Throwable {
971         FailureOnOddInvocations.invocations = 0;
972         final FailableDoublePredicate<Throwable> failablePredicate = FailureOnOddInvocations::testDouble;
973         assertThrows(SomeException.class, () -> failablePredicate.test(1d));
974         failablePredicate.test(1d);
975     }
976 
977     @Test
978     void testDoublePredicateAnd() throws Throwable {
979         assertTrue(FailableDoublePredicate.TRUE.and(FailableDoublePredicate.TRUE).test(0));
980         assertFalse(FailableDoublePredicate.TRUE.and(FailableDoublePredicate.FALSE).test(0));
981         assertFalse(FailableDoublePredicate.FALSE.and(FailableDoublePredicate.TRUE).test(0));
982         assertFalse(FailableDoublePredicate.FALSE.and(FailableDoublePredicate.FALSE).test(0));
983         // null tests
984         assertNullPointerException(
985             () -> assertFalse(FailableDoublePredicate.falsePredicate().and(null).test(0)));
986         assertNullPointerException(
987             () -> assertTrue(FailableDoublePredicate.truePredicate().and(null).test(0)));
988     }
989 
990     @Test
991     void testDoublePredicateNegate() throws Throwable {
992         assertFalse(FailableDoublePredicate.TRUE.negate().test(0d));
993         assertFalse(FailableDoublePredicate.truePredicate().negate().test(0d));
994         assertTrue(FailableDoublePredicate.FALSE.negate().test(0d));
995         assertTrue(FailableDoublePredicate.falsePredicate().negate().test(0d));
996     }
997 
998     @Test
999     void testDoublePredicateOr() throws Throwable {
1000         assertTrue(FailableDoublePredicate.TRUE.or(FailableDoublePredicate.TRUE).test(0));
1001         assertTrue(FailableDoublePredicate.TRUE.or(FailableDoublePredicate.FALSE).test(0));
1002         assertTrue(FailableDoublePredicate.FALSE.or(FailableDoublePredicate.TRUE).test(0));
1003         assertFalse(FailableDoublePredicate.FALSE.or(FailableDoublePredicate.FALSE).test(0));
1004         // null tests
1005         assertNullPointerException(
1006             () -> assertFalse(FailableDoublePredicate.falsePredicate().or(null).test(0)));
1007         assertNullPointerException(
1008             () -> assertTrue(FailableDoublePredicate.truePredicate().or(null).test(0)));
1009     }
1010 
1011     @Test
1012     void testDoubleUnaryOperatorAndThen() throws Throwable {
1013         final Testable<?, ?> testable = new Testable<>(null);
1014         final FailableDoubleUnaryOperator<Throwable> failing = t -> {
1015             testable.setThrowable(ERROR);
1016             testable.test();
1017             return 0d;
1018         };
1019         final FailableDoubleUnaryOperator<Throwable> nop = FailableDoubleUnaryOperator.nop();
1020         Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).applyAsDouble(0d));
1021         assertSame(ERROR, e);
1022         e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).applyAsDouble(0d));
1023         assertSame(ERROR, e);
1024         // Does not throw
1025         nop.andThen(nop);
1026         // Documented in Javadoc edge-case.
1027         assertNullPointerException(() -> failing.andThen(null));
1028     }
1029 
1030     @Test
1031     void testDoubleUnaryOperatorCompose() throws Throwable {
1032         final Testable<?, ?> testable = new Testable<>(null);
1033         final FailableDoubleUnaryOperator<Throwable> failing = t -> {
1034             testable.setThrowable(ERROR);
1035             testable.test();
1036             return 0d;
1037         };
1038         final FailableDoubleUnaryOperator<Throwable> nop = FailableDoubleUnaryOperator.nop();
1039         Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.compose(failing).applyAsDouble(0d));
1040         assertSame(ERROR, e);
1041         e = assertThrows(OutOfMemoryError.class, () -> failing.compose(nop).applyAsDouble(0d));
1042         assertSame(ERROR, e);
1043         // Does not throw
1044         nop.compose(nop);
1045         // Documented in Javadoc edge-case.
1046         assertNullPointerException(() -> failing.compose(null));
1047     }
1048 
1049     @Test
1050     void testDoubleUnaryOperatorIdentity() throws Throwable {
1051         final FailableDoubleUnaryOperator<Throwable> nop = FailableDoubleUnaryOperator.identity();
1052         // Does not throw
1053         nop.compose(nop);
1054         // Documented in Javadoc edge-case.
1055         assertNullPointerException(() -> nop.compose(null));
1056     }
1057 
1058     @Test
1059     void testFailableBiFunctionNop() throws Throwable {
1060         assertNull(FailableBiFunction.nop().apply("Foo", "Bar"), "Expect NOP to return null");
1061     }
1062 
1063     @Test
1064     void testFailableConsumerNop() throws Throwable {
1065         // Expect nothing thrown
1066         FailableConsumer.nop().accept("Foo");
1067     }
1068 
1069     @Test
1070     void testFailableDoubleFunctionNop() throws Throwable {
1071         assertNull(FailableDoubleFunction.nop().apply(Double.MAX_VALUE), "Expect NOP to return null");
1072     }
1073 
1074     @Test
1075     void testFailableDoubleToIntFunctionNop() throws Throwable {
1076         assertEquals(0, FailableDoubleToIntFunction.nop().applyAsInt(Double.MAX_VALUE), "Expect NOP to return 0");
1077     }
1078 
1079     @Test
1080     void testFailableDoubleToLongFunctionNop() throws Throwable {
1081         assertEquals(0, FailableDoubleToLongFunction.nop().applyAsLong(Double.MAX_VALUE), "Expect NOP to return 0");
1082     }
1083 
1084     @Test
1085     void testFailableIntFunctionNop() throws Throwable {
1086         assertNull(FailableIntFunction.nop().apply(Integer.MAX_VALUE), "Expect NOP to return null");
1087     }
1088 
1089     @Test
1090     void testFailableIntToDoubleFunctionNop() throws Throwable {
1091         assertEquals(0, FailableIntToDoubleFunction.nop().applyAsDouble(Integer.MAX_VALUE), "Expect NOP to return 0");
1092     }
1093 
1094     @Test
1095     void testFailableIntToFloatFunctionNop() throws Throwable {
1096         assertEquals(0, FailableIntToFloatFunction.nop().applyAsFloat(Integer.MAX_VALUE), "Expect NOP to return 0");
1097     }
1098 
1099     @Test
1100     void testFailableIntToLongFunctionNop() throws Throwable {
1101         assertEquals(0, FailableIntToLongFunction.nop().applyAsLong(Integer.MAX_VALUE), "Expect NOP to return 0");
1102     }
1103 
1104     @Test
1105     void testFailableLongFunctionNop() throws Throwable {
1106         assertNull(FailableLongFunction.nop().apply(Long.MAX_VALUE), "Expect NOP to return null");
1107     }
1108 
1109     @Test
1110     void testFailableLongToDoubleFunctionNop() throws Throwable {
1111         assertEquals(0, FailableLongToDoubleFunction.nop().applyAsDouble(Long.MAX_VALUE), "Expect NOP to return 0");
1112     }
1113 
1114     @Test
1115     void testFailableLongToIntFunctionNop() throws Throwable {
1116         assertEquals(0, FailableLongToIntFunction.nop().applyAsInt(Long.MAX_VALUE), "Expect NOP to return 0");
1117     }
1118 
1119     @Test
1120     void testFailableObjDoubleConsumerNop() throws Throwable {
1121         // Expect nothing thrown
1122         FailableObjDoubleConsumer.nop().accept("Foo", Double.MAX_VALUE);
1123     }
1124 
1125     @Test
1126     void testFailableObjIntConsumerNop() throws Throwable {
1127         // Expect nothing thrown
1128         FailableObjIntConsumer.nop().accept("Foo", Integer.MAX_VALUE);
1129     }
1130 
1131     @Test
1132     void testFailableObjLongConsumerNop() throws Throwable {
1133         // Expect nothing thrown
1134         FailableObjLongConsumer.nop().accept("Foo", Long.MAX_VALUE);
1135     }
1136 
1137     @Test
1138     void testFailableToBooleanFunctionNop() throws Throwable {
1139         assertEquals(false, FailableToBooleanFunction.nop().applyAsBoolean("Foo"), "Expect NOP to return false");
1140     }
1141 
1142     @Test
1143     void testFailableToDoubleBiFunctionNop() throws Throwable {
1144         assertEquals(0, FailableToDoubleBiFunction.nop().applyAsDouble("Foo", "Bar"), "Expect NOP to return 0");
1145     }
1146 
1147     @Test
1148     void testFailableToDoubleFunctionNop() throws Throwable {
1149         assertEquals(0, FailableToDoubleFunction.nop().applyAsDouble("Foo"), "Expect NOP to return 0");
1150     }
1151 
1152     @Test
1153     void testFailableToIntBiFunctionNop() throws Throwable {
1154         assertEquals(0, FailableToIntBiFunction.nop().applyAsInt("Foo", "Bar"), "Expect NOP to return 0");
1155     }
1156 
1157     @Test
1158     void testFailableToIntFunctionNop() throws Throwable {
1159         assertEquals(0, FailableToIntFunction.nop().applyAsInt("Foo"), "Expect NOP to return 0");
1160     }
1161 
1162     @Test
1163     void testFailableToLongBiFunctionNop() throws Throwable {
1164         assertEquals(0, FailableToLongBiFunction.nop().applyAsLong("Foo", "Bar"), "Expect NOP to return 0");
1165     }
1166 
1167     @Test
1168     void testFailableToLongFunctionNop() throws Throwable {
1169         assertEquals(0, FailableToLongFunction.nop().applyAsLong("Foo"), "Expect NOP to return 0");
1170     }
1171 
1172     @Test
1173     void testFunction() {
1174         final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
1175         final FailableFunction<Throwable, Integer, Throwable> failableFunction = th -> {
1176             testable.setThrowable(th);
1177             return testable.testAsInteger();
1178         };
1179         final Function<Throwable, Integer> function = Failable.asFunction(failableFunction);
1180         Throwable e = assertThrows(IllegalStateException.class, () -> function.apply(ILLEGAL_STATE_EXCEPTION));
1181         assertSame(ILLEGAL_STATE_EXCEPTION, e);
1182 
1183         testable.setThrowable(ERROR);
1184         e = assertThrows(OutOfMemoryError.class, () -> function.apply(ERROR));
1185         assertSame(ERROR, e);
1186 
1187         final IOException ioe = new IOException("Unknown I/O error");
1188         testable.setThrowable(ioe);
1189         e = assertThrows(UncheckedIOException.class, () -> function.apply(ioe));
1190         final Throwable t = e.getCause();
1191         assertNotNull(t);
1192         assertSame(ioe, t);
1193 
1194         assertEquals(0, function.apply(null).intValue());
1195     }
1196 
1197     @Test
1198     void testFunctionAndThen() throws IOException {
1199         // Unchecked usage pattern in JRE
1200         final Function<Object, Integer> nopFunction = t -> null;
1201         nopFunction.andThen(nopFunction);
1202         // Checked usage pattern
1203         final FailableFunction<Object, Integer, IOException> failingFunction = t -> {
1204             throw new IOException();
1205         };
1206         final FailableFunction<Object, Integer, IOException> nopFailableFunction = FailableFunction.nop();
1207         //
1208         assertThrows(IOException.class, () -> failingFunction.andThen(failingFunction).apply(null));
1209         assertThrows(IOException.class, () -> failingFunction.andThen(nopFailableFunction).apply(null));
1210         //
1211         assertThrows(IOException.class, () -> nopFailableFunction.andThen(failingFunction).apply(null));
1212         nopFailableFunction.andThen(nopFailableFunction).apply(null);
1213         // Documented in Javadoc edge-case.
1214         assertNullPointerException(() -> failingFunction.andThen(null));
1215     }
1216 
1217     @Test
1218     void testFunctionCompose() throws Throwable {
1219         final Testable<?, ?> testable = new Testable<>(null);
1220         final FailableFunction<Object, Integer, Throwable> failing = t -> {
1221             testable.setThrowable(ERROR);
1222             testable.test();
1223             return 0;
1224         };
1225         final FailableFunction<Object, Integer, Throwable> nop = FailableFunction.nop();
1226         Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.compose(failing).apply(0));
1227         assertSame(ERROR, e);
1228         e = assertThrows(OutOfMemoryError.class, () -> failing.compose(nop).apply(0));
1229         assertSame(ERROR, e);
1230         // Does not throw
1231         nop.compose(nop);
1232         // Documented in Javadoc edge-case.
1233         assertNullPointerException(() -> failing.compose(null));
1234     }
1235 
1236     @Test
1237     void testFunctionFunction() throws Exception {
1238         assertEquals("foo", FailableFunction.function(this::throwingFunction).andThen(this::throwingFunction).apply("foo"));
1239     }
1240 
1241     @Test
1242     void testFunctionIdentity() throws Throwable {
1243         final FailableFunction<Integer, Integer, Throwable> nop = FailableFunction.identity();
1244         // Does not throw
1245         nop.compose(nop);
1246         // Documented in Javadoc edge-case.
1247         assertNullPointerException(() -> nop.compose(null));
1248     }
1249 
1250     @Test
1251     void testGetAsBooleanSupplier() {
1252         final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
1253         Throwable e = assertThrows(IllegalStateException.class,
1254             () -> Failable.getAsBoolean(testable::testAsBooleanPrimitive));
1255         assertSame(ILLEGAL_STATE_EXCEPTION, e);
1256 
1257         testable.setThrowable(ERROR);
1258         e = assertThrows(OutOfMemoryError.class, () -> Failable.getAsBoolean(testable::testAsBooleanPrimitive));
1259         assertSame(ERROR, e);
1260 
1261         final IOException ioe = new IOException("Unknown I/O error");
1262         testable.setThrowable(ioe);
1263         e = assertThrows(UncheckedIOException.class, () -> Failable.getAsBoolean(testable::testAsBooleanPrimitive));
1264         final Throwable t = e.getCause();
1265         assertNotNull(t);
1266         assertSame(ioe, t);
1267 
1268         testable.setThrowable(null);
1269         assertFalse(Failable.getAsBoolean(testable::testAsBooleanPrimitive));
1270     }
1271 
1272     @Test
1273     void testGetAsDoubleSupplier() {
1274         final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
1275         Throwable e = assertThrows(IllegalStateException.class,
1276             () -> Failable.getAsDouble(testable::testAsDoublePrimitive));
1277         assertSame(ILLEGAL_STATE_EXCEPTION, e);
1278 
1279         testable.setThrowable(ERROR);
1280         e = assertThrows(OutOfMemoryError.class, () -> Failable.getAsDouble(testable::testAsDoublePrimitive));
1281         assertSame(ERROR, e);
1282 
1283         final IOException ioe = new IOException("Unknown I/O error");
1284         testable.setThrowable(ioe);
1285         e = assertThrows(UncheckedIOException.class, () -> Failable.getAsDouble(testable::testAsDoublePrimitive));
1286         final Throwable t = e.getCause();
1287         assertNotNull(t);
1288         assertSame(ioe, t);
1289 
1290         testable.setThrowable(null);
1291         assertEquals(0, Failable.getAsDouble(testable::testAsDoublePrimitive));
1292     }
1293 
1294     @Test
1295     void testGetAsIntSupplier() {
1296         final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
1297         Throwable e = assertThrows(IllegalStateException.class, () -> Failable.getAsInt(testable::testAsIntPrimitive));
1298         assertSame(ILLEGAL_STATE_EXCEPTION, e);
1299 
1300         testable.setThrowable(ERROR);
1301         e = assertThrows(OutOfMemoryError.class, () -> Failable.getAsInt(testable::testAsIntPrimitive));
1302         assertSame(ERROR, e);
1303 
1304         final IOException ioe = new IOException("Unknown I/O error");
1305         testable.setThrowable(ioe);
1306         e = assertThrows(UncheckedIOException.class, () -> Failable.getAsInt(testable::testAsIntPrimitive));
1307         final Throwable t = e.getCause();
1308         assertNotNull(t);
1309         assertSame(ioe, t);
1310 
1311         testable.setThrowable(null);
1312         final int i = Failable.getAsInt(testable::testAsInteger);
1313         assertEquals(0, i);
1314     }
1315 
1316     @Test
1317     void testGetAsLongSupplier() {
1318         final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
1319         Throwable e = assertThrows(IllegalStateException.class,
1320             () -> Failable.getAsLong(testable::testAsLongPrimitive));
1321         assertSame(ILLEGAL_STATE_EXCEPTION, e);
1322 
1323         testable.setThrowable(ERROR);
1324         e = assertThrows(OutOfMemoryError.class, () -> Failable.getAsLong(testable::testAsLongPrimitive));
1325         assertSame(ERROR, e);
1326 
1327         final IOException ioe = new IOException("Unknown I/O error");
1328         testable.setThrowable(ioe);
1329         e = assertThrows(UncheckedIOException.class, () -> Failable.getAsLong(testable::testAsLongPrimitive));
1330         final Throwable t = e.getCause();
1331         assertNotNull(t);
1332         assertSame(ioe, t);
1333 
1334         testable.setThrowable(null);
1335         final long i = Failable.getAsLong(testable::testAsLongPrimitive);
1336         assertEquals(0, i);
1337     }
1338 
1339     @Test
1340     void testGetAsShortSupplier() {
1341         final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
1342         Throwable e = assertThrows(IllegalStateException.class,
1343             () -> Failable.getAsShort(testable::testAsShortPrimitive));
1344         assertSame(ILLEGAL_STATE_EXCEPTION, e);
1345 
1346         testable.setThrowable(ERROR);
1347         e = assertThrows(OutOfMemoryError.class, () -> Failable.getAsShort(testable::testAsShortPrimitive));
1348         assertSame(ERROR, e);
1349 
1350         final IOException ioe = new IOException("Unknown I/O error");
1351         testable.setThrowable(ioe);
1352         e = assertThrows(UncheckedIOException.class, () -> Failable.getAsShort(testable::testAsShortPrimitive));
1353         final Throwable t = e.getCause();
1354         assertNotNull(t);
1355         assertSame(ioe, t);
1356 
1357         testable.setThrowable(null);
1358         final short i = Failable.getAsShort(testable::testAsShortPrimitive);
1359         assertEquals(0, i);
1360     }
1361 
1362     @Test
1363     void testGetFromSupplier() {
1364         FailureOnOddInvocations.invocations = 0;
1365         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class,
1366             () -> Failable.run(FailureOnOddInvocations::new));
1367         final Throwable cause = e.getCause();
1368         assertNotNull(cause);
1369         assertInstanceOf(SomeException.class, cause);
1370         assertEquals("Odd Invocation: 1", cause.getMessage());
1371         final FailureOnOddInvocations instance = Failable.call(FailureOnOddInvocations::new);
1372         assertNotNull(instance);
1373     }
1374 
1375     @Test
1376     void testGetSupplier() {
1377         final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION);
1378         Throwable e = assertThrows(IllegalStateException.class, () -> Failable.get(testable::testAsInteger));
1379         assertSame(ILLEGAL_STATE_EXCEPTION, e);
1380 
1381         testable.setThrowable(ERROR);
1382         e = assertThrows(OutOfMemoryError.class, () -> Failable.get(testable::testAsInteger));
1383         assertSame(ERROR, e);
1384 
1385         final IOException ioe = new IOException("Unknown I/O error");
1386         testable.setThrowable(ioe);
1387         e = assertThrows(UncheckedIOException.class, () -> Failable.get(testable::testAsInteger));
1388         final Throwable t = e.getCause();
1389         assertNotNull(t);
1390         assertSame(ioe, t);
1391 
1392         testable.setThrowable(null);
1393         final Integer i = Failable.apply(Testable::testAsInteger, testable);
1394         assertNotNull(i);
1395         assertEquals(0, i.intValue());
1396     }
1397 
1398     @Test
1399     void testIntConsumerAndThen() throws Throwable {
1400         final Testable<?, ?> testable = new Testable<>(null);
1401         final FailableIntConsumer<Throwable> failing = t -> {
1402             testable.setThrowable(ERROR);
1403             testable.test();
1404         };
1405         final FailableIntConsumer<Throwable> nop = FailableIntConsumer.nop();
1406         Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).accept(0));
1407         assertSame(ERROR, e);
1408         e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).accept(0));
1409         assertSame(ERROR, e);
1410         // Does not throw
1411         nop.andThen(nop);
1412         // Documented in Javadoc edge-case.
1413         assertNullPointerException(() -> failing.andThen(null));
1414     }
1415 
1416     @Test
1417     void testIntPredicate() throws Throwable {
1418         FailureOnOddInvocations.invocations = 0;
1419         final FailableIntPredicate<Throwable> failablePredicate = FailureOnOddInvocations::testInt;
1420         assertThrows(SomeException.class, () -> failablePredicate.test(1));
1421         failablePredicate.test(1);
1422     }
1423 
1424     @Test
1425     void testIntPredicateAnd() throws Throwable {
1426         assertTrue(FailableIntPredicate.TRUE.and(FailableIntPredicate.TRUE).test(0));
1427         assertFalse(FailableIntPredicate.TRUE.and(FailableIntPredicate.FALSE).test(0));
1428         assertFalse(FailableIntPredicate.FALSE.and(FailableIntPredicate.TRUE).test(0));
1429         assertFalse(FailableIntPredicate.FALSE.and(FailableIntPredicate.FALSE).test(0));
1430         // null tests
1431         assertNullPointerException(
1432             () -> assertFalse(FailableIntPredicate.falsePredicate().and(null).test(0)));
1433         assertNullPointerException(
1434             () -> assertTrue(FailableIntPredicate.truePredicate().and(null).test(0)));
1435     }
1436 
1437     @Test
1438     void testIntPredicateNegate() throws Throwable {
1439         assertFalse(FailableIntPredicate.TRUE.negate().test(0));
1440         assertFalse(FailableIntPredicate.truePredicate().negate().test(0));
1441         assertTrue(FailableIntPredicate.FALSE.negate().test(0));
1442         assertTrue(FailableIntPredicate.falsePredicate().negate().test(0));
1443     }
1444 
1445     @Test
1446     void testIntPredicateOr() throws Throwable {
1447         assertTrue(FailableIntPredicate.TRUE.or(FailableIntPredicate.TRUE).test(0));
1448         assertTrue(FailableIntPredicate.TRUE.or(FailableIntPredicate.FALSE).test(0));
1449         assertTrue(FailableIntPredicate.FALSE.or(FailableIntPredicate.TRUE).test(0));
1450         assertFalse(FailableIntPredicate.FALSE.or(FailableIntPredicate.FALSE).test(0));
1451         // null tests
1452         assertNullPointerException(
1453             () -> assertFalse(FailableIntPredicate.falsePredicate().or(null).test(0)));
1454         assertNullPointerException(
1455             () -> assertTrue(FailableIntPredicate.truePredicate().or(null).test(0)));
1456     }
1457 
1458     @Test
1459     void testIntUnaryOperatorAndThen() throws Throwable {
1460         final Testable<?, ?> testable = new Testable<>(null);
1461         final FailableIntUnaryOperator<Throwable> failing = t -> {
1462             testable.setThrowable(ERROR);
1463             testable.test();
1464             return 0;
1465         };
1466         final FailableIntUnaryOperator<Throwable> nop = FailableIntUnaryOperator.nop();
1467         Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).applyAsInt(0));
1468         assertSame(ERROR, e);
1469         e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).applyAsInt(0));
1470         assertSame(ERROR, e);
1471         // Does not throw
1472         nop.andThen(nop);
1473         // Documented in Javadoc edge-case.
1474         assertNullPointerException(() -> failing.andThen(null));
1475     }
1476 
1477     @Test
1478     void testIntUnaryOperatorCompose() throws Throwable {
1479         final Testable<?, ?> testable = new Testable<>(null);
1480         final FailableIntUnaryOperator<Throwable> failing = t -> {
1481             testable.setThrowable(ERROR);
1482             testable.test();
1483             return 0;
1484         };
1485         final FailableIntUnaryOperator<Throwable> nop = FailableIntUnaryOperator.nop();
1486         Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.compose(failing).applyAsInt(0));
1487         assertSame(ERROR, e);
1488         e = assertThrows(OutOfMemoryError.class, () -> failing.compose(nop).applyAsInt(0));
1489         assertSame(ERROR, e);
1490         // Does not throw
1491         nop.compose(nop);
1492         // Documented in Javadoc edge-case.
1493         assertNullPointerException(() -> failing.compose(null));
1494     }
1495 
1496     @Test
1497     void testIntUnaryOperatorIdentity() throws Throwable {
1498         final FailableIntUnaryOperator<Throwable> nop = FailableIntUnaryOperator.identity();
1499         // Does not throw
1500         nop.compose(nop);
1501         // Documented in Javadoc edge-case.
1502         assertNullPointerException(() -> nop.compose(null));
1503     }
1504 
1505     @Test
1506     void testLongConsumerAndThen() throws Throwable {
1507         final Testable<?, ?> testable = new Testable<>(null);
1508         final FailableLongConsumer<Throwable> failing = t -> {
1509             testable.setThrowable(ERROR);
1510             testable.test();
1511         };
1512         final FailableLongConsumer<Throwable> nop = FailableLongConsumer.nop();
1513         Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).accept(0L));
1514         assertSame(ERROR, e);
1515         e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).accept(0L));
1516         assertSame(ERROR, e);
1517         // Does not throw
1518         nop.andThen(nop);
1519         // Documented in Javadoc edge-case.
1520         assertNullPointerException(() -> failing.andThen(null));
1521     }
1522 
1523     @Test
1524     void testLongPredicate() throws Throwable {
1525         FailureOnOddInvocations.invocations = 0;
1526         final FailableLongPredicate<Throwable> failablePredicate = FailureOnOddInvocations::testLong;
1527         assertThrows(SomeException.class, () -> failablePredicate.test(1L));
1528         failablePredicate.test(1L);
1529     }
1530 
1531     @Test
1532     void testLongPredicateAnd() throws Throwable {
1533         assertTrue(FailableLongPredicate.TRUE.and(FailableLongPredicate.TRUE).test(0));
1534         assertFalse(FailableLongPredicate.TRUE.and(FailableLongPredicate.FALSE).test(0));
1535         assertFalse(FailableLongPredicate.FALSE.and(FailableLongPredicate.TRUE).test(0));
1536         assertFalse(FailableLongPredicate.FALSE.and(FailableLongPredicate.FALSE).test(0));
1537         // null tests
1538         assertNullPointerException(() -> assertFalse(FailableLongPredicate.falsePredicate().and(null).test(0)));
1539         assertNullPointerException(() -> assertTrue(FailableLongPredicate.truePredicate().and(null).test(0)));
1540     }
1541 
1542     @Test
1543     void testLongPredicateNegate() throws Throwable {
1544         assertFalse(FailableLongPredicate.TRUE.negate().test(0L));
1545         assertFalse(FailableLongPredicate.truePredicate().negate().test(0L));
1546         assertTrue(FailableLongPredicate.FALSE.negate().test(0L));
1547         assertTrue(FailableLongPredicate.falsePredicate().negate().test(0L));
1548     }
1549 
1550     @Test
1551     void testLongPredicateOr() throws Throwable {
1552         assertTrue(FailableLongPredicate.TRUE.or(FailableLongPredicate.TRUE).test(0));
1553         assertTrue(FailableLongPredicate.TRUE.or(FailableLongPredicate.FALSE).test(0));
1554         assertTrue(FailableLongPredicate.FALSE.or(FailableLongPredicate.TRUE).test(0));
1555         assertFalse(FailableLongPredicate.FALSE.or(FailableLongPredicate.FALSE).test(0));
1556         // null tests
1557         assertNullPointerException(() -> assertFalse(FailableLongPredicate.falsePredicate().or(null).test(0)));
1558         assertNullPointerException(() -> assertTrue(FailableLongPredicate.truePredicate().or(null).test(0)));
1559     }
1560 
1561     @Test
1562     void testLongUnaryOperatorAndThen() throws Throwable {
1563         final Testable<?, ?> testable = new Testable<>(null);
1564         final FailableLongUnaryOperator<Throwable> failing = t -> {
1565             testable.setThrowable(ERROR);
1566             testable.test();
1567             return 0L;
1568         };
1569         final FailableLongUnaryOperator<Throwable> nop = FailableLongUnaryOperator.nop();
1570         Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).applyAsLong(0L));
1571         assertSame(ERROR, e);
1572         e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).applyAsLong(0L));
1573         assertSame(ERROR, e);
1574         // Does not throw
1575         nop.andThen(nop);
1576         // Documented in Javadoc edge-case.
1577         assertNullPointerException(() -> failing.andThen(null));
1578     }
1579 
1580     @Test
1581     void testLongUnaryOperatorCompose() throws Throwable {
1582         final Testable<?, ?> testable = new Testable<>(null);
1583         final FailableLongUnaryOperator<Throwable> failing = t -> {
1584             testable.setThrowable(ERROR);
1585             testable.test();
1586             return 0L;
1587         };
1588         final FailableLongUnaryOperator<Throwable> nop = FailableLongUnaryOperator.nop();
1589         Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.compose(failing).applyAsLong(0L));
1590         assertSame(ERROR, e);
1591         e = assertThrows(OutOfMemoryError.class, () -> failing.compose(nop).applyAsLong(0L));
1592         assertSame(ERROR, e);
1593         // Does not throw
1594         nop.compose(nop);
1595         // Documented in Javadoc edge-case.
1596         assertNullPointerException(() -> failing.compose(null));
1597     }
1598 
1599     @Test
1600     void testLongUnaryOperatorIdentity() throws Throwable {
1601         final FailableLongUnaryOperator<Throwable> nop = FailableLongUnaryOperator.identity();
1602         // Does not throw
1603         nop.compose(nop);
1604         // Documented in Javadoc edge-case.
1605         assertNullPointerException(() -> nop.compose(null));
1606     }
1607 
1608     @Test
1609     /** Test that asPredicate(FailablePredicate) is converted to -> Predicate  */
1610     void testPredicate() {
1611         FailureOnOddInvocations.invocations = 0;
1612         final FailablePredicate<Object, Throwable> failablePredicate = t -> FailureOnOddInvocations.testGetBool();
1613         final Predicate<?> predicate = Failable.asPredicate(failablePredicate);
1614         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class,
1615             () -> predicate.test(null));
1616         final Throwable cause = e.getCause();
1617         assertNotNull(cause);
1618         assertInstanceOf(SomeException.class, cause);
1619         assertEquals("Odd Invocation: 1", cause.getMessage());
1620         final boolean instance = predicate.test(null);
1621         assertNotNull(instance);
1622     }
1623 
1624     @Test
1625     void testPredicateAnd() throws Throwable {
1626         assertTrue(FailablePredicate.TRUE.and(FailablePredicate.TRUE).test(null));
1627         assertFalse(FailablePredicate.TRUE.and(FailablePredicate.FALSE).test(null));
1628         assertFalse(FailablePredicate.FALSE.and(FailablePredicate.TRUE).test(null));
1629         assertFalse(FailablePredicate.FALSE.and(FailablePredicate.FALSE).test(null));
1630         // null tests
1631         assertNullPointerException(() -> assertFalse(FailablePredicate.FALSE.and(null).test(null)));
1632         assertNullPointerException(() -> assertTrue(FailablePredicate.TRUE.and(null).test(null)));
1633     }
1634 
1635     @Test
1636     void testPredicateNegate() throws Throwable {
1637         assertFalse(FailablePredicate.TRUE.negate().test(null));
1638         assertFalse(FailablePredicate.truePredicate().negate().test(null));
1639         assertTrue(FailablePredicate.FALSE.negate().test(null));
1640         assertTrue(FailablePredicate.falsePredicate().negate().test(null));
1641     }
1642 
1643     @Test
1644     void testPredicateOr() throws Throwable {
1645         assertTrue(FailablePredicate.TRUE.or(FailablePredicate.TRUE).test(null));
1646         assertTrue(FailablePredicate.TRUE.or(FailablePredicate.FALSE).test(null));
1647         assertTrue(FailablePredicate.FALSE.or(FailablePredicate.TRUE).test(null));
1648         assertFalse(FailablePredicate.FALSE.or(FailablePredicate.FALSE).test(null));
1649         // null tests
1650         assertNullPointerException(() -> assertFalse(FailablePredicate.FALSE.or(null).test(null)));
1651         assertNullPointerException(() -> assertTrue(FailablePredicate.TRUE.or(null).test(null)));
1652     }
1653 
1654     @Test
1655     void testRunnable() {
1656         FailureOnOddInvocations.invocations = 0;
1657         final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class,
1658             () -> Failable.run(FailureOnOddInvocations::new));
1659         final Throwable cause = e.getCause();
1660         assertNotNull(cause);
1661         assertInstanceOf(SomeException.class, cause);
1662         assertEquals("Odd Invocation: 1", cause.getMessage());
1663 
1664         // Even invocations, should not throw an exception
1665         Failable.run(FailureOnOddInvocations::new);
1666         Failable.run(null);
1667     }
1668 
1669     /**
1670      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
1671      * Object and Throwable.
1672      */
1673     @Test
1674     void testThrows_FailableBiConsumer_Object_Throwable() {
1675         assertThrows(IOException.class, () -> new FailableBiConsumer<Object, Object, Throwable>() {
1676 
1677             @Override
1678             public void accept(final Object object1, final Object object2) throws Throwable {
1679                 throw new IOException("test");
1680             }
1681         }.accept(new Object(), new Object()));
1682     }
1683 
1684     /**
1685      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
1686      * generic test types.
1687      */
1688     @Test
1689     void testThrows_FailableBiConsumer_String_IOException() {
1690         assertThrows(IOException.class, () -> new FailableBiConsumer<String, String, IOException>() {
1691 
1692             @Override
1693             public void accept(final String object1, final String object2) throws IOException {
1694                 throw new IOException("test");
1695 
1696             }
1697         }.accept(StringUtils.EMPTY, StringUtils.EMPTY));
1698     }
1699 
1700     /**
1701      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
1702      * Object and Throwable.
1703      */
1704     @Test
1705     void testThrows_FailableBiFunction_Object_Throwable() {
1706         assertThrows(IOException.class, () -> new FailableBiFunction<Object, Object, Object, Throwable>() {
1707 
1708             @Override
1709             public Object apply(final Object input1, final Object input2) throws Throwable {
1710                 throw new IOException("test");
1711             }
1712         }.apply(new Object(), new Object()));
1713     }
1714 
1715     /**
1716      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
1717      * generic test types.
1718      */
1719     @Test
1720     void testThrows_FailableBiFunction_String_IOException() {
1721         assertThrows(IOException.class, () -> new FailableBiFunction<String, String, String, IOException>() {
1722 
1723             @Override
1724             public String apply(final String input1, final String input2) throws IOException {
1725                 throw new IOException("test");
1726             }
1727         }.apply(StringUtils.EMPTY, StringUtils.EMPTY));
1728     }
1729 
1730     /**
1731      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
1732      * Object and Throwable.
1733      */
1734     @Test
1735     void testThrows_FailableBiPredicate_Object_Throwable() {
1736         assertThrows(IOException.class, () -> new FailableBiPredicate<Object, Object, Throwable>() {
1737 
1738             @Override
1739             public boolean test(final Object object1, final Object object2) throws Throwable {
1740                 throw new IOException("test");
1741             }
1742         }.test(new Object(), new Object()));
1743     }
1744 
1745     /**
1746      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
1747      * generic test types.
1748      */
1749     @Test
1750     void testThrows_FailableBiPredicate_String_IOException() {
1751         assertThrows(IOException.class, () -> new FailableBiPredicate<String, String, IOException>() {
1752 
1753             @Override
1754             public boolean test(final String object1, final String object2) throws IOException {
1755                 throw new IOException("test");
1756             }
1757         }.test(StringUtils.EMPTY, StringUtils.EMPTY));
1758     }
1759 
1760     /**
1761      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
1762      * generic test types.
1763      */
1764     @Test
1765     void testThrows_FailableBooleanSupplier_IOException() {
1766         assertThrows(IOException.class, () -> new FailableBooleanSupplier<IOException>() {
1767 
1768             @Override
1769             public boolean getAsBoolean() throws IOException {
1770                 throw new IOException("test");
1771             }
1772         }.getAsBoolean());
1773     }
1774 
1775     /**
1776      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
1777      * Object and Throwable.
1778      */
1779     @Test
1780     void testThrows_FailableBooleanSupplier_Throwable() {
1781         assertThrows(IOException.class, () -> new FailableBooleanSupplier<Throwable>() {
1782 
1783             @Override
1784             public boolean getAsBoolean() throws Throwable {
1785                 throw new IOException("test");
1786             }
1787         }.getAsBoolean());
1788     }
1789 
1790     /**
1791      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
1792      * generic test types.
1793      */
1794     @Test
1795     void testThrows_FailableByteConsumer_IOException() {
1796         assertThrows(IOException.class, () -> new FailableByteConsumer<IOException>() {
1797 
1798             @Override
1799             public void accept(final byte value) throws IOException {
1800                 throw new IOException("test");
1801             }
1802         }.accept((byte) 0));
1803     }
1804 
1805     /**
1806      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
1807      * Object and Throwable.
1808      */
1809     @Test
1810     void testThrows_FailableByteConsumer_Throwable() {
1811         assertThrows(IOException.class, () -> new FailableByteConsumer<Throwable>() {
1812 
1813             @Override
1814             public void accept(final byte value) throws Throwable {
1815                 throw new IOException("test");
1816 
1817             }
1818         }.accept((byte) 0));
1819     }
1820 
1821     /**
1822      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
1823      * generic test types.
1824      */
1825     @Test
1826     void testThrows_FailableByteSupplier_IOException() {
1827         assertThrows(IOException.class, () -> new FailableByteSupplier<IOException>() {
1828 
1829             @Override
1830             public byte getAsByte() throws IOException {
1831                 throw new IOException("test");
1832             }
1833         }.getAsByte());
1834     }
1835 
1836     /**
1837      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
1838      * Object and Throwable.
1839      */
1840     @Test
1841     void testThrows_FailableByteSupplier_Throwable() {
1842         assertThrows(IOException.class, () -> new FailableByteSupplier<Throwable>() {
1843 
1844             @Override
1845             public byte getAsByte() throws Throwable {
1846                 throw new IOException("test");
1847             }
1848         }.getAsByte());
1849     }
1850 
1851     /**
1852      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
1853      * Object and Throwable.
1854      */
1855     @Test
1856     void testThrows_FailableCallable_Object_Throwable() {
1857         assertThrows(IOException.class, () -> new FailableCallable<Object, Throwable>() {
1858 
1859             @Override
1860             public Object call() throws Throwable {
1861                 throw new IOException("test");
1862             }
1863         }.call());
1864     }
1865 
1866     /**
1867      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
1868      * generic test types.
1869      */
1870     @Test
1871     void testThrows_FailableCallable_String_IOException() {
1872         assertThrows(IOException.class, () -> new FailableCallable<String, IOException>() {
1873 
1874             @Override
1875             public String call() throws IOException {
1876                 throw new IOException("test");
1877             }
1878         }.call());
1879     }
1880 
1881     /**
1882      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
1883      * Object and Throwable.
1884      */
1885     @Test
1886     void testThrows_FailableConsumer_Object_Throwable() {
1887         assertThrows(IOException.class, () -> new FailableConsumer<Object, Throwable>() {
1888 
1889             @Override
1890             public void accept(final Object object) throws Throwable {
1891                 throw new IOException("test");
1892 
1893             }
1894         }.accept(new Object()));
1895     }
1896 
1897     /**
1898      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
1899      * generic test types.
1900      */
1901     @Test
1902     void testThrows_FailableConsumer_String_IOException() {
1903         assertThrows(IOException.class, () -> new FailableConsumer<String, IOException>() {
1904 
1905             @Override
1906             public void accept(final String object) throws IOException {
1907                 throw new IOException("test");
1908 
1909             }
1910         }.accept(StringUtils.EMPTY));
1911     }
1912 
1913     /**
1914      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
1915      * generic test types.
1916      */
1917     @Test
1918     void testThrows_FailableDoubleBinaryOperator_IOException() {
1919         assertThrows(IOException.class, () -> new FailableDoubleBinaryOperator<IOException>() {
1920 
1921             @Override
1922             public double applyAsDouble(final double left, final double right) throws IOException {
1923                 throw new IOException("test");
1924             }
1925         }.applyAsDouble(0, 0));
1926     }
1927 
1928     /**
1929      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
1930      * Object and Throwable.
1931      */
1932     @Test
1933     void testThrows_FailableDoubleBinaryOperator_Throwable() {
1934         assertThrows(IOException.class, () -> new FailableDoubleBinaryOperator<Throwable>() {
1935 
1936             @Override
1937             public double applyAsDouble(final double left, final double right) throws Throwable {
1938                 throw new IOException("test");
1939             }
1940         }.applyAsDouble(0, 0));
1941     }
1942 
1943     /**
1944      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
1945      * generic test types.
1946      */
1947     @Test
1948     void testThrows_FailableDoubleConsumer_IOException() {
1949         assertThrows(IOException.class, () -> new FailableDoubleConsumer<IOException>() {
1950 
1951             @Override
1952             public void accept(final double value) throws IOException {
1953                 throw new IOException("test");
1954             }
1955         }.accept(0));
1956     }
1957 
1958     /**
1959      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
1960      * Object and Throwable.
1961      */
1962     @Test
1963     void testThrows_FailableDoubleConsumer_Throwable() {
1964         assertThrows(IOException.class, () -> new FailableDoubleConsumer<Throwable>() {
1965 
1966             @Override
1967             public void accept(final double value) throws Throwable {
1968                 throw new IOException("test");
1969 
1970             }
1971         }.accept(0));
1972     }
1973 
1974     /**
1975      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
1976      * generic test types.
1977      */
1978     @Test
1979     void testThrows_FailableDoubleFunction_IOException() {
1980         assertThrows(IOException.class, () -> new FailableDoubleFunction<String, IOException>() {
1981 
1982             @Override
1983             public String apply(final double input) throws IOException {
1984                 throw new IOException("test");
1985             }
1986         }.apply(0));
1987     }
1988 
1989     /**
1990      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
1991      * Object and Throwable.
1992      */
1993     @Test
1994     void testThrows_FailableDoubleFunction_Throwable() {
1995         assertThrows(IOException.class, () -> new FailableDoubleFunction<Object, Throwable>() {
1996 
1997             @Override
1998             public Object apply(final double input) throws Throwable {
1999                 throw new IOException("test");
2000             }
2001         }.apply(0));
2002     }
2003 
2004     /**
2005      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2006      * generic test types.
2007      */
2008     @Test
2009     void testThrows_FailableDoubleSupplier_IOException() {
2010         assertThrows(IOException.class, () -> new FailableDoubleSupplier<IOException>() {
2011 
2012             @Override
2013             public double getAsDouble() throws IOException {
2014                 throw new IOException("test");
2015             }
2016         }.getAsDouble());
2017     }
2018 
2019     /**
2020      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2021      * Object and Throwable.
2022      */
2023     @Test
2024     void testThrows_FailableDoubleSupplier_Throwable() {
2025         assertThrows(IOException.class, () -> new FailableDoubleSupplier<Throwable>() {
2026 
2027             @Override
2028             public double getAsDouble() throws Throwable {
2029                 throw new IOException("test");
2030             }
2031         }.getAsDouble());
2032     }
2033 
2034     /**
2035      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2036      * generic test types.
2037      */
2038     @Test
2039     void testThrows_FailableDoubleToIntFunction_IOException() {
2040         assertThrows(IOException.class, () -> new FailableDoubleToIntFunction<IOException>() {
2041 
2042             @Override
2043             public int applyAsInt(final double value) throws IOException {
2044                 throw new IOException("test");
2045             }
2046         }.applyAsInt(0));
2047     }
2048 
2049     /**
2050      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2051      * Object and Throwable.
2052      */
2053     @Test
2054     void testThrows_FailableDoubleToIntFunction_Throwable() {
2055         assertThrows(IOException.class, () -> new FailableDoubleToIntFunction<Throwable>() {
2056 
2057             @Override
2058             public int applyAsInt(final double value) throws Throwable {
2059                 throw new IOException("test");
2060             }
2061         }.applyAsInt(0));
2062     }
2063 
2064     /**
2065      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2066      * generic test types.
2067      */
2068     @Test
2069     void testThrows_FailableDoubleToLongFunction_IOException() {
2070         assertThrows(IOException.class, () -> new FailableDoubleToLongFunction<IOException>() {
2071 
2072             @Override
2073             public int applyAsLong(final double value) throws IOException {
2074                 throw new IOException("test");
2075             }
2076         }.applyAsLong(0));
2077     }
2078 
2079     /**
2080      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2081      * Object and Throwable.
2082      */
2083     @Test
2084     void testThrows_FailableDoubleToLongFunction_Throwable() {
2085         assertThrows(IOException.class, () -> new FailableDoubleToLongFunction<Throwable>() {
2086 
2087             @Override
2088             public int applyAsLong(final double value) throws Throwable {
2089                 throw new IOException("test");
2090             }
2091         }.applyAsLong(0));
2092     }
2093 
2094     /**
2095      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2096      * Object and Throwable.
2097      */
2098     @Test
2099     void testThrows_FailableFunction_Object_Throwable() {
2100         assertThrows(IOException.class, () -> new FailableFunction<Object, Object, Throwable>() {
2101 
2102             @Override
2103             public Object apply(final Object input) throws Throwable {
2104                 throw new IOException("test");
2105             }
2106         }.apply(new Object()));
2107     }
2108 
2109     /**
2110      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2111      * generic test types.
2112      */
2113     @Test
2114     void testThrows_FailableFunction_String_IOException() {
2115         assertThrows(IOException.class, () -> new FailableFunction<String, String, IOException>() {
2116 
2117             @Override
2118             public String apply(final String input) throws IOException {
2119                 throw new IOException("test");
2120             }
2121         }.apply(StringUtils.EMPTY));
2122     }
2123 
2124     /**
2125      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2126      * generic test types.
2127      */
2128     @Test
2129     void testThrows_FailableIntBinaryOperator_IOException() {
2130         assertThrows(IOException.class, () -> new FailableIntBinaryOperator<IOException>() {
2131 
2132             @Override
2133             public int applyAsInt(final int left, final int right) throws IOException {
2134                 throw new IOException("test");
2135             }
2136         }.applyAsInt(0, 0));
2137     }
2138 
2139     /**
2140      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2141      * Object and Throwable.
2142      */
2143     @Test
2144     void testThrows_FailableIntBinaryOperator_Throwable() {
2145         assertThrows(IOException.class, () -> new FailableIntBinaryOperator<Throwable>() {
2146 
2147             @Override
2148             public int applyAsInt(final int left, final int right) throws Throwable {
2149                 throw new IOException("test");
2150             }
2151         }.applyAsInt(0, 0));
2152     }
2153 
2154     /**
2155      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2156      * generic test types.
2157      */
2158     @Test
2159     void testThrows_FailableIntConsumer_IOException() {
2160         assertThrows(IOException.class, () -> new FailableIntConsumer<IOException>() {
2161 
2162             @Override
2163             public void accept(final int value) throws IOException {
2164                 throw new IOException("test");
2165             }
2166         }.accept(0));
2167     }
2168 
2169     /**
2170      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2171      * Object and Throwable.
2172      */
2173     @Test
2174     void testThrows_FailableIntConsumer_Throwable() {
2175         assertThrows(IOException.class, () -> new FailableIntConsumer<Throwable>() {
2176 
2177             @Override
2178             public void accept(final int value) throws Throwable {
2179                 throw new IOException("test");
2180 
2181             }
2182         }.accept(0));
2183     }
2184 
2185     /**
2186      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2187      * Object and Throwable.
2188      */
2189     @Test
2190     void testThrows_FailableIntFunction_Object_Throwable() {
2191         assertThrows(IOException.class, () -> new FailableIntFunction<Object, Throwable>() {
2192 
2193             @Override
2194             public Object apply(final int input) throws Throwable {
2195                 throw new IOException("test");
2196             }
2197         }.apply(0));
2198     }
2199 
2200     /**
2201      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2202      * generic test types.
2203      */
2204     @Test
2205     void testThrows_FailableIntFunction_String_IOException() {
2206         assertThrows(IOException.class, () -> new FailableIntFunction<String, IOException>() {
2207 
2208             @Override
2209             public String apply(final int input) throws IOException {
2210                 throw new IOException("test");
2211             }
2212         }.apply(0));
2213     }
2214 
2215     /**
2216      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2217      * generic test types.
2218      */
2219     @Test
2220     void testThrows_FailableIntSupplier_IOException() {
2221         assertThrows(IOException.class, () -> new FailableIntSupplier<IOException>() {
2222 
2223             @Override
2224             public int getAsInt() throws IOException {
2225                 throw new IOException("test");
2226             }
2227         }.getAsInt());
2228     }
2229 
2230     /**
2231      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2232      * Object and Throwable.
2233      */
2234     @Test
2235     void testThrows_FailableIntSupplier_Throwable() {
2236         assertThrows(IOException.class, () -> new FailableIntSupplier<Throwable>() {
2237 
2238             @Override
2239             public int getAsInt() throws Throwable {
2240                 throw new IOException("test");
2241             }
2242         }.getAsInt());
2243     }
2244 
2245     /**
2246      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2247      * generic test types.
2248      */
2249     @Test
2250     void testThrows_FailableIntToDoubleFunction_IOException() {
2251         assertThrows(IOException.class, () -> new FailableIntToDoubleFunction<IOException>() {
2252 
2253             @Override
2254             public double applyAsDouble(final int value) throws IOException {
2255                 throw new IOException("test");
2256             }
2257         }.applyAsDouble(0));
2258     }
2259 
2260     /**
2261      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2262      * Object and Throwable.
2263      */
2264     @Test
2265     void testThrows_FailableIntToDoubleFunction_Throwable() {
2266         assertThrows(IOException.class, () -> new FailableIntToDoubleFunction<Throwable>() {
2267 
2268             @Override
2269             public double applyAsDouble(final int value) throws Throwable {
2270                 throw new IOException("test");
2271             }
2272         }.applyAsDouble(0));
2273     }
2274 
2275     /**
2276      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2277      * generic test types.
2278      */
2279     @Test
2280     void testThrows_FailableIntToFloatFunction_IOException() {
2281         assertThrows(IOException.class, () -> new FailableIntToFloatFunction<IOException>() {
2282 
2283             @Override
2284             public float applyAsFloat(final int value) throws IOException {
2285                 throw new IOException("test");
2286             }
2287         }.applyAsFloat(0));
2288     }
2289 
2290     /**
2291      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2292      * Object and Throwable.
2293      */
2294     @Test
2295     void testThrows_FailableIntToFloatFunction_Throwable() {
2296         assertThrows(IOException.class, () -> new FailableIntToFloatFunction<Throwable>() {
2297 
2298             @Override
2299             public float applyAsFloat(final int value) throws Throwable {
2300                 throw new IOException("test");
2301             }
2302         }.applyAsFloat(0));
2303     }
2304 
2305     /**
2306      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2307      * generic test types.
2308      */
2309     @Test
2310     void testThrows_FailableIntToLongFunction_IOException() {
2311         assertThrows(IOException.class, () -> new FailableIntToLongFunction<IOException>() {
2312 
2313             @Override
2314             public long applyAsLong(final int value) throws IOException {
2315                 throw new IOException("test");
2316             }
2317         }.applyAsLong(0));
2318     }
2319 
2320     /**
2321      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2322      * Object and Throwable.
2323      */
2324     @Test
2325     void testThrows_FailableIntToLongFunction_Throwable() {
2326         assertThrows(IOException.class, () -> new FailableIntToLongFunction<Throwable>() {
2327 
2328             @Override
2329             public long applyAsLong(final int value) throws Throwable {
2330                 throw new IOException("test");
2331             }
2332         }.applyAsLong(0));
2333     }
2334 
2335     /**
2336      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2337      * generic test types.
2338      */
2339     @Test
2340     void testThrows_FailableLongBinaryOperator_IOException() {
2341         assertThrows(IOException.class, () -> new FailableLongBinaryOperator<IOException>() {
2342 
2343             @Override
2344             public long applyAsLong(final long left, final long right) throws IOException {
2345                 throw new IOException("test");
2346             }
2347         }.applyAsLong(0, 0));
2348     }
2349 
2350     /**
2351      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2352      * Object and Throwable.
2353      */
2354     @Test
2355     void testThrows_FailableLongBinaryOperator_Throwable() {
2356         assertThrows(IOException.class, () -> new FailableLongBinaryOperator<Throwable>() {
2357 
2358             @Override
2359             public long applyAsLong(final long left, final long right) throws Throwable {
2360                 throw new IOException("test");
2361             }
2362         }.applyAsLong(0, 0));
2363     }
2364 
2365     /**
2366      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2367      * generic test types.
2368      */
2369     @Test
2370     void testThrows_FailableLongConsumer_IOException() {
2371         assertThrows(IOException.class, () -> new FailableLongConsumer<IOException>() {
2372 
2373             @Override
2374             public void accept(final long object) throws IOException {
2375                 throw new IOException("test");
2376 
2377             }
2378         }.accept(0));
2379      }
2380 
2381     /**
2382      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2383      * Object and Throwable.
2384      */
2385     @Test
2386     void testThrows_FailableLongConsumer_Throwable() {
2387         assertThrows(IOException.class, () -> new FailableLongConsumer<Throwable>() {
2388 
2389             @Override
2390             public void accept(final long object) throws Throwable {
2391                 throw new IOException("test");
2392 
2393             }
2394         }.accept(0));
2395     }
2396 
2397     /**
2398      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2399      * generic test types.
2400      */
2401     @Test
2402     void testThrows_FailableLongFunction_IOException() {
2403         assertThrows(IOException.class, () -> new FailableLongFunction<String, IOException>() {
2404 
2405             @Override
2406             public String apply(final long input) throws IOException {
2407                 throw new IOException("test");
2408             }
2409         }.apply(0));
2410     }
2411 
2412     /**
2413      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2414      * Object and Throwable.
2415      */
2416     @Test
2417     void testThrows_FailableLongFunction_Throwable() {
2418         assertThrows(IOException.class, () -> new FailableLongFunction<Object, Throwable>() {
2419 
2420             @Override
2421             public Object apply(final long input) throws Throwable {
2422                 throw new IOException("test");
2423             }
2424         }.apply(0));
2425     }
2426 
2427     /**
2428      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2429      * generic test types.
2430      */
2431     @Test
2432     void testThrows_FailableLongSupplier_IOException() {
2433         assertThrows(IOException.class, () -> new FailableLongSupplier<IOException>() {
2434 
2435             @Override
2436             public long getAsLong() throws IOException {
2437                 throw new IOException("test");
2438             }
2439         }.getAsLong());
2440     }
2441 
2442     /**
2443      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2444      * Object and Throwable.
2445      */
2446     @Test
2447     void testThrows_FailableLongSupplier_Throwable() {
2448         assertThrows(IOException.class, () -> new FailableLongSupplier<Throwable>() {
2449 
2450             @Override
2451             public long getAsLong() throws Throwable {
2452                 throw new IOException("test");
2453             }
2454         }.getAsLong());
2455     }
2456 
2457     /**
2458      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2459      * generic test types.
2460      */
2461     @Test
2462     void testThrows_FailableLongToDoubleFunction_IOException() {
2463         assertThrows(IOException.class, () -> new FailableLongToDoubleFunction<IOException>() {
2464 
2465             @Override
2466             public double applyAsDouble(final long value) throws IOException {
2467                 throw new IOException("test");
2468             }
2469         }.applyAsDouble(0));
2470     }
2471 
2472     /**
2473      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2474      * Object and Throwable.
2475      */
2476     @Test
2477     void testThrows_FailableLongToDoubleFunction_Throwable() {
2478         assertThrows(IOException.class, () -> new FailableLongToDoubleFunction<Throwable>() {
2479 
2480             @Override
2481             public double applyAsDouble(final long value) throws Throwable {
2482                 throw new IOException("test");
2483             }
2484         }.applyAsDouble(0));
2485     }
2486 
2487     /**
2488      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2489      * generic test types.
2490      */
2491     @Test
2492     void testThrows_FailableLongToIntFunction_IOException() {
2493         assertThrows(IOException.class, () -> new FailableLongToIntFunction<IOException>() {
2494 
2495             @Override
2496             public int applyAsInt(final long value) throws IOException {
2497                 throw new IOException("test");
2498             }
2499         }.applyAsInt(0));
2500     }
2501 
2502     /**
2503      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2504      * Object and Throwable.
2505      */
2506     @Test
2507     void testThrows_FailableLongToIntFunction_Throwable() {
2508         assertThrows(IOException.class, () -> new FailableLongToIntFunction<Throwable>() {
2509 
2510             @Override
2511             public int applyAsInt(final long value) throws Throwable {
2512                 throw new IOException("test");
2513             }
2514         }.applyAsInt(0));
2515     }
2516 
2517     /**
2518      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2519      * Object and Throwable.
2520      */
2521     @Test
2522     void testThrows_FailableObjDoubleConsumer_Object_Throwable() {
2523         assertThrows(IOException.class, () -> new FailableObjDoubleConsumer<Object, Throwable>() {
2524 
2525             @Override
2526             public void accept(final Object object, final double value) throws Throwable {
2527                 throw new IOException("test");
2528 
2529             }
2530         }.accept(new Object(), 0));
2531     }
2532 
2533     /**
2534      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2535      * generic test types.
2536      */
2537     @Test
2538     void testThrows_FailableObjDoubleConsumer_String_IOException() {
2539         assertThrows(IOException.class, () -> new FailableObjDoubleConsumer<String, IOException>() {
2540 
2541             @Override
2542             public void accept(final String object, final double value) throws IOException {
2543                 throw new IOException("test");
2544             }
2545         }.accept(StringUtils.EMPTY, 0));
2546     }
2547 
2548     /**
2549      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2550      * Object and Throwable.
2551      */
2552     @Test
2553     void testThrows_FailableObjIntConsumer_Object_Throwable() {
2554         assertThrows(IOException.class, () -> new FailableObjIntConsumer<Object, Throwable>() {
2555 
2556             @Override
2557             public void accept(final Object object, final int value) throws Throwable {
2558                 throw new IOException("test");
2559 
2560             }
2561         }.accept(new Object(), 0));
2562     }
2563 
2564     /**
2565      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2566      * generic test types.
2567      */
2568     @Test
2569     void testThrows_FailableObjIntConsumer_String_IOException() {
2570         assertThrows(IOException.class, () -> new FailableObjIntConsumer<String, IOException>() {
2571 
2572             @Override
2573             public void accept(final String object, final int value) throws IOException {
2574                 throw new IOException("test");
2575             }
2576         }.accept(StringUtils.EMPTY, 0));
2577     }
2578 
2579     /**
2580      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2581      * Object and Throwable.
2582      */
2583     @Test
2584     void testThrows_FailableObjLongConsumer_Object_Throwable() {
2585         assertThrows(IOException.class, () -> new FailableObjLongConsumer<Object, Throwable>() {
2586 
2587             @Override
2588             public void accept(final Object object, final long value) throws Throwable {
2589                 throw new IOException("test");
2590 
2591             }
2592         }.accept(new Object(), 0));
2593     }
2594 
2595     /**
2596      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2597      * generic test types.
2598      */
2599     @Test
2600     void testThrows_FailableObjLongConsumer_String_IOException() {
2601         assertThrows(IOException.class, () -> new FailableObjLongConsumer<String, IOException>() {
2602 
2603             @Override
2604             public void accept(final String object, final long value) throws IOException {
2605                 throw new IOException("test");
2606             }
2607         }.accept(StringUtils.EMPTY, 0));
2608         final FailableObjLongConsumer<String, IOException> f = (o, l) -> {
2609             throw new IOException("test");
2610         };
2611         assertThrows(IOException.class, () -> f.accept(StringUtils.EMPTY, 0));
2612     }
2613 
2614     /**
2615      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2616      * Object and Throwable.
2617      */
2618     @Test
2619     void testThrows_FailablePredicate_Object_Throwable() {
2620         assertThrows(IOException.class, () -> new FailablePredicate<Object, Throwable>() {
2621 
2622             @Override
2623             public boolean test(final Object object) throws Throwable {
2624                 throw new IOException("test");
2625             }
2626         }.test(new Object()));
2627     }
2628 
2629     /**
2630      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2631      * generic test types.
2632      */
2633     @Test
2634     void testThrows_FailablePredicate_String_IOException() {
2635         assertThrows(IOException.class, () -> new FailablePredicate<String, IOException>() {
2636 
2637             @Override
2638             public boolean test(final String object) throws IOException {
2639                 throw new IOException("test");
2640             }
2641         }.test(StringUtils.EMPTY));
2642     }
2643 
2644     /**
2645      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2646      * generic test types.
2647      */
2648     @Test
2649     void testThrows_FailableRunnable_IOException() {
2650         assertThrows(IOException.class, () -> new FailableRunnable<IOException>() {
2651 
2652             @Override
2653             public void run() throws IOException {
2654                 throw new IOException("test");
2655             }
2656         }.run());
2657     }
2658 
2659     /**
2660      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2661      * Object and Throwable.
2662      */
2663     @Test
2664     void testThrows_FailableRunnable_Throwable() {
2665         assertThrows(IOException.class, () -> new FailableRunnable<Throwable>() {
2666 
2667             @Override
2668             public void run() throws Throwable {
2669                 throw new IOException("test");
2670 
2671             }
2672         }.run());
2673     }
2674 
2675     /**
2676      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2677      * generic test types.
2678      */
2679     @Test
2680     void testThrows_FailableShortSupplier_IOException() {
2681         assertThrows(IOException.class, () -> new FailableShortSupplier<IOException>() {
2682 
2683             @Override
2684             public short getAsShort() throws IOException {
2685                 throw new IOException("test");
2686             }
2687         }.getAsShort());
2688     }
2689 
2690     /**
2691      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2692      * Object and Throwable.
2693      */
2694     @Test
2695     void testThrows_FailableShortSupplier_Throwable() {
2696         assertThrows(IOException.class, () -> new FailableShortSupplier<Throwable>() {
2697 
2698             @Override
2699             public short getAsShort() throws Throwable {
2700                 throw new IOException("test");
2701             }
2702         }.getAsShort());
2703     }
2704 
2705     /**
2706      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2707      * Object and Throwable.
2708      */
2709     @Test
2710     void testThrows_FailableSupplier_Object_Throwable() {
2711         assertThrows(IOException.class, () -> new FailableSupplier<Object, Throwable>() {
2712 
2713             @Override
2714             public Object get() throws Throwable {
2715                 throw new IOException("test");
2716             }
2717         }.get());
2718     }
2719 
2720     /**
2721      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2722      * generic test types.
2723      */
2724     @Test
2725     void testThrows_FailableSupplier_String_IOException() {
2726         assertThrows(IOException.class, () -> new FailableSupplier<String, IOException>() {
2727 
2728             @Override
2729             public String get() throws IOException {
2730                 throw new IOException("test");
2731             }
2732         }.get());
2733     }
2734 
2735     /**
2736      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2737      * Object and Throwable.
2738      */
2739     @Test
2740     void testThrows_FailableToBooleanFunction_Object_Throwable() {
2741         assertThrows(IOException.class, () -> new FailableToBooleanFunction<Object, Throwable>() {
2742 
2743             @Override
2744             public boolean applyAsBoolean(final Object t) throws Throwable {
2745                 throw new IOException("test");
2746             }
2747         }.applyAsBoolean(new Object()));
2748     }
2749 
2750     /**
2751      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2752      * generic test types.
2753      */
2754     @Test
2755     void testThrows_FailableToBooleanFunction_String_IOException() {
2756         assertThrows(IOException.class, () -> new FailableToBooleanFunction<String, IOException>() {
2757 
2758             @Override
2759             public boolean applyAsBoolean(final String t) throws IOException {
2760                 throw new IOException("test");
2761             }
2762         }.applyAsBoolean(StringUtils.EMPTY));
2763     }
2764 
2765     /**
2766      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2767      * Object and Throwable.
2768      */
2769     @Test
2770     void testThrows_FailableToDoubleBiFunction_Object_Throwable() {
2771         assertThrows(IOException.class, () -> new FailableToDoubleBiFunction<Object, Object, Throwable>() {
2772 
2773             @Override
2774             public double applyAsDouble(final Object t, final Object u) throws Throwable {
2775                 throw new IOException("test");
2776             }
2777         }.applyAsDouble(new Object(), new Object()));
2778     }
2779 
2780     /**
2781      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2782      * generic test types.
2783      */
2784     @Test
2785     void testThrows_FailableToDoubleBiFunction_String_IOException() {
2786         assertThrows(IOException.class, () -> new FailableToDoubleBiFunction<String, String, IOException>() {
2787 
2788             @Override
2789             public double applyAsDouble(final String t, final String u) throws IOException {
2790                 throw new IOException("test");
2791             }
2792         }.applyAsDouble(StringUtils.EMPTY, StringUtils.EMPTY));
2793     }
2794 
2795     /**
2796      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2797      * Object and Throwable.
2798      */
2799     @Test
2800     void testThrows_FailableToDoubleFunction_Object_Throwable() {
2801         assertThrows(IOException.class, () -> new FailableToDoubleFunction<Object, Throwable>() {
2802 
2803             @Override
2804             public double applyAsDouble(final Object t) throws Throwable {
2805                 throw new IOException("test");
2806             }
2807         }.applyAsDouble(new Object()));
2808     }
2809 
2810     /**
2811      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2812      * generic test types.
2813      */
2814     @Test
2815     void testThrows_FailableToDoubleFunction_String_IOException() {
2816         assertThrows(IOException.class, () -> new FailableToDoubleFunction<String, IOException>() {
2817 
2818             @Override
2819             public double applyAsDouble(final String t) throws IOException {
2820                 throw new IOException("test");
2821             }
2822         }.applyAsDouble(StringUtils.EMPTY));
2823     }
2824 
2825     /**
2826      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2827      * Object and Throwable.
2828      */
2829     @Test
2830     void testThrows_FailableToIntBiFunction_Object_Throwable() {
2831         assertThrows(IOException.class, () -> new FailableToIntBiFunction<Object, Object, Throwable>() {
2832 
2833             @Override
2834             public int applyAsInt(final Object t, final Object u) throws Throwable {
2835                 throw new IOException("test");
2836             }
2837         }.applyAsInt(new Object(), new Object()));
2838     }
2839 
2840     /**
2841      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2842      * generic test types.
2843      */
2844     @Test
2845     void testThrows_FailableToIntBiFunction_String_IOException() {
2846         assertThrows(IOException.class, () -> new FailableToIntBiFunction<String, String, IOException>() {
2847 
2848             @Override
2849             public int applyAsInt(final String t, final String u) throws IOException {
2850                 throw new IOException("test");
2851             }
2852         }.applyAsInt(StringUtils.EMPTY, StringUtils.EMPTY));
2853     }
2854 
2855     /**
2856      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2857      * Object and Throwable.
2858      */
2859     @Test
2860     void testThrows_FailableToIntFunction_Object_Throwable() {
2861         assertThrows(IOException.class, () -> new FailableToIntFunction<Object, Throwable>() {
2862 
2863             @Override
2864             public int applyAsInt(final Object t) throws Throwable {
2865                 throw new IOException("test");
2866             }
2867         }.applyAsInt(new Object()));
2868     }
2869 
2870     /**
2871      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2872      * generic test types.
2873      */
2874     @Test
2875     void testThrows_FailableToIntFunction_String_IOException() {
2876         assertThrows(IOException.class, () -> new FailableToIntFunction<String, IOException>() {
2877 
2878             @Override
2879             public int applyAsInt(final String t) throws IOException {
2880                 throw new IOException("test");
2881             }
2882         }.applyAsInt(StringUtils.EMPTY));
2883     }
2884 
2885     /**
2886      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2887      * Object and Throwable.
2888      */
2889     @Test
2890     void testThrows_FailableToLongBiFunction_Object_Throwable() {
2891         assertThrows(IOException.class, () -> new FailableToLongBiFunction<Object, Object, Throwable>() {
2892 
2893             @Override
2894             public long applyAsLong(final Object t, final Object u) throws Throwable {
2895                 throw new IOException("test");
2896             }
2897         }.applyAsLong(new Object(), new Object()));
2898     }
2899 
2900     /**
2901      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2902      * generic test types.
2903      */
2904     @Test
2905     void testThrows_FailableToLongBiFunction_String_IOException() {
2906         assertThrows(IOException.class, () -> new FailableToLongBiFunction<String, String, IOException>() {
2907 
2908             @Override
2909             public long applyAsLong(final String t, final String u) throws IOException {
2910                 throw new IOException("test");
2911             }
2912         }.applyAsLong(StringUtils.EMPTY, StringUtils.EMPTY));
2913     }
2914 
2915     /**
2916      * Tests that our failable interface is properly defined to throw any exception using the top level generic types
2917      * Object and Throwable.
2918      */
2919     @Test
2920     void testThrows_FailableToLongFunction_Object_Throwable() {
2921         assertThrows(IOException.class, () -> new FailableToLongFunction<Object, Throwable>() {
2922 
2923             @Override
2924             public long applyAsLong(final Object t) throws Throwable {
2925                 throw new IOException("test");
2926             }
2927         }.applyAsLong(new Object()));
2928     }
2929 
2930     /**
2931      * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as
2932      * generic test types.
2933      */
2934     @Test
2935     void testThrows_FailableToLongFunction_String_IOException() {
2936         assertThrows(IOException.class, () -> new FailableToLongFunction<String, IOException>() {
2937 
2938             @Override
2939             public long applyAsLong(final String t) throws IOException {
2940                 throw new IOException("test");
2941             }
2942         }.applyAsLong(StringUtils.EMPTY));
2943     }
2944 
2945     @Test
2946     void testTryWithResources() {
2947         final CloseableObject closeable = new CloseableObject();
2948         final FailableConsumer<Throwable, ? extends Throwable> consumer = closeable::run;
2949         Throwable e = assertThrows(IllegalStateException.class,
2950             () -> Failable.tryWithResources(() -> consumer.accept(ILLEGAL_STATE_EXCEPTION), closeable::close));
2951         assertSame(ILLEGAL_STATE_EXCEPTION, e);
2952 
2953         assertTrue(closeable.isClosed());
2954         closeable.reset();
2955         e = assertThrows(OutOfMemoryError.class,
2956             () -> Failable.tryWithResources(() -> consumer.accept(ERROR), closeable::close));
2957         assertSame(ERROR, e);
2958 
2959         assertTrue(closeable.isClosed());
2960         closeable.reset();
2961         final IOException ioe = new IOException("Unknown I/O error");
2962         final UncheckedIOException uioe = assertThrows(UncheckedIOException.class,
2963             () -> Failable.tryWithResources(() -> consumer.accept(ioe), closeable::close));
2964         final IOException cause = uioe.getCause();
2965         assertSame(ioe, cause);
2966 
2967         assertTrue(closeable.isClosed());
2968         closeable.reset();
2969         Failable.tryWithResources(() -> consumer.accept(null), closeable::close);
2970         assertTrue(closeable.isClosed());
2971     }
2972 
2973     private String throwingFunction(final String input) throws Exception {
2974         return input;
2975     }
2976 
2977 }