zookeeper-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From an...@apache.org
Subject [06/51] [partial] zookeeper git commit: ZOOKEEPER-3032: MAVEN MIGRATION - branch-3.5 - zookeeper-server
Date Wed, 24 Oct 2018 09:31:01 GMT
http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-server/src/test/java/org/apache/zookeeper/test/FourLetterWordsQuorumTest.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/FourLetterWordsQuorumTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/FourLetterWordsQuorumTest.java
new file mode 100644
index 0000000..28fbde5
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/FourLetterWordsQuorumTest.java
@@ -0,0 +1,119 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.test;
+
+import java.io.IOException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.zookeeper.TestableZooKeeper;
+import org.apache.zookeeper.common.X509Exception.SSLContextException;
+
+import static org.apache.zookeeper.client.FourLetterWordMain.send4LetterWord;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class FourLetterWordsQuorumTest extends QuorumBase {
+    protected static final Logger LOG =
+        LoggerFactory.getLogger(FourLetterWordsQuorumTest.class);
+
+    /** Test the various four letter words */
+    @Test
+    public void testFourLetterWords() throws Exception {
+        String servers[] = hostPort.split(",");
+        for (String hp : servers) {
+            verify(hp, "ruok", "imok");
+            verify(hp, "envi", "java.version");
+            verify(hp, "conf", "clientPort");
+            verify(hp, "stat", "Outstanding");
+            verify(hp, "srvr", "Outstanding");
+            verify(hp, "cons", "queued");
+            verify(hp, "dump", "Session");
+            verify(hp, "wchs", "watches");
+            verify(hp, "wchp", "");
+            verify(hp, "wchc", "");
+
+            verify(hp, "srst", "reset");
+            verify(hp, "crst", "reset");
+
+            verify(hp, "stat", "Outstanding");
+            verify(hp, "srvr", "Outstanding");
+            verify(hp, "cons", "queued");
+
+            TestableZooKeeper zk = createClient(hp);
+            String sid = getHexSessionId(zk.getSessionId());
+
+            verify(hp, "stat", "queued");
+            verify(hp, "srvr", "Outstanding");
+            verify(hp, "cons", sid);
+            verify(hp, "dump", sid);
+            verify(hp, "dirs", "size");
+
+            zk.getData("/", true, null);
+
+            verify(hp, "stat", "queued");
+            verify(hp, "srvr", "Outstanding");
+            verify(hp, "cons", sid);
+            verify(hp, "dump", sid);
+            verify(hp, "wchs", "watching 1");
+            verify(hp, "wchp", sid);
+            verify(hp, "wchc", sid);
+            verify(hp, "dirs", "size");
+
+            zk.close();
+
+            verify(hp, "ruok", "imok");
+            verify(hp, "envi", "java.version");
+            verify(hp, "conf", "clientPort");
+            verify(hp, "stat", "Outstanding");
+            verify(hp, "srvr", "Outstanding");
+            verify(hp, "cons", "queued");
+            verify(hp, "dump", "Session");
+            verify(hp, "wchs", "watch");
+            verify(hp, "wchp", "");
+            verify(hp, "wchc", "");
+            verify(hp, "dirs", "size");
+
+            verify(hp, "srst", "reset");
+            verify(hp, "crst", "reset");
+
+            verify(hp, "stat", "Outstanding");
+            verify(hp, "srvr", "Outstanding");
+            verify(hp, "cons", "queued");
+
+            verify(hp, "mntr", "zk_version\t");
+        }
+    }
+
+    private void verify(String hp, String cmd, String expected)
+        throws IOException, SSLContextException
+    {
+        for(HostPort hpobj: parseHostPortList(hp)) {
+            String resp = send4LetterWord(hpobj.host, hpobj.port, cmd);
+            LOG.info("cmd " + cmd + " expected " + expected + " got " + resp);
+            if (cmd.equals("dump")) {
+                Assert.assertTrue(resp.contains(expected)
+                        || resp.contains("Sessions with Ephemerals"));
+            } else {
+                Assert.assertTrue(resp.contains(expected));
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-server/src/test/java/org/apache/zookeeper/test/FourLetterWordsTest.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/FourLetterWordsTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/FourLetterWordsTest.java
new file mode 100644
index 0000000..ad71eab
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/FourLetterWordsTest.java
@@ -0,0 +1,245 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.test;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.regex.Pattern;
+
+import org.apache.zookeeper.TestableZooKeeper;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.common.IOUtils;
+import org.apache.zookeeper.common.X509Exception.SSLContextException;
+
+import static org.apache.zookeeper.client.FourLetterWordMain.send4LetterWord;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.Timeout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FourLetterWordsTest extends ClientBase {
+    protected static final Logger LOG =
+        LoggerFactory.getLogger(FourLetterWordsTest.class);
+
+    @Rule
+    public Timeout timeout = new Timeout(30000);
+
+    /** Test the various four letter words */
+    @Test
+    public void testFourLetterWords() throws Exception {
+        verify("ruok", "imok");
+        verify("envi", "java.version");
+        verify("conf", "clientPort");
+        verify("stat", "Outstanding");
+        verify("srvr", "Outstanding");
+        verify("cons", "queued");
+        verify("dump", "Session");
+        verify("wchs", "watches");
+        verify("wchp", "");
+        verify("wchc", "");
+
+        verify("srst", "reset");
+        verify("crst", "reset");
+
+        verify("stat", "Outstanding");
+        verify("srvr", "Outstanding");
+        verify("cons", "queued");
+        verify("gtmk", "306");
+        verify("isro", "rw");
+
+        TestableZooKeeper zk = createClient();
+        String sid = getHexSessionId(zk.getSessionId());
+
+        verify("stat", "queued");
+        verify("srvr", "Outstanding");
+        verify("cons", sid);
+        verify("dump", sid);
+        verify("dirs", "size");
+
+        zk.getData("/", true, null);
+
+        verify("stat", "queued");
+        verify("srvr", "Outstanding");
+        verify("cons", sid);
+        verify("dump", sid);
+
+        verify("wchs", "watching 1");
+        verify("wchp", sid);
+        verify("wchc", sid);
+        verify("dirs", "size");
+        zk.close();
+
+        verify("ruok", "imok");
+        verify("envi", "java.version");
+        verify("conf", "clientPort");
+        verify("stat", "Outstanding");
+        verify("srvr", "Outstanding");
+        verify("cons", "queued");
+        verify("dump", "Session");
+        verify("wchs", "watch");
+        verify("wchp", "");
+        verify("wchc", "");
+
+        verify("srst", "reset");
+        verify("crst", "reset");
+
+        verify("stat", "Outstanding");
+        verify("srvr", "Outstanding");
+        verify("cons", "queued");
+        verify("mntr", "zk_server_state\tstandalone");
+        verify("mntr", "num_alive_connections");
+        verify("stat", "Connections");
+        verify("srvr", "Connections");
+        verify("dirs", "size");
+    }
+
+    private String sendRequest(String cmd) throws IOException, SSLContextException {
+      HostPort hpobj = ClientBase.parseHostPortList(hostPort).get(0);
+      return send4LetterWord(hpobj.host, hpobj.port, cmd);
+    }
+    private String sendRequest(String cmd, int timeout) throws IOException, SSLContextException {
+        HostPort hpobj = ClientBase.parseHostPortList(hostPort).get(0);
+        return send4LetterWord(hpobj.host, hpobj.port, cmd, false, timeout);
+      }
+
+    private void verify(String cmd, String expected) throws IOException, SSLContextException {
+        String resp = sendRequest(cmd);
+        LOG.info("cmd " + cmd + " expected " + expected + " got " + resp);
+        Assert.assertTrue(resp.contains(expected));
+    }
+    
+    @Test
+    public void testValidateStatOutput() throws Exception {
+        ZooKeeper zk1 = createClient();
+        ZooKeeper zk2 = createClient();
+        
+        String resp = sendRequest("stat");
+        BufferedReader in = new BufferedReader(new StringReader(resp));
+
+        String line;
+        // first line should be version info
+        line = in.readLine();
+        Assert.assertTrue(Pattern.matches("^.*\\s\\d+\\.\\d+\\.\\d+-.*$", line));
+        Assert.assertTrue(Pattern.matches("^Clients:$", in.readLine()));
+
+        int count = 0;
+        while ((line = in.readLine()).length() > 0) {
+            count++;
+            Assert.assertTrue(Pattern.matches("^ /.*:\\d+\\[\\d+\\]\\(queued=\\d+,recved=\\d+,sent=\\d+\\)$", line));
+        }
+        // ensure at least the two clients we created are accounted for
+        Assert.assertTrue(count >= 2);
+
+        line = in.readLine();
+        Assert.assertTrue(Pattern.matches("^Latency min/avg/max: \\d+/\\d+/\\d+$", line));
+        line = in.readLine();
+        Assert.assertTrue(Pattern.matches("^Received: \\d+$", line));
+        line = in.readLine();
+        Assert.assertTrue(Pattern.matches("^Sent: \\d+$", line));
+        line = in.readLine();
+        Assert.assertTrue(Pattern.matches("^Connections: \\d+$", line));
+        line = in.readLine();
+        Assert.assertTrue(Pattern.matches("^Outstanding: \\d+$", line));
+        line = in.readLine();
+        Assert.assertTrue(Pattern.matches("^Zxid: 0x[\\da-fA-F]+$", line));
+        line = in.readLine();
+        Assert.assertTrue(Pattern.matches("^Mode: .*$", line));
+        line = in.readLine();
+        Assert.assertTrue(Pattern.matches("^Node count: \\d+$", line));
+
+        zk1.close();
+        zk2.close();
+    }
+
+    @Test
+    public void testValidateConsOutput() throws Exception {
+        ZooKeeper zk1 = createClient();
+        ZooKeeper zk2 = createClient();
+        
+        String resp = sendRequest("cons");
+        BufferedReader in = new BufferedReader(new StringReader(resp));
+
+        String line;
+        int count = 0;
+        while ((line = in.readLine()) != null && line.length() > 0) {
+            count++;
+            Assert.assertTrue(line, Pattern.matches("^ /.*:\\d+\\[\\d+\\]\\(queued=\\d+,recved=\\d+,sent=\\d+.*\\)$", line));
+        }
+        // ensure at least the two clients we created are accounted for
+        Assert.assertTrue(count >= 2);
+
+        zk1.close();
+        zk2.close();
+    }
+
+    @Test(timeout=60000)
+    public void testValidateSocketTimeout() throws Exception {
+        /**
+         * testing positive scenario that even with timeout parameter the
+         * functionality works fine
+         */
+        String resp = sendRequest("isro", 2000);
+        Assert.assertTrue(resp.contains("rw"));
+    }
+
+    @Test
+    public void testSetTraceMask() throws Exception {
+        String gtmkResp = sendRequest("gtmk");
+        Assert.assertNotNull(gtmkResp);
+        gtmkResp = gtmkResp.trim();
+        Assert.assertFalse(gtmkResp.isEmpty());
+        long formerMask = Long.valueOf(gtmkResp);
+        try {
+            verify(buildSetTraceMaskRequest(0), "0");
+            verify("gtmk", "0");
+        } finally {
+            // Restore former value.
+            sendRequest(buildSetTraceMaskRequest(formerMask));
+        }
+    }
+
+    /**
+     * Builds a SetTraceMask request to be sent to the server, consisting of
+     * "stmk" followed by the 8-byte long representation of the trace mask.
+     *
+     * @param mask trace mask to set
+     * @return built request
+     * @throws IOException if there is an I/O error
+     */
+    private String buildSetTraceMaskRequest(long mask) throws IOException {
+        ByteArrayOutputStream baos = null;
+        DataOutputStream dos = null;
+        try {
+            baos = new ByteArrayOutputStream();
+            dos = new DataOutputStream(baos);
+            dos.writeBytes("stmk");
+            dos.writeLong(mask);
+        } finally {
+            IOUtils.closeStream(dos);
+            IOUtils.closeStream(baos);
+        }
+        return new String(baos.toByteArray());
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-server/src/test/java/org/apache/zookeeper/test/FourLetterWordsWhiteListTest.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/FourLetterWordsWhiteListTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/FourLetterWordsWhiteListTest.java
new file mode 100644
index 0000000..f5d6967
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/FourLetterWordsWhiteListTest.java
@@ -0,0 +1,251 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.test;
+
+import java.io.IOException;
+
+import org.apache.zookeeper.TestableZooKeeper;
+import org.apache.zookeeper.common.X509Exception.SSLContextException;
+
+import static org.apache.zookeeper.client.FourLetterWordMain.send4LetterWord;
+
+import org.apache.zookeeper.server.command.FourLetterCommands;
+import org.junit.Assert;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FourLetterWordsWhiteListTest extends ClientBase {
+    protected static final Logger LOG =
+        LoggerFactory.getLogger(FourLetterWordsWhiteListTest.class);
+
+    /*
+     * ZOOKEEPER-2693: test white list of four letter words.
+     * For 3.5.x default white list is empty. Verify that is
+     * the case (except 'stat' command which is enabled in ClientBase
+     * which other tests depend on.).
+     */
+    @Test(timeout=30000)
+    public void testFourLetterWordsAllDisabledByDefault() throws Exception {
+        stopServer();
+        FourLetterCommands.resetWhiteList();
+        System.setProperty("zookeeper.4lw.commands.whitelist", "stat");
+        startServer();
+
+        // Default white list for 3.5.x is empty, so all command should fail.
+        verifyAllCommandsFail();
+
+        TestableZooKeeper zk = createClient();
+
+        verifyAllCommandsFail();
+
+        zk.getData("/", true, null);
+
+        verifyAllCommandsFail();
+
+        zk.close();
+
+        verifyFuzzyMatch("stat", "Outstanding");
+        verifyAllCommandsFail();
+    }
+
+    @Test(timeout=30000)
+    public void testFourLetterWordsEnableSomeCommands() throws Exception {
+        stopServer();
+        FourLetterCommands.resetWhiteList();
+        System.setProperty("zookeeper.4lw.commands.whitelist", "stat, ruok, isro");
+        startServer();
+        // stat, ruok and isro are white listed.
+        verifyFuzzyMatch("stat", "Outstanding");
+        verifyExactMatch("ruok", "imok");
+        verifyExactMatch("isro", "rw");
+
+        // Rest of commands fail.
+        verifyExactMatch("conf", generateExpectedMessage("conf"));
+        verifyExactMatch("cons", generateExpectedMessage("cons"));
+        verifyExactMatch("crst", generateExpectedMessage("crst"));
+        verifyExactMatch("dirs", generateExpectedMessage("dirs"));
+        verifyExactMatch("dump", generateExpectedMessage("dump"));
+        verifyExactMatch("envi", generateExpectedMessage("envi"));
+        verifyExactMatch("gtmk", generateExpectedMessage("gtmk"));
+        verifyExactMatch("stmk", generateExpectedMessage("stmk"));
+        verifyExactMatch("srst", generateExpectedMessage("srst"));
+        verifyExactMatch("wchc", generateExpectedMessage("wchc"));
+        verifyExactMatch("wchp", generateExpectedMessage("wchp"));
+        verifyExactMatch("wchs", generateExpectedMessage("wchs"));
+        verifyExactMatch("mntr", generateExpectedMessage("mntr"));
+    }
+
+    @Test(timeout=30000)
+    public void testISROEnabledWhenReadOnlyModeEnabled() throws Exception {
+        stopServer();
+        FourLetterCommands.resetWhiteList();
+        System.setProperty("zookeeper.4lw.commands.whitelist", "stat");
+        System.setProperty("readonlymode.enabled", "true");
+        startServer();
+        verifyExactMatch("isro", "rw");
+        System.clearProperty("readonlymode.enabled");
+    }
+
+    @Test(timeout=30000)
+    public void testFourLetterWordsInvalidConfiguration() throws Exception {
+        stopServer();
+        FourLetterCommands.resetWhiteList();
+        System.setProperty("zookeeper.4lw.commands.whitelist", "foo bar" +
+                " foo,,, " +
+                "bar :.,@#$%^&*() , , , , bar, bar, stat,        ");
+        startServer();
+
+        // Just make sure we are good when admin made some mistakes in config file.
+        verifyAllCommandsFail();
+        // But still, what's valid in white list will get through.
+        verifyFuzzyMatch("stat", "Outstanding");
+    }
+
+    @Test(timeout=30000)
+    public void testFourLetterWordsEnableAllCommandsThroughAsterisk() throws Exception {
+        stopServer();
+        FourLetterCommands.resetWhiteList();
+        System.setProperty("zookeeper.4lw.commands.whitelist", "*");
+        startServer();
+        verifyAllCommandsSuccess();
+    }
+
+    @Test(timeout=30000)
+    public void testFourLetterWordsEnableAllCommandsThroughExplicitList() throws Exception {
+        stopServer();
+        FourLetterCommands.resetWhiteList();
+        System.setProperty("zookeeper.4lw.commands.whitelist",
+                "ruok, envi, conf, stat, srvr, cons, dump," +
+                        "wchs, wchp, wchc, srst, crst, " +
+                        "dirs, mntr, gtmk, isro, stmk");
+        startServer();
+        verifyAllCommandsSuccess();
+    }
+
+
+    private void verifyAllCommandsSuccess() throws Exception {
+        verifyExactMatch("ruok", "imok");
+        verifyFuzzyMatch("envi", "java.version");
+        verifyFuzzyMatch("conf", "clientPort");
+        verifyFuzzyMatch("stat", "Outstanding");
+        verifyFuzzyMatch("srvr", "Outstanding");
+        verifyFuzzyMatch("cons", "queued");
+        verifyFuzzyMatch("dump", "Session");
+        verifyFuzzyMatch("wchs", "watches");
+        verifyFuzzyMatch("wchp", "");
+        verifyFuzzyMatch("wchc", "");
+
+        verifyFuzzyMatch("srst", "reset");
+        verifyFuzzyMatch("crst", "reset");
+
+        verifyFuzzyMatch("stat", "Outstanding");
+        verifyFuzzyMatch("srvr", "Outstanding");
+        verifyFuzzyMatch("cons", "queued");
+        verifyFuzzyMatch("gtmk", "306");
+        verifyFuzzyMatch("isro", "rw");
+
+        TestableZooKeeper zk = createClient();
+        String sid = getHexSessionId(zk.getSessionId());
+
+        verifyFuzzyMatch("stat", "queued");
+        verifyFuzzyMatch("srvr", "Outstanding");
+        verifyFuzzyMatch("cons", sid);
+        verifyFuzzyMatch("dump", sid);
+        verifyFuzzyMatch("dirs", "size");
+
+        zk.getData("/", true, null);
+
+        verifyFuzzyMatch("stat", "queued");
+        verifyFuzzyMatch("srvr", "Outstanding");
+        verifyFuzzyMatch("cons", sid);
+        verifyFuzzyMatch("dump", sid);
+
+        verifyFuzzyMatch("wchs", "watching 1");
+        verifyFuzzyMatch("wchp", sid);
+        verifyFuzzyMatch("wchc", sid);
+        verifyFuzzyMatch("dirs", "size");
+        zk.close();
+
+        verifyExactMatch("ruok", "imok");
+        verifyFuzzyMatch("envi", "java.version");
+        verifyFuzzyMatch("conf", "clientPort");
+        verifyFuzzyMatch("stat", "Outstanding");
+        verifyFuzzyMatch("srvr", "Outstanding");
+        verifyFuzzyMatch("cons", "queued");
+        verifyFuzzyMatch("dump", "Session");
+        verifyFuzzyMatch("wchs", "watch");
+        verifyFuzzyMatch("wchp", "");
+        verifyFuzzyMatch("wchc", "");
+
+        verifyFuzzyMatch("srst", "reset");
+        verifyFuzzyMatch("crst", "reset");
+
+        verifyFuzzyMatch("stat", "Outstanding");
+        verifyFuzzyMatch("srvr", "Outstanding");
+        verifyFuzzyMatch("cons", "queued");
+        verifyFuzzyMatch("mntr", "zk_server_state\tstandalone");
+        verifyFuzzyMatch("mntr", "num_alive_connections");
+        verifyFuzzyMatch("stat", "Connections");
+        verifyFuzzyMatch("srvr", "Connections");
+        verifyFuzzyMatch("dirs", "size");
+    }
+
+    private void verifyAllCommandsFail() throws Exception {
+        verifyExactMatch("ruok", generateExpectedMessage("ruok"));
+        verifyExactMatch("conf", generateExpectedMessage("conf"));
+        verifyExactMatch("cons", generateExpectedMessage("cons"));
+        verifyExactMatch("crst", generateExpectedMessage("crst"));
+        verifyExactMatch("dirs", generateExpectedMessage("dirs"));
+        verifyExactMatch("dump", generateExpectedMessage("dump"));
+        verifyExactMatch("envi", generateExpectedMessage("envi"));
+        verifyExactMatch("gtmk", generateExpectedMessage("gtmk"));
+        verifyExactMatch("stmk", generateExpectedMessage("stmk"));
+        verifyExactMatch("srst", generateExpectedMessage("srst"));
+        verifyExactMatch("wchc", generateExpectedMessage("wchc"));
+        verifyExactMatch("wchp", generateExpectedMessage("wchp"));
+        verifyExactMatch("wchs", generateExpectedMessage("wchs"));
+        verifyExactMatch("mntr", generateExpectedMessage("mntr"));
+        verifyExactMatch("isro", generateExpectedMessage("isro"));
+
+        // srvr is enabled by default due to the sad fact zkServer.sh uses it.
+        verifyFuzzyMatch("srvr", "Outstanding");
+    }
+
+    private String sendRequest(String cmd) throws IOException, SSLContextException {
+      HostPort hpobj = ClientBase.parseHostPortList(hostPort).get(0);
+      return send4LetterWord(hpobj.host, hpobj.port, cmd);
+    }
+
+    private void verifyFuzzyMatch(String cmd, String expected) throws IOException, SSLContextException {
+        String resp = sendRequest(cmd);
+        LOG.info("cmd " + cmd + " expected " + expected + " got " + resp);
+        Assert.assertTrue(resp.contains(expected));
+    }
+
+    private String generateExpectedMessage(String command) {
+        return command + " is not executed because it is not in the whitelist.";
+    }
+
+    private void verifyExactMatch(String cmd, String expected) throws IOException, SSLContextException {
+        String resp = sendRequest(cmd);
+        LOG.info("cmd " + cmd + " expected an exact match of " + expected + "; got " + resp);
+        Assert.assertTrue(resp.trim().equals(expected));
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-server/src/test/java/org/apache/zookeeper/test/GetChildren2Test.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/GetChildren2Test.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/GetChildren2Test.java
new file mode 100644
index 0000000..e41fffe
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/GetChildren2Test.java
@@ -0,0 +1,136 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.apache.zookeeper.data.Stat;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class GetChildren2Test extends ClientBase {
+    private ZooKeeper zk;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        zk = createClient();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        super.tearDown();
+
+        zk.close();
+    }
+
+    @Test
+    public void testChild()
+        throws IOException, KeeperException, InterruptedException
+    {
+        String name = "/foo";
+        zk.create(name, name.getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+
+        String childname = name + "/bar";
+        zk.create(childname, childname.getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.EPHEMERAL);
+
+        Stat stat = new Stat();
+        List<String> s = zk.getChildren(name, false, stat);
+
+        Assert.assertEquals(stat.getCzxid(), stat.getMzxid());
+        Assert.assertEquals(stat.getCzxid() + 1, stat.getPzxid());
+        Assert.assertEquals(stat.getCtime(), stat.getMtime());
+        Assert.assertEquals(1, stat.getCversion());
+        Assert.assertEquals(0, stat.getVersion());
+        Assert.assertEquals(0, stat.getAversion());
+        Assert.assertEquals(0, stat.getEphemeralOwner());
+        Assert.assertEquals(name.length(), stat.getDataLength());
+        Assert.assertEquals(1, stat.getNumChildren());
+        Assert.assertEquals(s.size(), stat.getNumChildren());
+
+        s = zk.getChildren(childname, false, stat);
+
+        Assert.assertEquals(stat.getCzxid(), stat.getMzxid());
+        Assert.assertEquals(stat.getCzxid(), stat.getPzxid());
+        Assert.assertEquals(stat.getCtime(), stat.getMtime());
+        Assert.assertEquals(0, stat.getCversion());
+        Assert.assertEquals(0, stat.getVersion());
+        Assert.assertEquals(0, stat.getAversion());
+        Assert.assertEquals(zk.getSessionId(), stat.getEphemeralOwner());
+        Assert.assertEquals(childname.length(), stat.getDataLength());
+        Assert.assertEquals(0, stat.getNumChildren());
+        Assert.assertEquals(s.size(), stat.getNumChildren());
+    }
+
+    @Test
+    public void testChildren()
+        throws IOException, KeeperException, InterruptedException
+    {
+        String name = "/foo";
+        zk.create(name, name.getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+
+        List<String> children = new ArrayList<String>();
+        List<String> children_s = new ArrayList<String>();
+
+        for (int i = 0; i < 10; i++) {
+            String childname = name + "/bar" + i;
+            String childname_s = "bar" + i;
+            children.add(childname);
+            children_s.add(childname_s);
+        }
+
+        for(int i = 0; i < children.size(); i++) {
+            String childname = children.get(i);
+            zk.create(childname, childname.getBytes(), Ids.OPEN_ACL_UNSAFE,
+                    CreateMode.EPHEMERAL);
+
+            Stat stat = new Stat();
+            List<String> s = zk.getChildren(name, false, stat);
+
+            Assert.assertEquals(stat.getCzxid(), stat.getMzxid());
+            Assert.assertEquals(stat.getCzxid() + i + 1, stat.getPzxid());
+            Assert.assertEquals(stat.getCtime(), stat.getMtime());
+            Assert.assertEquals(i + 1, stat.getCversion());
+            Assert.assertEquals(0, stat.getVersion());
+            Assert.assertEquals(0, stat.getAversion());
+            Assert.assertEquals(0, stat.getEphemeralOwner());
+            Assert.assertEquals(name.length(), stat.getDataLength());
+            Assert.assertEquals(i + 1, stat.getNumChildren());
+            Assert.assertEquals(s.size(), stat.getNumChildren());
+        }
+        List<String> p = zk.getChildren(name, false, null);
+        List<String> c_a = children_s;
+        List<String> c_b = p;
+        Collections.sort(c_a);
+        Collections.sort(c_b);
+        Assert.assertEquals(c_a.size(), 10);
+        Assert.assertEquals(c_a, c_b);
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-server/src/test/java/org/apache/zookeeper/test/GetProposalFromTxnTest.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/GetProposalFromTxnTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/GetProposalFromTxnTest.java
new file mode 100644
index 0000000..660980a
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/GetProposalFromTxnTest.java
@@ -0,0 +1,137 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.test;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.apache.jute.Record;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.PortAssignment;
+import org.apache.zookeeper.ZKTestCase;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.apache.zookeeper.ZooDefs.OpCode;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.server.ServerCnxnFactory;
+import org.apache.zookeeper.server.SyncRequestProcessor;
+import org.apache.zookeeper.server.ZKDatabase;
+import org.apache.zookeeper.server.ZooKeeperServer;
+import org.apache.zookeeper.server.quorum.Leader.Proposal;
+import org.apache.zookeeper.server.util.SerializeUtils;
+import org.apache.zookeeper.txn.TxnHeader;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test loading committed proposal from txnlog. Learner uses these proposals to
+ * catch-up with leader
+ */
+public class GetProposalFromTxnTest extends ZKTestCase{
+    private static String HOSTPORT = "127.0.0.1:" + PortAssignment.unique();
+    private static final int CONNECTION_TIMEOUT = 3000;
+
+    private static final int MSG_COUNT = 2000;
+
+    /**
+     * Test loading proposal from txnlog
+     *
+     * @throws Exception
+     *             an exception might be thrown here
+     */
+    @Test
+    public void testGetProposalFromTxn() throws Exception {
+        File tmpDir = ClientBase.createTmpDir();
+        ClientBase.setupTestEnv();
+        ZooKeeperServer zks = new ZooKeeperServer(tmpDir, tmpDir, 3000);
+        SyncRequestProcessor.setSnapCount(100);
+        final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]);
+        ServerCnxnFactory f = ServerCnxnFactory.createFactory(PORT, -1);
+        f.startup(zks);
+        Assert.assertTrue("waiting for server being up ",
+                ClientBase.waitForServerUp(HOSTPORT, CONNECTION_TIMEOUT));
+        ZooKeeper zk = ClientBase.createZKClient(HOSTPORT);
+
+        // Generate transaction so we will have some txnlog
+        Long[] zxids = new Long[MSG_COUNT];
+        try {
+            String data = "data";
+            byte[] bytes = data.getBytes();
+            for (int i = 0; i < MSG_COUNT; i++) {
+                Stat stat = new Stat();
+                zk.create("/invalidsnap-" + i, bytes, Ids.OPEN_ACL_UNSAFE,
+                        CreateMode.PERSISTENT);
+                zk.getData("/invalidsnap-" + i, null, stat);
+                zxids[i] = stat.getCzxid();
+            }
+
+        } finally {
+            zk.close();
+        }
+
+        // shutdown and start zookeeper again
+        f.shutdown();
+        zks.shutdown();
+        Assert.assertTrue("waiting for server to shutdown",
+                ClientBase.waitForServerDown(HOSTPORT, CONNECTION_TIMEOUT));
+        zks = new ZooKeeperServer(tmpDir, tmpDir, 3000);
+        zks.startdata();
+
+        ZKDatabase db = zks.getZKDatabase();
+
+        // Set sizeLimit to be very high number, so we can pull all transactions
+        // from txnlog
+        Iterator<Proposal> itr = db.getProposalsFromTxnLog(zxids[0], 10000000);
+
+        int createCount = 0;
+        ArrayList<Long> retrievedZxids = new ArrayList<Long>(MSG_COUNT);
+
+        // Get zxid of create requests
+        while (itr.hasNext()) {
+            Proposal proposal = itr.next();
+            TxnHeader hdr = new TxnHeader();
+            Record rec = SerializeUtils.deserializeTxn(
+                    proposal.packet.getData(), hdr);
+            if (hdr.getType() == OpCode.create) {
+                retrievedZxids.add(hdr.getZxid());
+                createCount++;
+            }
+        }
+
+        // All zxid should match what we created
+        Assert.assertTrue("Zxids missmatches",
+                Arrays.equals(zxids, retrievedZxids.toArray(new Long[0])));
+
+        // There should be 2000 create requests
+        Assert.assertTrue("create proposal count == " + MSG_COUNT,
+                (createCount == MSG_COUNT));
+
+        // We are requesting half the number of transaction from the snapshot
+        // this should exceed threshold (ZKDatabase.snapshotSizeFactor)
+        db.setSnapshotSizeFactor(0.33);
+        long sizeLimit = db.calculateTxnLogSizeLimit();
+
+        itr = db.getProposalsFromTxnLog(zxids[MSG_COUNT / 2], sizeLimit);
+        Assert.assertFalse("Expect empty proposal", (itr.hasNext()));
+        f.shutdown();
+        zks.shutdown();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-server/src/test/java/org/apache/zookeeper/test/HierarchicalQuorumTest.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/HierarchicalQuorumTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/HierarchicalQuorumTest.java
new file mode 100644
index 0000000..e477c98
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/HierarchicalQuorumTest.java
@@ -0,0 +1,336 @@
+/* Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.zookeeper.PortAssignment;
+import org.apache.zookeeper.TestableZooKeeper;
+import org.apache.zookeeper.jmx.CommonNames;
+import org.apache.zookeeper.server.quorum.QuorumPeer;
+import org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer;
+import org.apache.zookeeper.server.quorum.flexible.QuorumHierarchical;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class HierarchicalQuorumTest extends ClientBase {
+    private static final Logger LOG = LoggerFactory.getLogger(QuorumBase.class);
+
+    File s1dir, s2dir, s3dir, s4dir, s5dir;
+    QuorumPeer s1, s2, s3, s4, s5;
+    protected int port1;
+    protected int port2;
+    protected int port3;
+    protected int port4;
+    protected int port5;
+
+    protected int leport1;
+    protected int leport2;
+    protected int leport3;
+    protected int leport4;
+    protected int leport5;
+
+    protected int clientport1;
+    protected int clientport2;
+    protected int clientport3;
+    protected int clientport4;
+    protected int clientport5;
+    
+    
+    Properties qp;
+    protected final ClientHammerTest cht = new ClientHammerTest();
+    
+    @Override
+    public void setUp() throws Exception {
+        setupTestEnv();
+
+        JMXEnv.setUp();
+
+        setUpAll();
+
+        port1 = PortAssignment.unique();
+        port2 = PortAssignment.unique();
+        port3 = PortAssignment.unique();
+        port4 = PortAssignment.unique();
+        port5 = PortAssignment.unique();
+        leport1 = PortAssignment.unique();
+        leport2 = PortAssignment.unique();
+        leport3 = PortAssignment.unique();
+        leport4 = PortAssignment.unique();
+        leport5 = PortAssignment.unique();
+        clientport1 = PortAssignment.unique();
+        clientport2 = PortAssignment.unique();
+        clientport3 = PortAssignment.unique();
+        clientport4 = PortAssignment.unique();
+        clientport5 = PortAssignment.unique();
+        
+        hostPort = "127.0.0.1:" + clientport1 
+            + ",127.0.0.1:" + clientport2 
+            + ",127.0.0.1:" + clientport3 
+            + ",127.0.0.1:" + clientport4 
+            + ",127.0.0.1:" + clientport5;
+        LOG.info("Ports are: " + hostPort);
+
+        s1dir = ClientBase.createTmpDir();
+        s2dir = ClientBase.createTmpDir();
+        s3dir = ClientBase.createTmpDir();
+        s4dir = ClientBase.createTmpDir();
+        s5dir = ClientBase.createTmpDir();
+
+        String config = "group.1=1:2:3\n" +
+        "group.2=4:5\n" +
+        "weight.1=1\n" +
+        "weight.2=1\n" +
+        "weight.3=1\n" +
+        "weight.4=0\n" +
+        "weight.5=0\n" +
+        "server.1=127.0.0.1:" + port1 + ":" + leport1 + ";" + clientport1 + "\n" +
+        "server.2=127.0.0.1:" + port2 + ":" + leport2 + ";" + clientport2 + "\n" +
+        "server.3=127.0.0.1:" + port3 + ":" + leport3 + ";" + clientport3 + "\n" +
+        "server.4=127.0.0.1:" + port4 + ":" + leport4 + ";" + clientport4 + "\n" +
+        "server.5=127.0.0.1:" + port5 + ":" + leport5 + ";" + clientport5 + "\n";
+
+        ByteArrayInputStream is = new ByteArrayInputStream(config.getBytes());
+        this.qp = new Properties();
+        
+        qp.load(is);
+        startServers();
+
+        cht.hostPort = hostPort;
+        cht.setUpAll();
+        
+        LOG.info("Setup finished");
+    }
+    
+    /**
+     * This method is here to keep backwards compatibility with the test code 
+     * written before observers. 
+     * @throws Exception
+     */
+    void startServers() throws Exception {
+        startServers(false);
+    }
+    
+    /**
+     * Starts 5 Learners. When withObservers == false, all 5 are Followers.
+     * When withObservers == true, 3 are Followers and 2 Observers.
+     * @param withObservers
+     * @throws Exception
+     */
+    void startServers(boolean withObservers) throws Exception {
+        int tickTime = 2000;
+        int initLimit = 3;
+        int syncLimit = 3;
+        HashMap<Long,QuorumServer> peers = new HashMap<Long,QuorumServer>();
+        peers.put(Long.valueOf(1), new QuorumServer(1, 
+                new InetSocketAddress("127.0.0.1", port1),
+                new InetSocketAddress("127.0.0.1", leport1),
+                new InetSocketAddress("127.0.0.1", clientport1)));        
+        peers.put(Long.valueOf(2), new QuorumServer(2, 
+                new InetSocketAddress("127.0.0.1", port2),
+                new InetSocketAddress("127.0.0.1", leport2),
+                new InetSocketAddress("127.0.0.1", clientport2)));
+        peers.put(Long.valueOf(3), new QuorumServer(3, 
+                new InetSocketAddress("127.0.0.1", port3),
+                new InetSocketAddress("127.0.0.1", leport3),
+                new InetSocketAddress("127.0.0.1", clientport3)));
+        peers.put(Long.valueOf(4), new QuorumServer(4,
+                new InetSocketAddress("127.0.0.1", port4),
+                new InetSocketAddress("127.0.0.1", leport4),
+                new InetSocketAddress("127.0.0.1", clientport4),
+                withObservers ? QuorumPeer.LearnerType.OBSERVER
+                        : QuorumPeer.LearnerType.PARTICIPANT));
+        peers.put(Long.valueOf(5), new QuorumServer(5,
+                new InetSocketAddress("127.0.0.1", port5),
+                new InetSocketAddress("127.0.0.1", leport5),
+                new InetSocketAddress("127.0.0.1", clientport5),
+                withObservers ? QuorumPeer.LearnerType.OBSERVER
+                        : QuorumPeer.LearnerType.PARTICIPANT));
+
+        LOG.info("creating QuorumPeer 1 port " + clientport1);
+        
+        if (withObservers) {
+               qp.setProperty("server.4", "127.0.0.1:" + port4 + ":" + leport4 + ":observer" + ";" + clientport4);
+               qp.setProperty("server.5", "127.0.0.1:" + port5 + ":" + leport5 +  ":observer" + ";" + clientport5);
+        }
+        QuorumHierarchical hq1 = new QuorumHierarchical(qp); 
+        s1 = new QuorumPeer(peers, s1dir, s1dir, clientport1, 3, 1, tickTime, initLimit, syncLimit, hq1);
+        Assert.assertEquals(clientport1, s1.getClientPort());
+        
+        LOG.info("creating QuorumPeer 2 port " + clientport2);
+        QuorumHierarchical hq2 = new QuorumHierarchical(qp); 
+        s2 = new QuorumPeer(peers, s2dir, s2dir, clientport2, 3, 2, tickTime, initLimit, syncLimit, hq2);
+        Assert.assertEquals(clientport2, s2.getClientPort());
+        
+        LOG.info("creating QuorumPeer 3 port " + clientport3);
+        QuorumHierarchical hq3 = new QuorumHierarchical(qp); 
+        s3 = new QuorumPeer(peers, s3dir, s3dir, clientport3, 3, 3, tickTime, initLimit, syncLimit, hq3);
+        Assert.assertEquals(clientport3, s3.getClientPort());
+        
+        LOG.info("creating QuorumPeer 4 port " + clientport4);
+        QuorumHierarchical hq4 = new QuorumHierarchical(qp); 
+        s4 = new QuorumPeer(peers, s4dir, s4dir, clientport4, 3, 4, tickTime, initLimit, syncLimit, hq4);
+        if (withObservers) {
+            s4.setLearnerType(QuorumPeer.LearnerType.OBSERVER);
+        }
+        Assert.assertEquals(clientport4, s4.getClientPort());
+                       
+        LOG.info("creating QuorumPeer 5 port " + clientport5);
+        QuorumHierarchical hq5 = new QuorumHierarchical(qp); 
+        s5 = new QuorumPeer(peers, s5dir, s5dir, clientport5, 3, 5, tickTime, initLimit, syncLimit, hq5);
+        if (withObservers) {
+            s5.setLearnerType(QuorumPeer.LearnerType.OBSERVER);
+        }
+        Assert.assertEquals(clientport5, s5.getClientPort());
+        
+        // Observers are currently only compatible with LeaderElection
+        if (withObservers) {
+            s1.setElectionType(0);
+            s2.setElectionType(0);
+            s3.setElectionType(0);
+            s4.setElectionType(0);
+            s5.setElectionType(0);
+        }
+        
+        LOG.info("start QuorumPeer 1");
+        s1.start();
+        LOG.info("start QuorumPeer 2");
+        s2.start();
+        LOG.info("start QuorumPeer 3");
+        s3.start();
+        LOG.info("start QuorumPeer 4" + (withObservers ? "(observer)" : ""));
+        s4.start();
+        LOG.info("start QuorumPeer 5" + (withObservers ? "(observer)" : ""));
+        s5.start();
+        LOG.info("started QuorumPeer 5");
+
+        LOG.info ("Closing ports " + hostPort);
+        for (String hp : hostPort.split(",")) {
+            Assert.assertTrue("waiting for server up",
+                       ClientBase.waitForServerUp(hp,
+                                    CONNECTION_TIMEOUT));
+            LOG.info(hp + " is accepting client connections");
+        }
+        final int numberOfPeers = 5;
+        // interesting to see what's there...
+        JMXEnv.dump();
+        // make sure we have these 5 servers listed
+        Set<String> ensureNames = new LinkedHashSet<String>();
+        for (int i = 1; i <= numberOfPeers; i++) {
+            ensureNames.add("InMemoryDataTree");
+        }
+        for (int i = 1; i <= numberOfPeers; i++) {
+            ensureNames.add("name0=ReplicatedServer_id" + i
+                 + ",name1=replica." + i + ",name2=");
+        }
+        for (int i = 1; i <= numberOfPeers; i++) {
+            for (int j = 1; j <= numberOfPeers; j++) {
+                ensureNames.add("name0=ReplicatedServer_id" + i
+                     + ",name1=replica." + j);
+            }
+        }
+        for (int i = 1; i <= numberOfPeers; i++) {
+            ensureNames.add("name0=ReplicatedServer_id" + i);
+        }
+        JMXEnv.ensureAll(ensureNames.toArray(new String[ensureNames.size()]));
+        for (int i = 1; i <= numberOfPeers; i++) {
+            // LocalPeerBean
+            String bean = CommonNames.DOMAIN + ":name0=ReplicatedServer_id" + i
+                    + ",name1=replica." + i;
+            JMXEnv.ensureBeanAttribute(bean, "ConfigVersion");
+            JMXEnv.ensureBeanAttribute(bean, "LearnerType");
+            JMXEnv.ensureBeanAttribute(bean, "ClientAddress");
+            JMXEnv.ensureBeanAttribute(bean, "ElectionAddress");
+            JMXEnv.ensureBeanAttribute(bean, "QuorumSystemInfo");
+            JMXEnv.ensureBeanAttribute(bean, "Leader");
+        }
+
+        for (int i = 1; i <= numberOfPeers; i++) {
+            for (int j = 1; j <= numberOfPeers; j++) {
+                if (j != i) {
+                    // RemotePeerBean
+                    String bean = CommonNames.DOMAIN + ":name0=ReplicatedServer_id" + i
+                            + ",name1=replica." + j;
+                    JMXEnv.ensureBeanAttribute(bean, "Name");
+                    JMXEnv.ensureBeanAttribute(bean, "LearnerType");
+                    JMXEnv.ensureBeanAttribute(bean, "ClientAddress");
+                    JMXEnv.ensureBeanAttribute(bean, "ElectionAddress");
+                    JMXEnv.ensureBeanAttribute(bean, "QuorumAddress");
+                    JMXEnv.ensureBeanAttribute(bean, "Leader");
+                }
+            }
+        }
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        LOG.info("TearDown started");
+        cht.tearDownAll();
+
+        LOG.info("Shutting down server 1");
+        shutdown(s1);
+        LOG.info("Shutting down server 2");
+        shutdown(s2);
+        LOG.info("Shutting down server 3");
+        shutdown(s3);
+        LOG.info("Shutting down server 4");
+        shutdown(s4);
+        LOG.info("Shutting down server 5");
+        shutdown(s5);
+        
+        for (String hp : hostPort.split(",")) {
+            Assert.assertTrue("waiting for server down",
+                       ClientBase.waitForServerDown(hp,
+                                           ClientBase.CONNECTION_TIMEOUT));
+            LOG.info(hp + " is no longer accepting client connections");
+        }
+
+        JMXEnv.tearDown();
+    }
+
+    protected void shutdown(QuorumPeer qp) {
+        QuorumBase.shutdown(qp);
+    }
+
+    protected TestableZooKeeper createClient()
+        throws IOException, InterruptedException
+    {
+        return createClient(hostPort);
+    }
+
+    protected TestableZooKeeper createClient(String hp)
+        throws IOException, InterruptedException
+    {
+        CountdownWatcher watcher = new CountdownWatcher();
+        return createClient(watcher, hp);
+    }
+
+    @Test
+    public void testHierarchicalQuorum() throws Throwable {
+        cht.runHammer(5, 10);
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-server/src/test/java/org/apache/zookeeper/test/IntegrityCheck.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/IntegrityCheck.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/IntegrityCheck.java
new file mode 100644
index 0000000..4914f2d
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/IntegrityCheck.java
@@ -0,0 +1,219 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.test;
+
+/**
+ * This is a simple test to check the integrity of ZooKeeper servers. The client
+ * simply cycles through blasting changes to ZooKeeper and the checking what it
+ * gets back.
+ *
+ * The check is very simple. The value of the last successful read or write is
+ * stored in lastValue. When we issue a request, that value becomes a possible
+ * value. The difficulty is that when a communication error happens, the client
+ * doesn't know if the set actually went through. So, our invariant that we
+ * check for is that we always read a value that is greater than or equal to
+ * a value that we have previously read or set. (Each time we set a value, the
+ * value will be one more than the previous set.)
+ */
+import java.util.Date;
+import java.util.HashMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.AsyncCallback.DataCallback;
+import org.apache.zookeeper.AsyncCallback.StatCallback;
+import org.apache.zookeeper.data.Stat;
+
+public class IntegrityCheck implements StatCallback, DataCallback {
+    private static final Logger LOG = LoggerFactory.getLogger(IntegrityCheck.class);
+
+    ZooKeeper zk;
+
+    HashMap<String, byte[]> lastValue = new HashMap<String, byte[]>();
+
+    int count;
+
+    String path;
+
+    int iteration;
+
+    int outstanding;
+
+    int errorCount;
+
+    synchronized void incOutstanding() {
+        outstanding++;
+    }
+
+    synchronized void decOutstanding() {
+        outstanding--;
+        notifyAll();
+    }
+
+    synchronized void waitOutstanding() throws InterruptedException {
+        while (outstanding > 0) {
+            wait();
+        }
+    }
+
+    IntegrityCheck(String hostPort, String path, int count) throws
+            Exception {
+        zk = ClientBase.createZKClient(hostPort);
+        this.path = path;
+        this.count = count;
+    }
+
+    public void run() throws InterruptedException, KeeperException {
+        try{
+            LOG.warn("Creating znodes for "+path);
+            doCreate();
+            LOG.warn("Staring the test loop for "+path);
+            while (true) {
+                LOG.warn("Staring write cycle for "+path);
+                doPopulate();
+                waitOutstanding();
+                LOG.warn("Staring read cycle for "+path);
+                readAll();
+                waitOutstanding();
+            }
+        }finally{
+            LOG.warn("Test loop terminated for "+path);
+        }
+    }
+
+    void readAll() {
+        for (int i = 0; i < count; i++) {
+            String cpath = path + "/" + i;
+            zk.getData(cpath, false, this, null);
+            incOutstanding();
+        }
+
+    }
+
+    void doCreate() throws InterruptedException, KeeperException {
+        // create top level znode
+        try{
+            zk.create(path, null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+        }catch(KeeperException.NodeExistsException e){
+            // ignore duplicate create
+        }
+        iteration++;
+        byte v[] = ("" + iteration).getBytes();
+        // create child znodes
+        for (int i = 0; i < count; i++) {
+            String cpath = path + "/" + i;
+            try{
+                if(i%10==0)
+                    LOG.warn("Creating znode "+cpath);
+                zk.create(cpath, v, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
+            }catch(KeeperException.NodeExistsException e){
+                // ignore duplicate create
+            }
+            lastValue.put(cpath, v);
+        }
+    }
+
+    void doPopulate() {
+        iteration++;
+        byte v[] = ("" + iteration).getBytes();
+        for (int i = 0; i < count; i++) {
+            String cpath = path + "/" + i;
+            zk.setData(cpath, v, -1, this, v);
+            incOutstanding();
+        }
+    }
+
+    synchronized void ensureConnected(){
+        while(zk.getState()!=ZooKeeper.States.CONNECTED){
+            try {
+                wait();
+            } catch (InterruptedException e) {
+                return;
+            }
+        }
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) {
+        if (args.length < 3) {
+            System.err.println("USAGE: IntegrityCheck zookeeperHostPort znode #children");
+            return;
+        }
+        int childrenCount=0;
+        try {
+            childrenCount=Integer.parseInt(args[2]);
+        } catch (NumberFormatException e) {
+            e.printStackTrace();
+            System.exit(1);
+        }
+
+        try{
+            final IntegrityCheck ctest = new IntegrityCheck(args[0], args[1],childrenCount);
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+                public void run() {
+                    System.out.println(new Date().toString()+": Error count = " + ctest.errorCount);
+                }
+            });
+            while(true){
+                try{
+                    ctest.ensureConnected();
+                    ctest.run();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            System.exit(2);
+        }
+    }
+
+    public void processResult(int rc, String path, Object ctx, Stat stat) {
+        if (rc == 0) {
+            lastValue.put(path, (byte[]) ctx);
+        }
+        decOutstanding();
+    }
+
+    public void processResult(int rc, String path, Object ctx, byte[] data,
+            Stat stat) {
+        if (rc == 0) {
+            String string = new String(data);
+            String lastString = null;
+            byte[] v = lastValue.get(path);
+            if (v != null) {
+                lastString = new String(v);
+            }
+            if (lastString != null
+                    && Integer.parseInt(string) < Integer.parseInt(lastString)) {
+                LOG.error("ERROR: Got " + string + " expected >= "
+                        + lastString);
+                errorCount++;
+            }
+            lastValue.put(path, (byte[]) ctx);
+        }
+        decOutstanding();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-server/src/test/java/org/apache/zookeeper/test/InvalidSnapshotTest.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/InvalidSnapshotTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/InvalidSnapshotTest.java
new file mode 100644
index 0000000..df32ba8
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/InvalidSnapshotTest.java
@@ -0,0 +1,110 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.test;
+
+import static org.apache.zookeeper.test.ClientBase.CONNECTION_TIMEOUT;
+
+import java.io.File;
+
+import org.apache.zookeeper.PortAssignment;
+import org.apache.zookeeper.ZKTestCase;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.server.LogFormatter;
+import org.apache.zookeeper.server.ServerCnxnFactory;
+import org.apache.zookeeper.server.SnapshotFormatter;
+import org.apache.zookeeper.server.SyncRequestProcessor;
+import org.apache.zookeeper.server.ZooKeeperServer;
+import org.junit.Assert;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class InvalidSnapshotTest extends ZKTestCase{
+    private final static Logger LOG = LoggerFactory.getLogger(InvalidSnapshotTest.class);
+    private static final String HOSTPORT =
+            "127.0.0.1:" + PortAssignment.unique();
+
+    private static final File testData = new File(
+            System.getProperty("test.data.dir", "build/test/data"));
+
+    /**
+     * Verify the LogFormatter by running it on a known file.
+     */
+    @Test
+    public void testLogFormatter() throws Exception {
+        File snapDir = new File(testData, "invalidsnap");
+        File logfile = new File(new File(snapDir, "version-2"), "log.274");
+        String[] args = {logfile.getCanonicalFile().toString()};
+        LogFormatter.main(args);
+    }
+
+    /**
+     * Verify the SnapshotFormatter by running it on a known file.
+     */
+    @Test
+    public void testSnapshotFormatter() throws Exception {
+        File snapDir = new File(testData, "invalidsnap");
+        File snapfile = new File(new File(snapDir, "version-2"), "snapshot.272");
+        String[] args = {snapfile.getCanonicalFile().toString()};
+        SnapshotFormatter.main(args);
+    }
+    
+    /**
+     * Verify the SnapshotFormatter by running it on a known file with one null data.
+     */
+    @Test
+    public void testSnapshotFormatterWithNull() throws Exception {
+        File snapDir = new File(testData, "invalidsnap");
+        File snapfile = new File(new File(snapDir, "version-2"), "snapshot.273");
+        String[] args = {snapfile.getCanonicalFile().toString()};
+        SnapshotFormatter.main(args);
+    }
+    
+    /**
+     * test the snapshot
+     * @throws Exception an exception could be expected
+     */
+    @Test
+    public void testSnapshot() throws Exception {
+        File snapDir = new File(testData, "invalidsnap");
+        ZooKeeperServer zks = new ZooKeeperServer(snapDir, snapDir, 3000);
+        SyncRequestProcessor.setSnapCount(1000);
+        final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]);
+        ServerCnxnFactory f = ServerCnxnFactory.createFactory(PORT, -1);
+        f.startup(zks);
+        LOG.info("starting up the zookeeper server .. waiting");
+        Assert.assertTrue("waiting for server being up",
+                ClientBase.waitForServerUp(HOSTPORT, CONNECTION_TIMEOUT));
+        ZooKeeper zk = ClientBase.createZKClient(HOSTPORT);
+        try {
+            // we know this from the data files
+            // this node is the last node in the snapshot
+
+            Assert.assertTrue(zk.exists("/9/9/8", false) != null);
+        } finally {
+            zk.close();
+        }
+        f.shutdown();
+        zks.shutdown();
+        Assert.assertTrue("waiting for server down",
+                   ClientBase.waitForServerDown(HOSTPORT,
+                           ClientBase.CONNECTION_TIMEOUT));
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-server/src/test/java/org/apache/zookeeper/test/JMXEnv.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/JMXEnv.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/JMXEnv.java
new file mode 100644
index 0000000..4edcc0e
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/JMXEnv.java
@@ -0,0 +1,322 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.test;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+
+import org.apache.zookeeper.jmx.CommonNames;
+import org.apache.zookeeper.jmx.MBeanRegistry;
+import org.junit.Assert;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class JMXEnv {
+    protected static final Logger LOG = LoggerFactory.getLogger(JMXEnv.class);
+
+    private static JMXConnectorServer cs;
+    private static JMXConnector cc;
+
+    public static void setUp() throws IOException {
+        MBeanServer mbs = MBeanRegistry.getInstance().getPlatformMBeanServer();
+        
+        JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://127.0.0.1");
+        cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+        cs.start();
+
+       JMXServiceURL addr = cs.getAddress();
+        
+       cc = JMXConnectorFactory.connect(addr);
+    }
+    
+    public static void tearDown() {
+        try {
+            if (cc != null) {
+                cc.close();
+            }
+        } catch (IOException e) {
+            LOG.warn("Unexpected, ignoring", e);
+            
+        }
+        cc = null;
+        try {
+            if (cs != null) {
+                cs.stop();
+            }
+        } catch (IOException e) {
+            LOG.warn("Unexpected, ignoring", e);
+            
+        }
+        cs = null;
+    }
+    
+    public static MBeanServerConnection conn() throws IOException {
+        return cc.getMBeanServerConnection();
+    }
+
+    /**
+     * Ensure that all of the specified names are registered.
+     * Note that these are components of the name, and in particular
+     * order matters - you want the more specific name (leafs) specified
+     * before their parent(s) (since names are hierarchical)
+     * It waits in a loop up to 60 seconds before failing if there is a
+     * mismatch.
+     * @param expectedNames
+     * @return
+     * @throws IOException
+     * @throws MalformedObjectNameException
+     */
+    public static Set<ObjectName> ensureAll(String... expectedNames)
+        throws IOException, InterruptedException
+    {
+        Set<ObjectName> beans;
+        Set<ObjectName> found;
+        int nTry = 0;
+        do {
+            if (nTry++ > 0) {
+                Thread.sleep(100);
+            }
+            try {
+                beans = conn().queryNames(
+                        new ObjectName(CommonNames.DOMAIN + ":*"), null);
+            } catch (MalformedObjectNameException e) {
+                throw new RuntimeException(e);
+            }
+        
+            found = new HashSet<ObjectName>();
+            for (String name : expectedNames) {
+                LOG.info("expect:" + name);
+                for (ObjectName bean : beans) {
+                    if (bean.toString().contains(name)) {
+                        LOG.info("found:" + name + " " + bean);
+                        found.add(bean);
+                        break;
+                    }
+                }
+                beans.removeAll(found);
+            }
+        } while ((expectedNames.length != found.size()) && (nTry < 600));
+        Assert.assertEquals("expected " + Arrays.toString(expectedNames),
+                expectedNames.length, found.size());
+        return beans;
+    }
+
+    /**
+     * Ensure that only the specified names are registered.
+     * Note that these are components of the name, and in particular
+     * order matters - you want the more specific name (leafs) specified
+     * before their parent(s) (since names are hierarchical)
+     * @param expectedNames
+     * @return
+     * @throws IOException
+     * @throws MalformedObjectNameException
+     */
+    public static Set<ObjectName> ensureOnly(String... expectedNames)
+        throws IOException, InterruptedException
+    {
+        LOG.info("ensureOnly:" + Arrays.toString(expectedNames));
+        Set<ObjectName> beans = ensureAll(expectedNames);
+        for (ObjectName bean : beans) {
+            LOG.info("unexpected:" + bean.toString());
+        }
+        Assert.assertEquals(0, beans.size());
+        return beans;
+    }
+    
+    public static void ensureNone(String... expectedNames)
+        throws IOException, InterruptedException
+    {
+        Set<ObjectName> beans;
+        int nTry = 0;
+        boolean foundUnexpected = false;
+        String unexpectedName = "";
+        do {
+            if (nTry++ > 0) {
+                Thread.sleep(100);
+            }
+            try {
+                beans = conn().queryNames(
+                        new ObjectName(CommonNames.DOMAIN + ":*"), null);
+            } catch (MalformedObjectNameException e) {
+                throw new RuntimeException(e);
+            }
+  
+            foundUnexpected = false; 
+            for (String name : expectedNames) {
+                for (ObjectName bean : beans) {
+                    if (bean.toString().contains(name)) {
+                        LOG.info("didntexpect:" + name);
+                        foundUnexpected = true;
+                        unexpectedName = name + " " + bean.toString();
+                        break;
+                    }
+                }
+                if (foundUnexpected) {
+                    break;
+                }
+            }
+        } while ((foundUnexpected) && (nTry < 600));
+        if (foundUnexpected) {
+            LOG.info("List of all beans follows:");
+            for (ObjectName bean : beans) {
+                LOG.info("bean:" + bean.toString());
+            }
+            Assert.fail(unexpectedName);
+        }
+    }
+
+    public static void dump() throws IOException {
+        LOG.info("JMXEnv.dump() follows");
+        Set<ObjectName> beans;
+        try {
+            beans = conn().queryNames(
+                    new ObjectName(CommonNames.DOMAIN + ":*"), null);
+        } catch (MalformedObjectNameException e) {
+            throw new RuntimeException(e);
+        }
+        for (ObjectName bean : beans) {
+            LOG.info("bean:" + bean.toString());
+        }
+    }
+
+    /**
+     * Ensure that the specified parent names are registered. Note that these
+     * are components of the name. It waits in a loop up to 60 seconds before
+     * failing if there is a mismatch. This will return the beans which are not
+     * matched.
+     * 
+     * {@link https://issues.apache.org/jira/browse/ZOOKEEPER-1858}
+     * 
+     * @param expectedNames
+     *            - expected beans
+     * @return the beans which are not matched with the given expected names
+     * 
+     * @throws IOException
+     * @throws InterruptedException
+     */
+    public static Set<ObjectName> ensureParent(String... expectedNames)
+            throws IOException, InterruptedException {
+        LOG.info("ensureParent:" + Arrays.toString(expectedNames));
+
+        Set<ObjectName> beans;
+        int nTry = 0;
+        Set<ObjectName> found = new HashSet<ObjectName>();
+        do {
+            if (nTry++ > 0) {
+                Thread.sleep(500);
+            }
+            try {
+                beans = conn().queryNames(
+                        new ObjectName(CommonNames.DOMAIN + ":*"), null);
+            } catch (MalformedObjectNameException e) {
+                throw new RuntimeException(e);
+            }
+            found.clear();
+            for (String name : expectedNames) {
+                LOG.info("expect:" + name);
+                for (ObjectName bean : beans) {
+                    // check the existence of name in bean
+                    if (compare(bean.toString(), name)) {
+                        LOG.info("found:" + name + " " + bean);
+                        found.add(bean);
+                        break;
+                    }
+                }
+                beans.removeAll(found);
+            }
+        } while (expectedNames.length != found.size() && nTry < 120);
+        Assert.assertEquals("expected " + Arrays.toString(expectedNames),
+                expectedNames.length, found.size());
+        return beans;
+    }
+
+    /**
+     * Ensure that the specified bean name and its attribute is registered. Note
+     * that these are components of the name. It waits in a loop up to 60
+     * seconds before failing if there is a mismatch. This will return the beans
+     * which are not matched.
+     *
+     * @param expectedName
+     *            - expected bean
+     * @param expectedAttribute
+     *            - expected attribute
+     * @return the value of the attribute
+     *
+     * @throws Exception
+     */
+    public static Object ensureBeanAttribute(String expectedName,
+            String expectedAttribute) throws Exception {
+        String value = "";
+        LOG.info("ensure bean:{}, attribute:{}", new Object[] { expectedName,
+                expectedAttribute });
+
+        Set<ObjectName> beans;
+        int nTry = 0;
+        do {
+            if (nTry++ > 0) {
+                Thread.sleep(500);
+            }
+            try {
+                beans = conn().queryNames(
+                        new ObjectName(CommonNames.DOMAIN + ":*"), null);
+            } catch (MalformedObjectNameException e) {
+                throw new RuntimeException(e);
+            }
+            LOG.info("expect:" + expectedName);
+            for (ObjectName bean : beans) {
+                // check the existence of name in bean
+                if (bean.toString().equals(expectedName)) {
+                    LOG.info("found:{} {}", new Object[] { expectedName, bean });
+                    return conn().getAttribute(bean, expectedAttribute);
+                }
+            }
+        } while (nTry < 120);
+        Assert.fail("Failed to find bean:" + expectedName + ", attribute:"
+                + expectedAttribute);
+        return value;
+    }
+
+    /**
+     * Comparing that the given name exists in the bean. For component beans,
+     * the component name will be present at the end of the bean name
+     * 
+     * For example 'StandaloneServer' will present in the bean name like
+     * 'org.apache.ZooKeeperService:name0=StandaloneServer_port-1'
+     */
+    private static boolean compare(String bean, String name) {
+        String[] names = bean.split("=");
+        if (names.length > 0 && names[names.length - 1].contains(name)) {
+            return true;
+        }
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/43d71c2e/zookeeper-server/src/test/java/org/apache/zookeeper/test/KeeperStateTest.java
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/KeeperStateTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/KeeperStateTest.java
new file mode 100644
index 0000000..f849eab
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/KeeperStateTest.java
@@ -0,0 +1,76 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zookeeper.test;
+
+import java.util.EnumSet;
+
+import org.apache.zookeeper.ZKTestCase;
+import org.apache.zookeeper.KeeperException.Code;
+import org.apache.zookeeper.Watcher.Event.KeeperState;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class KeeperStateTest extends ZKTestCase {
+    
+    @Test
+    public void testIntConversion() {
+        // Ensure that we can convert all valid integers to KeeperStates
+        EnumSet<KeeperState> allStates = EnumSet.allOf(KeeperState.class);
+
+        for(KeeperState as : allStates) {
+            Assert.assertEquals(as, KeeperState.fromInt( as.getIntValue() ) );
+        }
+    }
+
+    @Test
+    public void testInvalidIntConversion() {
+        try {
+            KeeperState.fromInt(324142);
+            Assert.fail("Was able to create an invalid KeeperState via an integer");
+        } catch(RuntimeException re) {
+            // we're good.
+        }
+
+    }
+
+    /** Validate that the deprecated constant still works. There were issues
+     * found with switch statements - which need compile time constants.
+     */
+    @Test
+    @SuppressWarnings("deprecation")
+    public void testDeprecatedCodeOkInSwitch() {
+        int test = 1;
+        switch (test) {
+        case Code.Ok:
+            Assert.assertTrue(true);
+            break;
+        }
+    }
+
+    /** Verify the enum works (paranoid) */
+    @Test
+    public void testCodeOKInSwitch() {
+        Code test = Code.OK;
+        switch (test) {
+        case OK:
+            Assert.assertTrue(true);
+            break;
+        }
+    }
+}


Mime
View raw message