### Question:
FutureUtils { public static <T> T wait(String message, Optional<Future<? extends T>> task) { if (task.isPresent()) { return wait(message, task.get()); } else { throw new TaskNotScheduledException(message); } }  static T wait(String message, Optional<Future<? extends T>> task); static T wait(String message, Future<T> task); static T wait(String message, Future<T> task, long seconds);  }### Answer:
@Test(expected = TaskNotScheduledException.class) public void taskOptionalEmpty() { FutureUtils.wait("Test ok", Optional.empty()); }
@Test public void taskOptionalCompleted() { TestTask task = new TestTask("ok"); Future<String> future = executor.submit(task); String value = FutureUtils.wait("Test ok", Optional.of(future)); assertEquals("OK", value); }
@Test public void taskCompleted() { TestTask task = new TestTask("ok"); Future<String> future = executor.submit(task); String value = FutureUtils.wait("Test ok", future); assertEquals("OK", value); }
@Test(expected = TaskTimeoutException.class) public void taskTimeout() { TestTask task = new TestTask("timeout", 2000); Future<String> future = executor.submit(task); FutureUtils.wait("Test timeout", future, 1); }
@Test(expected = TestException.class) public void taskBaseException() { TestTask task = new TestTask("exception", 500, TestException::new); Future<String> future = executor.submit(task); FutureUtils.wait("exception", future, 1); }
@Test(expected = TaskExecutionException.class) public void taskCheckedException() { TestTask task = new TestTask("exception", 500, IOException::new); Future<String> future = executor.submit(task); FutureUtils.wait("exception", future, 1); }
@Test(expected = TaskCancelledException.class) public void taskCancelled() { TestTask task = new TestTask("cancelled", 2000); Future<String> future = executor.submit(task); executor.submit(() -> { try { Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } future.cancel(true); }); FutureUtils.wait("Test cancelled", future, 3); }