Skip to content

Commit

Permalink
INT-4088 ZookeeperLeaderTests: fix race condition
Browse files Browse the repository at this point in the history
Two initiators for the same path, same `SmartLifecycleRoleController` and, finally, same `adapter`.
So, one initiator after `yield()` stops the `adapter` and at the same time another starts it.

Since there is no barrier in between events and assertion, we end up with an early "re-granting".

* Add `CountDownLatch yieldBarrier` to `countDown()` after performing second `adapter.isRunning()` assert
* `LeaderEventPublisher` waits for the `yieldBarrier` after the first `OnRevokedEvent`
  • Loading branch information
artembilan committed Mar 11, 2017
1 parent 8036a4b commit 823885b
Showing 1 changed file with 17 additions and 0 deletions.
Expand Up @@ -24,6 +24,7 @@

import java.util.Collections;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

Expand Down Expand Up @@ -62,6 +63,8 @@ public class ZookeeperLeaderTests extends ZookeeperTestSupport {
private final SmartLifecycleRoleController controller = new SmartLifecycleRoleController(
Collections.singletonList("sitest"), Collections.<SmartLifecycle>singletonList(this.adapter));

private final CountDownLatch yieldBarrier = new CountDownLatch(1);

@Test
public void testLeader() throws Exception {
assertFalse(this.adapter.isRunning());
Expand All @@ -87,6 +90,8 @@ public void testLeader() throws Exception {

assertFalse(this.adapter.isRunning());

this.yieldBarrier.countDown();

event = this.events.poll(30, TimeUnit.SECONDS);
assertNotNull(event);
assertThat(event, instanceOf(OnGrantedEvent.class));
Expand All @@ -105,13 +110,25 @@ public void testLeader() throws Exception {
private LeaderEventPublisher publisher() {
return new DefaultLeaderEventPublisher(new ApplicationEventPublisher() {

volatile boolean onRevokedEventHappened;

@Override
public void publishEvent(Object event) {
}

@Override
public void publishEvent(ApplicationEvent event) {
AbstractLeaderEvent leadershipEvent = (AbstractLeaderEvent) event;
if (this.onRevokedEventHappened) {
try {
yieldBarrier.await(10, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
}
onRevokedEventHappened = event instanceof OnRevokedEvent;
controller.onApplicationEvent((AbstractLeaderEvent) event);
events.add(leadershipEvent);
}
Expand Down

0 comments on commit 823885b

Please sign in to comment.