RepeatingRunnable implements Runnable { public static Cancelable startIn(double delay, double period, String description, Consumer<Double> timeConsumingAction, EventScheduler eventScheduler) { return startAt(eventScheduler.getTimeProvider().getTime() + delay, period, description, timeConsumingAction, eventScheduler); } private  RepeatingRunnable(
            double time,
            double period,
            String description,
            Consumer<Double> timeConsumingAction,
            EventScheduler eventScheduler,
            boolean isDaemon,
            AtomicBoolean canceled,
            boolean fixedDelay); static Cancelable startIn(double delay, double period, String description, Consumer<Double> timeConsumingAction, EventScheduler eventScheduler); static Cancelable startAt(double time, double period, String description, Consumer<Double> timeConsumingAction, EventScheduler eventScheduler); static Cancelable startAtDaemon(double time, double period, String description, Runnable r, EventScheduler eventScheduler); static Cancelable startAtDaemon(double time, double period, String description, Consumer<Double> timeConsumingAction, EventScheduler eventScheduler); static Cancelable startInDaemon(double delay, double period, String description, Runnable r, EventScheduler eventScheduler); static Cancelable startInDaemon(double delay, double period, String description, Consumer<Double> timeConsumingAction, EventScheduler eventScheduler); static Cancelable startInWithFixedDelay(double delay, double period, String description, Consumer<Double> timeConsumingAction, EventScheduler eventScheduler); static Cancelable startAtWithFixedDelay(double time, double period, String description, Consumer<Double> timeConsumingAction, EventScheduler eventScheduler); static Cancelable startAtDaemonWithFixedDelay(double time, double period, String description, Runnable r, EventScheduler eventScheduler); static Cancelable startAtDaemonWithFixedDelay(double time, double period, String description, Consumer<Double> timeConsumingAction, EventScheduler eventScheduler); static Cancelable startInDaemonWithFixedDelay(double delay, double period, String description, Runnable r, EventScheduler eventScheduler); static Cancelable startInDaemonWithFixedDelay(double delay, double period, String description, Consumer<Double> timeConsumingAction, EventScheduler eventScheduler); @Override void run();  }
@Test public void whenCancelled_thenRunnableDoesNotRunAgain() { ArrayList<Double> executionTimes = new ArrayList<>(); simpleDiscreteEventScheduler.pause(); Cancelable cancelable = RepeatingRunnable.startIn(0, 1, "Test Event", executionTimes::add, simpleDiscreteEventScheduler); simpleDiscreteEventScheduler.doAt(10, cancelable::cancel); simpleDiscreteEventScheduler.doAt(100, simpleDiscreteEventScheduler::stop); simpleDiscreteEventScheduler.unPause(); Assertions.assertEquals(10, executionTimes.size()); }
@Test public void whenRunnableIsNotADamonEvent_theSchedulerKnowsItDoesNotHaveOnlyDamonEvents() { simpleDiscreteEventScheduler.pause(); RepeatingRunnable.startIn(0, 1, "Test Event", time -> {}, simpleDiscreteEventScheduler); simpleDiscreteEventScheduler.doAt(20, () -> Preconditions.checkState(!simpleDiscreteEventScheduler.hasOnlyDaemonEvents())); simpleDiscreteEventScheduler.doAtDaemon(100, simpleDiscreteEventScheduler::stop, "Shutdown Event"); simpleDiscreteEventScheduler.unPause(); Assertions.assertNull(exceptionSwallowingEventExecutor.getFirstExceptionEncountered()); }