2020package org .elasticsearch .client ;
2121
2222import java .util .concurrent .TimeUnit ;
23+ import java .util .concurrent .atomic .AtomicLong ;
2324
2425import org .elasticsearch .client .DeadHostState .TimeSupplier ;
2526
2627import static org .hamcrest .MatcherAssert .assertThat ;
2728import static org .hamcrest .Matchers .equalTo ;
2829import static org .hamcrest .Matchers .greaterThan ;
30+ import static org .hamcrest .Matchers .greaterThanOrEqualTo ;
2931import static org .hamcrest .Matchers .is ;
3032import static org .hamcrest .Matchers .lessThan ;
3133import static org .junit .Assert .assertEquals ;
@@ -36,10 +38,9 @@ public class DeadHostStateTests extends RestClientTestCase {
3638 private static long [] EXPECTED_TIMEOUTS_SECONDS = new long []{60 , 84 , 120 , 169 , 240 , 339 , 480 , 678 , 960 , 1357 , 1800 };
3739
3840 public void testInitialDeadHostStateDefaultTimeSupplier () {
39- assumeFalse ("https://github.com/elastic/elasticsearch/issues/33747" , System .getProperty ("os.name" ).startsWith ("Windows" ));
4041 DeadHostState deadHostState = new DeadHostState (DeadHostState .TimeSupplier .DEFAULT );
4142 long currentTime = System .nanoTime ();
42- assertThat (deadHostState .getDeadUntilNanos (), greaterThan (currentTime ));
43+ assertThat (deadHostState .getDeadUntilNanos (), greaterThanOrEqualTo (currentTime ));
4344 assertThat (deadHostState .getFailedAttempts (), equalTo (1 ));
4445 }
4546
@@ -54,13 +55,13 @@ public void testDeadHostStateFromPreviousDefaultTimeSupplier() {
5455 }
5556 }
5657
57- public void testCompareToDefaultTimeSupplier () {
58- assumeFalse ("https://github.com/elastic/elasticsearch/issues/33747" , System .getProperty ("os.name" ).startsWith ("Windows" ));
58+ public void testCompareToTimeSupplier () {
5959 int numObjects = randomIntBetween (EXPECTED_TIMEOUTS_SECONDS .length , 30 );
6060 DeadHostState [] deadHostStates = new DeadHostState [numObjects ];
6161 for (int i = 0 ; i < numObjects ; i ++) {
6262 if (i == 0 ) {
63- deadHostStates [i ] = new DeadHostState (DeadHostState .TimeSupplier .DEFAULT );
63+ // this test requires a strictly increasing timer
64+ deadHostStates [i ] = new DeadHostState (new StrictMonotonicTimeSupplier ());
6465 } else {
6566 deadHostStates [i ] = new DeadHostState (deadHostStates [i - 1 ]);
6667 }
@@ -136,4 +137,23 @@ public String toString() {
136137 return "configured[" + nanoTime + "]" ;
137138 }
138139 }
140+
141+ /**
142+ * Simulates a monotonically strict increasing time (i.e. the value increases on every call to <code>#nanoTime()</code>). This ensures
143+ * that even if we call this time supplier in a very tight loop we always notice time moving forward. This does not happen for real
144+ * timer implementations (e.g. on Linux <code>clock_gettime</code> provides microsecond resolution).
145+ */
146+ static class StrictMonotonicTimeSupplier implements DeadHostState .TimeSupplier {
147+ private final AtomicLong time = new AtomicLong (0 );
148+
149+ @ Override
150+ public long nanoTime () {
151+ return time .incrementAndGet ();
152+ }
153+
154+ @ Override
155+ public String toString () {
156+ return "strict monotonic[" + time .get () + "]" ;
157+ }
158+ }
139159}
0 commit comments