Skip to content

Commit 7e2c7a3

Browse files
committed
DeterministicScheduler supports customizable tick precision
This change adds a constructor which takes a TimeUnit for custom precision, but does not modify the default constructor in order to avoid breaking existing tests which could overflow a long using very long periods of time.
1 parent 60addb0 commit 7e2c7a3

File tree

2 files changed

+33
-3
lines changed

2 files changed

+33
-3
lines changed

jmock/src/main/java/org/jmock/lib/concurrent/DeterministicScheduler.java

+20-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.Collection;
44
import java.util.List;
5+
import java.util.Objects;
56
import java.util.concurrent.Callable;
67
import java.util.concurrent.Delayed;
78
import java.util.concurrent.ExecutionException;
@@ -27,7 +28,23 @@
2728
*/
2829
public class DeterministicScheduler implements ScheduledExecutorService {
2930
private final DeltaQueue<ScheduledTask<?>> deltaQueue = new DeltaQueue<ScheduledTask<?>>();
30-
31+
32+
private final TimeUnit tickTimeUnit;
33+
34+
public DeterministicScheduler() {
35+
this(TimeUnit.MILLISECONDS);
36+
}
37+
38+
/**
39+
* A {@link TimeUnit} may be provided for custom tick precision. This can be helpful when operating
40+
* with nanosecond or microsecond precision.
41+
*
42+
* @param tickTimeUnit Time unit to use for ticks.
43+
*/
44+
public DeterministicScheduler(TimeUnit tickTimeUnit) {
45+
this.tickTimeUnit = Objects.requireNonNull(tickTimeUnit, "TimeUnit is required");
46+
}
47+
3148
/**
3249
* Runs time forwards by a given duration, executing any commands scheduled for
3350
* execution during that time period, and any background tasks spawned by the
@@ -210,7 +227,7 @@ public boolean repeats() {
210227
}
211228

212229
public long getDelay(TimeUnit unit) {
213-
return unit.convert(deltaQueue.delay(this), TimeUnit.MILLISECONDS);
230+
return unit.convert(deltaQueue.delay(this), tickTimeUnit);
214231
}
215232

216233
public int compareTo(Delayed o) {
@@ -258,7 +275,7 @@ public void run() {
258275
}
259276

260277
private long toTicks(long duration, TimeUnit timeUnit) {
261-
return TimeUnit.MILLISECONDS.convert(duration, timeUnit);
278+
return tickTimeUnit.convert(duration, timeUnit);
262279
}
263280

264281
private UnsupportedSynchronousOperationException blockingOperationsNotSupported() {

jmock/src/test/java/org/jmock/test/unit/lib/concurrent/DeterministicSchedulerTests.java

+13
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,19 @@ public void testGetDelayWithManyScheduledTasks() throws Exception {
135135
assertEquals(10, task3.getDelay(TimeUnit.SECONDS));
136136
}
137137

138+
public void testGetDelayWithManyScheduledTasksWithMicrosecondPrecision() throws Exception {
139+
DeterministicScheduler microsecondScheduler = new DeterministicScheduler(TimeUnit.MICROSECONDS);
140+
ScheduledFuture<?> task1 = microsecondScheduler.schedule(commandA, 10, TimeUnit.MICROSECONDS);
141+
ScheduledFuture<?> task2 = microsecondScheduler.schedule(commandA, 20, TimeUnit.MICROSECONDS);
142+
ScheduledFuture<?> task3 = microsecondScheduler.schedule(commandA, 15, TimeUnit.MICROSECONDS);
143+
144+
microsecondScheduler.tick(5, TimeUnit.MICROSECONDS);
145+
146+
assertEquals(5, task1.getDelay(TimeUnit.MICROSECONDS));
147+
assertEquals(15, task2.getDelay(TimeUnit.MICROSECONDS));
148+
assertEquals(10, task3.getDelay(TimeUnit.MICROSECONDS));
149+
}
150+
138151
public void testGetDelayOnPassedTasks() throws Exception {
139152
final Throwable thrown = new IllegalStateException();
140153

0 commit comments

Comments
 (0)