http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/main/resources/lib/log4j-1.2.17.LICENSE.txt
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/main/resources/lib/log4j-1.2.17.LICENSE.txt 
b/zookeeper-server/src/main/resources/lib/log4j-1.2.17.LICENSE.txt
new file mode 100644
index 0000000..6279e52
--- /dev/null
+++ b/zookeeper-server/src/main/resources/lib/log4j-1.2.17.LICENSE.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright 1999-2005 The Apache Software Foundation
+
+   Licensed 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.

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/main/resources/lib/slf4j-1.7.25.LICENSE.txt
----------------------------------------------------------------------
diff --git a/zookeeper-server/src/main/resources/lib/slf4j-1.7.25.LICENSE.txt 
b/zookeeper-server/src/main/resources/lib/slf4j-1.7.25.LICENSE.txt
new file mode 100644
index 0000000..315bd49
--- /dev/null
+++ b/zookeeper-server/src/main/resources/lib/slf4j-1.7.25.LICENSE.txt
@@ -0,0 +1,24 @@
+Copyright (c) 2004-2017 QOS.ch
+All rights reserved.
+
+Permission is hereby granted, free  of charge, to any person obtaining
+a  copy  of this  software  and  associated  documentation files  (the
+"Software"), to  deal in  the Software without  restriction, including
+without limitation  the rights to  use, copy, modify,  merge, publish,
+distribute,  sublicense, and/or sell  copies of  the Software,  and to
+permit persons to whom the Software  is furnished to do so, subject to
+the following conditions:
+
+The  above  copyright  notice  and  this permission  notice  shall  be
+included in all copies or substantial portions of the Software.
+
+THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/ClientReconnectTest.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/ClientReconnectTest.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/ClientReconnectTest.java
new file mode 100644
index 0000000..8d66a7e
--- /dev/null
+++ 
b/zookeeper-server/src/test/java/org/apache/zookeeper/ClientReconnectTest.java
@@ -0,0 +1,78 @@
+/**
+ * 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;
+
+
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.channels.SocketChannel;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.zookeeper.client.HostProvider;
+import org.junit.Test;
+
+public class ClientReconnectTest extends TestCase {
+    private SocketChannel sc;
+    private CountDownLatch countDownLatch = new CountDownLatch(3);
+    
+    class MockCnxn extends ClientCnxnSocketNIO {
+        MockCnxn() throws IOException {
+            super();
+        }
+
+        @Override
+        void registerAndConnect(SocketChannel sock, InetSocketAddress addr) 
throws
+        IOException {
+            countDownLatch.countDown();
+            throw new IOException("failed to register");
+        }
+
+        @Override
+        SocketChannel createSock() {
+            return sc;
+        }
+    }
+
+    @Test
+    public void testClientReconnect() throws IOException, InterruptedException 
{
+        HostProvider hostProvider = mock(HostProvider.class);
+        when(hostProvider.size()).thenReturn(1);
+        InetSocketAddress inaddr = new InetSocketAddress(1111);
+        when(hostProvider.next(anyLong())).thenReturn(inaddr);
+        ZooKeeper zk = mock(ZooKeeper.class);
+        sc =  SocketChannel.open();
+
+        ClientCnxnSocketNIO nioCnxn = new MockCnxn();
+        ClientWatchManager watcher = mock(ClientWatchManager.class);
+        ClientCnxn clientCnxn = new ClientCnxn(
+                "tmp", hostProvider, 5000,
+                zk, watcher, nioCnxn, false);
+        clientCnxn.start();
+        countDownLatch.await(5000, TimeUnit.MILLISECONDS);
+        Assert.assertTrue(countDownLatch.getCount() == 0);
+        clientCnxn.close();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/JUnit4ZKTestRunner.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/JUnit4ZKTestRunner.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/JUnit4ZKTestRunner.java
new file mode 100644
index 0000000..37149cc
--- /dev/null
+++ 
b/zookeeper-server/src/test/java/org/apache/zookeeper/JUnit4ZKTestRunner.java
@@ -0,0 +1,86 @@
+/**
+ * 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;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.junit.Test;
+import org.junit.internal.runners.statements.InvokeMethod;
+import org.junit.runners.BlockJUnit4ClassRunner;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.Statement;
+
+/**
+ * The sole responsibility of this class is to print to the log when a test
+ * starts and when it finishes.
+ */
+public class JUnit4ZKTestRunner extends BlockJUnit4ClassRunner {
+    private static final Logger LOG = 
LoggerFactory.getLogger(JUnit4ZKTestRunner.class);
+
+    public JUnit4ZKTestRunner(Class<?> klass) throws InitializationError {
+        super(klass);
+    }
+
+    public class LoggedInvokeMethod extends InvokeMethod {
+        private final FrameworkMethod method;
+        private final String name;
+
+        public LoggedInvokeMethod(FrameworkMethod method, Object target) {
+            super(method, target);
+            this.method = method;
+            name = method.getName();
+        }
+
+        @Override
+        public void evaluate() throws Throwable {
+            LOG.info("RUNNING TEST METHOD {}", name);
+            try {
+                super.evaluate();
+                Runtime rt = Runtime.getRuntime();
+                long usedKB = (rt.totalMemory() - rt.freeMemory()) / 1024;
+                LOG.info("Memory used {}", usedKB);
+                ThreadGroup tg = Thread.currentThread().getThreadGroup();
+                while (tg.getParent() != null) {
+                    tg = tg.getParent();
+                }
+                LOG.info("Number of threads {}", tg.activeCount());
+            } catch (Throwable t) {
+                // The test method threw an exception, but it might be an
+                // expected exception as defined in the @Test annotation.
+                // Check the annotation and log an appropriate message.
+                Test annotation = this.method.getAnnotation(Test.class);
+                if (annotation != null && annotation.expected() != null &&
+                        annotation.expected().isAssignableFrom(t.getClass())) {
+                    LOG.info("TEST METHOD {} THREW EXPECTED EXCEPTION {}", 
name,
+                        annotation.expected());
+                } else {
+                    LOG.info("TEST METHOD FAILED {}", name, t);
+                }
+                throw t;
+            }
+            LOG.info("FINISHED TEST METHOD {}", name);
+        }
+    }
+
+    @Override
+    protected Statement methodInvoker(FrameworkMethod method, Object test) {
+        return new LoggedInvokeMethod(method, test);
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/JaasConfiguration.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/JaasConfiguration.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/JaasConfiguration.java
new file mode 100644
index 0000000..bf145d0
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/JaasConfiguration.java
@@ -0,0 +1,75 @@
+/**
+ * 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;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
+
+/**
+ * This helper class allows to programmatically create a JAAS configuration.
+ * Each section must have a name and a login module, and a set of key/values
+ * to describe login options.
+ *
+ * Example:
+ *   jaas = new JaasConfiguration();
+ *   jaas.addSection("Server", 
"org.apache.zookeeper.server.auth.DigestLoginModule",
+ *                   "username", "passowrd");
+ */
+public class JaasConfiguration extends javax.security.auth.login.Configuration 
{
+    private final Map<String, AppConfigurationEntry[]> sections =
+      new HashMap<String, AppConfigurationEntry[]>();
+
+    public JaasConfiguration() {
+    }
+
+    /**
+     * Add a section to the jaas.conf
+     * @param name Section name
+     * @param loginModuleName Login module name
+     * @param args login key/value args
+     */
+    public void addSection(String name, String loginModuleName, String... 
args) {
+        Map<String, String> conf = new HashMap<String, String>();
+        // loop through the args (must be key/value sequence)
+        for (int i = 0; i < args.length - 1; i += 2) {
+            conf.put(args[i], args[i + 1]);
+        }
+        addSection(name, loginModuleName, conf);
+    }
+
+    /**
+     * Add a section to the jaas.conf
+     * @param name Section name
+     * @param loginModuleName Login module name
+     * @param conf login key/value args
+     */
+    public void addSection(String name, String loginModuleName, final 
Map<String,String> conf) {
+        AppConfigurationEntry[] entries = new AppConfigurationEntry[1];
+        entries[0] = new AppConfigurationEntry(loginModuleName, 
LoginModuleControlFlag.REQUIRED, conf);
+        this.sections.put(name, entries);
+    }
+
+    @Override
+    public AppConfigurationEntry[] getAppConfigurationEntry(String appName) {
+        return sections.get(appName);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/MockPacket.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/MockPacket.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/MockPacket.java
new file mode 100644
index 0000000..f4bb19a
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/MockPacket.java
@@ -0,0 +1,46 @@
+/**
+ * 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;
+
+import org.apache.zookeeper.proto.RequestHeader;
+import org.apache.zookeeper.proto.ReplyHeader;
+import org.apache.jute.Record;
+import org.apache.zookeeper.ZooKeeper.WatchRegistration;
+import java.nio.ByteBuffer;
+
+public class MockPacket extends ClientCnxn.Packet {
+
+    public MockPacket(RequestHeader requestHeader, ReplyHeader replyHeader,
+               Record request, Record response,
+               WatchRegistration watchRegistration) {
+        super(requestHeader, replyHeader, request, response, 
watchRegistration);
+    }
+
+    public MockPacket(RequestHeader requestHeader, ReplyHeader replyHeader,
+               Record request, Record response,
+               WatchRegistration watchRegistration, boolean readOnly) {
+        super(requestHeader, replyHeader, request, response, 
watchRegistration, readOnly);
+    }
+
+    public ByteBuffer createAndReturnBB() {
+        createBB();
+        return this.bb;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/MultiResponseTest.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/MultiResponseTest.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/MultiResponseTest.java
new file mode 100644
index 0000000..a03feb3
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/MultiResponseTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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;
+
+import junit.framework.TestCase;
+import org.apache.jute.BinaryInputArchive;
+import org.apache.jute.BinaryOutputArchive;
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.server.ByteBufferInputStream;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public class MultiResponseTest extends TestCase {
+    public void testRoundTrip() throws IOException {
+        MultiResponse response = new MultiResponse();
+
+        response.add(new OpResult.CheckResult());
+        response.add(new OpResult.CreateResult("foo-bar"));
+        response.add(new OpResult.DeleteResult());
+
+        Stat s = new Stat();
+        s.setCzxid(546);
+        response.add(new OpResult.SetDataResult(s));
+
+        MultiResponse decodedResponse = codeDecode(response);
+
+        assertEquals(response, decodedResponse);
+        assertEquals(response.hashCode(), decodedResponse.hashCode());
+    }
+
+    @Test
+    public void testEmptyRoundTrip() throws IOException {
+        MultiResponse result = new MultiResponse();
+        MultiResponse decodedResult = codeDecode(result);
+
+        assertEquals(result, decodedResult);
+        assertEquals(result.hashCode(), decodedResult.hashCode());
+    }
+
+    private MultiResponse codeDecode(MultiResponse request) throws IOException 
{
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        BinaryOutputArchive boa = BinaryOutputArchive.getArchive(baos);
+        request.serialize(boa, "result");
+        baos.close();
+        ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());
+        bb.rewind();
+
+        BinaryInputArchive bia = BinaryInputArchive.getArchive(new 
ByteBufferInputStream(bb));
+        MultiResponse decodedRequest = new MultiResponse();
+        decodedRequest.deserialize(bia, "result");
+        return decodedRequest;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/MultiTransactionRecordTest.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/MultiTransactionRecordTest.java
 
b/zookeeper-server/src/test/java/org/apache/zookeeper/MultiTransactionRecordTest.java
new file mode 100644
index 0000000..3749564
--- /dev/null
+++ 
b/zookeeper-server/src/test/java/org/apache/zookeeper/MultiTransactionRecordTest.java
@@ -0,0 +1,68 @@
+/**
+ * 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;
+
+import junit.framework.TestCase;
+import org.apache.jute.BinaryInputArchive;
+import org.apache.jute.BinaryOutputArchive;
+import org.apache.zookeeper.server.ByteBufferInputStream;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public class MultiTransactionRecordTest extends TestCase {
+    @Test
+    public void testRoundTrip() throws IOException {
+        MultiTransactionRecord request = new MultiTransactionRecord();
+        request.add(Op.check("check", 1));
+        request.add(Op.create("create", "create data".getBytes(), 
ZooDefs.Ids.CREATOR_ALL_ACL, ZooDefs.Perms.ALL));
+        request.add(Op.delete("delete", 17));
+        request.add(Op.setData("setData", "set data".getBytes(), 19));
+
+        MultiTransactionRecord decodedRequest = codeDecode(request);
+
+        assertEquals(request, decodedRequest);
+        assertEquals(request.hashCode(), decodedRequest.hashCode());
+    }
+
+    @Test
+    public void testEmptyRoundTrip() throws IOException {
+        MultiTransactionRecord request = new MultiTransactionRecord();
+        MultiTransactionRecord decodedRequest = codeDecode(request);
+
+        assertEquals(request, decodedRequest);
+        assertEquals(request.hashCode(), decodedRequest.hashCode());
+    }
+
+    private MultiTransactionRecord codeDecode(MultiTransactionRecord request) 
throws IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        BinaryOutputArchive boa = BinaryOutputArchive.getArchive(baos);
+        request.serialize(boa, "request");
+        baos.close();
+        ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());
+        bb.rewind();
+
+        BinaryInputArchive bia = BinaryInputArchive.getArchive(new 
ByteBufferInputStream(bb));
+        MultiTransactionRecord decodedRequest = new MultiTransactionRecord();
+        decodedRequest.deserialize(bia, "request");
+        return decodedRequest;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/PortAssignment.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/PortAssignment.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/PortAssignment.java
new file mode 100644
index 0000000..06f9361
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/PortAssignment.java
@@ -0,0 +1,35 @@
+/**
+ * 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;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Assign ports to tests */
+public class PortAssignment {
+    private static final Logger LOG = 
LoggerFactory.getLogger(PortAssignment.class);
+
+    private static int nextPort = 11221;
+
+    /** Assign a new, unique port to the test */
+    public synchronized static int unique() {
+        LOG.info("assigning port " + nextPort);
+        return nextPort++;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/SaslAuthTest.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/SaslAuthTest.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/SaslAuthTest.java
new file mode 100644
index 0000000..eac0703
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/SaslAuthTest.java
@@ -0,0 +1,213 @@
+/**
+ * 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;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.zookeeper.ClientCnxn.SendThread;
+import org.apache.zookeeper.Watcher.Event.KeeperState;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.apache.zookeeper.data.ACL;
+import org.apache.zookeeper.data.Id;
+import org.apache.zookeeper.test.ClientBase;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class SaslAuthTest extends ClientBase {
+    @BeforeClass
+    public static void init() {
+        System.setProperty("zookeeper.authProvider.1",
+                "org.apache.zookeeper.server.auth.SASLAuthenticationProvider");
+        try {
+            File tmpDir = createTmpDir();
+            File saslConfFile = new File(tmpDir, "jaas.conf");
+            String jaasContent = getJaasFileContent();
+            FileWriter fwriter = new FileWriter(saslConfFile);
+            fwriter.write(jaasContent);
+            fwriter.close();
+            System.setProperty("java.security.auth.login.config", 
saslConfFile.getAbsolutePath());
+        } catch (IOException e) {
+            // could not create tmp directory to hold JAAS conf file : test 
will
+            // fail now.
+        }
+    }
+
+    private static String getJaasFileContent() {
+        StringBuilder jaasContent=new StringBuilder();
+        String newLine = System.getProperty("line.separator");
+        jaasContent.append("Server {");
+        jaasContent.append(newLine);
+        jaasContent.append("org.apache.zookeeper.server.auth.DigestLoginModule 
required");
+        jaasContent.append(newLine);
+        jaasContent.append("user_super=\"test\";");
+        jaasContent.append(newLine);
+        jaasContent.append("};");
+        jaasContent.append(newLine);
+        jaasContent.append("Client {");
+        jaasContent.append(newLine);
+        jaasContent.append("org.apache.zookeeper.server.auth.DigestLoginModule 
required");
+        jaasContent.append(newLine);
+        jaasContent.append("username=\"super\"");
+        jaasContent.append(newLine);
+        jaasContent.append("password=\"test\";");
+        jaasContent.append(newLine);
+        jaasContent.append("};");
+        jaasContent.append(newLine);
+        return jaasContent.toString();
+    }
+
+    @AfterClass
+    public static void clean() {
+        System.clearProperty("zookeeper.authProvider.1");
+        System.clearProperty("java.security.auth.login.config");
+    }
+
+    private AtomicInteger authFailed = new AtomicInteger(0);
+    
+    @Override
+    protected TestableZooKeeper createClient(String hp)
+    throws IOException, InterruptedException
+    {
+        MyWatcher watcher = new MyWatcher();
+        return createClient(watcher, hp);
+    }
+
+    private class MyWatcher extends CountdownWatcher {
+        @Override
+        public synchronized void process(WatchedEvent event) {
+            if (event.getState() == KeeperState.AuthFailed) {
+                authFailed.incrementAndGet();
+            }
+            else {
+                super.process(event);
+            }
+        }
+    }
+
+    @Test
+    public void testAuth() throws Exception {
+        ZooKeeper zk = createClient();
+        try {
+            zk.create("/path1", null, Ids.CREATOR_ALL_ACL, 
CreateMode.PERSISTENT);
+            Thread.sleep(1000);
+        } finally {
+            zk.close();
+        }
+    }
+
+    @Test
+    public void testValidSaslIds() throws Exception {
+        ZooKeeper zk = createClient();
+
+        List<String> validIds = new ArrayList<String>();
+        validIds.add("user");
+        validIds.add("service/host.name.com");
+        validIds.add("user@KERB.REALM");
+        validIds.add("service/host.name.com@KERB.REALM");
+
+        int i = 0;
+        for(String validId: validIds) {
+            List<ACL> aclList = new ArrayList<ACL>();
+            ACL acl = new ACL(0,new Id("sasl",validId));
+            aclList.add(acl);
+            zk.create("/valid"+i,null,aclList,CreateMode.PERSISTENT);
+            i++;
+        }
+    }
+
+    @Test
+    public void testInvalidSaslIds() throws Exception {
+        ZooKeeper zk = createClient();
+
+        List<String> invalidIds = new ArrayList<String>();
+        invalidIds.add("user@KERB.REALM/server.com");
+        invalidIds.add("user@KERB.REALM1@KERB.REALM2");
+
+        int i = 0;
+        for(String invalidId: invalidIds) {
+            List<ACL> aclList = new ArrayList<ACL>();
+            try {
+                ACL acl = new ACL(0,new Id("sasl",invalidId));
+                aclList.add(acl);
+                zk.create("/invalid"+i,null,aclList,CreateMode.PERSISTENT);
+                Assert.fail("SASLAuthenticationProvider.isValid() failed to 
catch invalid Id.");
+            }
+            catch (KeeperException.InvalidACLException e) {
+                // ok.
+            }
+            finally {
+                i++;
+            }
+        }
+    }
+    
+    @Test
+    public void testZKOperationsAfterClientSaslAuthFailure() throws Exception {
+        CountdownWatcher watcher = new CountdownWatcher();
+        ZooKeeper zk = new ZooKeeper(hostPort, CONNECTION_TIMEOUT, watcher);
+        watcher.waitForConnected(CONNECTION_TIMEOUT);
+        try {
+            setSaslFailureFlag(zk);
+
+            // try node creation for around 15 second,
+            int totalTry = 10;
+            int tryCount = 0;
+
+            boolean success = false;
+            while (!success && tryCount++ <= totalTry) {
+                try {
+                    zk.create("/saslAuthFail", "data".getBytes(), 
Ids.OPEN_ACL_UNSAFE,
+                            CreateMode.PERSISTENT_SEQUENTIAL);
+                    success = true;
+                } catch (KeeperException.ConnectionLossException e) {
+                    Thread.sleep(1000);
+                    // do nothing
+                }
+            }
+            assertTrue("ZNode creation is failing continuously after Sasl auth 
failure.", success);
+
+        } finally {
+            zk.close();
+        }
+    }
+
+    // set saslLoginFailed to true to simulate the LoginException
+    private void setSaslFailureFlag(ZooKeeper zk) throws Exception {
+        Field cnxnField = zk.getClass().getDeclaredField("cnxn");
+        cnxnField.setAccessible(true);
+        ClientCnxn clientCnxn = (ClientCnxn) cnxnField.get(zk);
+        Field sendThreadField = 
clientCnxn.getClass().getDeclaredField("sendThread");
+        sendThreadField.setAccessible(true);
+        SendThread sendThread = (SendThread) sendThreadField.get(clientCnxn);
+        Field saslLoginFailedField = 
sendThread.getClass().getDeclaredField("saslLoginFailed");
+        saslLoginFailedField.setAccessible(true);
+        saslLoginFailedField.setBoolean(sendThread, true);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/ServerConfigTest.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/ServerConfigTest.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/ServerConfigTest.java
new file mode 100644
index 0000000..27faa74
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/ServerConfigTest.java
@@ -0,0 +1,74 @@
+/**
+ * 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;
+
+import org.apache.zookeeper.server.ServerConfig;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+
+public class ServerConfigTest {
+
+    private ServerConfig serverConfig;
+
+    @Before
+    public void setUp() {
+        serverConfig = new ServerConfig();
+    }
+
+    @Test(expected=IllegalArgumentException.class)
+    public void testFewArguments() {
+        String[] args = {"2181"};
+        serverConfig.parse(args);
+    }
+
+    @Test
+    public void testValidArguments() {
+        String[] args = {"2181", "/data/dir", "60000", "10000"};
+        serverConfig.parse(args);
+
+        assertEquals(2181, serverConfig.getClientPortAddress().getPort());
+        assertTrue(checkEquality("/data/dir", serverConfig.getDataDir()));
+        assertEquals(60000, serverConfig.getTickTime());
+        assertEquals(10000, serverConfig.getMaxClientCnxns());
+    }
+
+    @Test(expected=IllegalArgumentException.class)
+    public void testTooManyArguments() {
+        String[] args = {"2181", "/data/dir", "60000", "10000", "9999"};
+        serverConfig.parse(args);
+    }
+
+    boolean checkEquality(String a, String b) {
+        assertNotNull(a);
+        assertNotNull(b);
+        return a.equals(b);
+    }
+
+    boolean checkEquality(String a, File b) {
+        assertNotNull(a);
+        assertNotNull(b);
+        return new File(a).equals(b);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/TestableZooKeeper.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/TestableZooKeeper.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/TestableZooKeeper.java
new file mode 100644
index 0000000..dd70056
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/TestableZooKeeper.java
@@ -0,0 +1,133 @@
+/**
+ * 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;
+
+import java.io.IOException;
+import java.net.SocketAddress;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.jute.Record;
+import org.apache.zookeeper.proto.ReplyHeader;
+import org.apache.zookeeper.proto.RequestHeader;
+
+public class TestableZooKeeper extends ZooKeeper {
+
+    public TestableZooKeeper(String host, int sessionTimeout,
+            Watcher watcher) throws IOException {
+        super(host, sessionTimeout, watcher);
+    }
+    
+    @Override
+    public List<String> getChildWatches() {
+        return super.getChildWatches();
+    }
+
+
+    @Override
+    public List<String> getDataWatches() {
+        return super.getDataWatches();
+    }
+
+
+    @Override
+    public List<String> getExistWatches() {
+        return super.getExistWatches();
+    }
+
+    /**
+     * Cause this ZooKeeper object to disconnect from the server. It will then
+     * later attempt to reconnect.
+     */
+    public void testableConnloss() throws IOException {
+        synchronized(cnxn) {
+            cnxn.sendThread.testableCloseSocket();
+        }
+    }
+
+    /**
+     * Cause this ZooKeeper object to stop receiving from the ZooKeeperServer
+     * for the given number of milliseconds.
+     * @param ms the number of milliseconds to pause.
+     * @return true if the connection is paused, otherwise false
+     */
+    public boolean pauseCnxn(final long ms) {
+        final CountDownLatch initiatedPause = new CountDownLatch(1);
+        new Thread() {
+            public void run() {
+                synchronized(cnxn) {
+                    try {
+                        try {
+                            cnxn.sendThread.testableCloseSocket();
+                        } catch (IOException e) {
+                            e.printStackTrace();
+                        } finally {
+                            initiatedPause.countDown();
+                        }
+                        Thread.sleep(ms);
+                    } catch (InterruptedException e) {
+                    }
+                }
+            }
+        }.start();
+
+        try {
+            return initiatedPause.await(ms, TimeUnit.MILLISECONDS);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+    
+    public boolean testableWaitForShutdown(int wait)
+        throws InterruptedException
+    {
+        return super.testableWaitForShutdown(wait);
+    }
+
+    public SocketAddress testableLocalSocketAddress() {
+        return super.testableLocalSocketAddress();
+    }
+
+    public SocketAddress testableRemoteSocketAddress() {
+        return super.testableRemoteSocketAddress();
+    }
+
+    /**
+     * @return the last zxid as seen by the client session
+     */
+    public long testableLastZxid() {
+        return cnxn.getLastZxid();
+    }
+
+    public ReplyHeader submitRequest(RequestHeader h, Record request,
+            Record response, WatchRegistration watchRegistration) throws 
InterruptedException {
+        return cnxn.submitRequest(h, request, response, watchRegistration);
+    }
+
+    /** Testing only!!! Really!!!! This is only here to test when the client
+     * disconnects from the server w/o sending a session disconnect (ie
+     * ending the session cleanly). The server will eventually notice the
+     * client is no longer pinging and will timeout the session.
+     */
+    public void disconnect() {
+        cnxn.disconnect();
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/VerGenTest.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/VerGenTest.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/VerGenTest.java
new file mode 100644
index 0000000..607edbb
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/VerGenTest.java
@@ -0,0 +1,78 @@
+/**
+ * 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;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.zookeeper.test.ClientBase;
+import org.apache.zookeeper.version.util.VerGen;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+
+/**
+ * Test VerGen, used during the build.
+ *
+ */
+@RunWith(Parameterized.class)
+public class VerGenTest extends ZKTestCase {
+    @Parameters
+    public static Collection<Object[]> data() {
+            return Arrays.asList(new Object[][] {
+                            {"1.2.3", new Object[] {1, 2, 3, null}},
+                            {"1.2.3-dev", new Object[] {1, 2, 3, "dev"}},
+                            {"1.2.3-SNAPSHOT", new Object[] {1, 2, 3, 
"SNAPSHOT"}},
+                            {"1.2.3-SNAPSHOT", new Object[] {1, 2, 3, 
"SNAPSHOT"}},
+                            {"1.2.3-foo-bar+123", new Object[] {1, 2, 3, 
"foo-bar+123"}},
+                            {"1.2.3.4.5-SNAPSHOT", new Object[] {1, 2, 3, 
"SNAPSHOT"}},
+                            {"1.2.3.4.5-foo-bar+123", new Object[] {1, 2, 3, 
"foo-bar+123"}}
+            });
+    }
+
+    private String input;
+
+    private Object[] expected;
+
+    public VerGenTest(String input, Object[] expected) {
+        this.input = input;
+        this.expected = expected;
+    }
+
+    @Test
+    public void testParser() {
+        VerGen.Version v = VerGen.parseVersionString(input);
+        Assert.assertEquals(expected[0], v.maj);
+        Assert.assertEquals(expected[1], v.min);
+        Assert.assertEquals(expected[2], v.micro);
+        Assert.assertEquals(expected[3], v.qualifier);
+    }
+
+    @Test
+    public void testGenFile() throws Exception {
+        VerGen.Version v = VerGen.parseVersionString(input);
+        File outputDir = ClientBase.createTmpDir();
+        VerGen.generateFile(outputDir, v, "1", "Nov1");
+        ClientBase.recursiveDelete(outputDir);
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/ZKTestCase.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/ZKTestCase.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/ZKTestCase.java
new file mode 100644
index 0000000..9098fc4
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/ZKTestCase.java
@@ -0,0 +1,88 @@
+/**
+ * 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;
+
+import org.junit.Assume;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.junit.Rule;
+import org.junit.rules.MethodRule;
+import org.junit.rules.TestWatchman;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.FrameworkMethod;
+
+import java.io.IOException;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+
+/**
+ * Base class for a non-parameterized ZK test.
+ *
+ * Basic utilities shared by all tests. Also logging of various events during
+ * the test execution (start/stop/success/failure/etc...)
+ */
+@RunWith(JUnit4ZKTestRunner.class)
+public class ZKTestCase {
+    private static final Logger LOG = 
LoggerFactory.getLogger(ZKTestCase.class);
+
+    private String testName;
+
+    protected String getTestName() {
+        return testName;
+    }
+
+    @Rule
+    public MethodRule watchman = new TestWatchman() {
+        @Override
+        public void starting(FrameworkMethod method) {
+            testName = method.getName();
+            // ZOOKEEPER-2693 disables all 4lw by default.
+            // Here we enable the 4lw which ZooKeeper tests depends.
+            System.setProperty("zookeeper.4lw.commands.whitelist", "*");
+
+            LOG.info("STARTING " + testName);
+        }
+
+        @Override
+        public void finished(FrameworkMethod method) {
+            LOG.info("FINISHED " + testName);
+        }
+
+        @Override
+        public void succeeded(FrameworkMethod method) {
+            LOG.info("SUCCEEDED " + testName);
+        }
+
+        @Override
+        public void failed(Throwable e, FrameworkMethod method) {
+            LOG.info("FAILED " + testName, e);
+        }
+
+    };
+
+    protected void assumeIPv6Available() {
+        try {
+            InetAddress address = Inet6Address.getByName("0:0:0:0:0:0:0:1");
+            Assume.assumeTrue(address.isReachable(1000));
+        } catch (IOException exception) {
+            Assume.assumeTrue(false);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/ZooKeeperTest.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/ZooKeeperTest.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/ZooKeeperTest.java
new file mode 100644
index 0000000..2cdc4cb
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/ZooKeeperTest.java
@@ -0,0 +1,281 @@
+/**
+ * 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;
+
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.zookeeper.AsyncCallback.VoidCallback;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.apache.zookeeper.test.ClientBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * 
+ * Testing Zookeeper public methods
+ *
+ */
+public class ZooKeeperTest extends ClientBase {
+
+    @Test
+    public void testDeleteRecursive() throws IOException, InterruptedException,
+            KeeperException {
+        final ZooKeeper zk = createClient();
+        // making sure setdata works on /
+        zk.setData("/", "some".getBytes(), -1);
+        zk.create("/a", "some".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+
+        zk.create("/a/b", "some".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+
+        zk.create("/a/b/v", "some".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+
+        zk.create("/a/b/v/1", "some".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+
+        zk.create("/a/c", "some".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+
+        zk.create("/a/c/v", "some".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+
+        List<String> children = zk.getChildren("/a", false);
+
+        Assert.assertEquals("2 children - b & c should be present ", children
+                .size(), 2);
+        Assert.assertTrue(children.contains("b"));
+        Assert.assertTrue(children.contains("c"));
+
+        ZKUtil.deleteRecursive(zk, "/a");
+        Assert.assertNull(zk.exists("/a", null));
+    }
+
+    @Test
+    public void testDeleteRecursiveAsync() throws IOException,
+            InterruptedException, KeeperException {
+        final ZooKeeper zk = createClient();
+        // making sure setdata works on /
+        zk.setData("/", "some".getBytes(), -1);
+        zk.create("/a", "some".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+
+        zk.create("/a/b", "some".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+
+        zk.create("/a/b/v", "some".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+
+        zk.create("/a/b/v/1", "some".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+
+        zk.create("/a/c", "some".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+
+        zk.create("/a/c/v", "some".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                CreateMode.PERSISTENT);
+
+        for (int i = 0; i < 50; ++i) {
+            zk.create("/a/c/" + i, "some".getBytes(), Ids.OPEN_ACL_UNSAFE,
+                    CreateMode.PERSISTENT);
+        }
+        List<String> children = zk.getChildren("/a", false);
+
+        Assert.assertEquals("2 children - b & c should be present ", children
+                .size(), 2);
+        Assert.assertTrue(children.contains("b"));
+        Assert.assertTrue(children.contains("c"));
+
+        VoidCallback cb = new VoidCallback() {
+
+            @Override
+            public void processResult(int rc, String path, Object ctx) {
+                synchronized (ctx) {
+                    ((AtomicInteger) ctx).set(4);
+                    ctx.notify();
+                }
+            }
+
+        };
+        final AtomicInteger ctx = new AtomicInteger(3);
+        ZKUtil.deleteRecursive(zk, "/a", cb, ctx);
+        synchronized (ctx) {
+            ctx.wait();
+        }
+        Assert.assertEquals(4, ((AtomicInteger) ctx).get());
+    }
+    
+    @Test
+    public void testStatWhenPathDoesNotExist() throws IOException,
+               InterruptedException {
+       final ZooKeeper zk = createClient();
+       ZooKeeperMain main = new ZooKeeperMain(zk);
+       String cmdstring = "stat /invalidPath";
+       main.cl.parseCommand(cmdstring);
+       try {
+               main.processZKCmd(main.cl);
+               Assert.fail("As Node does not exist, command should fail by 
throwing No Node Exception.");
+       } catch (KeeperException e) {
+               Assert.assertEquals("KeeperErrorCode = NoNode for 
/invalidPath", e.getMessage());
+       }
+    }
+
+    @Test
+    public void testParseWithExtraSpaces() throws Exception {
+        final ZooKeeper zk = createClient();
+        ZooKeeperMain zkMain = new ZooKeeperMain(zk);
+        String cmdstring = "      ls       /  ";
+        zkMain.cl.parseCommand(cmdstring);
+        Assert.assertEquals("Spaces also considered as characters", 
zkMain.cl.getNumArguments(), 2);
+        Assert.assertEquals("ls is not taken as first argument", 
zkMain.cl.getCmdArgument(0), "ls");
+        Assert.assertEquals("/ is not taken as second argument", 
zkMain.cl.getCmdArgument(1), "/");
+    }
+
+    @Test
+    public void testCheckInvalidAcls() throws Exception {
+         final ZooKeeper zk = createClient();
+            ZooKeeperMain zkMain = new ZooKeeperMain(zk);
+            String cmdstring = "create -s -e /node data ip:scheme:gggsd"; 
//invalid acl's
+            try{
+                 zkMain.executeLine(cmdstring);
+            }catch(KeeperException.InvalidACLException e){
+                fail("For Invalid ACls should not throw exception");
+            }
+    }
+
+    @Test
+    public void testDeleteWithInvalidVersionNo() throws Exception {
+         final ZooKeeper zk = createClient();
+            ZooKeeperMain zkMain = new ZooKeeperMain(zk);
+            String cmdstring = "create -s -e /node1 data "; 
+            String cmdstring1 = "delete /node1 2";//invalid dataversion no
+                 zkMain.executeLine(cmdstring);
+           try{
+               zkMain.executeLine(cmdstring1);
+                     
+            }catch(KeeperException.BadVersionException e){
+                fail("For Invalid dataversion number should not throw 
exception");
+            }
+    }
+
+    @Test
+    public void testCliCommandsNotEchoingUsage() throws Exception {
+            // setup redirect out/err streams to get System.in/err, use this 
judiciously!
+           final PrintStream systemErr = System.err; // get current err
+           final ByteArrayOutputStream errContent = new 
ByteArrayOutputStream();
+           System.setErr(new PrintStream(errContent));
+           final ZooKeeper zk = createClient();
+           ZooKeeperMain zkMain = new ZooKeeperMain(zk);
+           String cmd1 = "printwatches";
+           zkMain.executeLine(cmd1);
+           String cmd2 = "history";
+           zkMain.executeLine(cmd2);
+           String cmd3 = "redo";
+           zkMain.executeLine(cmd3);
+           // revert redirect of out/err streams - important step!
+           System.setErr(systemErr);
+           if (errContent.toString().contains("ZooKeeper -server host:port cmd 
args")) {
+                fail("CLI commands (history, redo, connect, printwatches) 
display usage info!");
+            }
+    }
+
+     @Test
+    public void testParseWithQuotes() throws Exception {
+        final ZooKeeper zk = createClient();
+        ZooKeeperMain zkMain = new ZooKeeperMain(zk);
+        for (String quoteChar : new String[] {"'", "\""}) {
+            String cmdstring = String.format("create /node %1$squoted 
data%1$s", quoteChar);
+            zkMain.cl.parseCommand(cmdstring);
+            Assert.assertEquals("quotes combine arguments", 
zkMain.cl.getNumArguments(), 3);
+            Assert.assertEquals("create is not taken as first argument", 
zkMain.cl.getCmdArgument(0), "create");
+            Assert.assertEquals("/node is not taken as second argument", 
zkMain.cl.getCmdArgument(1), "/node");
+            Assert.assertEquals("quoted data is not taken as third argument", 
zkMain.cl.getCmdArgument(2), "quoted data");
+        }
+    }
+
+    @Test
+    public void testParseWithMixedQuotes() throws Exception {
+        final ZooKeeper zk = createClient();
+        ZooKeeperMain zkMain = new ZooKeeperMain(zk);
+        for (String[] quoteChars : new String[][] {{"'", "\""}, {"\"", "'"}}) {
+            String outerQuotes = quoteChars[0];
+            String innerQuotes = quoteChars[1];
+            String cmdstring = String.format("create /node %1$s%2$squoted 
data%2$s%1$s", outerQuotes, innerQuotes);
+            zkMain.cl.parseCommand(cmdstring);
+            Assert.assertEquals("quotes combine arguments", 
zkMain.cl.getNumArguments(), 3);
+            Assert.assertEquals("create is not taken as first argument", 
zkMain.cl.getCmdArgument(0), "create");
+            Assert.assertEquals("/node is not taken as second argument", 
zkMain.cl.getCmdArgument(1), "/node");
+            Assert.assertEquals("quoted data is not taken as third argument", 
zkMain.cl.getCmdArgument(2), innerQuotes + "quoted data" + innerQuotes);
+        }
+    }
+
+    @Test
+    public void testParseWithEmptyQuotes() throws Exception {
+        final ZooKeeper zk = createClient();
+        ZooKeeperMain zkMain = new ZooKeeperMain(zk);
+        String cmdstring = "create /node ''";
+        zkMain.cl.parseCommand(cmdstring);
+        Assert.assertEquals("empty quotes should produce arguments", 
zkMain.cl.getNumArguments(), 3);
+        Assert.assertEquals("create is not taken as first argument", 
zkMain.cl.getCmdArgument(0), "create");
+        Assert.assertEquals("/node is not taken as second argument", 
zkMain.cl.getCmdArgument(1), "/node");
+        Assert.assertEquals("empty string is not taken as third argument", 
zkMain.cl.getCmdArgument(2), "");
+    }
+
+    @Test
+    public void testParseWithMultipleQuotes() throws Exception {
+        final ZooKeeper zk = createClient();
+        ZooKeeperMain zkMain = new ZooKeeperMain(zk);
+        String cmdstring = "create /node '' ''";
+        zkMain.cl.parseCommand(cmdstring);
+        Assert.assertEquals("expected 5 arguments", 
zkMain.cl.getNumArguments(), 4);
+        Assert.assertEquals("create is not taken as first argument", 
zkMain.cl.getCmdArgument(0), "create");
+        Assert.assertEquals("/node is not taken as second argument", 
zkMain.cl.getCmdArgument(1), "/node");
+        Assert.assertEquals("empty string is not taken as third argument", 
zkMain.cl.getCmdArgument(2), "");
+        Assert.assertEquals("empty string is not taken as fourth argument", 
zkMain.cl.getCmdArgument(3), "");
+    }
+
+    // ZOOKEEPER-2467 : Testing negative number for redo command
+    @Test
+    public void testRedoWithNegativeCmdNumber() throws Exception {
+        final ZooKeeper zk = createClient();
+        ZooKeeperMain zkMain = new ZooKeeperMain(zk);
+        String cmd1 = "redo -1";
+
+        // setup redirect out/err streams to get System.in/err, use this
+        // judiciously!
+        final PrintStream systemOut = System.out; // get current out
+        final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
+        System.setOut(new PrintStream(outContent));
+        try {
+            zkMain.executeLine(cmd1);
+            Assert.assertEquals("Command index out of range", outContent
+                    .toString().trim());
+        } finally {
+            // revert redirect of out/err streams - important step!
+            System.setOut(systemOut);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/common/TimeTest.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/common/TimeTest.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/common/TimeTest.java
new file mode 100644
index 0000000..d938556
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/common/TimeTest.java
@@ -0,0 +1,109 @@
+/**
+ * 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.common;
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.test.ClientBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Command line program for demonstrating robustness to clock
+ * changes.
+ * <p/>
+ * How to run:
+ * ant clean compile-test
+ * echo build/test/lib/*.jar build/lib/*.jar build/classes build/test/classes 
| sed -e 's/ /:/g' > cp
+ * java -cp $(cat cp) org.apache.zookeeper.common.TimeTest | tee 
log-without-patch
+ * <p/>
+ * After test program starts, in another window, do commands:
+ * date -s '+1hour'
+ * date -s '-1hour'
+ * <p/>
+ * As long as there isn't any expired event, the experiment is successful.
+ */
+public class TimeTest extends ClientBase {
+    private static final long mt0 = System.currentTimeMillis();
+    private static final long nt0 = Time.currentElapsedTime();
+
+    private static AtomicInteger watchCount = new AtomicInteger(0);
+
+
+    public static void main(String[] args) throws Exception {
+        System.out.printf("Starting\n");
+        final TimeTest test = new TimeTest();
+        System.out.printf("After construct\n");
+        test.setUp();
+        ZooKeeper zk = test.createClient();
+        zk.create("/ephemeral", new byte[]{1, 2, 3},
+                ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
+        while (Time.currentElapsedTime() - nt0 < 100000) {
+            System.out.printf("%d\t%s\n", discrepancy(),
+                    zk.exists("/ephemeral",
+                            watchCount.get() == 0 ? createWatcher() : null) != 
null);
+            waitByYielding(500);
+        }
+    }
+
+    private static Watcher createWatcher() {
+        watchCount.incrementAndGet();
+        return new Watcher() {
+            @Override
+            public void process(WatchedEvent event) {
+                watchCount.decrementAndGet();
+                System.out.printf("%d event = %s\n", discrepancy(), event);
+            }
+        };
+
+    }
+
+    private static void waitByYielding(long delay) {
+        long t0 = Time.currentElapsedTime();
+        while (Time.currentElapsedTime() < t0 + delay) {
+            Thread.yield();
+        }
+    }
+
+    private static long discrepancy() {
+        return (System.currentTimeMillis() - mt0) - (Time.currentElapsedTime() 
- nt0);
+    }
+
+    @Test
+    public void testElapsedTimeToDate() throws Exception {
+        long walltime = Time.currentWallTime();
+        long elapsedTime = Time.currentElapsedTime();
+        Thread.sleep(200);
+
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(Time.elapsedTimeToDate(elapsedTime));
+        int calculatedDate = cal.get(Calendar.HOUR_OF_DAY);
+        cal.setTime(new Date(walltime));
+        int realDate = cal.get(Calendar.HOUR_OF_DAY);
+
+        Assert.assertEquals(calculatedDate, realDate);
+    }
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/ACLCountTest.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/test/ACLCountTest.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/test/ACLCountTest.java
new file mode 100644
index 0000000..88b8869
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/ACLCountTest.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 static org.apache.zookeeper.test.ClientBase.CONNECTION_TIMEOUT;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.PortAssignment;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZKTestCase;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.Watcher.Event.KeeperState;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.apache.zookeeper.data.ACL;
+import org.apache.zookeeper.data.Stat;
+import org.apache.zookeeper.server.ServerCnxnFactory;
+import org.apache.zookeeper.server.SyncRequestProcessor;
+import org.apache.zookeeper.server.ZooKeeperServer;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ACLCountTest extends ZKTestCase implements Watcher {
+    private static final Logger LOG = LoggerFactory.getLogger(ACLTest.class);
+    private static final String HOSTPORT =
+        "127.0.0.1:" + PortAssignment.unique();
+    private volatile CountDownLatch startSignal;
+
+    /**
+     *
+     * Create a node and add 4 ACL values to it, but there are only 2 unique 
ACL values,
+     * and each is repeated once:
+     *
+     *   ACL(ZooDefs.Perms.READ,ZooDefs.Ids.ANYONE_ID_UNSAFE);
+     *   ACL(ZooDefs.Perms.ALL,ZooDefs.Ids.AUTH_IDS);
+     *   ACL(ZooDefs.Perms.READ,ZooDefs.Ids.ANYONE_ID_UNSAFE);
+     *   ACL(ZooDefs.Perms.ALL,ZooDefs.Ids.AUTH_IDS);
+     *
+     * Even though we've added 4 ACL values, there should only be 2 ACLs for 
that node,
+     * since there are only 2 *unique* ACL values.
+     */
+    @Test
+    public void testAclCount() throws Exception {
+        File tmpDir = ClientBase.createTmpDir();
+        ClientBase.setupTestEnv();
+        ZooKeeperServer zks = new ZooKeeperServer(tmpDir, tmpDir, 3000);
+        SyncRequestProcessor.setSnapCount(1000);
+        final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]);
+        ServerCnxnFactory f = ServerCnxnFactory.createFactory(PORT, -1);
+        f.startup(zks);
+        ZooKeeper zk;
+
+        final ArrayList<ACL> CREATOR_ALL_AND_WORLD_READABLE =
+          new ArrayList<ACL>() { {
+            add(new ACL(ZooDefs.Perms.READ,ZooDefs.Ids.ANYONE_ID_UNSAFE));
+            add(new ACL(ZooDefs.Perms.ALL,ZooDefs.Ids.AUTH_IDS));
+            add(new ACL(ZooDefs.Perms.READ,ZooDefs.Ids.ANYONE_ID_UNSAFE));
+            add(new ACL(ZooDefs.Perms.ALL,ZooDefs.Ids.AUTH_IDS));
+        }};
+
+        try {
+            LOG.info("starting up the zookeeper server .. waiting");
+            Assert.assertTrue("waiting for server being up",
+                    ClientBase.waitForServerUp(HOSTPORT, CONNECTION_TIMEOUT));
+            zk = new ZooKeeper(HOSTPORT, CONNECTION_TIMEOUT, this);
+
+            zk.addAuthInfo("digest", "pat:test".getBytes());
+            zk.setACL("/", Ids.CREATOR_ALL_ACL, -1);
+
+            String path = "/path";
+
+            try {
+              Assert.assertEquals(4,CREATOR_ALL_AND_WORLD_READABLE.size());
+            }
+            catch (Exception e) {
+              LOG.error("Something is fundamentally wrong with ArrayList's 
add() method. add()ing four times to an empty ArrayList should result in an 
ArrayList with 4 members.");
+              throw e;
+            }
+
+            
zk.create(path,path.getBytes(),CREATOR_ALL_AND_WORLD_READABLE,CreateMode.PERSISTENT);
+            List<ACL> acls = zk.getACL("/path", new Stat());
+            Assert.assertEquals(2,acls.size());
+        }
+        catch (Exception e) {
+          // test failed somehow.
+          Assert.assertTrue(false);
+        }
+
+        f.shutdown();
+        zks.shutdown();
+    }
+
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see 
org.apache.zookeeper.Watcher#process(org.apache.zookeeper.WatcherEvent)
+     */
+    public void process(WatchedEvent event) {
+        LOG.info("Event:" + event.getState() + " " + event.getType() + " "
+                 + event.getPath());
+        if (event.getState() == KeeperState.SyncConnected) {
+            if (startSignal != null && startSignal.getCount() > 0) {
+                LOG.info("startsignal.countDown()");
+                startSignal.countDown();
+            } else {
+                LOG.warn("startsignal " + startSignal);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/ACLRootTest.java
----------------------------------------------------------------------
diff --git 
a/zookeeper-server/src/test/java/org/apache/zookeeper/test/ACLRootTest.java 
b/zookeeper-server/src/test/java/org/apache/zookeeper/test/ACLRootTest.java
new file mode 100644
index 0000000..7307cbf
--- /dev/null
+++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/ACLRootTest.java
@@ -0,0 +1,98 @@
+/**
+ * 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 org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.ZooDefs.Ids;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ACLRootTest extends ClientBase {
+    private static final Logger LOG = 
LoggerFactory.getLogger(ACLRootTest.class);
+
+    @Test
+    public void testRootAcl() throws Exception {
+        ZooKeeper zk = createClient();
+        try {
+            // set auth using digest
+            zk.addAuthInfo("digest", "pat:test".getBytes());
+            zk.setACL("/", Ids.CREATOR_ALL_ACL, -1);
+            zk.getData("/", false, null);
+            zk.close();
+            // verify no access
+            zk = createClient();
+            try {
+                zk.getData("/", false, null);
+                Assert.fail("validate auth");
+            } catch (KeeperException.NoAuthException e) {
+                // expected
+            }
+            try {
+                zk.create("/apps", null, Ids.CREATOR_ALL_ACL,
+                        CreateMode.PERSISTENT);
+                Assert.fail("validate auth");
+            } catch (KeeperException.InvalidACLException e) {
+                // expected
+            }
+            zk.addAuthInfo("digest", "world:anyone".getBytes());
+            try {
+                zk.create("/apps", null, Ids.CREATOR_ALL_ACL,
+                        CreateMode.PERSISTENT);
+                Assert.fail("validate auth");
+            } catch (KeeperException.NoAuthException e) {
+                // expected
+            }
+            zk.close();
+            // verify access using original auth
+            zk = createClient();
+            zk.addAuthInfo("digest", "pat:test".getBytes());
+            zk.getData("/", false, null);
+            zk.create("/apps", null, Ids.CREATOR_ALL_ACL,
+                    CreateMode.PERSISTENT);
+            zk.delete("/apps", -1);
+            // reset acl (back to open) and verify accessible again
+            zk.setACL("/", Ids.OPEN_ACL_UNSAFE, -1);
+            zk.close();
+            zk = createClient();
+            zk.getData("/", false, null);
+            zk.create("/apps", null, Ids.OPEN_ACL_UNSAFE,
+                    CreateMode.PERSISTENT);
+            try {
+                zk.create("/apps", null, Ids.CREATOR_ALL_ACL,
+                        CreateMode.PERSISTENT);
+                Assert.fail("validate auth");
+            } catch (KeeperException.InvalidACLException e) {
+                // expected
+            }
+            zk.delete("/apps", -1);
+            zk.addAuthInfo("digest", "world:anyone".getBytes());
+            zk.create("/apps", null, Ids.CREATOR_ALL_ACL,
+                    CreateMode.PERSISTENT);
+            zk.close();
+            zk = createClient();
+            zk.delete("/apps", -1);
+        } finally {
+            zk.close();
+        }
+    }
+}

Reply via email to