Просмотр исходного кода

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
Jason Tedor 9 лет назад
Родитель
Сommit
3d329e3ba0

+ 8 - 0
core/src/main/java/org/elasticsearch/common/util/concurrent/PrioritizedRunnable.java

@@ -51,6 +51,14 @@ public abstract class PrioritizedRunnable implements Runnable, Comparable<Priori
         return creationDate;
     }
 
+    /**
+     * The elapsed time in milliseconds since this instance was created,
+     * as calculated by the difference between {@link System#nanoTime()}
+     * at the time of creation, and {@link System#nanoTime()} at the
+     * time of invocation of this method
+     *
+     * @return the age in milliseconds calculated
+     */
     public long getAgeInMillis() {
         return TimeUnit.MILLISECONDS.convert(relativeTimeProvider.getAsLong() - creationDate, TimeUnit.NANOSECONDS);
     }

+ 27 - 1
core/src/test/java/org/elasticsearch/common/util/concurrent/PrioritizedRunnableTests.java

@@ -25,14 +25,17 @@ import org.elasticsearch.test.ESTestCase;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
 
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+
 public class PrioritizedRunnableTests extends ESTestCase {
+
+    // test unit conversion with a controlled clock
     public void testGetAgeInMillis() throws Exception {
         AtomicLong time = new AtomicLong();
 
         PrioritizedRunnable runnable = new PrioritizedRunnable(Priority.NORMAL, time::get) {
             @Override
             public void run() {
-
             }
         };
         assertEquals(0, runnable.getAgeInMillis());
@@ -40,4 +43,27 @@ public class PrioritizedRunnableTests extends ESTestCase {
         time.addAndGet(TimeUnit.NANOSECONDS.convert(milliseconds, TimeUnit.MILLISECONDS));
         assertEquals(milliseconds, runnable.getAgeInMillis());
     }
+
+    // test age advances with System#nanoTime
+    public void testGetAgeInMillisWithRealClock() throws InterruptedException {
+        long nanosecondsInMillisecond = TimeUnit.NANOSECONDS.convert(1, TimeUnit.MILLISECONDS);
+        PrioritizedRunnable runnable = new PrioritizedRunnable(Priority.NORMAL) {
+            @Override
+            public void run() {
+            }
+        };
+
+        // force at least one millisecond to elapse, but ensure the
+        // clock has enough resolution to observe the passage of time
+        long start = System.nanoTime();
+        long elapsed;
+        while ((elapsed = (System.nanoTime() - start)) < nanosecondsInMillisecond) {
+            // busy spin
+        }
+
+        // creation happened before start, so age will be at least as
+        // large as elapsed
+        assertThat(runnable.getAgeInMillis(), greaterThanOrEqualTo(TimeUnit.MILLISECONDS.convert(elapsed, TimeUnit.NANOSECONDS)));
+    }
+
 }