Skip to content

Commit 3d329e3

Browse files
committed
Add real clock test for age of PrioritizedRunnable
This commit adds a test for calculating the age of PrioritizedRunnable that allows real clock time to elapse. The test ensures that at least one millisecond has passed, and that the resolution of System#nanoTime on the underlying system is actually able to detect this. Relates #15995
1 parent b4538a5 commit 3d329e3

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

core/src/main/java/org/elasticsearch/common/util/concurrent/PrioritizedRunnable.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ public long getCreationDateInNanos() {
5151
return creationDate;
5252
}
5353

54+
/**
55+
* The elapsed time in milliseconds since this instance was created,
56+
* as calculated by the difference between {@link System#nanoTime()}
57+
* at the time of creation, and {@link System#nanoTime()} at the
58+
* time of invocation of this method
59+
*
60+
* @return the age in milliseconds calculated
61+
*/
5462
public long getAgeInMillis() {
5563
return TimeUnit.MILLISECONDS.convert(relativeTimeProvider.getAsLong() - creationDate, TimeUnit.NANOSECONDS);
5664
}

core/src/test/java/org/elasticsearch/common/util/concurrent/PrioritizedRunnableTests.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,45 @@
2525
import java.util.concurrent.TimeUnit;
2626
import java.util.concurrent.atomic.AtomicLong;
2727

28+
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
29+
2830
public class PrioritizedRunnableTests extends ESTestCase {
31+
32+
// test unit conversion with a controlled clock
2933
public void testGetAgeInMillis() throws Exception {
3034
AtomicLong time = new AtomicLong();
3135

3236
PrioritizedRunnable runnable = new PrioritizedRunnable(Priority.NORMAL, time::get) {
3337
@Override
3438
public void run() {
35-
3639
}
3740
};
3841
assertEquals(0, runnable.getAgeInMillis());
3942
int milliseconds = randomIntBetween(1, 256);
4043
time.addAndGet(TimeUnit.NANOSECONDS.convert(milliseconds, TimeUnit.MILLISECONDS));
4144
assertEquals(milliseconds, runnable.getAgeInMillis());
4245
}
46+
47+
// test age advances with System#nanoTime
48+
public void testGetAgeInMillisWithRealClock() throws InterruptedException {
49+
long nanosecondsInMillisecond = TimeUnit.NANOSECONDS.convert(1, TimeUnit.MILLISECONDS);
50+
PrioritizedRunnable runnable = new PrioritizedRunnable(Priority.NORMAL) {
51+
@Override
52+
public void run() {
53+
}
54+
};
55+
56+
// force at least one millisecond to elapse, but ensure the
57+
// clock has enough resolution to observe the passage of time
58+
long start = System.nanoTime();
59+
long elapsed;
60+
while ((elapsed = (System.nanoTime() - start)) < nanosecondsInMillisecond) {
61+
// busy spin
62+
}
63+
64+
// creation happened before start, so age will be at least as
65+
// large as elapsed
66+
assertThat(runnable.getAgeInMillis(), greaterThanOrEqualTo(TimeUnit.MILLISECONDS.convert(elapsed, TimeUnit.NANOSECONDS)));
67+
}
68+
4369
}

0 commit comments

Comments
 (0)