diff options
Diffstat (limited to 'src/test/java/org/apache/commons/lang3/function')
20 files changed, 4144 insertions, 0 deletions
diff --git a/src/test/java/org/apache/commons/lang3/function/AnnotationTestFixture.java b/src/test/java/org/apache/commons/lang3/function/AnnotationTestFixture.java new file mode 100644 index 000000000..a179a1f84 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/AnnotationTestFixture.java @@ -0,0 +1,29 @@ +/* + * 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.function; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@interface AnnotationTestFixture { + // empty +} diff --git a/src/test/java/org/apache/commons/lang3/function/BooleanConsumerTest.java b/src/test/java/org/apache/commons/lang3/function/BooleanConsumerTest.java new file mode 100644 index 000000000..2a2101fac --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/BooleanConsumerTest.java @@ -0,0 +1,80 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.commons.lang3.AbstractLangTest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link BooleanConsumer}. + */ +public class BooleanConsumerTest extends AbstractLangTest { + + private BooleanConsumer accept(final BooleanConsumer consumer, final boolean expected) { + consumer.accept(expected); + return consumer; + } + + @Test + public void testAccept() { + final AtomicBoolean aBool = new AtomicBoolean(); + accept(aBool::lazySet, true); + assertTrue(aBool.get()); + accept(aBool::lazySet, false); + assertFalse(aBool.get()); + } + + @Test + public void testAndThen() throws Throwable { + final BooleanConsumer nop = BooleanConsumer.nop(); + nop.andThen(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> nop.andThen(null)); + + final AtomicBoolean aBool1 = new AtomicBoolean(); + final AtomicBoolean aBool2 = new AtomicBoolean(); + + final BooleanConsumer bc = aBool1::lazySet; + final BooleanConsumer composite = bc.andThen(aBool2::lazySet); + + composite.accept(true); + assertTrue(aBool1.get()); + assertTrue(aBool2.get()); + + composite.accept(false); + assertFalse(aBool1.get()); + assertFalse(aBool2.get()); + + // Check order + final BooleanConsumer bad = value -> { + throw new IllegalStateException(); + }; + final BooleanConsumer badComposite = bad.andThen(aBool2::lazySet); + + Assertions.assertThrows(IllegalStateException.class, () -> badComposite.accept(true)); + assertFalse(aBool2.get(), "Second consumer should not be invoked"); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/function/ConsumersTest.java b/src/test/java/org/apache/commons/lang3/function/ConsumersTest.java new file mode 100644 index 000000000..35c7dda7b --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/ConsumersTest.java @@ -0,0 +1,49 @@ +/* + * 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.function; + +import java.util.function.Consumer; +import java.util.stream.Stream; + +import org.apache.commons.lang3.AbstractLangTest; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link Consumers}. + */ +public class ConsumersTest extends AbstractLangTest { + + /** + * Tests {@link Consumers#nop()}. + */ + @Test + public void testNop() { + Stream.of("").forEach(Consumers.nop()); + // + final Consumer<?> c1 = Consumers.nop(); + c1.accept(null); + final Consumer<Object> c2 = Consumers.nop(); + c2.accept(null); + final Consumer<String> c3 = Consumers.nop(); + c3.accept(null); + // + Consumers.nop().accept(null); + Consumers.nop().accept(""); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/function/FailableFunctionsTest.java b/src/test/java/org/apache/commons/lang3/function/FailableFunctionsTest.java new file mode 100644 index 000000000..37cd3a161 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/FailableFunctionsTest.java @@ -0,0 +1,2671 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +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.AbstractLangTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +/** + * Tests "failable" interfaces defined in this package. + */ +public class FailableFunctionsTest 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 short testAsShortPrimitive() throws Throwable { + return testAsShortPrimitive(throwable); + } + + public short testAsShortPrimitive(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; + } + } + + private static final OutOfMemoryError ERROR = new OutOfMemoryError(); + + private static final IllegalStateException ILLEGAL_STATE_EXCEPTION = new IllegalStateException(); + + @Test + public void testAcceptBiConsumer() { + final Testable<?, ?> testable = new Testable<>(null); + Throwable e = assertThrows(IllegalStateException.class, + () -> Failable.accept(Testable::test, testable, ILLEGAL_STATE_EXCEPTION)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + e = assertThrows(OutOfMemoryError.class, () -> Failable.accept(Testable::test, testable, ERROR)); + assertSame(ERROR, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Failable.accept(Testable::test, testable, ioe)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + testable.setThrowable(null); + Failable.accept(Testable::test, testable, (Throwable) null); + } + + @Test + public void testAcceptConsumer() { + final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + Throwable e = assertThrows(IllegalStateException.class, () -> Failable.accept(Testable::test, testable)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + testable.setThrowable(ERROR); + e = assertThrows(OutOfMemoryError.class, () -> Failable.accept(Testable::test, testable)); + assertSame(ERROR, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Failable.accept(Testable::test, testable)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + testable.setThrowable(null); + Failable.accept(Testable::test, testable); + } + + @Test + public void testAcceptDoubleConsumer() { + final Testable<?, Double> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + Throwable e = assertThrows(IllegalStateException.class, () -> Failable.accept(testable::testDouble, 1d)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(ERROR); + e = assertThrows(OutOfMemoryError.class, () -> Failable.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, () -> Failable.accept(testable::testDouble, 1d)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(null); + Failable.accept(testable::testDouble, 1d); + assertEquals(1, testable.getAcceptedPrimitiveObject1()); + } + + @Test + public void testAcceptIntConsumer() { + final Testable<?, Integer> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + Throwable e = assertThrows(IllegalStateException.class, () -> Failable.accept(testable::testInt, 1)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(ERROR); + e = assertThrows(OutOfMemoryError.class, () -> Failable.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, () -> Failable.accept(testable::testInt, 1)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(null); + Failable.accept(testable::testInt, 1); + assertEquals(1, testable.getAcceptedPrimitiveObject1()); + } + + @Test + public void testAcceptLongConsumer() { + final Testable<?, Long> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + Throwable e = assertThrows(IllegalStateException.class, () -> Failable.accept(testable::testLong, 1L)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(ERROR); + e = assertThrows(OutOfMemoryError.class, () -> Failable.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, () -> Failable.accept(testable::testLong, 1L)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(null); + Failable.accept(testable::testLong, 1L); + assertEquals(1, testable.getAcceptedPrimitiveObject1()); + } + + @Test + public void testAcceptObjDoubleConsumer() { + final Testable<String, Double> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + Throwable e = assertThrows(IllegalStateException.class, + () -> Failable.accept(testable::testObjDouble, "X", 1d)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + assertNull(testable.getAcceptedObject()); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(ERROR); + e = assertThrows(OutOfMemoryError.class, () -> Failable.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, () -> Failable.accept(testable::testObjDouble, "X", 1d)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + assertNull(testable.getAcceptedObject()); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(null); + Failable.accept(testable::testObjDouble, "X", 1d); + assertEquals("X", testable.getAcceptedObject()); + assertEquals(1d, testable.getAcceptedPrimitiveObject1()); + } + + @Test + public void testAcceptObjIntConsumer() { + final Testable<String, Integer> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + Throwable e = assertThrows(IllegalStateException.class, () -> Failable.accept(testable::testObjInt, "X", 1)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + assertNull(testable.getAcceptedObject()); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(ERROR); + e = assertThrows(OutOfMemoryError.class, () -> Failable.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, () -> Failable.accept(testable::testObjInt, "X", 1)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + assertNull(testable.getAcceptedObject()); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(null); + Failable.accept(testable::testObjInt, "X", 1); + assertEquals("X", testable.getAcceptedObject()); + assertEquals(1, testable.getAcceptedPrimitiveObject1()); + } + + @Test + public void testAcceptObjLongConsumer() { + final Testable<String, Long> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + Throwable e = assertThrows(IllegalStateException.class, () -> Failable.accept(testable::testObjLong, "X", 1L)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + assertNull(testable.getAcceptedObject()); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(ERROR); + e = assertThrows(OutOfMemoryError.class, () -> Failable.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, () -> Failable.accept(testable::testObjLong, "X", 1L)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + assertNull(testable.getAcceptedObject()); + assertNull(testable.getAcceptedPrimitiveObject1()); + + testable.setThrowable(null); + Failable.accept(testable::testObjLong, "X", 1L); + assertEquals("X", testable.getAcceptedObject()); + assertEquals(1L, testable.getAcceptedPrimitiveObject1()); + } + + @Test + public void testApplyBiFunction() { + final Testable<?, ?> testable = new Testable<>(null); + Throwable e = assertThrows(IllegalStateException.class, + () -> Failable.apply(Testable::testAsInteger, testable, ILLEGAL_STATE_EXCEPTION)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + e = assertThrows(OutOfMemoryError.class, () -> Failable.apply(Testable::testAsInteger, testable, ERROR)); + assertSame(ERROR, e); + + final IOException ioe = new IOException("Unknown I/O error"); + e = assertThrows(UncheckedIOException.class, () -> Failable.apply(Testable::testAsInteger, testable, ioe)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + final Integer i = Failable.apply(Testable::testAsInteger, testable, (Throwable) null); + assertNotNull(i); + assertEquals(0, i.intValue()); + } + + @Test + public void testApplyDoubleBinaryOperator() { + final Testable<?, Double> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + final Throwable e = assertThrows(IllegalStateException.class, + () -> Failable.applyAsDouble(testable::testDoubleDouble, 1d, 2d)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + final Testable<?, Double> testable2 = new Testable<>(null); + final double i = Failable.applyAsDouble(testable2::testDoubleDouble, 1d, 2d); + assertEquals(3d, i); + } + + @Test + public void testApplyFunction() { + final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + Throwable e = assertThrows(IllegalStateException.class, + () -> Failable.apply(Testable::testAsInteger, testable)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + testable.setThrowable(ERROR); + e = assertThrows(OutOfMemoryError.class, () -> Failable.apply(Testable::testAsInteger, testable)); + assertSame(ERROR, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Failable.apply(Testable::testAsInteger, testable)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + testable.setThrowable(null); + final Integer i = Failable.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 = Failable.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 Failable.rethrow(ex); + } + assertNotNull(instance); + } + + @Test + public void testAsConsumer() { + final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + final Consumer<Testable<?, ?>> consumer = Failable.asConsumer(Testable::test); + Throwable e = assertThrows(IllegalStateException.class, () -> consumer.accept(testable)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + 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); + Failable.accept(Testable::test, testable); + } + + @Test + public void testAsRunnable() { + FailureOnOddInvocations.invocations = 0; + final Runnable runnable = Failable.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 = Failable.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() throws Throwable { + final Testable<?, ?> testable = new Testable<>(null); + final FailableBiConsumer<Testable<?, ?>, Throwable, Throwable> failableBiConsumer = (t, th) -> { + t.setThrowable(th); + t.test(); + }; + final BiConsumer<Testable<?, ?>, Throwable> consumer = Failable.asBiConsumer(failableBiConsumer); + Throwable e = assertThrows(IllegalStateException.class, + () -> consumer.accept(testable, ILLEGAL_STATE_EXCEPTION)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + e = assertThrows(OutOfMemoryError.class, () -> consumer.accept(testable, ERROR)); + assertSame(ERROR, e); + + e = assertThrows(OutOfMemoryError.class, () -> failableBiConsumer.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 testBiConsumerAndThen() throws Throwable { + final Testable<?, ?> testable = new Testable<>(null); + final FailableBiConsumer<Testable<?, ?>, Throwable, Throwable> failing = (t, th) -> { + t.setThrowable(th); + t.test(); + }; + final FailableBiConsumer<Testable<?, ?>, Throwable, Throwable> nop = FailableBiConsumer.nop(); + Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).accept(testable, ERROR)); + assertSame(ERROR, e); + e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).accept(testable, ERROR)); + assertSame(ERROR, e); + // Does not throw + nop.andThen(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> failing.andThen(null)); + } + + @Test + public void testBiFunction() { + final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + final FailableBiFunction<Testable<?, ?>, Throwable, Integer, Throwable> failableBiFunction = (t, th) -> { + t.setThrowable(th); + return t.testAsInteger(); + }; + final BiFunction<Testable<?, ?>, Throwable, Integer> biFunction = Failable.asBiFunction(failableBiFunction); + Throwable e = assertThrows(IllegalStateException.class, + () -> biFunction.apply(testable, ILLEGAL_STATE_EXCEPTION)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + 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 + public void testBiFunctionAndThen() throws IOException { + // Unchecked usage pattern in JRE + final BiFunction<Object, Integer, Integer> nopBiFunction = (t, u) -> null; + final Function<Object, Integer> nopFunction = t -> null; + nopBiFunction.andThen(nopFunction); + // Checked usage pattern + final FailableBiFunction<Object, Integer, Integer, IOException> failingBiFunctionTest = (t, u) -> { + throw new IOException(); + }; + final FailableFunction<Object, Integer, IOException> failingFunction = t -> { + throw new IOException(); + }; + final FailableBiFunction<Object, Integer, Integer, IOException> nopFailableBiFunction = FailableBiFunction + .nop(); + final FailableFunction<Object, Integer, IOException> nopFailableFunction = FailableFunction.nop(); + // + assertThrows(IOException.class, () -> failingBiFunctionTest.andThen(failingFunction).apply(null, null)); + assertThrows(IOException.class, () -> failingBiFunctionTest.andThen(nopFailableFunction).apply(null, null)); + // + assertThrows(IOException.class, () -> nopFailableBiFunction.andThen(failingFunction).apply(null, null)); + nopFailableBiFunction.andThen(nopFailableFunction).apply(null, null); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> failingBiFunctionTest.andThen(null)); + } + + @Test + @DisplayName("Test that asPredicate(FailableBiPredicate) is converted to -> BiPredicate ") + public void testBiPredicate() { + FailureOnOddInvocations.invocations = 0; + final FailableBiPredicate<Object, Object, Throwable> failableBiPredicate = (t1, t2) -> FailureOnOddInvocations + .failingBool(); + final BiPredicate<?, ?> predicate = Failable.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()); + assertTrue(predicate.test(null, null)); + } + + @Test + public void testBiPredicateAnd() throws Throwable { + assertTrue(FailableBiPredicate.TRUE.and(FailableBiPredicate.TRUE).test(null, null)); + assertFalse(FailableBiPredicate.TRUE.and(FailableBiPredicate.FALSE).test(null, null)); + assertFalse(FailableBiPredicate.FALSE.and(FailableBiPredicate.TRUE).test(null, null)); + assertFalse(FailableBiPredicate.FALSE.and(FailableBiPredicate.FALSE).test(null, null)); + // null tests + assertThrows(NullPointerException.class, + () -> assertFalse(FailableBiPredicate.falsePredicate().and(null).test(null, null))); + assertThrows(NullPointerException.class, + () -> assertTrue(FailableBiPredicate.truePredicate().and(null).test(null, null))); + } + + @Test + public void testBiPredicateNegate() throws Throwable { + assertFalse(FailableBiPredicate.TRUE.negate().test(null, null)); + assertFalse(FailableBiPredicate.truePredicate().negate().test(null, null)); + assertTrue(FailableBiPredicate.FALSE.negate().test(null, null)); + assertTrue(FailableBiPredicate.falsePredicate().negate().test(null, null)); + } + + @Test + public void testBiPredicateOr() throws Throwable { + assertTrue(FailableBiPredicate.TRUE.or(FailableBiPredicate.TRUE).test(null, null)); + assertTrue(FailableBiPredicate.TRUE.or(FailableBiPredicate.FALSE).test(null, null)); + assertTrue(FailableBiPredicate.FALSE.or(FailableBiPredicate.TRUE).test(null, null)); + assertFalse(FailableBiPredicate.FALSE.or(FailableBiPredicate.FALSE).test(null, null)); + // null tests + assertThrows(NullPointerException.class, + () -> assertFalse(FailableBiPredicate.falsePredicate().or(null).test(null, null))); + assertThrows(NullPointerException.class, + () -> assertTrue(FailableBiPredicate.truePredicate().or(null).test(null, null))); + } + + @Test + public void testCallable() { + FailureOnOddInvocations.invocations = 0; + final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, + () -> Failable.run(FailureOnOddInvocations::new)); + final Throwable cause = e.getCause(); + assertNotNull(cause); + assertTrue(cause instanceof SomeException); + assertEquals("Odd Invocation: 1", cause.getMessage()); + final FailureOnOddInvocations instance = Failable.call(FailureOnOddInvocations::new); + assertNotNull(instance); + } + + @Test + public void testConsumerAndThen() throws Throwable { + final Testable<?, ?> testable = new Testable<>(null); + final FailableConsumer<Throwable, Throwable> failableConsumer = th -> { + testable.setThrowable(th); + testable.test(); + }; + final FailableConsumer<Throwable, Throwable> nop = FailableConsumer.nop(); + final Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failableConsumer).accept(ERROR)); + assertSame(ERROR, e); + // Does not throw + nop.andThen(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> failableConsumer.andThen(null)); + } + + @Test + public void testDoubleConsumerAndThen() throws Throwable { + final Testable<?, ?> testable = new Testable<>(null); + final FailableDoubleConsumer<Throwable> failing = t -> { + testable.setThrowable(ERROR); + testable.test(); + }; + final FailableDoubleConsumer<Throwable> nop = FailableDoubleConsumer.nop(); + Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).accept(0d)); + assertSame(ERROR, e); + e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).accept(0d)); + assertSame(ERROR, e); + // Does not throw + nop.andThen(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> failing.andThen(null)); + } + + @Test + public void testDoublePredicate() throws Throwable { + FailureOnOddInvocations.invocations = 0; + final FailableDoublePredicate<Throwable> failablePredicate = FailureOnOddInvocations::testDouble; + assertThrows(SomeException.class, () -> failablePredicate.test(1d)); + failablePredicate.test(1d); + } + + @Test + public void testDoublePredicateAnd() throws Throwable { + assertTrue(FailableDoublePredicate.TRUE.and(FailableDoublePredicate.TRUE).test(0)); + assertFalse(FailableDoublePredicate.TRUE.and(FailableDoublePredicate.FALSE).test(0)); + assertFalse(FailableDoublePredicate.FALSE.and(FailableDoublePredicate.TRUE).test(0)); + assertFalse(FailableDoublePredicate.FALSE.and(FailableDoublePredicate.FALSE).test(0)); + // null tests + assertThrows(NullPointerException.class, + () -> assertFalse(FailableDoublePredicate.falsePredicate().and(null).test(0))); + assertThrows(NullPointerException.class, + () -> assertTrue(FailableDoublePredicate.truePredicate().and(null).test(0))); + } + + @Test + public void testDoublePredicateNegate() throws Throwable { + assertFalse(FailableDoublePredicate.TRUE.negate().test(0d)); + assertFalse(FailableDoublePredicate.truePredicate().negate().test(0d)); + assertTrue(FailableDoublePredicate.FALSE.negate().test(0d)); + assertTrue(FailableDoublePredicate.falsePredicate().negate().test(0d)); + } + + @Test + public void testDoublePredicateOr() throws Throwable { + assertTrue(FailableDoublePredicate.TRUE.or(FailableDoublePredicate.TRUE).test(0)); + assertTrue(FailableDoublePredicate.TRUE.or(FailableDoublePredicate.FALSE).test(0)); + assertTrue(FailableDoublePredicate.FALSE.or(FailableDoublePredicate.TRUE).test(0)); + assertFalse(FailableDoublePredicate.FALSE.or(FailableDoublePredicate.FALSE).test(0)); + // null tests + assertThrows(NullPointerException.class, + () -> assertFalse(FailableDoublePredicate.falsePredicate().or(null).test(0))); + assertThrows(NullPointerException.class, + () -> assertTrue(FailableDoublePredicate.truePredicate().or(null).test(0))); + } + + @Test + public void testDoubleUnaryOperatorAndThen() throws Throwable { + final Testable<?, ?> testable = new Testable<>(null); + final FailableDoubleUnaryOperator<Throwable> failing = t -> { + testable.setThrowable(ERROR); + testable.test(); + return 0d; + }; + final FailableDoubleUnaryOperator<Throwable> nop = FailableDoubleUnaryOperator.nop(); + Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).applyAsDouble(0d)); + assertSame(ERROR, e); + e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).applyAsDouble(0d)); + assertSame(ERROR, e); + // Does not throw + nop.andThen(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> failing.andThen(null)); + } + + @Test + public void testDoubleUnaryOperatorCompose() throws Throwable { + final Testable<?, ?> testable = new Testable<>(null); + final FailableDoubleUnaryOperator<Throwable> failing = t -> { + testable.setThrowable(ERROR); + testable.test(); + return 0d; + }; + final FailableDoubleUnaryOperator<Throwable> nop = FailableDoubleUnaryOperator.nop(); + Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.compose(failing).applyAsDouble(0d)); + assertSame(ERROR, e); + e = assertThrows(OutOfMemoryError.class, () -> failing.compose(nop).applyAsDouble(0d)); + assertSame(ERROR, e); + // Does not throw + nop.compose(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> failing.compose(null)); + } + + @Test + public void testDoubleUnaryOperatorIdentity() throws Throwable { + final FailableDoubleUnaryOperator<Throwable> nop = FailableDoubleUnaryOperator.identity(); + // Does not throw + nop.compose(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> nop.compose(null)); + } + + @Test + public void testFunction() { + final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + final FailableFunction<Throwable, Integer, Throwable> failableFunction = th -> { + testable.setThrowable(th); + return testable.testAsInteger(); + }; + final Function<Throwable, Integer> function = Failable.asFunction(failableFunction); + Throwable e = assertThrows(IllegalStateException.class, () -> function.apply(ILLEGAL_STATE_EXCEPTION)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + 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 testFunctionAndThen() throws IOException { + // Unchecked usage pattern in JRE + final Function<Object, Integer> nopFunction = t -> null; + nopFunction.andThen(nopFunction); + // Checked usage pattern + final FailableFunction<Object, Integer, IOException> failingFunction = t -> { + throw new IOException(); + }; + final FailableFunction<Object, Integer, IOException> nopFailableFunction = FailableFunction.nop(); + // + assertThrows(IOException.class, () -> failingFunction.andThen(failingFunction).apply(null)); + assertThrows(IOException.class, () -> failingFunction.andThen(nopFailableFunction).apply(null)); + // + assertThrows(IOException.class, () -> nopFailableFunction.andThen(failingFunction).apply(null)); + nopFailableFunction.andThen(nopFailableFunction).apply(null); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> failingFunction.andThen(null)); + } + + @Test + public void testFunctionCompose() throws Throwable { + final Testable<?, ?> testable = new Testable<>(null); + final FailableFunction<Object, Integer, Throwable> failing = t -> { + testable.setThrowable(ERROR); + testable.test(); + return 0; + }; + final FailableFunction<Object, Integer, Throwable> nop = FailableFunction.nop(); + Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.compose(failing).apply(0)); + assertSame(ERROR, e); + e = assertThrows(OutOfMemoryError.class, () -> failing.compose(nop).apply(0)); + assertSame(ERROR, e); + // Does not throw + nop.compose(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> failing.compose(null)); + } + + @Test + public void testFunctionIdentity() throws Throwable { + final FailableFunction<Integer, Integer, Throwable> nop = FailableFunction.identity(); + // Does not throw + nop.compose(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> nop.compose(null)); + } + + @Test + public void testGetAsBooleanSupplier() { + final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + Throwable e = assertThrows(IllegalStateException.class, + () -> Failable.getAsBoolean(testable::testAsBooleanPrimitive)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + testable.setThrowable(ERROR); + e = assertThrows(OutOfMemoryError.class, () -> Failable.getAsBoolean(testable::testAsBooleanPrimitive)); + assertSame(ERROR, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Failable.getAsBoolean(testable::testAsBooleanPrimitive)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + testable.setThrowable(null); + assertFalse(Failable.getAsBoolean(testable::testAsBooleanPrimitive)); + } + + @Test + public void testGetAsDoubleSupplier() { + final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + Throwable e = assertThrows(IllegalStateException.class, + () -> Failable.getAsDouble(testable::testAsDoublePrimitive)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + testable.setThrowable(ERROR); + e = assertThrows(OutOfMemoryError.class, () -> Failable.getAsDouble(testable::testAsDoublePrimitive)); + assertSame(ERROR, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Failable.getAsDouble(testable::testAsDoublePrimitive)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + testable.setThrowable(null); + assertEquals(0, Failable.getAsDouble(testable::testAsDoublePrimitive)); + } + + @Test + public void testGetAsIntSupplier() { + final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + Throwable e = assertThrows(IllegalStateException.class, () -> Failable.getAsInt(testable::testAsIntPrimitive)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + testable.setThrowable(ERROR); + e = assertThrows(OutOfMemoryError.class, () -> Failable.getAsInt(testable::testAsIntPrimitive)); + assertSame(ERROR, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Failable.getAsInt(testable::testAsIntPrimitive)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + testable.setThrowable(null); + final int i = Failable.getAsInt(testable::testAsInteger); + assertEquals(0, i); + } + + @Test + public void testGetAsLongSupplier() { + final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + Throwable e = assertThrows(IllegalStateException.class, + () -> Failable.getAsLong(testable::testAsLongPrimitive)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + testable.setThrowable(ERROR); + e = assertThrows(OutOfMemoryError.class, () -> Failable.getAsLong(testable::testAsLongPrimitive)); + assertSame(ERROR, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Failable.getAsLong(testable::testAsLongPrimitive)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + testable.setThrowable(null); + final long i = Failable.getAsLong(testable::testAsLongPrimitive); + assertEquals(0, i); + } + + @Test + public void testGetAsShortSupplier() { + final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + Throwable e = assertThrows(IllegalStateException.class, + () -> Failable.getAsShort(testable::testAsShortPrimitive)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + testable.setThrowable(ERROR); + e = assertThrows(OutOfMemoryError.class, () -> Failable.getAsShort(testable::testAsShortPrimitive)); + assertSame(ERROR, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Failable.getAsShort(testable::testAsShortPrimitive)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + testable.setThrowable(null); + final short i = Failable.getAsShort(testable::testAsShortPrimitive); + assertEquals(0, i); + } + + @Test + public void testGetFromSupplier() { + FailureOnOddInvocations.invocations = 0; + final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, + () -> Failable.run(FailureOnOddInvocations::new)); + final Throwable cause = e.getCause(); + assertNotNull(cause); + assertTrue(cause instanceof SomeException); + assertEquals("Odd Invocation: 1", cause.getMessage()); + final FailureOnOddInvocations instance = Failable.call(FailureOnOddInvocations::new); + assertNotNull(instance); + } + + @Test + public void testGetSupplier() { + final Testable<?, ?> testable = new Testable<>(ILLEGAL_STATE_EXCEPTION); + Throwable e = assertThrows(IllegalStateException.class, () -> Failable.get(testable::testAsInteger)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + testable.setThrowable(ERROR); + e = assertThrows(OutOfMemoryError.class, () -> Failable.get(testable::testAsInteger)); + assertSame(ERROR, e); + + final IOException ioe = new IOException("Unknown I/O error"); + testable.setThrowable(ioe); + e = assertThrows(UncheckedIOException.class, () -> Failable.get(testable::testAsInteger)); + final Throwable t = e.getCause(); + assertNotNull(t); + assertSame(ioe, t); + + testable.setThrowable(null); + final Integer i = Failable.apply(Testable::testAsInteger, testable); + assertNotNull(i); + assertEquals(0, i.intValue()); + } + + @Test + public void testIntConsumerAndThen() throws Throwable { + final Testable<?, ?> testable = new Testable<>(null); + final FailableIntConsumer<Throwable> failing = t -> { + testable.setThrowable(ERROR); + testable.test(); + }; + final FailableIntConsumer<Throwable> nop = FailableIntConsumer.nop(); + Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).accept(0)); + assertSame(ERROR, e); + e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).accept(0)); + assertSame(ERROR, e); + // Does not throw + nop.andThen(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> failing.andThen(null)); + } + + @Test + public void testIntPredicate() throws Throwable { + FailureOnOddInvocations.invocations = 0; + final FailableIntPredicate<Throwable> failablePredicate = FailureOnOddInvocations::testInt; + assertThrows(SomeException.class, () -> failablePredicate.test(1)); + failablePredicate.test(1); + } + + @Test + public void testIntPredicateAnd() throws Throwable { + assertTrue(FailableIntPredicate.TRUE.and(FailableIntPredicate.TRUE).test(0)); + assertFalse(FailableIntPredicate.TRUE.and(FailableIntPredicate.FALSE).test(0)); + assertFalse(FailableIntPredicate.FALSE.and(FailableIntPredicate.TRUE).test(0)); + assertFalse(FailableIntPredicate.FALSE.and(FailableIntPredicate.FALSE).test(0)); + // null tests + assertThrows(NullPointerException.class, + () -> assertFalse(FailableIntPredicate.falsePredicate().and(null).test(0))); + assertThrows(NullPointerException.class, + () -> assertTrue(FailableIntPredicate.truePredicate().and(null).test(0))); + } + + @Test + public void testIntPredicateNegate() throws Throwable { + assertFalse(FailableIntPredicate.TRUE.negate().test(0)); + assertFalse(FailableIntPredicate.truePredicate().negate().test(0)); + assertTrue(FailableIntPredicate.FALSE.negate().test(0)); + assertTrue(FailableIntPredicate.falsePredicate().negate().test(0)); + } + + @Test + public void testIntPredicateOr() throws Throwable { + assertTrue(FailableIntPredicate.TRUE.or(FailableIntPredicate.TRUE).test(0)); + assertTrue(FailableIntPredicate.TRUE.or(FailableIntPredicate.FALSE).test(0)); + assertTrue(FailableIntPredicate.FALSE.or(FailableIntPredicate.TRUE).test(0)); + assertFalse(FailableIntPredicate.FALSE.or(FailableIntPredicate.FALSE).test(0)); + // null tests + assertThrows(NullPointerException.class, + () -> assertFalse(FailableIntPredicate.falsePredicate().or(null).test(0))); + assertThrows(NullPointerException.class, + () -> assertTrue(FailableIntPredicate.truePredicate().or(null).test(0))); + } + + @Test + public void testIntUnaryOperatorAndThen() throws Throwable { + final Testable<?, ?> testable = new Testable<>(null); + final FailableIntUnaryOperator<Throwable> failing = t -> { + testable.setThrowable(ERROR); + testable.test(); + return 0; + }; + final FailableIntUnaryOperator<Throwable> nop = FailableIntUnaryOperator.nop(); + Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).applyAsInt(0)); + assertSame(ERROR, e); + e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).applyAsInt(0)); + assertSame(ERROR, e); + // Does not throw + nop.andThen(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> failing.andThen(null)); + } + + @Test + public void testIntUnaryOperatorCompose() throws Throwable { + final Testable<?, ?> testable = new Testable<>(null); + final FailableIntUnaryOperator<Throwable> failing = t -> { + testable.setThrowable(ERROR); + testable.test(); + return 0; + }; + final FailableIntUnaryOperator<Throwable> nop = FailableIntUnaryOperator.nop(); + Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.compose(failing).applyAsInt(0)); + assertSame(ERROR, e); + e = assertThrows(OutOfMemoryError.class, () -> failing.compose(nop).applyAsInt(0)); + assertSame(ERROR, e); + // Does not throw + nop.compose(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> failing.compose(null)); + } + + @Test + public void testIntUnaryOperatorIdentity() throws Throwable { + final FailableIntUnaryOperator<Throwable> nop = FailableIntUnaryOperator.identity(); + // Does not throw + nop.compose(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> nop.compose(null)); + } + + @Test + public void testLongConsumerAndThen() throws Throwable { + final Testable<?, ?> testable = new Testable<>(null); + final FailableLongConsumer<Throwable> failing = t -> { + testable.setThrowable(ERROR); + testable.test(); + }; + final FailableLongConsumer<Throwable> nop = FailableLongConsumer.nop(); + Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).accept(0L)); + assertSame(ERROR, e); + e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).accept(0L)); + assertSame(ERROR, e); + // Does not throw + nop.andThen(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> failing.andThen(null)); + } + + @Test + public void testLongPredicate() throws Throwable { + FailureOnOddInvocations.invocations = 0; + final FailableLongPredicate<Throwable> failablePredicate = FailureOnOddInvocations::testLong; + assertThrows(SomeException.class, () -> failablePredicate.test(1L)); + failablePredicate.test(1L); + } + + @Test + public void testLongPredicateAnd() throws Throwable { + assertTrue(FailableLongPredicate.TRUE.and(FailableLongPredicate.TRUE).test(0)); + assertFalse(FailableLongPredicate.TRUE.and(FailableLongPredicate.FALSE).test(0)); + assertFalse(FailableLongPredicate.FALSE.and(FailableLongPredicate.TRUE).test(0)); + assertFalse(FailableLongPredicate.FALSE.and(FailableLongPredicate.FALSE).test(0)); + // null tests + assertThrows(NullPointerException.class, () -> assertFalse(FailableLongPredicate.falsePredicate().and(null).test(0))); + assertThrows(NullPointerException.class, () -> assertTrue(FailableLongPredicate.truePredicate().and(null).test(0))); + } + + @Test + public void testLongPredicateNegate() throws Throwable { + assertFalse(FailableLongPredicate.TRUE.negate().test(0L)); + assertFalse(FailableLongPredicate.truePredicate().negate().test(0L)); + assertTrue(FailableLongPredicate.FALSE.negate().test(0L)); + assertTrue(FailableLongPredicate.falsePredicate().negate().test(0L)); + } + + @Test + public void testLongPredicateOr() throws Throwable { + assertTrue(FailableLongPredicate.TRUE.or(FailableLongPredicate.TRUE).test(0)); + assertTrue(FailableLongPredicate.TRUE.or(FailableLongPredicate.FALSE).test(0)); + assertTrue(FailableLongPredicate.FALSE.or(FailableLongPredicate.TRUE).test(0)); + assertFalse(FailableLongPredicate.FALSE.or(FailableLongPredicate.FALSE).test(0)); + // null tests + assertThrows(NullPointerException.class, () -> assertFalse(FailableLongPredicate.falsePredicate().or(null).test(0))); + assertThrows(NullPointerException.class, () -> assertTrue(FailableLongPredicate.truePredicate().or(null).test(0))); + } + + @Test + public void testLongUnaryOperatorAndThen() throws Throwable { + final Testable<?, ?> testable = new Testable<>(null); + final FailableLongUnaryOperator<Throwable> failing = t -> { + testable.setThrowable(ERROR); + testable.test(); + return 0L; + }; + final FailableLongUnaryOperator<Throwable> nop = FailableLongUnaryOperator.nop(); + Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.andThen(failing).applyAsLong(0L)); + assertSame(ERROR, e); + e = assertThrows(OutOfMemoryError.class, () -> failing.andThen(nop).applyAsLong(0L)); + assertSame(ERROR, e); + // Does not throw + nop.andThen(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> failing.andThen(null)); + } + + @Test + public void testLongUnaryOperatorCompose() throws Throwable { + final Testable<?, ?> testable = new Testable<>(null); + final FailableLongUnaryOperator<Throwable> failing = t -> { + testable.setThrowable(ERROR); + testable.test(); + return 0L; + }; + final FailableLongUnaryOperator<Throwable> nop = FailableLongUnaryOperator.nop(); + Throwable e = assertThrows(OutOfMemoryError.class, () -> nop.compose(failing).applyAsLong(0L)); + assertSame(ERROR, e); + e = assertThrows(OutOfMemoryError.class, () -> failing.compose(nop).applyAsLong(0L)); + assertSame(ERROR, e); + // Does not throw + nop.compose(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> failing.compose(null)); + } + + @Test + public void testLongUnaryOperatorIdentity() throws Throwable { + final FailableLongUnaryOperator<Throwable> nop = FailableLongUnaryOperator.identity(); + // Does not throw + nop.compose(nop); + // Documented in Javadoc edge-case. + assertThrows(NullPointerException.class, () -> nop.compose(null)); + } + + @Test + @DisplayName("Test that asPredicate(FailablePredicate) is converted to -> Predicate ") + public void testPredicate() { + FailureOnOddInvocations.invocations = 0; + final FailablePredicate<Object, Throwable> failablePredicate = t -> FailureOnOddInvocations.failingBool(); + final Predicate<?> predicate = Failable.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 testPredicateAnd() throws Throwable { + assertTrue(FailablePredicate.TRUE.and(FailablePredicate.TRUE).test(null)); + assertFalse(FailablePredicate.TRUE.and(FailablePredicate.FALSE).test(null)); + assertFalse(FailablePredicate.FALSE.and(FailablePredicate.TRUE).test(null)); + assertFalse(FailablePredicate.FALSE.and(FailablePredicate.FALSE).test(null)); + // null tests + assertThrows(NullPointerException.class, () -> assertFalse(FailablePredicate.FALSE.and(null).test(null))); + assertThrows(NullPointerException.class, () -> assertTrue(FailablePredicate.TRUE.and(null).test(null))); + } + + @Test + public void testPredicateOr() throws Throwable { + assertTrue(FailablePredicate.TRUE.or(FailablePredicate.TRUE).test(null)); + assertTrue(FailablePredicate.TRUE.or(FailablePredicate.FALSE).test(null)); + assertTrue(FailablePredicate.FALSE.or(FailablePredicate.TRUE).test(null)); + assertFalse(FailablePredicate.FALSE.or(FailablePredicate.FALSE).test(null)); + // null tests + assertThrows(NullPointerException.class, () -> assertFalse(FailablePredicate.FALSE.or(null).test(null))); + assertThrows(NullPointerException.class, () -> assertTrue(FailablePredicate.TRUE.or(null).test(null))); + } + + @Test + public void testPredicateNegate() throws Throwable { + assertFalse(FailablePredicate.TRUE.negate().test(null)); + assertFalse(FailablePredicate.truePredicate().negate().test(null)); + assertTrue(FailablePredicate.FALSE.negate().test(null)); + assertTrue(FailablePredicate.falsePredicate().negate().test(null)); + } + + @Test + public void testRunnable() { + FailureOnOddInvocations.invocations = 0; + final UndeclaredThrowableException e = assertThrows(UndeclaredThrowableException.class, + () -> Failable.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 + Failable.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 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 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 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 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 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 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 String and IOExceptions as + * generic test types. + */ + @Test + public void testThrows_FailableBooleanSupplier_IOException() { + new FailableBooleanSupplier<IOException>() { + + @Override + public boolean getAsBoolean() 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_FailableBooleanSupplier_Throwable() { + new FailableBooleanSupplier<Throwable>() { + + @Override + public boolean getAsBoolean() throws Throwable { + 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 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 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 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 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 String and IOExceptions as + * generic test types. + */ + @Test + public void testThrows_FailableDoubleBinaryOperator_IOException() { + new FailableDoubleBinaryOperator<IOException>() { + + @Override + public double applyAsDouble(final double left, final double right) 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_FailableDoubleBinaryOperator_Throwable() { + new FailableDoubleBinaryOperator<Throwable>() { + + @Override + public double applyAsDouble(final double left, final double right) 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_FailableDoubleConsumer_IOException() { + new FailableDoubleConsumer<IOException>() { + + @Override + public void accept(final double value) 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_FailableDoubleConsumer_Throwable() { + new FailableDoubleConsumer<Throwable>() { + + @Override + public void accept(final double value) 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_FailableDoubleFunction_IOException() { + new FailableDoubleFunction<String, IOException>() { + + @Override + public String apply(final double 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_FailableDoubleFunction_Throwable() { + new FailableDoubleFunction<Object, Throwable>() { + + @Override + public Object apply(final double 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_FailableDoubleSupplier_IOException() { + new FailableDoubleSupplier<IOException>() { + + @Override + public double getAsDouble() 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_FailableDoubleSupplier_Throwable() { + new FailableDoubleSupplier<Throwable>() { + + @Override + public double getAsDouble() 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_FailableDoubleToIntFunction_IOException() { + new FailableDoubleToIntFunction<IOException>() { + + @Override + public int applyAsInt(final double value) 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_FailableDoubleToIntFunction_Throwable() { + new FailableDoubleToIntFunction<Throwable>() { + + @Override + public int applyAsInt(final double value) 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_FailableDoubleToLongFunction_IOException() { + new FailableDoubleToLongFunction<IOException>() { + + @Override + public int applyAsLong(final double value) 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_FailableDoubleToLongFunction_Throwable() { + new FailableDoubleToLongFunction<Throwable>() { + + @Override + public int applyAsLong(final double value) throws Throwable { + 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 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 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 String and IOExceptions as + * generic test types. + */ + @Test + public void testThrows_FailableIntBinaryOperator_IOException() { + new FailableIntBinaryOperator<IOException>() { + + @Override + public int applyAsInt(final int left, final int right) 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_FailableIntBinaryOperator_Throwable() { + new FailableIntBinaryOperator<Throwable>() { + + @Override + public int applyAsInt(final int left, final int right) 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_FailableIntConsumer_IOException() { + new FailableIntConsumer<IOException>() { + + @Override + public void accept(final int value) 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_FailableIntConsumer_Throwable() { + new FailableIntConsumer<Throwable>() { + + @Override + public void accept(final int value) throws Throwable { + 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_FailableIntFunction_Object_Throwable() { + new FailableIntFunction<Object, Throwable>() { + + @Override + public Object apply(final int 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_FailableIntFunction_String_IOException() { + new FailableIntFunction<String, IOException>() { + + @Override + public String apply(final int input) throws IOException { + 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_FailableIntSupplier_IOException() { + new FailableIntSupplier<IOException>() { + + @Override + public int getAsInt() 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_FailableIntSupplier_Throwable() { + new FailableIntSupplier<Throwable>() { + + @Override + public int getAsInt() 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_FailableIntToDoubleFunction_IOException() { + new FailableIntToDoubleFunction<IOException>() { + + @Override + public double applyAsDouble(final int value) 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_FailableIntToDoubleFunction_Throwable() { + new FailableIntToDoubleFunction<Throwable>() { + + @Override + public double applyAsDouble(final int value) 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_FailableIntToLongFunction_IOException() { + new FailableIntToLongFunction<IOException>() { + + @Override + public long applyAsLong(final int value) 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_FailableIntToLongFunction_Throwable() { + new FailableIntToLongFunction<Throwable>() { + + @Override + public long applyAsLong(final int value) 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_FailableLongBinaryOperator_IOException() { + new FailableLongBinaryOperator<IOException>() { + + @Override + public long applyAsLong(final long left, final long right) 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_FailableLongBinaryOperator_Throwable() { + new FailableLongBinaryOperator<Throwable>() { + + @Override + public long applyAsLong(final long left, final long right) 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_FailableLongConsumer_IOException() { + new FailableLongConsumer<IOException>() { + + @Override + public void accept(final long 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_FailableLongConsumer_Throwable() { + new FailableLongConsumer<Throwable>() { + + @Override + public void accept(final long 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_FailableLongFunction_IOException() { + new FailableLongFunction<String, IOException>() { + + @Override + public String apply(final long 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_FailableLongFunction_Throwable() { + new FailableLongFunction<Object, Throwable>() { + + @Override + public Object apply(final long 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_FailableLongSupplier_IOException() { + new FailableLongSupplier<IOException>() { + + @Override + public long getAsLong() 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_FailableLongSupplier_Throwable() { + new FailableLongSupplier<Throwable>() { + + @Override + public long getAsLong() 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_FailableLongToDoubleFunction_IOException() { + new FailableLongToDoubleFunction<IOException>() { + + @Override + public double applyAsDouble(final long value) 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_FailableLongToDoubleFunction_Throwable() { + new FailableLongToDoubleFunction<Throwable>() { + + @Override + public double applyAsDouble(final long value) 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_FailableLongToIntFunction_IOException() { + new FailableLongToIntFunction<IOException>() { + + @Override + public int applyAsInt(final long value) 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_FailableLongToIntFunction_Throwable() { + new FailableLongToIntFunction<Throwable>() { + + @Override + public int applyAsInt(final long value) throws Throwable { + 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_FailableObjDoubleConsumer_Object_Throwable() { + new FailableObjDoubleConsumer<Object, Throwable>() { + + @Override + public void accept(final Object object, final double value) 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_FailableObjDoubleConsumer_String_IOException() { + new FailableObjDoubleConsumer<String, IOException>() { + + @Override + public void accept(final String object, final double value) 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_FailableObjIntConsumer_Object_Throwable() { + new FailableObjIntConsumer<Object, Throwable>() { + + @Override + public void accept(final Object object, final int value) 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_FailableObjIntConsumer_String_IOException() { + new FailableObjIntConsumer<String, IOException>() { + + @Override + public void accept(final String object, final int value) 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_FailableObjLongConsumer_Object_Throwable() { + new FailableObjLongConsumer<Object, Throwable>() { + + @Override + public void accept(final Object object, final long value) 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_FailableObjLongConsumer_String_IOException() { + new FailableObjLongConsumer<String, IOException>() { + + @Override + public void accept(final String object, final long value) 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 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 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 String and IOExceptions as + * generic test types. + */ + @Test + public void testThrows_FailableRunnable_IOException() { + new 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_FailableRunnable_Throwable() { + new 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_FailableShortSupplier_IOException() { + new FailableShortSupplier<IOException>() { + + @Override + public short getAsShort() 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_FailableShortSupplier_Throwable() { + new FailableShortSupplier<Throwable>() { + + @Override + public short getAsShort() throws Throwable { + 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 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 FailableSupplier<String, IOException>() { + + @Override + public String get() 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_FailableToDoubleBiFunction_Object_Throwable() { + new FailableToDoubleBiFunction<Object, Object, Throwable>() { + + @Override + public double applyAsDouble(final Object t, final Object u) 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_FailableToDoubleBiFunction_String_IOException() { + new FailableToDoubleBiFunction<String, String, IOException>() { + + @Override + public double applyAsDouble(final String t, final String u) 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_FailableToDoubleFunction_Object_Throwable() { + new FailableToDoubleFunction<Object, Throwable>() { + + @Override + public double applyAsDouble(final Object t) 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_FailableToDoubleFunction_String_IOException() { + new FailableToDoubleFunction<String, IOException>() { + + @Override + public double applyAsDouble(final String t) 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_FailableToIntBiFunction_Object_Throwable() { + new FailableToIntBiFunction<Object, Object, Throwable>() { + + @Override + public int applyAsInt(final Object t, final Object u) 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_FailableToIntBiFunction_String_IOException() { + new FailableToIntBiFunction<String, String, IOException>() { + + @Override + public int applyAsInt(final String t, final String u) 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_FailableToIntFunction_Object_Throwable() { + new FailableToIntFunction<Object, Throwable>() { + + @Override + public int applyAsInt(final Object t) 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_FailableToIntFunction_String_IOException() { + new FailableToIntFunction<String, IOException>() { + + @Override + public int applyAsInt(final String t) 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_FailableToLongBiFunction_Object_Throwable() { + new FailableToLongBiFunction<Object, Object, Throwable>() { + + @Override + public long applyAsLong(final Object t, final Object u) 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_FailableToLongBiFunction_String_IOException() { + new FailableToLongBiFunction<String, String, IOException>() { + + @Override + public long applyAsLong(final String t, final String u) 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_FailableToLongFunction_Object_Throwable() { + new FailableToLongFunction<Object, Throwable>() { + + @Override + public long applyAsLong(final Object t) 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_FailableToLongFunction_String_IOException() { + new FailableToLongFunction<String, IOException>() { + + @Override + public long applyAsLong(final String t) throws IOException { + throw new IOException("test"); + } + }; + } + + @Test + public void testTryWithResources() { + final CloseableObject closeable = new CloseableObject(); + final FailableConsumer<Throwable, ? extends Throwable> consumer = closeable::run; + Throwable e = assertThrows(IllegalStateException.class, + () -> Failable.tryWithResources(() -> consumer.accept(ILLEGAL_STATE_EXCEPTION), closeable::close)); + assertSame(ILLEGAL_STATE_EXCEPTION, e); + + assertTrue(closeable.isClosed()); + closeable.reset(); + e = assertThrows(OutOfMemoryError.class, + () -> Failable.tryWithResources(() -> consumer.accept(ERROR), closeable::close)); + assertSame(ERROR, e); + + assertTrue(closeable.isClosed()); + closeable.reset(); + final IOException ioe = new IOException("Unknown I/O error"); + final UncheckedIOException uioe = assertThrows(UncheckedIOException.class, + () -> Failable.tryWithResources(() -> consumer.accept(ioe), closeable::close)); + final IOException cause = uioe.getCause(); + assertSame(ioe, cause); + + assertTrue(closeable.isClosed()); + closeable.reset(); + Failable.tryWithResources(() -> consumer.accept(null), closeable::close); + assertTrue(closeable.isClosed()); + } + + @Test + public void testFailableDoubleToIntFunctionNop() throws Throwable { + assertEquals(0, FailableDoubleToIntFunction.nop().applyAsInt(Double.MAX_VALUE), "Expect NOP to return 0"); + } + + @Test + public void testFailableDoubleToLongFunctionNop() throws Throwable { + assertEquals(0, FailableDoubleToLongFunction.nop().applyAsLong(Double.MAX_VALUE), "Expect NOP to return 0"); + } + + @Test + public void testFailableIntToDoubleFunctionNop() throws Throwable { + assertEquals(0, FailableIntToDoubleFunction.nop().applyAsDouble(Integer.MAX_VALUE), "Expect NOP to return 0"); + } + + @Test + public void testFailableIntToLongFunctionNop() throws Throwable { + assertEquals(0, FailableIntToLongFunction.nop().applyAsLong(Integer.MAX_VALUE), "Expect NOP to return 0"); + } + + @Test + public void testFailableLongToDoubleFunctionNop() throws Throwable { + assertEquals(0, FailableLongToDoubleFunction.nop().applyAsDouble(Long.MAX_VALUE), "Expect NOP to return 0"); + } + + @Test + public void testFailableLongToIntFunctionNop() throws Throwable { + assertEquals(0, FailableLongToIntFunction.nop().applyAsInt(Long.MAX_VALUE), "Expect NOP to return 0"); + } + + @Test + public void testFailableToIntFunctionNop() throws Throwable { + assertEquals(0, FailableToIntFunction.nop().applyAsInt("Foo"), "Expect NOP to return 0"); + } + + @Test + public void testFailableToIntBiFunctionNop() throws Throwable { + assertEquals(0, FailableToIntBiFunction.nop().applyAsInt("Foo", "Bar"), "Expect NOP to return 0"); + } + + @Test + public void testFailableToLongFunctionNop() throws Throwable { + assertEquals(0, FailableToLongFunction.nop().applyAsLong("Foo"), "Expect NOP to return 0"); + } + + @Test + public void testFailableToLongBiFunctionNop() throws Throwable { + assertEquals(0, FailableToLongBiFunction.nop().applyAsLong("Foo", "Bar"), "Expect NOP to return 0"); + } + + @Test + public void testFailableToDoubleFunctionNop() throws Throwable { + assertEquals(0, FailableToDoubleFunction.nop().applyAsDouble("Foo"), "Expect NOP to return 0"); + } + + @Test + public void testFailableToDoubleBiFunctionNop() throws Throwable { + assertEquals(0, FailableToDoubleBiFunction.nop().applyAsDouble("Foo", "Bar"), "Expect NOP to return 0"); + } + + @Test + public void testFailableBiFunctionNop() throws Throwable { + assertNull(FailableBiFunction.nop().apply("Foo", "Bar"), "Expect NOP to return null"); + } + + @Test + public void testFailableDoubleFunctionNop() throws Throwable { + assertNull(FailableDoubleFunction.nop().apply(Double.MAX_VALUE), "Expect NOP to return null"); + } + + @Test + public void testFailableIntFunctionNop() throws Throwable { + assertNull(FailableIntFunction.nop().apply(Integer.MAX_VALUE), "Expect NOP to return null"); + } + + @Test + public void testFailableLongFunctionNop() throws Throwable { + assertNull(FailableLongFunction.nop().apply(Long.MAX_VALUE), "Expect NOP to return null"); + } + + @Test + public void testFailableConsumerNop() throws Throwable { + // Expect nothing thrown + FailableConsumer.nop().accept("Foo"); + } + + @Test + public void testFailableObjDoubleConsumerNop() throws Throwable { + // Expect nothing thrown + FailableObjDoubleConsumer.nop().accept("Foo", Double.MAX_VALUE); + } + + @Test + public void testFailableObjIntConsumerNop() throws Throwable { + // Expect nothing thrown + FailableObjIntConsumer.nop().accept("Foo", Integer.MAX_VALUE); + } + + @Test + public void testFailableObjLongConsumerNop() throws Throwable { + // Expect nothing thrown + FailableObjLongConsumer.nop().accept("Foo", Long.MAX_VALUE); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/function/IntToCharFunctionTest.java b/src/test/java/org/apache/commons/lang3/function/IntToCharFunctionTest.java new file mode 100644 index 000000000..adbfdca09 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/IntToCharFunctionTest.java @@ -0,0 +1,35 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.apache.commons.lang3.AbstractLangTest; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link IntToCharFunction}. + */ +public class IntToCharFunctionTest extends AbstractLangTest { + + @Test + public void test() { + final IntToCharFunction func = i -> (char) i; + assertEquals('A', func.applyAsChar(65)); + } +} diff --git a/src/test/java/org/apache/commons/lang3/function/MethodFixtures.java b/src/test/java/org/apache/commons/lang3/function/MethodFixtures.java new file mode 100644 index 000000000..527154dc0 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/MethodFixtures.java @@ -0,0 +1,223 @@ +/* + * 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.function; + +import java.io.IOException; +import java.lang.reflect.Method; + +import org.apache.commons.lang3.AbstractLangTest; +import org.apache.commons.lang3.exception.CustomCheckedException; +import org.apache.commons.lang3.exception.CustomUncheckedException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; + +class MethodFixtures extends AbstractLangTest { + + static MethodFixtures INSTANCE = new MethodFixtures(); + + static Method getDeclaredMethod(final String name, final Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { + return MethodFixtures.class.getDeclaredMethod(name, parameterTypes); + } + + static Method getMethodForGetString() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("getString"); + } + + static Method getMethodForGetString1Arg() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("getString1Arg", String.class); + } + + static Method getMethodForGetString1ArgChecked() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("getString1ArgChecked", String.class); + } + + static Method getMethodForGetString1ArgThrowsChecked() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("getString1ArgThrowsChecked", String.class); + } + + static Method getMethodForGetString1ArgThrowsUnchecked() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("getString1ArgThrowsUnchecked", String.class); + } + + static Method getMethodForGetString2Arg() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("getString2Args", String.class, String.class); + } + + static Method getMethodForGetStringChecked() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("getStringChecked"); + } + + static Method getMethodForGetStringsVarArg() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("getStringArrayVarStringArgs", String[].class); + } + + static Method getMethodForGetStringThrowsChecked() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("getStringThrowsChecked"); + } + + static Method getMethodForGetStringThrowsUnchecked() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("getStringThrowsUnchecked"); + } + + static Method getMethodForGetStringVarStringArgs() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("geStringtVarStringArgs", String[].class); + } + + static Method getMethodForSetString1Arg() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("setValue1", String.class); + } + + static Method getMethodForSetString1ArgThrows() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("setValue1Throws", String.class); + } + + static Method getMethodForSetString1ArgThrowsChecked() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("setValue1ThrowsChecked", String.class); + } + + static Method getMethodForSetString1ArgThrowsUnchecked() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("setValue1ThrowsUnchecked", String.class); + } + + static Method getMethodForSetString2Args() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("setValue1And2", String.class, String.class); + } + + static Method getMethodForSetStringsVarArg() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("setValueArray", String[].class); + } + + static Method getMethodForStaticGetString() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("staticGetString"); + } + + static Method getMethodForVoidMethod() throws NoSuchMethodException, SecurityException { + return getDeclaredMethod("voidMethod"); + } + + public static String staticGetString() { + return "Static.ABC"; + } + + private String value1; + + private String value2; + + private String[] valueArray; + + @BeforeEach + @AfterEach + public void clear() { + value1 = null; + value1 = null; + valueArray = null; + } + + public String geStringtVarStringArgs(final String... strings) { + return "XYZ"; + } + + @AnnotationTestFixture + public String getString() { + return "ABC"; + } + + public String getString1Arg(final String value) { + return value; + } + + @SuppressWarnings("unused") // IOException is declared but never thrown. + public String getString1ArgChecked(final String value) throws IOException { + return value; + } + + public String getString1ArgThrowsChecked(final String value) throws CustomCheckedException { + throw new CustomCheckedException("getString1ArgThrowsChecked"); + } + + public String getString1ArgThrowsUnchecked(final String value) { + throw new CustomUncheckedException("getString1ArgThrowsUnchecked"); + } + + @AnnotationTestFixture + public String getString2() { + return "EFG"; + } + + public String getString2Args(final String value1, final String value2) { + return value1 + value2; + } + + public String[] getStringArrayVarStringArgs(final String... strings) { + return strings; + } + + public String getStringChecked() throws Exception { + return "ABC"; + } + + public String getStringThrowsChecked() throws CustomCheckedException { + throw new CustomCheckedException("getStringThrowsChecked"); + } + + public String getStringThrowsUnchecked() { + throw new CustomUncheckedException("getStringThrowsUnchecked"); + } + + String getValue1() { + return value1; + } + + String getValue2() { + return value2; + } + + String[] getValueArray() { + return valueArray; + } + + void setValue1(final String value1) throws Exception { + this.value1 = value1; + } + + void setValue1And2(final String value1, final String value2) throws Exception { + this.value1 = value1; + this.value2 = value2; + } + + void setValue1ThrowsChecked(final String value1) throws CustomCheckedException { + throw new CustomCheckedException("setValue1ThrowsChecked"); + } + + void setValue1ThrowsUnchecked(final String value1) { + throw new CustomUncheckedException("setValue1ThrowsUnchecked"); + } + + void setValue2(final String value2) { + this.value2 = value2; + } + + void setValueArray(final String... values) throws Exception { + this.valueArray = values; + } + + public void voidMethod() { + // noop + } + +} diff --git a/src/test/java/org/apache/commons/lang3/function/MethodInvokersBiConsumerTest.java b/src/test/java/org/apache/commons/lang3/function/MethodInvokersBiConsumerTest.java new file mode 100644 index 000000000..9d02c2432 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/MethodInvokersBiConsumerTest.java @@ -0,0 +1,56 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.lang.reflect.Method; +import java.util.function.BiConsumer; + +import org.junit.jupiter.api.Test; + +/** + * Tests {@link MethodInvokers#asBiConsumer(Method)}. + */ +public class MethodInvokersBiConsumerTest extends MethodFixtures { + + @Test + public void testApply1Arg() throws NoSuchMethodException, SecurityException { + final BiConsumer<Object, Object> biConsumer = MethodInvokers.asBiConsumer(getMethodForSetString1Arg()); + biConsumer.accept(INSTANCE, "A"); + assertEquals("A", INSTANCE.getValue1()); + biConsumer.accept(INSTANCE, "B"); + assertEquals("B", INSTANCE.getValue1()); + } + + @Test + public void testConstructorForNull() throws SecurityException { + assertThrows(NullPointerException.class, () -> MethodInvokers.asBiConsumer(null)); + } + + @Test + public void testToString() throws SecurityException, ReflectiveOperationException { + // Should not blow up and must return _something_ + final BiConsumer<Object, Object> biConsumer = MethodInvokers.asBiConsumer(getMethodForSetString1Arg()); + assertFalse(biConsumer.toString().isEmpty()); + assertFalse(biConsumer.toString().isEmpty()); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/function/MethodInvokersBiFunctionTest.java b/src/test/java/org/apache/commons/lang3/function/MethodInvokersBiFunctionTest.java new file mode 100644 index 000000000..90c24ce2f --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/MethodInvokersBiFunctionTest.java @@ -0,0 +1,65 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.lang.reflect.Method; +import java.util.function.BiFunction; + +import org.apache.commons.lang3.exception.CustomUncheckedException; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link MethodInvokers#asBiFunction(Method)}. + */ +public class MethodInvokersBiFunctionTest extends MethodFixtures { + + @Test + public void testApply1Arg() throws NoSuchMethodException, SecurityException { + final BiFunction<MethodFixtures, String, String> func = MethodInvokers.asBiFunction(getMethodForGetString1Arg()); + assertEquals(INSTANCE.getString1Arg("A"), func.apply(INSTANCE, "A")); + } + + @Test + public void testApply1ArgThrowsUnchecked() throws NoSuchMethodException, SecurityException { + final BiFunction<MethodFixtures, String, String> func = MethodInvokers.asBiFunction(getMethodForGetString1ArgThrowsUnchecked()); + assertThrows(CustomUncheckedException.class, () -> func.apply(INSTANCE, "A")); + } + + @Test + public void testConstructorForNull() throws SecurityException { + assertThrows(NullPointerException.class, () -> MethodInvokers.asBiFunction(null)); + } + + @Test + public void testFullExample() throws SecurityException, ReflectiveOperationException { + final Method method = String.class.getMethod("charAt", int.class); + final BiFunction<String, Integer, Character> function = MethodInvokers.asBiFunction(method); + assertEquals('C', function.apply("ABC", 2)); + } + + @Test + public void testToString() throws SecurityException, ReflectiveOperationException { + // Should not blow up and must return _something_ + assertFalse(MethodInvokers.asBiFunction(getMethodForGetString1Arg()).toString().isEmpty()); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/function/MethodInvokersFailableBiConsumerTest.java b/src/test/java/org/apache/commons/lang3/function/MethodInvokersFailableBiConsumerTest.java new file mode 100644 index 000000000..4d369d993 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/MethodInvokersFailableBiConsumerTest.java @@ -0,0 +1,62 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.lang.reflect.Method; + +import org.apache.commons.lang3.exception.CustomCheckedException; +import org.apache.commons.lang3.exception.CustomUncheckedException; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link MethodInvokers#asFailableBiConsumer(Method)}. + */ +public class MethodInvokersFailableBiConsumerTest extends MethodFixtures { + + @Test + public void testApply1Arg() throws Throwable { + MethodInvokers.asFailableBiConsumer(getMethodForSetString1Arg()).accept(INSTANCE, "A"); + assertEquals("A", INSTANCE.getValue1()); + } + + @Test + public void testApply1ArgThrowsChecked() throws Exception { + assertThrows(CustomCheckedException.class, () -> MethodInvokers.asFailableBiConsumer(getMethodForSetString1ArgThrowsChecked()).accept(INSTANCE, "A")); + } + + @Test + public void testApply1ArgThrowsUnchecked() throws Exception { + assertThrows(CustomUncheckedException.class, () -> MethodInvokers.asFailableBiConsumer(getMethodForSetString1ArgThrowsUnchecked()).accept(INSTANCE, "A")); + } + + @Test + public void testConstructorForNull() throws Exception { + assertThrows(NullPointerException.class, () -> MethodInvokers.asFailableBiConsumer(null)); + } + + @Test + public void testToString() throws SecurityException, ReflectiveOperationException { + // Should not blow up and must return _something_ + assertFalse(MethodInvokers.asFailableBiConsumer(getMethodForSetString1Arg()).toString().isEmpty()); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/function/MethodInvokersFailableBiFunctionTest.java b/src/test/java/org/apache/commons/lang3/function/MethodInvokersFailableBiFunctionTest.java new file mode 100644 index 000000000..4b768cb5a --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/MethodInvokersFailableBiFunctionTest.java @@ -0,0 +1,69 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.lang.reflect.Method; + +import org.apache.commons.lang3.exception.CustomCheckedException; +import org.apache.commons.lang3.exception.CustomUncheckedException; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link MethodInvokers#asFailableBiFunction(Method)}. + */ +public class MethodInvokersFailableBiFunctionTest extends MethodFixtures { + + @Test + public void testApply1Arg() throws Throwable { + // Use a local variable typed to the interface to make sure we compile. + final FailableBiFunction<MethodFixtures, String, String[], Throwable> func = MethodInvokers.asFailableBiFunction(getMethodForGetString1ArgChecked()); + assertEquals(INSTANCE.getString1ArgChecked("A"), func.apply(INSTANCE, "A")); + } + + @Test + public void testApply1ArgThrowsChecked() throws NoSuchMethodException, SecurityException { + // Use a local variable typed to the interface to make sure we compile. + final FailableBiFunction<MethodFixtures, String, String[], Throwable> func = MethodInvokers + .asFailableBiFunction(getMethodForGetString1ArgThrowsChecked()); + assertThrows(CustomCheckedException.class, () -> func.apply(INSTANCE, "A")); + } + + @Test + public void testApply1ArgThrowsUnchecked() throws NoSuchMethodException, SecurityException { + // Use a local variable typed to the interface to make sure we compile. + final FailableBiFunction<MethodFixtures, String, String[], Throwable> func = MethodInvokers + .asFailableBiFunction(getMethodForGetString1ArgThrowsUnchecked()); + assertThrows(CustomUncheckedException.class, () -> func.apply(INSTANCE, "A")); + } + + @Test + public void testConstructorForNull() throws SecurityException { + assertThrows(NullPointerException.class, () -> MethodInvokers.asFailableBiFunction(null)); + } + + @Test + public void testToString() throws SecurityException, Throwable { + // Should not blow up and must return _something_ + assertFalse(MethodInvokers.asFailableBiFunction(getMethodForGetString1ArgChecked()).toString().isEmpty()); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/function/MethodInvokersFailableFunctionTest.java b/src/test/java/org/apache/commons/lang3/function/MethodInvokersFailableFunctionTest.java new file mode 100644 index 000000000..8e3ddf2ab --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/MethodInvokersFailableFunctionTest.java @@ -0,0 +1,84 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.lang3.exception.UncheckedException; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link MethodInvokers#asFailableFunction(Method)}. + */ +public class MethodInvokersFailableFunctionTest extends MethodFixtures { + + @Test + public void testApply0Arg() throws Throwable { + assertEquals(INSTANCE.getString(), MethodInvokers.asFailableFunction(getMethodForGetString()).apply(INSTANCE)); + } + + @Test + public void testConstructorForNull() throws SecurityException { + assertThrows(NullPointerException.class, () -> MethodInvokers.asFailableFunction((Method) null)); + } + + @Test + public void testBuildVarArg() throws SecurityException, NoSuchMethodException { + MethodInvokers.asFailableFunction(getMethodForGetStringVarStringArgs()); + } + + @Test + public void testFindAndInvoke() throws SecurityException { + // Finding + final List<FailableFunction<Object, Object, Throwable>> invokers = Stream.of(MethodFixtures.class.getDeclaredMethods()) + .filter(m -> m.isAnnotationPresent(AnnotationTestFixture.class)).map(MethodInvokers::asFailableFunction).collect(Collectors.toList()); + assertEquals(2, invokers.size()); + // ... + // Invoking + final Set<Object> set = invokers.stream().map(i -> { + try { + return i.apply(MethodFixtures.INSTANCE); + } catch (final Throwable e) { + throw new UncheckedException(e); + } + }).collect(Collectors.toSet()); + assertEquals(new HashSet<>(Arrays.asList(INSTANCE.getString(), INSTANCE.getString2())), set); + } + + @Test + public void testThrowsChecked() throws Exception { + assertThrows(Exception.class, () -> MethodInvokers.asFailableFunction(getMethodForGetStringThrowsChecked()).apply(INSTANCE)); + } + + @Test + public void testToString() throws SecurityException, ReflectiveOperationException { + // Should not blow up and must return _something_ + assertFalse(MethodInvokers.asFailableFunction(getMethodForGetString()).toString().isEmpty()); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/function/MethodInvokersFailableSupplierTest.java b/src/test/java/org/apache/commons/lang3/function/MethodInvokersFailableSupplierTest.java new file mode 100644 index 000000000..62ccc602e --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/MethodInvokersFailableSupplierTest.java @@ -0,0 +1,44 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +import java.lang.reflect.Method; + +import org.junit.jupiter.api.Test; + +/** + * Tests {@link MethodInvokers#asFailableSupplier(Method)}. + */ +public class MethodInvokersFailableSupplierTest extends MethodFixtures { + + @Test + public void testSupplierStatic() throws Throwable { + assertEquals(staticGetString(), MethodInvokers.asFailableSupplier(getMethodForStaticGetString()).get()); + assertEquals(staticGetString(), MethodInvokers.asFailableSupplier(getMethodForStaticGetString()).get()); + } + + @Test + public void testSupplierToString() throws SecurityException, ReflectiveOperationException { + // Should not blow up and must return _something_ + assertFalse(MethodInvokers.asFailableSupplier(getMethodForStaticGetString()).toString().isEmpty()); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/function/MethodInvokersFunctionTest.java b/src/test/java/org/apache/commons/lang3/function/MethodInvokersFunctionTest.java new file mode 100644 index 000000000..eb556f93c --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/MethodInvokersFunctionTest.java @@ -0,0 +1,101 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.lang3.exception.CustomUncheckedException; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link MethodInvokers#asFunction(Method)}. + */ +public class MethodInvokersFunctionTest extends MethodFixtures { + + @Test + public void testApply0Arg() throws NoSuchMethodException, SecurityException { + final Function<MethodFixtures, String> func = MethodInvokers.asFunction(getMethodForGetString()); + assertEquals(INSTANCE.getString(), func.apply(INSTANCE)); + } + + @Test + public void testApply0ArgThrowsUnchecked() throws NoSuchMethodException, SecurityException { + final Function<MethodFixtures, String> func = MethodInvokers.asFunction(getMethodForGetStringThrowsUnchecked()); + assertThrows(CustomUncheckedException.class, () -> func.apply(INSTANCE)); + } + + @Test + public void testBuildVarArg() throws SecurityException, NoSuchMethodException { + MethodInvokers.asFunction(getMethodForGetStringVarStringArgs()); + } + + @Test + public void testConstructorForNull() throws SecurityException { + assertThrows(NullPointerException.class, () -> MethodInvokers.asFunction(null)); + } + + @Test + public void testFindAndInvoke() throws SecurityException { + // Finding + final List<Function<Object, Object>> invokers = Stream.of(MethodFixtures.class.getDeclaredMethods()) + .filter(m -> m.isAnnotationPresent(AnnotationTestFixture.class)).map(MethodInvokers::asFunction).collect(Collectors.toList()); + assertEquals(2, invokers.size()); + // ... + // Invoking + final Set<Object> set1 = invokers.stream().map(i -> i.apply(MethodFixtures.INSTANCE)).collect(Collectors.toSet()); + assertEquals(new HashSet<>(Arrays.asList(INSTANCE.getString(), INSTANCE.getString2())), set1); + final Set<Object> set2 = Stream.of(INSTANCE).map(invokers.get(0)).collect(Collectors.toSet()); + final Set<Object> set3 = Stream.of(INSTANCE).map(invokers.get(1)).collect(Collectors.toSet()); + set2.addAll(set3); + assertEquals(new HashSet<>(Arrays.asList(INSTANCE.getString(), INSTANCE.getString2())), set2); + } + + @Test + public void testFullExample() throws SecurityException, ReflectiveOperationException { + final Method method = String.class.getMethod("length"); + final Function<String, Integer> function = MethodInvokers.asFunction(method); + assertEquals(3, function.apply("ABC")); + } + + @Test + public void testMapComputeIfAbsent() throws NoSuchMethodException, SecurityException { + final Map<MethodFixtures, String> map = new HashMap<>(); + map.computeIfAbsent(INSTANCE, MethodInvokers.asFunction(getMethodForGetString())); + assertEquals(INSTANCE.getString(), map.get(INSTANCE)); + } + + @Test + public void testToString() throws SecurityException, ReflectiveOperationException { + // Should not blow up and must return _something_ + assertFalse(MethodInvokers.asFunction(getMethodForGetString()).toString().isEmpty()); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/function/MethodInvokersSupplierTest.java b/src/test/java/org/apache/commons/lang3/function/MethodInvokersSupplierTest.java new file mode 100644 index 000000000..99ba0673e --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/MethodInvokersSupplierTest.java @@ -0,0 +1,48 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; + +import java.lang.reflect.Method; +import java.util.function.Supplier; + +import org.junit.jupiter.api.Test; + +/** + * Tests {@link MethodInvokers#asSupplier(Method)}. + */ +public class MethodInvokersSupplierTest extends MethodFixtures { + + @Test + public void testSupplierStaticGetMethod() throws NoSuchMethodException, SecurityException { + final Supplier<String> supplier = MethodInvokers.asSupplier(getMethodForStaticGetString()); + assertEquals(staticGetString(), supplier.get()); + assertEquals(staticGetString(), supplier.get()); + } + + @Test + public void testSupplierStaticGetMethodToString() throws SecurityException, ReflectiveOperationException { + // Should not blow up and must return _something_ + final Supplier<Object> supplier = MethodInvokers.asSupplier(getMethodForStaticGetString()); + assertFalse(supplier.toString().isEmpty()); + assertFalse(supplier.toString().isEmpty()); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/function/Objects.java b/src/test/java/org/apache/commons/lang3/function/Objects.java new file mode 100755 index 000000000..f07a0edbd --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/Objects.java @@ -0,0 +1,164 @@ +/* + * 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.function; + +import java.util.function.Supplier; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import org.apache.commons.lang3.ObjectUtils; + +/** + * This class provides some replacements for the corresponding methods in + * {@link java.util.Objects}. The replacements have the advantage, that they are properly + * annotated with {@link Nullable}, and/or {@link Nonnull}, so they let the + * compiler know what their respective results are. + * + * The various {@code requireNonNull} methods are particularly handy, when + * dealing with external code, that a) doesn't support the {@link Nonnull} + * annotation, or if you know for other reasons, that an object is non-null. + * Take for example, a {@link java.util.Map map}, that you have filled with + * non-null values. So, in your opinion, the following should be perfectly + * valid code: + * <pre> + * final Map<String,Object> map = getMapOfNonNullValues(); + * final @Nonnull Object o = map.get("SomeKey"); + * </pre> + * However, if your Java compiler *does* null analysis, it will reject this + * example as invalid, because {@link java.util.Map#get(Object)} might return + * a null value. As a workaround, you can use this: + * <pre> + * import static org.apache.commons.lang3.function.Objects.requireNonNull; + * + * final Map<String,Object> map = getMapOfNonNullValues(); + * final @Nonnull Object o = requireNonNull(map.get("SomeKey")); + * </pre> + * + * This class is somewhat redundant with regards to {@link ObjectUtils}. + * For example, {@link #requireNonNull(Object, Object)} is almost equivalent + * with {@link ObjectUtils#defaultIfNull(Object, Object)}. However, it isn't + * quite the same, because the latter can, in fact, return null. The former + * can't, and the Java compiler confirms this.(An alternative to redundancy + * would have been to change the {@code ObjectUtils} class. However, that + * would mean loosing upwards compatibility, and we don't do that.) + * + * @since 3.12.0 + */ +public class Objects { + + /** + * Checks, whether the given object is non-null. If so, returns the non-null + * object as a result value. Otherwise, a NullPointerException is thrown. + * @param <T> The type of parameter {@code value}, also the result type. + * @param value The value, which is being checked. + * @return The given input value, if it was found to be non-null. + * @throws NullPointerException The input value was null. + * @see java.util.Objects#requireNonNull(Object) + */ + public static <T> @Nonnull T requireNonNull(@Nullable final T value) throws NullPointerException { + return requireNonNull(value, "The value must not be null."); + } + + /** + * Checks, whether the given object is non-null. If so, returns the non-null + * object as a result value. Otherwise, invokes the given {@link Supplier}, + * and returns the suppliers result value. + * @param <T> The type of parameter {@code value}, also the result type of + * the default value supplier, and of the method itself. + * @param <E> The type of exception, that the {@code default value supplier}, + * may throw. + * @param value The value, which is being checked. + * @param defaultValueSupplier The supplier, which returns the default value. This default + * value <em>must</em> be non-null. The supplier will only be invoked, if + * necessary. (If the {@code value} parameter is null, that is.) + * @return The given input value, if it was found to be non-null. Otherwise, + * the value, that has been returned by the default value supplier. + * @see #requireNonNull(Object) + * @see #requireNonNull(Object, String) + * @see #requireNonNull(Object, Supplier) + * @throws NullPointerException The default value supplier is null, or the default + * value supplier has returned null. + */ + public static <T, E extends Throwable> @Nonnull T requireNonNull(@Nullable final T value, @Nonnull final FailableSupplier<T, E> defaultValueSupplier) throws NullPointerException { + if (value == null) { + final FailableSupplier<T, ?> supplier = requireNonNull(defaultValueSupplier, "The supplier must not be null"); + final T defaultValue; + try { + defaultValue = supplier.get(); + } catch (final Throwable t) { + throw Failable.rethrow(t); + } + return requireNonNull(defaultValue, "The supplier must not return null."); + } + return value; + } + + /** + * Checks, whether the given object is non-null. If so, returns the non-null + * object as a result value. Otherwise, a NullPointerException is thrown. + * @param <T> The type of parameter {@code value}, also the result type. + * @param value The value, which is being checked. + * @param msg A string, which is being used as the exceptions message, if the + * check fails. + * @return The given input value, if it was found to be non-null. + * @throws NullPointerException The input value was null. + * @see java.util.Objects#requireNonNull(Object, String) + * @see #requireNonNull(Object, Supplier) + */ + public static <T> @Nonnull T requireNonNull(@Nullable final T value, @Nonnull final String msg) throws NullPointerException { + if (value == null) { + throw new NullPointerException(msg); + } + return value; + } + + /** + * Checks, whether the given object is non-null. If so, returns the non-null + * object as a result value. Otherwise, a NullPointerException is thrown. + * @param <T> The type of parameter {@code value}, also the result type. + * @param value The value, which is being checked. + * @param msgSupplier A supplier, which creates the exception message, if the check fails. + * This supplier will only be invoked, if necessary. + * @return The given input value, if it was found to be non-null. + * @throws NullPointerException The input value was null. + * @see java.util.Objects#requireNonNull(Object, String) + * @see #requireNonNull(Object, String) + */ + public static <T> @Nonnull T requireNonNull(@Nullable final T value, @Nonnull final Supplier<String> msgSupplier) throws NullPointerException { + if (value == null) { + throw new NullPointerException(msgSupplier.get()); + } + return value; + } + + /** + * Checks, whether the given object is non-null. If so, returns the non-null + * object as a result value. Otherwise, a NullPointerException is thrown. + * @param <T> The type of parameter {@code value}, also the result type. + * @param value The value, which is being checked. + * @param defaultValue The default value, which is being returned, if the + * check fails, and the {@code value} is null. + * @throws NullPointerException The input value, and the default value are null. + * @return The given input value, if it was found to be non-null. + * @see java.util.Objects#requireNonNull(Object) + */ + public static <T> @Nonnull T requireNonNull(@Nullable final T value, @Nonnull final T defaultValue) throws NullPointerException { + return value == null ? requireNonNull(defaultValue) : value; + } +} diff --git a/src/test/java/org/apache/commons/lang3/function/ObjectsTest.java b/src/test/java/org/apache/commons/lang3/function/ObjectsTest.java new file mode 100755 index 000000000..36788830e --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/ObjectsTest.java @@ -0,0 +1,141 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.function.Supplier; + +import org.apache.commons.lang3.AbstractLangTest; +import org.junit.jupiter.api.Test; + +public class ObjectsTest extends AbstractLangTest { + + public static class TestableFailableSupplier<O, E extends Exception> implements FailableSupplier<O, E> { + private final FailableSupplier<O, E> supplier; + private boolean invoked; + + TestableFailableSupplier(final FailableSupplier<O, E> pSupplier) { + this.supplier = pSupplier; + } + + @Override + public O get() throws E { + invoked = true; + return supplier.get(); + } + + public boolean isInvoked() { + return invoked; + } + } + + public static class TestableSupplier<O> implements Supplier<O> { + private final Supplier<O> supplier; + private boolean invoked; + + TestableSupplier(final Supplier<O> pSupplier) { + this.supplier = pSupplier; + } + + @Override + public O get() { + invoked = true; + return supplier.get(); + } + + public boolean isInvoked() { + return invoked; + } + } + + @Test + void testRequireNonNullObject() { + assertSame("foo", Objects.requireNonNull("foo")); + try { + Objects.requireNonNull(null); + fail("Expected Exception"); + } catch (final NullPointerException e) { + assertEquals("The value must not be null.", e.getMessage()); + } + } + + @Test + void testRequireNonNullObjectFailableSupplierString() { + final TestableFailableSupplier<String, ?> supplier = new TestableFailableSupplier<>(() -> null); + assertSame("foo", Objects.requireNonNull("foo", supplier)); + assertFalse(supplier.isInvoked()); + try { + Objects.requireNonNull(null, supplier); + fail("Expected Exception"); + } catch (final NullPointerException e) { + assertEquals("The supplier must not return null.", e.getMessage()); + assertTrue(supplier.isInvoked()); + } + final TestableFailableSupplier<String, ?> supplier2 = new TestableFailableSupplier<>(() -> null); + try { + Objects.requireNonNull(null, supplier2); + fail("Expected Exception"); + } catch (final NullPointerException e) { + assertEquals("The supplier must not return null.", e.getMessage()); + assertTrue(supplier2.isInvoked()); + } + final TestableFailableSupplier<String, ?> supplier3 = new TestableFailableSupplier<>(() -> "bar"); + assertSame("bar", Objects.requireNonNull(null, supplier3)); + final RuntimeException rte = new RuntimeException(); + final TestableFailableSupplier<String, ?> supplier4 = new TestableFailableSupplier<>(() -> { + throw rte; + }); + try { + Objects.requireNonNull(null, supplier4); + fail("Expected Exception"); + } catch (final RuntimeException e) { + assertSame(rte, e); + assertTrue(supplier4.isInvoked()); + } + } + + @Test + void testRequireNonNullObjectString() { + assertSame("foo", Objects.requireNonNull("foo", "bar")); + try { + Objects.requireNonNull(null, "bar"); + fail("Expected Exception"); + } catch (final NullPointerException e) { + assertEquals("bar", e.getMessage()); + } + } + + @Test + void testRequireNonNullObjectSupplierString() { + final TestableSupplier<String> supplier = new TestableSupplier<>(() -> "bar"); + assertSame("foo", Objects.requireNonNull("foo", supplier)); + assertFalse(supplier.isInvoked()); + try { + Objects.requireNonNull(null, supplier); + fail("Expected Exception"); + } catch (final NullPointerException e) { + assertEquals("bar", e.getMessage()); + assertTrue(supplier.isInvoked()); + } + } +} diff --git a/src/test/java/org/apache/commons/lang3/function/SuppliersTest.java b/src/test/java/org/apache/commons/lang3/function/SuppliersTest.java new file mode 100644 index 000000000..1c912757c --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/SuppliersTest.java @@ -0,0 +1,42 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.util.function.Supplier; + +import org.apache.commons.lang3.AbstractLangTest; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link Suppliers}. + */ +public class SuppliersTest extends AbstractLangTest { + + /** + * Tests {@link Suppliers#get(Supplier)}. + */ + @Test + public void testGet() { + assertNull(Suppliers.get(null)); + assertNull(Suppliers.get(() -> null)); + assertEquals("foo", Suppliers.get(() -> "foo")); + } +} diff --git a/src/test/java/org/apache/commons/lang3/function/ToBooleanBiFunctionTest.java b/src/test/java/org/apache/commons/lang3/function/ToBooleanBiFunctionTest.java new file mode 100644 index 000000000..13c79f318 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/ToBooleanBiFunctionTest.java @@ -0,0 +1,35 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.apache.commons.lang3.AbstractLangTest; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link ToBooleanBiFunction}. + */ +public class ToBooleanBiFunctionTest extends AbstractLangTest { + + @Test + public void test() { + final ToBooleanBiFunction<String, Integer> func = (t, u) -> Integer.valueOf(t).equals(u); + assertTrue(func.applyAsBoolean("1", 1)); + } +} diff --git a/src/test/java/org/apache/commons/lang3/function/TriConsumerTest.java b/src/test/java/org/apache/commons/lang3/function/TriConsumerTest.java new file mode 100644 index 000000000..5a959f562 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/TriConsumerTest.java @@ -0,0 +1,72 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.commons.lang3.AbstractLangTest; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link TriConsumer}. + */ +public class TriConsumerTest extends AbstractLangTest { + + @Test + public void testAccept() throws Throwable { + final AtomicReference<Character> ref1 = new AtomicReference<>(); + final AtomicReference<Short> ref2 = new AtomicReference<>(); + final AtomicReference<String> ref3 = new AtomicReference<>(); + final TriConsumer<AtomicReference<Character>, AtomicReference<Short>, AtomicReference<String>> tri = (t, u, + v) -> { + ref1.set(Character.valueOf('a')); + ref2.set(Short.valueOf((short) 1)); + ref3.set("z"); + }; + tri.accept(ref1, ref2, ref3); + assertEquals(Character.valueOf('a'), ref1.get()); + assertEquals(Short.valueOf((short) 1), ref2.get()); + assertEquals("z", ref3.get()); + } + + @Test + public void testAndThen() throws Throwable { + final AtomicReference<Character> ref1 = new AtomicReference<>(); + final AtomicReference<Short> ref2 = new AtomicReference<>(); + final AtomicReference<String> ref3 = new AtomicReference<>(); + final TriConsumer<AtomicReference<Character>, AtomicReference<Short>, AtomicReference<String>> tri = (t, u, + v) -> { + ref1.set(Character.valueOf('a')); + ref2.set(Short.valueOf((short) 1)); + ref3.set("z"); + }; + final TriConsumer<AtomicReference<Character>, AtomicReference<Short>, AtomicReference<String>> triAfter = (t, u, + v) -> { + ref1.set(Character.valueOf('b')); + ref2.set(Short.valueOf((short) 2)); + ref3.set("zz"); + }; + tri.andThen(triAfter).accept(ref1, ref2, ref3); + assertEquals(Character.valueOf('b'), ref1.get()); + assertEquals(Short.valueOf((short) 2), ref2.get()); + assertEquals("zz", ref3.get()); + } + +} diff --git a/src/test/java/org/apache/commons/lang3/function/TriFunctionTest.java b/src/test/java/org/apache/commons/lang3/function/TriFunctionTest.java new file mode 100644 index 000000000..cdcf963b7 --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/function/TriFunctionTest.java @@ -0,0 +1,74 @@ +/* + * 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.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; + +import org.apache.commons.lang3.AbstractLangTest; +import org.junit.jupiter.api.Test; + +/** + * Tests {@link TriFunction}. + */ +public class TriFunctionTest extends AbstractLangTest { + + @Test + public void testAccept() throws Throwable { + final AtomicReference<Character> ref1 = new AtomicReference<>(); + final AtomicReference<Short> ref2 = new AtomicReference<>(); + final AtomicReference<String> ref3 = new AtomicReference<>(); + final TriFunction<AtomicReference<Character>, AtomicReference<Short>, AtomicReference<String>, String> tri = (t, u, v) -> { + ref1.set(Character.valueOf('a')); + ref2.set(Short.valueOf((short) 1)); + ref3.set("z"); + return "ABC"; + }; + assertEquals("ABC", tri.apply(ref1, ref2, ref3)); + assertEquals(Character.valueOf('a'), ref1.get()); + assertEquals(Short.valueOf((short) 1), ref2.get()); + assertEquals("z", ref3.get()); + } + + @Test + public void testAndThen() throws Throwable { + final AtomicReference<Character> ref1 = new AtomicReference<>(); + final AtomicReference<Short> ref2 = new AtomicReference<>(); + final AtomicReference<String> ref3 = new AtomicReference<>(); + final TriFunction<AtomicReference<Character>, AtomicReference<Short>, AtomicReference<String>, String> tri = (t, u, v) -> { + ref1.set(Character.valueOf('a')); + ref2.set(Short.valueOf((short) 1)); + ref3.set("z"); + return "9"; + }; + final Function<String, BigInteger> after = t -> { + ref1.set(Character.valueOf('b')); + ref2.set(Short.valueOf((short) 2)); + ref3.set("zz"); + return BigInteger.valueOf(Long.parseLong(t)).add(BigInteger.ONE); + }; + assertEquals(BigInteger.TEN, tri.andThen(after).apply(ref1, ref2, ref3)); + assertEquals(Character.valueOf('b'), ref1.get()); + assertEquals(Short.valueOf((short) 2), ref2.get()); + assertEquals("zz", ref3.get()); + } + +} |