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;
+ }
+ }
+}
|