Skip to content

Commit 7b30056

Browse files
committed
Fix race condition in scheduler engine test
This commit addresses a race condition in the scheduler engine test that a listener that throws an exception does not cause other listeners to be skipped. The race here is that we were counting down a latch, and then throwing an exception yet an assertion that expected the exception to have been thrown already could execute after the latch was counted down for the final time but before the exception was thrown and acted upon by the scheduler engine. This commit addresses this by moving the counting down of the latch to definitely be after the exception was acted upon by the scheduler engine.
1 parent 2def06a commit 7b30056

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/scheduler/SchedulerEngineTests.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@
2121
import java.util.concurrent.atomic.AtomicBoolean;
2222
import java.util.concurrent.atomic.AtomicInteger;
2323

24+
import static org.hamcrest.Matchers.any;
2425
import static org.hamcrest.Matchers.arrayWithSize;
2526
import static org.hamcrest.Matchers.equalTo;
2627
import static org.hamcrest.Matchers.instanceOf;
28+
import static org.mockito.Matchers.argThat;
29+
import static org.mockito.Mockito.doAnswer;
2730
import static org.mockito.Mockito.mock;
2831
import static org.mockito.Mockito.times;
2932
import static org.mockito.Mockito.verify;
@@ -39,6 +42,7 @@ public void testListenersThrowingExceptionsDoNotCauseOtherListenersToBeSkipped()
3942
final int numberOfListeners = randomIntBetween(1, 32);
4043
int numberOfFailingListeners = 0;
4144
final CountDownLatch latch = new CountDownLatch(numberOfListeners);
45+
4246
for (int i = 0; i < numberOfListeners; i++) {
4347
final AtomicBoolean trigger = new AtomicBoolean();
4448
final SchedulerEngine.Listener listener;
@@ -54,12 +58,17 @@ public void testListenersThrowingExceptionsDoNotCauseOtherListenersToBeSkipped()
5458
numberOfFailingListeners++;
5559
listener = event -> {
5660
if (trigger.compareAndSet(false, true)) {
57-
latch.countDown();
61+
// we count down the latch after this exception is caught and mock logged in SchedulerEngine#notifyListeners
5862
throw new RuntimeException(getTestName());
5963
} else {
6064
fail("listener invoked twice");
6165
}
6266
};
67+
doAnswer(invocationOnMock -> {
68+
// this happens after the listener has been notified, threw an exception, and then mock logged the exception
69+
latch.countDown();
70+
return null;
71+
}).when(mockLogger).warn(argThat(any(ParameterizedMessage.class)), argThat(any(RuntimeException.class)));
6372
}
6473
listeners.add(Tuple.tuple(listener, trigger));
6574
}
@@ -134,7 +143,7 @@ public void testListenersThrowingExceptionsDoNotCauseNextScheduledTaskToBeSkippe
134143
listenersLatch.await();
135144
assertTrue(listeners.stream().map(Tuple::v2).allMatch(count -> count.get() == numberOfSchedules));
136145
latch.await();
137-
assertFailedListenerLogMessage(mockLogger, numberOfListeners * numberOfSchedules);
146+
assertFailedListenerLogMessage(mockLogger, numberOfSchedules * numberOfListeners);
138147
verifyNoMoreInteractions(mockLogger);
139148
} finally {
140149
engine.stop();

0 commit comments

Comments
 (0)