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