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 bca48b096..b14ce27c9 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,23 @@ */ public class DeterministicScheduler implements ScheduledExecutorService { private final DeltaQueue> deltaQueue = new DeltaQueue>(); - + + private final TimeUnit tickTimeUnit; + + 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 * execution during that time period, and any background tasks spawned by the @@ -210,7 +227,7 @@ public boolean repeats() { } public long getDelay(TimeUnit unit) { - return unit.convert(deltaQueue.delay(this), TimeUnit.MILLISECONDS); + return unit.convert(deltaQueue.delay(this), tickTimeUnit); } public int compareTo(Delayed o) { @@ -258,7 +275,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 56846dabf..b7871bc0e 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();