diff --git a/jmock/src/main/java/org/jmock/lib/concurrent/DeterministicScheduler.java b/jmock/src/main/java/org/jmock/lib/concurrent/DeterministicScheduler.java index 61942640..529683b5 100644 --- a/jmock/src/main/java/org/jmock/lib/concurrent/DeterministicScheduler.java +++ b/jmock/src/main/java/org/jmock/lib/concurrent/DeterministicScheduler.java @@ -2,6 +2,7 @@ import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.concurrent.Callable; import java.util.concurrent.Delayed; import java.util.concurrent.ExecutionException; @@ -27,7 +28,22 @@ */ public class DeterministicScheduler implements ScheduledExecutorService { private final DeltaQueue> deltaQueue = new DeltaQueue>(); + private final TimeUnit tickTimeUnit; private long passedTicks = 0; + + public DeterministicScheduler() { + this(TimeUnit.MILLISECONDS); + } + + /** + * A {@link TimeUnit} may be provided for custom tick precision. This can be helpful when operating + * with nanosecond or microsecond precision. + * + * @param tickTimeUnit Time unit to use for ticks. + */ + public DeterministicScheduler(TimeUnit tickTimeUnit) { + this.tickTimeUnit = Objects.requireNonNull(tickTimeUnit, "TimeUnit is required"); + } /** * Runs time forwards by a given duration, executing any commands scheduled for @@ -219,7 +235,7 @@ public long getDelay(TimeUnit unit) { if (delay == null) { delay = ranAtTicks - passedTicks; } - return unit.convert(delay, TimeUnit.MILLISECONDS); + return unit.convert(delay, tickTimeUnit); } public int compareTo(Delayed o) { @@ -269,7 +285,7 @@ public void run() { } private long toTicks(long duration, TimeUnit timeUnit) { - return TimeUnit.MILLISECONDS.convert(duration, timeUnit); + return tickTimeUnit.convert(duration, timeUnit); } private UnsupportedSynchronousOperationException blockingOperationsNotSupported() { diff --git a/jmock/src/test/java/org/jmock/test/unit/lib/concurrent/DeterministicSchedulerTests.java b/jmock/src/test/java/org/jmock/test/unit/lib/concurrent/DeterministicSchedulerTests.java index 9b201505..96138691 100644 --- a/jmock/src/test/java/org/jmock/test/unit/lib/concurrent/DeterministicSchedulerTests.java +++ b/jmock/src/test/java/org/jmock/test/unit/lib/concurrent/DeterministicSchedulerTests.java @@ -135,6 +135,19 @@ public void testGetDelayWithManyScheduledTasks() throws Exception { assertEquals(10, task3.getDelay(TimeUnit.SECONDS)); } + public void testGetDelayWithManyScheduledTasksWithMicrosecondPrecision() throws Exception { + DeterministicScheduler microsecondScheduler = new DeterministicScheduler(TimeUnit.MICROSECONDS); + ScheduledFuture task1 = microsecondScheduler.schedule(commandA, 10, TimeUnit.MICROSECONDS); + ScheduledFuture task2 = microsecondScheduler.schedule(commandA, 20, TimeUnit.MICROSECONDS); + ScheduledFuture task3 = microsecondScheduler.schedule(commandA, 15, TimeUnit.MICROSECONDS); + + microsecondScheduler.tick(5, TimeUnit.MICROSECONDS); + + assertEquals(5, task1.getDelay(TimeUnit.MICROSECONDS)); + assertEquals(15, task2.getDelay(TimeUnit.MICROSECONDS)); + assertEquals(10, task3.getDelay(TimeUnit.MICROSECONDS)); + } + public void testGetDelayOnPassedTasks() throws Exception { final Throwable thrown = new IllegalStateException();