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