Browse Source

ZOOKEEPER-3269: Add queueEvent to the Testable facade

Add queueEvent to the Testable facade to enabled inserting events into the clients queue.

For testing and other reasons it would be very useful to add a way to inject an event into ZooKeeper's event queue. ZooKeeper already has the Testable for features such as this (low level, backdoor, testing, etc.). This queueEvent method would be particularly helpful to Apache Curator and we'd very much appreciate its inclusion.

Author: randgalt <jordan@jordanzimmerman.com>

Reviewers: andor@apache.org

Closes #799 from Randgalt/ZOOKEEPER-3269 and squashes the following commits:

0e3ab80a0 [randgalt] ZOOKEEPER-3269 - use explicit imports
f77574be1 [randgalt] ZOOKEEPER-3269 remove IDE introduced spacing changes
8b5222daf [randgalt] ZOOKEEPER-3269
randgalt 6 years ago
parent
commit
f0f75d8108

+ 7 - 0
zookeeper-server/src/main/java/org/apache/zookeeper/Testable.java

@@ -26,4 +26,11 @@ public interface Testable {
      * Cause the ZooKeeper instance to behave as if the session expired
      */
     void injectSessionExpiration();
+
+    /**
+     * Allow an event to be inserted into the event queue
+     *
+     * @param event event to insert
+     */
+    void queueEvent(WatchedEvent event);
 }

+ 1 - 1
zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeper.java

@@ -1236,7 +1236,7 @@ public class ZooKeeper implements AutoCloseable {
 
     // VisibleForTesting
     public Testable getTestable() {
-        return new ZooKeeperTestable(this, cnxn);
+        return new ZooKeeperTestable(cnxn);
     }
 
     /* Useful for testing watch handling behavior */

+ 7 - 3
zookeeper-server/src/main/java/org/apache/zookeeper/ZooKeeperTestable.java

@@ -25,11 +25,9 @@ class ZooKeeperTestable implements Testable {
     private static final Logger LOG = LoggerFactory
             .getLogger(ZooKeeperTestable.class);
 
-    private final ZooKeeper zooKeeper;
     private final ClientCnxn clientCnxn;
 
-    ZooKeeperTestable(ZooKeeper zooKeeper, ClientCnxn clientCnxn) {
-        this.zooKeeper = zooKeeper;
+    ZooKeeperTestable(ClientCnxn clientCnxn) {
         this.clientCnxn = clientCnxn;
     }
 
@@ -44,4 +42,10 @@ class ZooKeeperTestable implements Testable {
         clientCnxn.state = ZooKeeper.States.CLOSED;
         clientCnxn.sendThread.getClientCnxnSocket().onClosing();
     }
+
+    @Override
+    public void queueEvent(WatchedEvent event) {
+        LOG.info("queueEvent() called: {}", event);
+        clientCnxn.eventThread.queueEvent(event);
+    }
 }

+ 22 - 3
zookeeper-server/src/test/java/org/apache/zookeeper/test/SessionTimeoutTest.java

@@ -24,15 +24,12 @@ import org.apache.zookeeper.TestableZooKeeper;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.Watcher;
 import org.apache.zookeeper.ZooDefs;
-import org.apache.zookeeper.ZooKeeper;
-import org.apache.zookeeper.data.Stat;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
 import java.io.IOException;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -79,6 +76,28 @@ public class SessionTimeoutTest extends ClientBase {
         Assert.assertTrue(gotException);
     }
 
+    @Test
+    public void testQueueEvent() throws InterruptedException,
+            KeeperException {
+        final CountDownLatch eventLatch = new CountDownLatch(1);
+        Watcher watcher = new Watcher() {
+            @Override
+            public void process(WatchedEvent event) {
+                if ( event.getType() == Event.EventType.NodeDataChanged ) {
+                    if ( event.getPath().equals("/foo/bar") ) {
+                        eventLatch.countDown();
+                    }
+                }
+            }
+        };
+        zk.exists("/foo/bar", watcher);
+
+        WatchedEvent event = new WatchedEvent(Watcher.Event.EventType.NodeDataChanged,
+                Watcher.Event.KeeperState.SyncConnected, "/foo/bar");
+        zk.getTestable().queueEvent(event);
+        Assert.assertTrue(eventLatch.await(5, TimeUnit.SECONDS));
+    }
+
     /**
      * Make sure ephemerals get cleaned up when session disconnects.
      */