SchedulerImpl implements Scheduler { @Override public ScheduledCompletableFuture<Instant> after(Duration duration) { final Instant start = Instant.now(); return after(() -> start, duration); }  @Override ScheduledCompletableFuture<Instant> after(Duration duration); @Override ScheduledCompletableFuture<T> after(Callable<T> callable, Duration duration); @Override ScheduledCompletableFuture<T> before(CompletableFuture<T> promise, Duration timeout); @Override ScheduledCompletableFuture<Instant> at(Instant instant); @Override ScheduledCompletableFuture<T> at(Callable<T> callable, Instant instant); @Override ScheduledCompletableFuture<T> schedule(SchedulerRunnable runnable, TemporalAdjuster temporalAdjuster);  }
@Test @Timeout(value = 500, unit = TimeUnit.MILLISECONDS) public void testAfterCancelled() throws InterruptedException, InvocationTargetException, ExecutionException { AtomicBoolean check = new AtomicBoolean(); Callable<Boolean> callable = () -> check.getAndSet(true); ScheduledCompletableFuture<Boolean> after = scheduler.after(callable, Duration.ofMillis(200_0000)); after.cancel(true); Thread.sleep(100); assertTrue(after.isCancelled(), "Scheduled job cancelled before timeout"); Thread.sleep(200); assertFalse(check.get(), "Callable method should not been called"); assertThrows(CancellationException.class, () -> after.get()); }
@Test @Timeout(value = 300, unit = TimeUnit.MILLISECONDS) public void testAfterResolved() throws InterruptedException, ExecutionException { AtomicInteger check = new AtomicInteger(); Callable<Integer> callable = () -> { check.set(10); return 5; }; ScheduledCompletableFuture<Integer> after = scheduler.after(callable, Duration.ofMillis(100)); Thread.sleep(200); assertTrue(after.isDone(), "Scheduled job should finish done"); assertEquals(10, check.get(), "After CompletableFuture should return correct value"); assertEquals(5, after.get().intValue(), "After CompletableFuture should return correct value"); }
@Test @Timeout(value = 300, unit = TimeUnit.MILLISECONDS) public void testAfterResolvedWithException() throws Throwable { Callable<Void> callable = () -> { throw new FileNotFoundException("testBeforeTimeoutException"); }; ScheduledCompletableFuture<Void> after = scheduler.after(callable, Duration.ofMillis(100)); Thread.sleep(200); assertTrue(after.isDone(), "Scheduled job should be done"); assertTrue(after.getPromise().isCompletedExceptionally(), "After CompletableFuture should have completed with an exception"); assertThrows(FileNotFoundException.class, () -> { try { after.get(); } catch (ExecutionException e) { throw e.getCause(); } }); }
@Test @Timeout(value = 300, unit = TimeUnit.MILLISECONDS) public void testNegative() throws InterruptedException { Semaphore s = new Semaphore(0); scheduler.after(() -> { s.release(1); return null; }, Duration.ofMillis(-1000)); Thread.sleep(200); assertEquals(1, s.availablePermits(), "Negative value should mean after finished right away"); }
@Test @Timeout(value = 1, unit = TimeUnit.SECONDS) public void testDelay() throws InterruptedException { long duration = 5000; ScheduledCompletableFuture<Instant> future = scheduler.after(Duration.ofMillis(duration)); Thread.sleep(500); long timeLeft = future.getDelay(TimeUnit.MILLISECONDS); long expectedTimeLeft = duration - 450; assertTrue(timeLeft < expectedTimeLeft, "Delay should be less:" + timeLeft + " < " + expectedTimeLeft); future.cancel(true); }
@Test @Timeout(value = 1, unit = TimeUnit.SECONDS) public void testCompareTo() throws InterruptedException { long duration = 5000; ScheduledCompletableFuture<Instant> future1 = scheduler.after(Duration.ofMillis(duration)); Thread.sleep(500); ScheduledCompletableFuture<Instant> future2 = scheduler.after(Duration.ofMillis(duration)); int compare = future1.compareTo(future2); assertTrue(compare < 0, "First future should be less than second"); future1.cancel(true); future2.cancel(true); }