package io.trane.future; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import java.time.Duration; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import org.junit.Test; public class ExceptionFutureTest { private <T> T get(Future<T> future) throws CheckedFutureException { return future.get(Duration.ZERO); } Exception ex = new TestException(); /*** map ***/ @Test public void map() throws CheckedFutureException { Future<Integer> future = Future.exception(ex); assertEquals(future, future.map(i -> i + 1)); } /*** flatMap ***/ @Test public void flatMap() throws CheckedFutureException { Future<Integer> future = Future.exception(ex); assertEquals(future, future.flatMap(i -> Future.value(i + 1))); } /*** transform ***/ @Test public void transform() throws CheckedFutureException { Transformer<Integer, Integer> t = new Transformer<Integer, Integer>() { @Override public Integer onException(Throwable ex) { assertEquals(ExceptionFutureTest.this.ex, ex); return 2; } @Override public Integer onValue(Integer value) { return null; } }; Future<Integer> future = Future.exception(ex); assertEquals(new Integer(2), get(future.transform(t))); } @Test(expected = TestException.class) public void transformException() throws CheckedFutureException { Transformer<Integer, Integer> t = new Transformer<Integer, Integer>() { @Override public Integer onException(Throwable ex) { assertEquals(ExceptionFutureTest.this.ex, ex); throw new TestException(); } @Override public Integer onValue(Integer value) { return null; } }; Future<Integer> future = Future.exception(ex); get(future.transform(t)); } /*** transformWith ***/ @Test public void transformWith() throws CheckedFutureException { Transformer<Integer, Future<Integer>> t = new Transformer<Integer, Future<Integer>>() { @Override public Future<Integer> onException(Throwable ex) { assertEquals(ExceptionFutureTest.this.ex, ex); return Future.value(2); } @Override public Future<Integer> onValue(Integer value) { return null; } }; Future<Integer> future = Future.exception(ex); assertEquals(new Integer(2), get(future.transformWith(t))); } @Test(expected = TestException.class) public void transformWithException() throws CheckedFutureException { Transformer<Integer, Future<Integer>> t = new Transformer<Integer, Future<Integer>>() { @Override public Future<Integer> onException(Throwable ex) { assertEquals(ExceptionFutureTest.this.ex, ex); throw new TestException(); } @Override public Future<Integer> onValue(Integer value) { return null; } }; Future<Integer> future = Future.exception(ex); get(future.transformWith(t)); } /*** biMap ***/ @Test public void biMap() throws CheckedFutureException { Future<Integer> f = Future.exception(ex); assertEquals(f, f.biMap(Future.value(1), (a, b) -> a + b)); } /*** biFlatMap ***/ @Test public void biFlatMap() throws CheckedFutureException { Future<Integer> f = Future.exception(ex); assertEquals(f, f.biFlatMap(Future.value(1), (a, b) -> Future.value(a + b))); } /*** onSuccess ***/ @Test public void onSuccess() throws CheckedFutureException { Future<Integer> future = Future.exception(ex); assertEquals(future, future.onSuccess(i -> { })); } /*** onFailure ***/ @Test(expected = TestException.class) public void onFailure() throws CheckedFutureException { AtomicReference<Throwable> exception = new AtomicReference<>(); Future<Integer> future = Future.<Integer>exception(ex).onFailure(exception::set); assertEquals(ex, exception.get()); get(future); } @Test(expected = TestException.class) public void onFailureException() throws CheckedFutureException { Future<Integer> future = Future.<Integer>exception(ex).onFailure(ex -> { throw new NullPointerException(); }); get(future); } /*** respond ***/ @Test public void respond() { AtomicBoolean success = new AtomicBoolean(false); AtomicBoolean failure = new AtomicBoolean(false); final Responder<Integer> r = new Responder<Integer>() { @Override public void onException(Throwable ex) { failure.set(true); } @Override public void onValue(Integer value) { success.set(true); } }; Future.<Integer>exception(ex).respond(r); assertFalse(success.get()); assertTrue(failure.get()); } @Test(expected = TestException.class) public void respondException() throws CheckedFutureException { final Responder<Integer> r = new Responder<Integer>() { @Override public void onException(Throwable ex) { throw new NullPointerException(); } @Override public void onValue(Integer value) { throw new NullPointerException(); } }; Future<Integer> f = Future.<Integer>exception(ex).respond(r); get(f); } /*** rescue ***/ @Test public void rescue() throws CheckedFutureException { Future<Integer> future = Future.<Integer>exception(ex).rescue(r -> { assertEquals(ex, r); return Future.value(1); }); assertEquals(new Integer(1), get(future)); } @Test(expected = ArithmeticException.class) public void rescueException() throws CheckedFutureException { Future<Integer> future = Future.<Integer>exception(ex).rescue(r -> Future.value(1 / 0)); get(future); } /*** voided ***/ @Test(expected = TestException.class) public void voided() throws CheckedFutureException { Future<Void> future = Future.exception(ex).voided(); get(future); } /*** get ***/ @Test(expected = TestException.class) public void get() throws CheckedFutureException { Future<Integer> future = Future.exception(ex); future.get(Duration.ofMillis(1)); } @Test(expected = Error.class) public void getError() throws CheckedFutureException { Future<Integer> future = Future.exception(new Error()); future.get(Duration.ofMillis(1)); } @Test(expected = CheckedFutureException.class) public void getCheckedException() throws CheckedFutureException { Future<Integer> future = Future.exception(new Exception()); future.get(Duration.ofMillis(1)); } @Test(expected = TestException.class) public void getZeroTimeout() throws CheckedFutureException { Future<Integer> future = Future.exception(ex); assertEquals(new Integer(1), future.get(Duration.ZERO)); } @Test(expected = TestException.class) public void getNegativeTimeout() throws CheckedFutureException { Future<Integer> future = Future.exception(ex); assertEquals(new Integer(1), future.get(Duration.ofMillis(-1))); } /*** toString ***/ @Test public void toStringException() { String s = Future.exception(ex).toString(); assertEquals("ExceptionFuture(" + ex + ")", s); } @Test public void toStringNull() { String s = Future.exception(null).toString(); assertEquals("ExceptionFuture(null)", s); } /*** hashCode ***/ @Test public void testHashCode() { assertEquals(Future.exception(ex).hashCode(), Future.exception(ex).hashCode()); } @Test public void testHashCodeNotEquals() { assertNotEquals(Future.exception(ex).hashCode(), Future.exception(new NullPointerException()).hashCode()); } @Test public void testHashCodeNull() { assertEquals(Future.exception(null).hashCode(), Future.exception(null).hashCode()); } @Test public void testHashCodeNullNotEquals() { assertNotEquals(Future.exception(null).hashCode(), Future.exception(ex).hashCode()); } /*** equals ***/ @Test public void testEquals() { assertEquals(Future.exception(ex), Future.exception(ex)); } @Test public void testEqualsNotEquals() { assertNotEquals(Future.exception(ex), Future.exception(new NullPointerException())); } @Test public void testEqualsNotEqualsNull() { assertNotEquals(Future.exception(ex), null); } @Test public void testEqualsNotEqualsOtherClass() { assertNotEquals(Future.exception(ex), "s"); } @Test public void testEqualsNull() { assertEquals(Future.exception(null), Future.exception(null)); } @Test public void testEqualsNullNotEquals() { assertNotEquals(Future.exception(null), Future.exception(ex)); } }