diff options
Diffstat (limited to 'src/test/java/org/apache/commons/lang3/FunctionsTest.java')
-rw-r--r-- | src/test/java/org/apache/commons/lang3/FunctionsTest.java | 1097 |
1 files changed, 1097 insertions, 0 deletions
diff --git a/src/test/java/org/apache/commons/lang3/FunctionsTest.java b/src/test/java/org/apache/commons/lang3/FunctionsTest.java new file mode 100644 index 000000000..9f767afda --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/FunctionsTest.java @@ -0,0 +1,1097 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.lang3; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.concurrent.Callable; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.BiPredicate; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; + +import org.apache.commons.lang3.Functions.FailableBiConsumer; +import org.apache.commons.lang3.Functions.FailableBiFunction; +import org.apache.commons.lang3.Functions.FailableCallable; +import org.apache.commons.lang3.Functions.FailableConsumer; +import org.apache.commons.lang3.Functions.FailableFunction; +import org.apache.commons.lang3.Functions.FailableSupplier; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +public class FunctionsTest extends AbstractLangTest { + + public static class CloseableObject { + private boolean closed; + + public void close() { + closed = true; + } + + public boolean isClosed() { + return closed; + } + + public void reset() { + closed = false; + } + + public void run(final Throwable pTh) throws Throwable { + if (pTh != null) { + throw pTh; + } + } + } + + public static class FailureOnOddInvocations { + private static int invocations; + + static boolean failingBool() throws SomeException { + throwOnOdd(); + return true; + } + + static boolean testDouble(final double value) throws SomeException { + throwOnOdd(); + return true; + } + + static boolean testInt(final int value) throws SomeException { + throwOnOdd(); + return true; + } + + static boolean testLong(final long value) throws SomeException { + throwOnOdd(); + return true; + } + + private static void throwOnOdd() throws SomeException { + final int i = ++invocations; + if (i % 2 == 1) { + throw new SomeException("Odd Invocation: " + i); + } + } + + FailureOnOddInvocations() throws SomeException { + throwOnOdd(); + } + + boolean getAsBoolean() throws SomeException { + throwOnOdd(); + return true; + } + } + + public static class SomeException extends Exception { + + private static final long serialVersionUID = -4965704778119283411L; + + private Throwable t; + + SomeException(final String message) { + super(message); + } + + public void setThrowable(final Throwable throwable) { + t = throwable; + } + + public void test() throws Throwable { + if (t != null) { + throw t; + } + } + } + + public static class Testable<T, P> { + private T acceptedObject; + private P acceptedPrimitiveObject1; + private P acceptedPrimitiveObject2; + private Throwable throwable; + + Testable(final Throwable throwable) { + this.throwable = throwable; + } + + public T getAcceptedObject() { + return acceptedObject; + } + + public P getAcceptedPrimitiveObject1() { + return acceptedPrimitiveObject1; + } + + public P getAcceptedPrimitiveObject2() { + return acceptedPrimitiveObject2; + } + + public void setThrowable(final Throwable throwable) { + this.throwable = throwable; + } + + public void test() throws Throwable { + test(throwable); + } + + public Object test(final Object input1, final Object input2) throws Throwable { + test(throwable); + return acceptedObject; + } + + public void test(final Throwable throwable) throws Throwable { + if (throwable != null) { + throw throwable; + } + } + + public boolean testAsBooleanPrimitive() throws Throwable { + return testAsBooleanPrimitive(throwable); + } + + public boolean testAsBooleanPrimitive(final Throwable throwable) throws Throwable { + if (throwable != null) { + throw throwable; + } + return false; + } + + public double testAsDoublePrimitive() throws Throwable { + return testAsDoublePrimitive(throwable); + } + + public double testAsDoublePrimitive(final Throwable throwable) throws Throwable { + if (throwable != null) { + throw throwable; + } + return 0; + } + + public Integer testAsInteger() throws Throwable { + return testAsInteger(throwable); + } + + public Integer testAsInteger(final Throwable throwable) throws Throwable { + if (throwable != null) { + throw throwable; + } + return 0; + } + + public int testAsIntPrimitive() throws Throwable { + return testAsIntPrimitive(throwable); + } + + public int testAsIntPrimitive(final Throwable throwable) throws Throwable { + if (throwable != null) { + throw throwable; + } + return 0; + } + + public long testAsLongPrimitive() throws Throwable { + return testAsLongPrimitive(throwable); + } + + public long testAsLongPrimitive(final Throwable throwable) throws Throwable { + if (throwable != null) { + throw throwable; + } + return 0; + } + + public void testDouble(final double i) throws Throwable { + test(throwable); + acceptedPrimitiveObject1 = (P) ((Double) i); + } + + public double testDoubleDouble(final double i, final double j) throws Throwable { + test(throwable); + acceptedPrimitiveObject1 = (P) ((Double) i); + acceptedPrimitiveObject2 = (P) ((Double) j); + return 3d; + } + + public void testInt(final int i) throws Throwable { + test(throwable); + acceptedPrimitiveObject1 = (P) ((Integer) i); + } + + public void testLong(final long i) throws Throwable { + test(throwable); + acceptedPrimitiveObject1 = (P) ((Long) i); + } + + public void testObjDouble(final T object, final double i) throws Throwable { + test(throwable); + acceptedObject = object; + acceptedPrimitiveObject1 = (P) ((Double) i); + } + + public void testObjInt(final T object, final int i) throws Throwable { + test(throwable); + acceptedObject = object; + acceptedPrimitiveObject1 = (P) ((Integer) i); + } + + public void testObjLong(final T object, final long i) throws Throwable { + test(throwable); + acceptedObject = object; + acceptedPrimitiveObject1 = (P) ((Long) i); + } + } + + @Test + public void testAcceptBiConsumer() { + final IllegalStateException ise = new IllegalStateException(); + final Testable<?, ?> testable = new Testable<>(null); + Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(Testable::test, testable, ise)); + assertSame(ise, e); + + final Error error = new OutOfMemoryError(); + e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(Testable::test, testable, error)); + assertSame(error, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Functions.accept(Testable::test, testable, ioe)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + testable.setThrowable(null); + Functions.accept(Testable::test, testable, (Throwable) null); + } + + @Test + public void testAcceptConsumer() { + final IllegalStateException ise = new IllegalStateException(); + final Testable<?, ?> testable = new Testable<>(ise); + Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(Testable::test, testable)); + assertSame(ise, e); + + final Error error = new OutOfMemoryError(); + testable.setThrowable(error); + e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(Testable::test, testable)); + assertSame(error, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Functions.accept(Testable::test, testable)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + testable.setThrowable(null); + Functions.accept(Testable::test, testable); + } + + @Test + public void testAcceptDoubleConsumer() { + final IllegalStateException ise = new IllegalStateException(); + final Testable<?, Double> testable = new Testable<>(ise); + Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testDouble, 1d)); + assertSame(ise, e); + assertNull(testable.getAcceptedPrimitiveObject1()); + + final Error error = new OutOfMemoryError(); + testable.setThrowable(error); + e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testDouble, 1d)); + assertSame(error, e); + assertNull(testable.getAcceptedPrimitiveObject1()); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Functions.accept(testable::testDouble, 1d)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(null); + Functions.accept(testable::testDouble, 1d); + assertEquals(1, testable.getAcceptedPrimitiveObject1()); + } + + @Test + public void testAcceptIntConsumer() { + final IllegalStateException ise = new IllegalStateException(); + final Testable<?, Integer> testable = new Testable<>(ise); + Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testInt, 1)); + assertSame(ise, e); + assertNull(testable.getAcceptedPrimitiveObject1()); + + final Error error = new OutOfMemoryError(); + testable.setThrowable(error); + e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testInt, 1)); + assertSame(error, e); + assertNull(testable.getAcceptedPrimitiveObject1()); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Functions.accept(testable::testInt, 1)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(null); + Functions.accept(testable::testInt, 1); + assertEquals(1, testable.getAcceptedPrimitiveObject1()); + } + + @Test + public void testAcceptLongConsumer() { + final IllegalStateException ise = new IllegalStateException(); + final Testable<?, Long> testable = new Testable<>(ise); + Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testLong, 1L)); + assertSame(ise, e); + assertNull(testable.getAcceptedPrimitiveObject1()); + + final Error error = new OutOfMemoryError(); + testable.setThrowable(error); + e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testLong, 1L)); + assertSame(error, e); + assertNull(testable.getAcceptedPrimitiveObject1()); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Functions.accept(testable::testLong, 1L)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(null); + Functions.accept(testable::testLong, 1L); + assertEquals(1, testable.getAcceptedPrimitiveObject1()); + } + + @Test + public void testAcceptObjDoubleConsumer() { + final IllegalStateException ise = new IllegalStateException(); + final Testable<String, Double> testable = new Testable<>(ise); + Throwable e = assertThrows(IllegalStateException.class, + () -> Functions.accept(testable::testObjDouble, "X", 1d)); + assertSame(ise, e); + assertNull(testable.getAcceptedObject()); + assertNull(testable.getAcceptedPrimitiveObject1()); + + final Error error = new OutOfMemoryError(); + testable.setThrowable(error); + e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testObjDouble, "X", 1d)); + assertSame(error, e); + assertNull(testable.getAcceptedObject()); + assertNull(testable.getAcceptedPrimitiveObject1()); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Functions.accept(testable::testObjDouble, "X", 1d)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + assertNull(testable.getAcceptedObject()); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(null); + Functions.accept(testable::testObjDouble, "X", 1d); + assertEquals("X", testable.getAcceptedObject()); + assertEquals(1d, testable.getAcceptedPrimitiveObject1()); + } + + @Test + public void testAcceptObjIntConsumer() { + final IllegalStateException ise = new IllegalStateException(); + final Testable<String, Integer> testable = new Testable<>(ise); + Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testObjInt, "X", 1)); + assertSame(ise, e); + assertNull(testable.getAcceptedObject()); + assertNull(testable.getAcceptedPrimitiveObject1()); + + final Error error = new OutOfMemoryError(); + testable.setThrowable(error); + e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testObjInt, "X", 1)); + assertSame(error, e); + assertNull(testable.getAcceptedObject()); + assertNull(testable.getAcceptedPrimitiveObject1()); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Functions.accept(testable::testObjInt, "X", 1)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + assertNull(testable.getAcceptedObject()); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(null); + Functions.accept(testable::testObjInt, "X", 1); + assertEquals("X", testable.getAcceptedObject()); + assertEquals(1, testable.getAcceptedPrimitiveObject1()); + } + + @Test + public void testAcceptObjLongConsumer() { + final IllegalStateException ise = new IllegalStateException(); + final Testable<String, Long> testable = new Testable<>(ise); + Throwable e = assertThrows(IllegalStateException.class, () -> Functions.accept(testable::testObjLong, "X", 1L)); + assertSame(ise, e); + assertNull(testable.getAcceptedObject()); + assertNull(testable.getAcceptedPrimitiveObject1()); + + final Error error = new OutOfMemoryError(); + testable.setThrowable(error); + e = assertThrows(OutOfMemoryError.class, () -> Functions.accept(testable::testObjLong, "X", 1L)); + assertSame(error, e); + assertNull(testable.getAcceptedObject()); + assertNull(testable.getAcceptedPrimitiveObject1()); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Functions.accept(testable::testObjLong, "X", 1L)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + assertNull(testable.getAcceptedObject()); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(null); + Functions.accept(testable::testObjLong, "X", 1L); + assertEquals("X", testable.getAcceptedObject()); + assertEquals(1L, testable.getAcceptedPrimitiveObject1()); + } + + @Test + public void testApplyBiFunction() { + final IllegalStateException ise = new IllegalStateException(); + final Testable<?, ?> testable = new Testable<>(null); + Throwable e = assertThrows(IllegalStateException.class, + () -> Functions.apply(Testable::testAsInteger, testable, ise)); + assertSame(ise, e); + + final Error error = new OutOfMemoryError(); + e = assertThrows(OutOfMemoryError.class, () -> Functions.apply(Testable::testAsInteger, testable, error)); + assertSame(error, e); + + final IOException ioe = new IOException("Unknown I/O error"); + e = assertThrows(UncheckedIOException.class, () -> Functions.apply(Testable::testAsInteger, testable, ioe)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + final Integer i = Functions.apply(Testable::testAsInteger, testable, (Throwable) null); + assertNotNull(i); + assertEquals(0, i.intValue()); + } + + @Test + public void testApplyFunction() { + final IllegalStateException ise = new IllegalStateException(); + final Testable<?, ?> testable = new Testable<>(ise); + Throwable e = assertThrows(IllegalStateException.class, + () -> Functions.apply(Testable::testAsInteger, testable)); + assertSame(ise, e); + + final Error error = new OutOfMemoryError(); + testable.setThrowable(error); + e = assertThrows(OutOfMemoryError.class, () -> Functions.apply(Testable::testAsInteger, testable)); + assertSame(error, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Functions.apply(Testable::testAsInteger, testable)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + testable.setThrowable(null); + final Integer i = Functions.apply(Testable::testAsInteger, testable); + assertNotNull(i); + assertEquals(0, i.intValue()); + } + + @Test + public void testAsCallable() { + FailureOnOddInvocations.invocations = 0; + final FailableCallable<FailureOnOddInvocations, SomeException> failableCallable = FailureOnOddInvocations::new; + final Callable<FailureOnOddInvocations> callable = Functions.asCallable(failableCallable); + final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, callable::call); + final Throwable cause = e.getCause(); + assertNotNull(cause); + assertTrue(cause instanceof SomeException); + assertEquals("Odd Invocation: 1", cause.getMessage()); + final FailureOnOddInvocations instance; + try { + instance = callable.call(); + } catch (final Exception ex) { + throw Functions.rethrow(ex); + } + assertNotNull(instance); + } + + @Test + public void testAsConsumer() { + final IllegalStateException ise = new IllegalStateException(); + final Testable<?, ?> testable = new Testable<>(ise); + final Consumer<Testable<?, ?>> consumer = Functions.asConsumer(Testable::test); + Throwable e = assertThrows(IllegalStateException.class, () -> consumer.accept(testable)); + assertSame(ise, e); + + final Error error = new OutOfMemoryError(); + testable.setThrowable(error); + e = assertThrows(OutOfMemoryError.class, () -> consumer.accept(testable)); + assertSame(error, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> consumer.accept(testable)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + testable.setThrowable(null); + Functions.accept(Testable::test, testable); + } + + @Test + public void testAsRunnable() { + FailureOnOddInvocations.invocations = 0; + final Runnable runnable = Functions.asRunnable(FailureOnOddInvocations::new); + final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, runnable::run); + final Throwable cause = e.getCause(); + assertNotNull(cause); + assertTrue(cause instanceof SomeException); + assertEquals("Odd Invocation: 1", cause.getMessage()); + + // Even invocations, should not throw an exception + runnable.run(); + } + + @Test + public void testAsSupplier() { + FailureOnOddInvocations.invocations = 0; + final FailableSupplier<FailureOnOddInvocations, Throwable> failableSupplier = FailureOnOddInvocations::new; + final Supplier<FailureOnOddInvocations> supplier = Functions.asSupplier(failableSupplier); + final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, supplier::get); + final Throwable cause = e.getCause(); + assertNotNull(cause); + assertTrue(cause instanceof SomeException); + assertEquals("Odd Invocation: 1", cause.getMessage()); + assertNotNull(supplier.get()); + } + + @Test + public void testBiConsumer() { + final IllegalStateException ise = new IllegalStateException(); + final Testable<?, ?> testable = new Testable<>(null); + final FailableBiConsumer<Testable<?, ?>, Throwable, Throwable> failableBiConsumer = (t, th) -> { + t.setThrowable(th); + t.test(); + }; + final BiConsumer<Testable<?, ?>, Throwable> consumer = Functions.asBiConsumer(failableBiConsumer); + Throwable e = assertThrows(IllegalStateException.class, () -> consumer.accept(testable, ise)); + assertSame(ise, e); + + final Error error = new OutOfMemoryError(); + e = assertThrows(OutOfMemoryError.class, () -> consumer.accept(testable, error)); + assertSame(error, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> consumer.accept(testable, ioe)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + consumer.accept(testable, null); + } + + @Test + public void testBiFunction() { + final IllegalStateException ise = new IllegalStateException(); + final Testable<?, ?> testable = new Testable<>(ise); + final FailableBiFunction<Testable<?, ?>, Throwable, Integer, Throwable> failableBiFunction = (t, th) -> { + t.setThrowable(th); + return Integer.valueOf(t.testAsInteger()); + }; + final BiFunction<Testable<?, ?>, Throwable, Integer> biFunction = Functions.asBiFunction(failableBiFunction); + Throwable e = assertThrows(IllegalStateException.class, () -> biFunction.apply(testable, ise)); + assertSame(ise, e); + + final Error error = new OutOfMemoryError(); + testable.setThrowable(error); + e = assertThrows(OutOfMemoryError.class, () -> biFunction.apply(testable, error)); + assertSame(error, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> biFunction.apply(testable, ioe)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + assertEquals(0, biFunction.apply(testable, null).intValue()); + } + + @Test + @DisplayName("Test that asPredicate(FailableBiPredicate) is converted to -> BiPredicate ") + public void testBiPredicate() { + FailureOnOddInvocations.invocations = 0; + final Functions.FailableBiPredicate<Object, Object, Throwable> failableBiPredicate = (t1, + t2) -> FailureOnOddInvocations.failingBool(); + final BiPredicate<?, ?> predicate = Functions.asBiPredicate(failableBiPredicate); + final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, + () -> predicate.test(null, null)); + final Throwable cause = e.getCause(); + assertNotNull(cause); + assertTrue(cause instanceof SomeException); + assertEquals("Odd Invocation: 1", cause.getMessage()); + final boolean instance = predicate.test(null, null); + assertNotNull(instance); + } + + @Test + public void testCallable() { + FailureOnOddInvocations.invocations = 0; + final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, + () -> Functions.run(FailureOnOddInvocations::new)); + final Throwable cause = e.getCause(); + assertNotNull(cause); + assertTrue(cause instanceof SomeException); + assertEquals("Odd Invocation: 1", cause.getMessage()); + final FailureOnOddInvocations instance = Functions.call(FailureOnOddInvocations::new); + assertNotNull(instance); + } + + @Test + public void testConstructor() { + // We allow this, which must have been an omission to make the ctor private. + // We could make the ctor private in 4.0. + new Functions(); + } + + @Test + public void testFunction() { + final IllegalStateException ise = new IllegalStateException(); + final Testable<?, ?> testable = new Testable<>(ise); + final FailableFunction<Throwable, Integer, Throwable> failableFunction = th -> { + testable.setThrowable(th); + return Integer.valueOf(testable.testAsInteger()); + }; + final Function<Throwable, Integer> function = Functions.asFunction(failableFunction); + Throwable e = assertThrows(IllegalStateException.class, () -> function.apply(ise)); + assertSame(ise, e); + + final Error error = new OutOfMemoryError(); + testable.setThrowable(error); + e = assertThrows(OutOfMemoryError.class, () -> function.apply(error)); + assertSame(error, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> function.apply(ioe)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + assertEquals(0, function.apply(null).intValue()); + } + + @Test + public void testGetFromSupplier() { + FailureOnOddInvocations.invocations = 0; + final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, + () -> Functions.run(FailureOnOddInvocations::new)); + final Throwable cause = e.getCause(); + assertNotNull(cause); + assertTrue(cause instanceof SomeException); + assertEquals("Odd Invocation: 1", cause.getMessage()); + final FailureOnOddInvocations instance = Functions.call(FailureOnOddInvocations::new); + assertNotNull(instance); + } + + @Test + public void testGetSupplier() { + final IllegalStateException ise = new IllegalStateException(); + final Testable<?, ?> testable = new Testable<>(ise); + Throwable e = assertThrows(IllegalStateException.class, () -> Functions.get(testable::testAsInteger)); + assertSame(ise, e); + + final Error error = new OutOfMemoryError(); + testable.setThrowable(error); + e = assertThrows(OutOfMemoryError.class, () -> Functions.get(testable::testAsInteger)); + assertSame(error, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Functions.get(testable::testAsInteger)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + testable.setThrowable(null); + final Integer i = Functions.apply(Testable::testAsInteger, testable); + assertNotNull(i); + assertEquals(0, i.intValue()); + } + + @Test + @DisplayName("Test that asPredicate(FailablePredicate) is converted to -> Predicate ") + public void testPredicate() { + FailureOnOddInvocations.invocations = 0; + final Functions.FailablePredicate<Object, Throwable> failablePredicate = t -> FailureOnOddInvocations + .failingBool(); + final Predicate<?> predicate = Functions.asPredicate(failablePredicate); + final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, + () -> predicate.test(null)); + final Throwable cause = e.getCause(); + assertNotNull(cause); + assertTrue(cause instanceof SomeException); + assertEquals("Odd Invocation: 1", cause.getMessage()); + final boolean instance = predicate.test(null); + assertNotNull(instance); + } + + @Test + public void testRunnable() { + FailureOnOddInvocations.invocations = 0; + final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, + () -> Functions.run(FailureOnOddInvocations::new)); + final Throwable cause = e.getCause(); + assertNotNull(cause); + assertTrue(cause instanceof SomeException); + assertEquals("Odd Invocation: 1", cause.getMessage()); + + // Even invocations, should not throw an exception + Functions.run(FailureOnOddInvocations::new); + } + + /** + * Tests that our failable interface is properly defined to throw any exception. using the top level generic types + * Object and Throwable. + */ + @Test + public void testThrows_FailableBiConsumer_Object_Throwable() { + new Functions.FailableBiConsumer<Object, Object, Throwable>() { + + @Override + public void accept(final Object object1, final Object object2) throws Throwable { + throw new IOException("test"); + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as + * generic test types. + */ + @Test + public void testThrows_FailableBiConsumer_String_IOException() { + new Functions.FailableBiConsumer<String, String, IOException>() { + + @Override + public void accept(final String object1, final String object2) throws IOException { + throw new IOException("test"); + + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception. using the top level generic types + * Object and Throwable. + */ + @Test + public void testThrows_FailableBiFunction_Object_Throwable() { + new Functions.FailableBiFunction<Object, Object, Object, Throwable>() { + + @Override + public Object apply(final Object input1, final Object input2) throws Throwable { + throw new IOException("test"); + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as + * generic test types. + */ + @Test + public void testThrows_FailableBiFunction_String_IOException() { + new Functions.FailableBiFunction<String, String, String, IOException>() { + + @Override + public String apply(final String input1, final String input2) throws IOException { + throw new IOException("test"); + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception. using the top level generic types + * Object and Throwable. + */ + @Test + public void testThrows_FailableBiPredicate_Object_Throwable() { + new Functions.FailableBiPredicate<Object, Object, Throwable>() { + + @Override + public boolean test(final Object object1, final Object object2) throws Throwable { + throw new IOException("test"); + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as + * generic test types. + */ + @Test + public void testThrows_FailableBiPredicate_String_IOException() { + new Functions.FailableBiPredicate<String, String, IOException>() { + + @Override + public boolean test(final String object1, final String object2) throws IOException { + throw new IOException("test"); + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception. using the top level generic types + * Object and Throwable. + */ + @Test + public void testThrows_FailableCallable_Object_Throwable() { + new Functions.FailableCallable<Object, Throwable>() { + + @Override + public Object call() throws Throwable { + throw new IOException("test"); + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as + * generic test types. + */ + @Test + public void testThrows_FailableCallable_String_IOException() { + new Functions.FailableCallable<String, IOException>() { + + @Override + public String call() throws IOException { + throw new IOException("test"); + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception. using the top level generic types + * Object and Throwable. + */ + @Test + public void testThrows_FailableConsumer_Object_Throwable() { + new Functions.FailableConsumer<Object, Throwable>() { + + @Override + public void accept(final Object object) throws Throwable { + throw new IOException("test"); + + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as + * generic test types. + */ + @Test + public void testThrows_FailableConsumer_String_IOException() { + new Functions.FailableConsumer<String, IOException>() { + + @Override + public void accept(final String object) throws IOException { + throw new IOException("test"); + + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception. using the top level generic types + * Object and Throwable. + */ + @Test + public void testThrows_FailableFunction_Object_Throwable() { + new Functions.FailableFunction<Object, Object, Throwable>() { + + @Override + public Object apply(final Object input) throws Throwable { + throw new IOException("test"); + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as + * generic test types. + */ + @Test + public void testThrows_FailableFunction_String_IOException() { + new Functions.FailableFunction<String, String, IOException>() { + + @Override + public String apply(final String input) throws IOException { + throw new IOException("test"); + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception. using the top level generic types + * Object and Throwable. + */ + @Test + public void testThrows_FailablePredicate_Object_Throwable() { + new Functions.FailablePredicate<Object, Throwable>() { + + @Override + public boolean test(final Object object) throws Throwable { + throw new IOException("test"); + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as + * generic test types. + */ + @Test + public void testThrows_FailablePredicate_String_IOException() { + new Functions.FailablePredicate<String, IOException>() { + + @Override + public boolean test(final String object) throws IOException { + throw new IOException("test"); + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception. using the top level generic types + * Object and Throwable. + */ + @Test + public void testThrows_FailableRunnable_Object_Throwable() { + new Functions.FailableRunnable<Throwable>() { + + @Override + public void run() throws Throwable { + throw new IOException("test"); + + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as + * generic test types. + */ + @Test + public void testThrows_FailableRunnable_String_IOException() { + new Functions.FailableRunnable<IOException>() { + + @Override + public void run() throws IOException { + throw new IOException("test"); + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception. using the top level generic types + * Object and Throwable. + */ + @Test + public void testThrows_FailableSupplier_Object_Throwable() { + new Functions.FailableSupplier<Object, Throwable>() { + + @Override + public Object get() throws Throwable { + throw new IOException("test"); + } + }; + } + + /** + * Tests that our failable interface is properly defined to throw any exception using String and IOExceptions as + * generic test types. + */ + @Test + public void testThrows_FailableSupplier_String_IOException() { + new Functions.FailableSupplier<String, IOException>() { + + @Override + public String get() throws IOException { + throw new IOException("test"); + } + }; + } + + @Test + public void testTryWithResources() { + final CloseableObject co = new CloseableObject(); + final FailableConsumer<Throwable, ? extends Throwable> consumer = co::run; + final IllegalStateException ise = new IllegalStateException(); + Throwable e = assertThrows(IllegalStateException.class, + () -> Functions.tryWithResources(() -> consumer.accept(ise), co::close)); + assertSame(ise, e); + + assertTrue(co.isClosed()); + co.reset(); + final Error error = new OutOfMemoryError(); + e = assertThrows(OutOfMemoryError.class, + () -> Functions.tryWithResources(() -> consumer.accept(error), co::close)); + assertSame(error, e); + + assertTrue(co.isClosed()); + co.reset(); + final IOException ioe = new IOException("Unknown I/O error"); + final UncheckedIOException uioe = assertThrows(UncheckedIOException.class, + () -> Functions.tryWithResources(() -> consumer.accept(ioe), co::close)); + final IOException cause = uioe.getCause(); + assertSame(ioe, cause); + + assertTrue(co.isClosed()); + co.reset(); + Functions.tryWithResources(() -> consumer.accept(null), co::close); + assertTrue(co.isClosed()); + } +} |