From commits-return-7310-archive-asf-public=cust-asf.ponee.io@zookeeper.apache.org Wed Oct 24 11:32:21 2018 Return-Path: X-Original-To: archive-asf-public@cust-asf.ponee.io Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx-eu-01.ponee.io (Postfix) with SMTP id F2107180718 for ; Wed, 24 Oct 2018 11:32:18 +0200 (CEST) Received: (qmail 85488 invoked by uid 500); 24 Oct 2018 09:32:18 -0000 Mailing-List: contact commits-help@zookeeper.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@zookeeper.apache.org Delivered-To: mailing list commits@zookeeper.apache.org Received: (qmail 85150 invoked by uid 99); 24 Oct 2018 09:32:17 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 24 Oct 2018 09:32:17 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id B651CE1121; Wed, 24 Oct 2018 09:32:17 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: andor@apache.org To: commits@zookeeper.apache.org Date: Wed, 24 Oct 2018 09:32:20 -0000 Message-Id: <687fa887621142a48d794a79e79a1a53@git.apache.org> In-Reply-To: <0d0a9cdffdf445fca95a27db2fa4a2e1@git.apache.org> References: <0d0a9cdffdf445fca95a27db2fa4a2e1@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [04/36] zookeeper git commit: ZOOKEEPER-3032: MAVEN MIGRATION - branch-3.4 - zookeeper-server http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/ReadOnlyModeTest.java ---------------------------------------------------------------------- diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/ReadOnlyModeTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/ReadOnlyModeTest.java new file mode 100644 index 0000000..6f281d9 --- /dev/null +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/ReadOnlyModeTest.java @@ -0,0 +1,291 @@ +/** + * 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.ByteArrayOutputStream; +import java.io.LineNumberReader; +import java.io.StringReader; +import java.util.regex.Pattern; + +import junit.framework.Assert; + +import org.apache.log4j.Layout; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.apache.log4j.WriterAppender; +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.KeeperException.NotReadOnlyException; +import org.apache.zookeeper.Transaction; +import org.apache.zookeeper.ZKTestCase; +import org.apache.zookeeper.ZooDefs; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.ZooKeeper.States; +import org.apache.zookeeper.common.Time; +import org.apache.zookeeper.test.ClientBase.CountdownWatcher; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.slf4j.LoggerFactory; + + +public class ReadOnlyModeTest extends ZKTestCase { + private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(ReadOnlyModeTest.class); + private static int CONNECTION_TIMEOUT = QuorumBase.CONNECTION_TIMEOUT; + private QuorumUtil qu = new QuorumUtil(1); + + @Before + public void setUp() throws Exception { + System.setProperty("readonlymode.enabled", "true"); + qu.startQuorum(); + } + + @After + public void tearDown() throws Exception { + System.setProperty("readonlymode.enabled", "false"); + qu.tearDown(); + } + + /** + * Test write operations using multi request. + */ + @Test(timeout = 90000) + public void testMultiTransaction() throws Exception { + CountdownWatcher watcher = new CountdownWatcher(); + ZooKeeper zk = new ZooKeeper(qu.getConnString(), CONNECTION_TIMEOUT, + watcher, true); + watcher.waitForConnected(CONNECTION_TIMEOUT); // ensure zk got connected + + final String data = "Data to be read in RO mode"; + final String node1 = "/tnode1"; + final String node2 = "/tnode2"; + zk.create(node1, data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, + CreateMode.PERSISTENT); + + watcher.reset(); + qu.shutdown(2); + watcher.waitForConnected(CONNECTION_TIMEOUT); + Assert.assertEquals("Should be in r-o mode", States.CONNECTEDREADONLY, + zk.getState()); + + // read operation during r/o mode + String remoteData = new String(zk.getData(node1, false, null)); + Assert.assertEquals("Failed to read data in r-o mode", data, remoteData); + + try { + Transaction transaction = zk.transaction(); + transaction.setData(node1, "no way".getBytes(), -1); + transaction.create(node2, data.getBytes(), + ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); + transaction.commit(); + Assert.fail("Write operation using multi-transaction" + + " api has succeeded during RO mode"); + } catch (NotReadOnlyException e) { + // ok + } + + Assert.assertNull("Should have created the znode:" + node2, + zk.exists(node2, false)); + } + + /** + * Basic test of read-only client functionality. Tries to read and write + * during read-only mode, then regains a quorum and tries to write again. + */ + @Test(timeout = 90000) + public void testReadOnlyClient() throws Exception { + CountdownWatcher watcher = new CountdownWatcher(); + ZooKeeper zk = new ZooKeeper(qu.getConnString(), CONNECTION_TIMEOUT, + watcher, true); + watcher.waitForConnected(CONNECTION_TIMEOUT); // ensure zk got connected + + final String data = "Data to be read in RO mode"; + final String node = "/tnode"; + zk.create(node, data.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, + CreateMode.PERSISTENT); + + watcher.reset(); + qu.shutdown(2); + watcher.waitForConnected(CONNECTION_TIMEOUT); + + // read operation during r/o mode + String remoteData = new String(zk.getData(node, false, null)); + Assert.assertEquals(data, remoteData); + + try { + zk.setData(node, "no way".getBytes(), -1); + Assert.fail("Write operation has succeeded during RO mode"); + } catch (NotReadOnlyException e) { + // ok + } + + watcher.reset(); + qu.start(2); + Assert.assertTrue("waiting for server up", ClientBase.waitForServerUp( + "127.0.0.1:" + qu.getPeer(2).clientPort, CONNECTION_TIMEOUT)); + watcher.waitForConnected(CONNECTION_TIMEOUT); + zk.setData(node, "We're in the quorum now".getBytes(), -1); + + zk.close(); + } + + /** + * Ensures that upon connection to a read-only server client receives + * ConnectedReadOnly state notification. + */ + @Test(timeout = 90000) + public void testConnectionEvents() throws Exception { + CountdownWatcher watcher = new CountdownWatcher(); + ZooKeeper zk = new ZooKeeper(qu.getConnString(), CONNECTION_TIMEOUT, + watcher, true); + boolean success = false; + for (int i = 0; i < 30; i++) { + try { + zk.create("/test", "test".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, + CreateMode.PERSISTENT); + success=true; + break; + } catch(KeeperException.ConnectionLossException e) { + Thread.sleep(1000); + } + } + Assert.assertTrue("Did not succeed in connecting in 30s", success); + Assert.assertFalse("The connection should not be read-only yet", watcher.readOnlyConnected); + + // kill peer and wait no more than 5 seconds for read-only server + // to be started (which should take one tickTime (2 seconds)) + qu.shutdown(2); + long start = Time.currentElapsedTime(); + while (!(zk.getState() == States.CONNECTEDREADONLY)) { + Thread.sleep(200); + // FIXME this was originally 5 seconds, but realistically, on random/slow/virt hosts, there is no way to guarantee this + Assert.assertTrue("Can't connect to the server", + Time.currentElapsedTime() - start < 30000); + } + + watcher.waitForReadOnlyConnected(5000); + zk.close(); + } + + /** + * Tests a situation when client firstly connects to a read-only server and + * then connects to a majority server. Transition should be transparent for + * the user. + */ + @Test(timeout = 90000) + public void testSessionEstablishment() throws Exception { + qu.shutdown(2); + + CountdownWatcher watcher = new CountdownWatcher(); + LOG.debug("Connection string: {}", qu.getConnString()); + ZooKeeper zk = new ZooKeeper(qu.getConnString(), CONNECTION_TIMEOUT, + watcher, true); + watcher.waitForConnected(CONNECTION_TIMEOUT); + Assert.assertSame("should be in r/o mode", States.CONNECTEDREADONLY, zk + .getState()); + long fakeId = zk.getSessionId(); + LOG.info("Connected as r/o mode with state {} and session id {}", + zk.getState(), fakeId); + + watcher.reset(); + qu.start(2); + Assert.assertTrue("waiting for server up", ClientBase.waitForServerUp( + "127.0.0.1:" + qu.getPeer(2).clientPort, CONNECTION_TIMEOUT)); + LOG.info("Server 127.0.0.1:{} is up", qu.getPeer(2).clientPort); + // ZOOKEEPER-2722: wait until we can connect to a read-write server after the quorum + // is formed. Otherwise, it is possible that client first connects to a read-only server, + // then drops the connection because of shutting down of the read-only server caused + // by leader election / quorum forming between the read-only server and the newly started + // server. If we happen to execute the zk.create after the read-only server is shutdown and + // before the quorum is formed, we will get a ConnectLossException. + watcher.waitForSyncConnected(CONNECTION_TIMEOUT); + Assert.assertEquals("Should be in read-write mode", States.CONNECTED, + zk.getState()); + LOG.info("Connected as rw mode with state {} and session id {}", + zk.getState(), zk.getSessionId()); + zk.create("/test", "test".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, + CreateMode.PERSISTENT); + Assert.assertFalse("fake session and real session have same id", zk + .getSessionId() == fakeId); + zk.close(); + } + + /** + * Ensures that client seeks for r/w servers while it's connected to r/o + * server. + */ + @SuppressWarnings("deprecation") + @Test(timeout = 90000) + public void testSeekForRwServer() throws Exception { + + // setup the logger to capture all logs + Layout layout = Logger.getRootLogger().getAppender("CONSOLE") + .getLayout(); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + WriterAppender appender = new WriterAppender(layout, os); + appender.setImmediateFlush(true); + appender.setThreshold(Level.INFO); + Logger zlogger = Logger.getLogger("org.apache.zookeeper"); + zlogger.addAppender(appender); + + try { + qu.shutdown(2); + CountdownWatcher watcher = new CountdownWatcher(); + ZooKeeper zk = new ZooKeeper(qu.getConnString(), + CONNECTION_TIMEOUT, watcher, true); + watcher.waitForConnected(CONNECTION_TIMEOUT); + + // if we don't suspend a peer it will rejoin a quorum + qu.getPeer(1).peer.suspend(); + + // start two servers to form a quorum; client should detect this and + // connect to one of them + watcher.reset(); + qu.start(2); + qu.start(3); + ClientBase.waitForServerUp(qu.getConnString(), 2000); + watcher.waitForConnected(CONNECTION_TIMEOUT); + zk.create("/test", "test".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, + CreateMode.PERSISTENT); + + // resume poor fellow + qu.getPeer(1).peer.resume(); + } finally { + zlogger.removeAppender(appender); + } + + os.close(); + LineNumberReader r = new LineNumberReader(new StringReader(os + .toString())); + String line; + Pattern p = Pattern.compile(".*Majority server found.*"); + boolean found = false; + while ((line = r.readLine()) != null) { + if (p.matcher(line).matches()) { + found = true; + break; + } + } + Assert.assertTrue( + "Majority server wasn't found while connected to r/o server", + found); + } +} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/RecoveryTest.java ---------------------------------------------------------------------- diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/RecoveryTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/RecoveryTest.java new file mode 100644 index 0000000..c084a68 --- /dev/null +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/RecoveryTest.java @@ -0,0 +1,209 @@ +/** + * 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.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +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.Ids; +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 RecoveryTest extends ZKTestCase implements Watcher { + protected static final Logger LOG = LoggerFactory.getLogger(RecoveryTest.class); + + private static final String HOSTPORT = + "127.0.0.1:" + PortAssignment.unique(); + + private volatile CountDownLatch startSignal; + + /** + * Verify that if a server goes down that clients will reconnect + * automatically after the server is restarted. Note that this requires the + * server to restart within the connection timeout period. + * + * Also note that the client latches are used to eliminate any chance + * of spurrious connectionloss exceptions on the read ops. Specifically + * a sync operation will throw this exception if the server goes down + * (as recognized by the client) during the operation. If the operation + * occurs after the server is down, but before the client recognizes + * that the server is down (ping) then the op will throw connectionloss. + */ + @Test + public void testRecovery() throws Exception { + File tmpDir = ClientBase.createTmpDir(); + + ClientBase.setupTestEnv(); + ZooKeeperServer zks = new ZooKeeperServer(tmpDir, tmpDir, 3000); + + int oldSnapCount = SyncRequestProcessor.getSnapCount(); + SyncRequestProcessor.setSnapCount(1000); + try { + final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]); + ServerCnxnFactory f = ServerCnxnFactory.createFactory(PORT, -1); + f.startup(zks); + LOG.info("starting up the the server, waiting"); + + Assert.assertTrue("waiting for server up", + ClientBase.waitForServerUp(HOSTPORT, + CONNECTION_TIMEOUT)); + + startSignal = new CountDownLatch(1); + ZooKeeper zk = new ZooKeeper(HOSTPORT, CONNECTION_TIMEOUT, this); + startSignal.await(CONNECTION_TIMEOUT, + TimeUnit.MILLISECONDS); + Assert.assertTrue("count == 0", startSignal.getCount() == 0); + String path; + LOG.info("starting creating nodes"); + for (int i = 0; i < 10; i++) { + path = "/" + i; + zk.create(path, + (path + "!").getBytes(), + Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); + for (int j = 0; j < 10; j++) { + String subpath = path + "/" + j; + zk.create(subpath, (subpath + "!").getBytes(), + Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); + for (int k = 0; k < 20; k++) { + String subsubpath = subpath + "/" + k; + zk.create(subsubpath, (subsubpath + "!").getBytes(), + Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); + } + } + } + + f.shutdown(); + zks.shutdown(); + Assert.assertTrue("waiting for server down", + ClientBase.waitForServerDown(HOSTPORT, + CONNECTION_TIMEOUT)); + + zks = new ZooKeeperServer(tmpDir, tmpDir, 3000); + f = ServerCnxnFactory.createFactory(PORT, -1); + + startSignal = new CountDownLatch(1); + + f.startup(zks); + + Assert.assertTrue("waiting for server up", + ClientBase.waitForServerUp(HOSTPORT, + CONNECTION_TIMEOUT)); + + startSignal.await(CONNECTION_TIMEOUT, + TimeUnit.MILLISECONDS); + Assert.assertTrue("count == 0", startSignal.getCount() == 0); + + Stat stat = new Stat(); + for (int i = 0; i < 10; i++) { + path = "/" + i; + LOG.info("Checking " + path); + Assert.assertEquals(new String(zk.getData(path, false, stat)), path + + "!"); + for (int j = 0; j < 10; j++) { + String subpath = path + "/" + j; + Assert.assertEquals(new String(zk.getData(subpath, false, stat)), + subpath + "!"); + for (int k = 0; k < 20; k++) { + String subsubpath = subpath + "/" + k; + Assert.assertEquals(new String(zk.getData(subsubpath, false, + stat)), subsubpath + "!"); + } + } + } + f.shutdown(); + zks.shutdown(); + + Assert.assertTrue("waiting for server down", + ClientBase.waitForServerDown(HOSTPORT, + ClientBase.CONNECTION_TIMEOUT)); + + zks = new ZooKeeperServer(tmpDir, tmpDir, 3000); + f = ServerCnxnFactory.createFactory(PORT, -1); + + startSignal = new CountDownLatch(1); + + f.startup(zks); + + Assert.assertTrue("waiting for server up", + ClientBase.waitForServerUp(HOSTPORT, + CONNECTION_TIMEOUT)); + + startSignal.await(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); + Assert.assertTrue("count == 0", startSignal.getCount() == 0); + + stat = new Stat(); + LOG.info("Check 2"); + for (int i = 0; i < 10; i++) { + path = "/" + i; + Assert.assertEquals(new String(zk.getData(path, false, stat)), + path + "!"); + for (int j = 0; j < 10; j++) { + String subpath = path + "/" + j; + Assert.assertEquals(new String(zk.getData(subpath, false, stat)), + subpath + "!"); + for (int k = 0; k < 20; k++) { + String subsubpath = subpath + "/" + k; + Assert.assertEquals(new String(zk.getData(subsubpath, false, + stat)), subsubpath + "!"); + } + } + } + zk.close(); + + f.shutdown(); + zks.shutdown(); + + Assert.assertTrue("waiting for server down", + ClientBase.waitForServerDown(HOSTPORT, + CONNECTION_TIMEOUT)); + } finally { + SyncRequestProcessor.setSnapCount(oldSnapCount); + } + } + + /* + * (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 + && startSignal != null && startSignal.getCount() > 0) + { + startSignal.countDown(); + } + } +} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/RepeatStartupTest.java ---------------------------------------------------------------------- diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/RepeatStartupTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/RepeatStartupTest.java new file mode 100644 index 0000000..f714a2c --- /dev/null +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/RepeatStartupTest.java @@ -0,0 +1,69 @@ +/** + * 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.apache.zookeeper.CreateMode; +import org.apache.zookeeper.ZKTestCase; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.ZooDefs.Ids; +import org.apache.zookeeper.server.ServerCnxnFactory; +import org.apache.zookeeper.server.ZooKeeperServer; +import org.junit.Assert; +import org.junit.Test; + +public class RepeatStartupTest extends ZKTestCase { + + /** bring up 5 quorum peers and then shut them down + * and then bring one of the nodes as server + * + * @throws Exception might be thrown here + */ + @Test + public void testFail() throws Exception { + QuorumBase qb = new QuorumBase(); + qb.setUp(); + + System.out.println("Comment: the servers are at " + qb.hostPort); + ZooKeeper zk = qb.createClient(); + zk.create("/test", null, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); + zk.close(); + qb.shutdown(qb.s1); + qb.shutdown(qb.s2); + qb.shutdown(qb.s3); + qb.shutdown(qb.s4); + qb.shutdown(qb.s5); + String hp = qb.hostPort.split(",")[0]; + ZooKeeperServer zks = new ZooKeeperServer(qb.s1.getTxnFactory().getSnapDir(), + qb.s1.getTxnFactory().getDataDir(), 3000); + final int PORT = Integer.parseInt(hp.split(":")[1]); + ServerCnxnFactory factory = ServerCnxnFactory.createFactory(PORT, -1); + + factory.startup(zks); + System.out.println("Comment: starting factory"); + Assert.assertTrue("waiting for server up", + ClientBase.waitForServerUp("127.0.0.1:" + PORT, + QuorumTest.CONNECTION_TIMEOUT)); + factory.shutdown(); + zks.shutdown(); + Assert.assertTrue("waiting for server down", + ClientBase.waitForServerDown("127.0.0.1:" + PORT, + QuorumTest.CONNECTION_TIMEOUT)); + System.out.println("Comment: shutting down standalone"); + } +} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/RestoreCommittedLogTest.java ---------------------------------------------------------------------- diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/RestoreCommittedLogTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/RestoreCommittedLogTest.java new file mode 100644 index 0000000..65cc0e2 --- /dev/null +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/RestoreCommittedLogTest.java @@ -0,0 +1,91 @@ +/** + * 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.List; +import java.util.LinkedList; + +import org.apache.log4j.Logger; +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.ZooDefs.Ids; +import org.apache.zookeeper.server.quorum.Leader.Proposal; +import org.apache.zookeeper.server.ServerCnxnFactory; +import org.apache.zookeeper.server.SyncRequestProcessor; +import org.apache.zookeeper.server.ZooKeeperServer; +import org.apache.zookeeper.server.persistence.FileTxnSnapLog; +import org.junit.Assert; +import org.junit.Test; + +/** After a replica starts, it should load commits in its committedLog list. + * This test checks if committedLog != 0 after replica restarted. + */ +public class RestoreCommittedLogTest extends ZKTestCase implements Watcher { + private static final Logger LOG = Logger.getLogger(RestoreCommittedLogTest.class); + private static String HOSTPORT = "127.0.0.1:" + PortAssignment.unique(); + private static final int CONNECTION_TIMEOUT = 3000; + /** + * test the purge + * @throws Exception an exception might be thrown here + */ + @Test + public void testRestoreCommittedLog() 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 = new ZooKeeper(HOSTPORT, CONNECTION_TIMEOUT, this); + try { + for (int i = 0; i< 2000; i++) { + zk.create("/invalidsnap-" + i, new byte[0], Ids.OPEN_ACL_UNSAFE, + CreateMode.PERSISTENT); + } + } finally { + zk.close(); + } + f.shutdown(); + zks.shutdown(); + Assert.assertTrue("waiting for server to shutdown", + ClientBase.waitForServerDown(HOSTPORT, CONNECTION_TIMEOUT)); + + // start server again + zks = new ZooKeeperServer(tmpDir, tmpDir, 3000); + zks.startdata(); + LinkedList committedLog = zks.getZKDatabase().getCommittedLog(); + int logsize = committedLog.size(); + LOG.info("committedLog size = " + logsize); + Assert.assertTrue("log size != 0", (logsize != 0)); + zks.shutdown(); + } + + public void process(WatchedEvent event) { + // do nothing + } + +} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthDesignatedClientTest.java ---------------------------------------------------------------------- diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthDesignatedClientTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthDesignatedClientTest.java new file mode 100644 index 0000000..9e28278 --- /dev/null +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthDesignatedClientTest.java @@ -0,0 +1,104 @@ +/** + * 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.io.FileWriter; +import java.io.IOException; + +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.client.ZooKeeperSaslClient; +import org.junit.Assert; +import org.junit.Test; + +public class SaslAuthDesignatedClientTest extends ClientBase { + static { + System.setProperty("zookeeper.authProvider.1","org.apache.zookeeper.server.auth.SASLAuthenticationProvider"); + System.setProperty(ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY, "MyZookeeperClient"); + + try { + File tmpDir = createTmpDir(); + File saslConfFile = new File(tmpDir, "jaas.conf"); + FileWriter fwriter = new FileWriter(saslConfFile); + + fwriter.write("" + + "Server {\n" + + " org.apache.zookeeper.server.auth.DigestLoginModule required\n" + + " user_myuser=\"mypassword\";\n" + + "};\n" + + "Client {\n" + /* this 'Client' section has an incorrect password, but we're not configured + to use it (we're configured by the above System.setProperty(...LOGIN_CONTEXT_NAME_KEY...) to + use the 'MyZookeeperClient' section below, which has the correct password).*/ + " org.apache.zookeeper.server.auth.DigestLoginModule required\n" + + " username=\"myuser\"\n" + + " password=\"wrongpassword\";\n" + + "};" + + "MyZookeeperClient {\n" + + " org.apache.zookeeper.server.auth.DigestLoginModule required\n" + + " username=\"myuser\"\n" + + " password=\"mypassword\";\n" + + "};" + "\n"); + 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. + } + } + + @Test + public void testAuth() throws Exception { + ZooKeeper zk = createClient(); + try { + zk.create("/path1", null, Ids.CREATOR_ALL_ACL, CreateMode.PERSISTENT); + Thread.sleep(1000); + } catch (KeeperException e) { + Assert.fail("test failed :" + e); + } + finally { + zk.close(); + } + } + + @Test + public void testSaslConfig() throws Exception { + ZooKeeper zk = createClient(); + try { + zk.getChildren("/", false); + Assert.assertFalse(zk.getSaslClient(). + clientTunneledAuthenticationInProgress()); + Assert.assertEquals(zk.getSaslClient().getSaslState(), + ZooKeeperSaslClient.SaslState.COMPLETE); + Assert.assertNotNull( + javax.security.auth.login.Configuration.getConfiguration(). + getAppConfigurationEntry("MyZookeeperClient")); + Assert.assertSame(zk.getSaslClient().getLoginContext(), + "MyZookeeperClient"); + } catch (KeeperException e) { + Assert.fail("test failed :" + e); + } finally { + zk.close(); + } + } + + +} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthDesignatedServerTest.java ---------------------------------------------------------------------- diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthDesignatedServerTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthDesignatedServerTest.java new file mode 100644 index 0000000..aa30870 --- /dev/null +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthDesignatedServerTest.java @@ -0,0 +1,104 @@ +/** + * 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.io.FileWriter; +import java.io.IOException; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.Watcher.Event.KeeperState; +import org.apache.zookeeper.ZooDefs.Ids; +import org.apache.zookeeper.server.ZooKeeperSaslServer; +import org.apache.zookeeper.JaasConfiguration; +import org.junit.Assert; +import org.junit.Test; + +public class SaslAuthDesignatedServerTest extends ClientBase { + public static int AUTHENTICATION_TIMEOUT = 30000; + + static { + System.setProperty("zookeeper.authProvider.1","org.apache.zookeeper.server.auth.SASLAuthenticationProvider"); + System.setProperty(ZooKeeperSaslServer.LOGIN_CONTEXT_NAME_KEY, "MyZookeeperServer"); + + JaasConfiguration conf = new JaasConfiguration(); + + /* this 'Server' section has an incorrect password, but we're not configured + * to use it (we're configured by the above System.setProperty(...LOGIN_CONTEXT_NAME_KEY...) + * to use the 'MyZookeeperServer' section below, which has the correct password). + */ + conf.addSection("Server", "org.apache.zookeeper.server.auth.DigestLoginModule", + "user_myuser", "wrongpassword"); + + conf.addSection("MyZookeeperServer", "org.apache.zookeeper.server.auth.DigestLoginModule", + "user_myuser", "mypassword"); + + conf.addSection("Client", "org.apache.zookeeper.server.auth.DigestLoginModule", + "username", "myuser", "password", "mypassword"); + + javax.security.auth.login.Configuration.setConfiguration(conf); + } + + private AtomicInteger authFailed = new AtomicInteger(0); + + private class MyWatcher extends CountdownWatcher { + volatile CountDownLatch authCompleted; + + @Override + synchronized public void reset() { + authCompleted = new CountDownLatch(1); + super.reset(); + } + + @Override + public synchronized void process(WatchedEvent event) { + if (event.getState() == KeeperState.AuthFailed) { + authFailed.incrementAndGet(); + authCompleted.countDown(); + } else if (event.getState() == KeeperState.SaslAuthenticated) { + authCompleted.countDown(); + } else { + super.process(event); + } + } + } + + @Test + public void testAuth() throws Exception { + MyWatcher watcher = new MyWatcher(); + ZooKeeper zk = createClient(watcher); + watcher.authCompleted.await(AUTHENTICATION_TIMEOUT, TimeUnit.MILLISECONDS); + Assert.assertEquals(authFailed.get(), 0); + + try { + zk.create("/path1", null, Ids.CREATOR_ALL_ACL, CreateMode.PERSISTENT); + } catch (KeeperException e) { + Assert.fail("test failed :" + e); + } + finally { + zk.close(); + } + } +} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthFailDesignatedClientTest.java ---------------------------------------------------------------------- diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthFailDesignatedClientTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthFailDesignatedClientTest.java new file mode 100644 index 0000000..5291141 --- /dev/null +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthFailDesignatedClientTest.java @@ -0,0 +1,108 @@ +/** + * 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.io.FileWriter; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.TestableZooKeeper; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.Watcher.Event.KeeperState; +import org.apache.zookeeper.ZooDefs.Ids; +import org.apache.zookeeper.client.ZooKeeperSaslClient; +import org.junit.Assert; +import org.junit.Test; + +public class SaslAuthFailDesignatedClientTest extends ClientBase { + static { + System.setProperty("zookeeper.authProvider.1","org.apache.zookeeper.server.auth.SASLAuthenticationProvider"); + System.setProperty(ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY, "MyZookeeperClient"); + + try { + File tmpDir = createTmpDir(); + File saslConfFile = new File(tmpDir, "jaas.conf"); + FileWriter fwriter = new FileWriter(saslConfFile); + + fwriter.write("" + + "Server {\n" + + " org.apache.zookeeper.server.auth.DigestLoginModule required\n" + + " user_myuser=\"mypassword\";\n" + + "};\n" + + "Client {\n" + /* this 'Client' section has the correct password, but we're not configured + to use it (we're configured by the above System.setProperty(...LOGIN_CONTEXT_NAME_KEY...) to + use the 'MyZookeeperClient' section, which has an incorrect password).*/ + " org.apache.zookeeper.server.auth.DigestLoginModule required\n" + + " username=\"myuser\"\n" + + " password=\"mypassword\";\n" + + "};" + + "MyZookeeperClient {\n" + + " org.apache.zookeeper.server.auth.DigestLoginModule required\n" + + " username=\"myuser\"\n" + + " password=\"wrongpassword\";\n" + + "};" + "\n"); + 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 AtomicInteger authFailed = new AtomicInteger(0); + + 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 { + // Cannot use createClient here because server may close session before + // JMXEnv.ensureAll is called which will fail the test case + CountdownWatcher watcher = new CountdownWatcher(); + TestableZooKeeper zk = new TestableZooKeeper(hostPort, CONNECTION_TIMEOUT, watcher); + if (!watcher.clientConnected.await(CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS)) + { + Assert.fail("Unable to connect to server"); + } + try { + zk.create("/path1", null, Ids.CREATOR_ALL_ACL, CreateMode.PERSISTENT); + Assert.fail("Should have gotten exception."); + } catch (KeeperException e) { + // ok, exception as expected. + LOG.info("Got exception as expected: " + e); + } + finally { + zk.close(); + } + } +} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthFailNotifyTest.java ---------------------------------------------------------------------- diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthFailNotifyTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthFailNotifyTest.java new file mode 100644 index 0000000..2b00d86 --- /dev/null +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthFailNotifyTest.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 java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.TestableZooKeeper; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.Watcher.Event.KeeperState; +import org.apache.zookeeper.ZooDefs.Ids; +import org.junit.Test; +import org.junit.Assert; + +public class SaslAuthFailNotifyTest extends ClientBase { + static { + System.setProperty("zookeeper.authProvider.1","org.apache.zookeeper.server.auth.SASLAuthenticationProvider"); + System.setProperty("zookeeper.allowSaslFailedClients","true"); + + try { + File tmpDir = createTmpDir(); + File saslConfFile = new File(tmpDir, "jaas.conf"); + FileWriter fwriter = new FileWriter(saslConfFile); + + fwriter.write("" + + "Server {\n" + + " org.apache.zookeeper.server.auth.DigestLoginModule required\n" + + " user_super=\"test\";\n" + + "};\n" + + "Client {\n" + + " org.apache.zookeeper.server.auth.DigestLoginModule required\n" + + " username=\"super\"\n" + + " password=\"test1\";\n" + // NOTE: wrong password ('test' != 'test1') : this is to test SASL authentication failure. + "};" + "\n"); + fwriter.close(); + System.setProperty("java.security.auth.login.config",saslConfFile.getAbsolutePath()); + } + catch (IOException e) { + // could not create tmp directory to hold JAAS conf file. + } + } + + 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) { + synchronized(authFailed) { + authFailed.incrementAndGet(); + authFailed.notify(); + } + } + else { + super.process(event); + } + } + } + + @Test + public void testBadSaslAuthNotifiesWatch() throws Exception { + ZooKeeper zk = createClient(); + // wait for authFailed event from client's EventThread. + synchronized(authFailed) { + authFailed.wait(); + } + Assert.assertEquals(authFailed.get(),1); + zk.close(); + } +} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthFailTest.java ---------------------------------------------------------------------- diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthFailTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthFailTest.java new file mode 100644 index 0000000..33a505e --- /dev/null +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthFailTest.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.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.TestableZooKeeper; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.Watcher.Event.KeeperState; +import org.apache.zookeeper.ZooDefs.Ids; +import org.junit.Test; +import org.junit.Assert; + +public class SaslAuthFailTest extends ClientBase { + static { + System.setProperty("zookeeper.authProvider.1","org.apache.zookeeper.server.auth.SASLAuthenticationProvider"); + System.setProperty("zookeeper.allowSaslFailedClients","true"); + + try { + File tmpDir = createTmpDir(); + File saslConfFile = new File(tmpDir, "jaas.conf"); + FileWriter fwriter = new FileWriter(saslConfFile); + + fwriter.write("" + + "Server {\n" + + " org.apache.zookeeper.server.auth.DigestLoginModule required\n" + + " user_super=\"test\";\n" + + "};\n" + + "Client {\n" + + " org.apache.zookeeper.server.auth.DigestLoginModule required\n" + + " username=\"super\"\n" + + " password=\"test1\";\n" + // NOTE: wrong password ('test' != 'test1') : this is to test SASL authentication failure. + "};" + "\n"); + 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 + public void testAuthFail() throws Exception { + ZooKeeper zk = createClient(); + try { + zk.create("/path1", null, Ids.CREATOR_ALL_ACL, CreateMode.PERSISTENT); + Assert.fail("Should have gotten exception."); + } catch(Exception e ) { + // ok, exception as expected. + LOG.info("Got exception as expected: " + e); + } finally { + zk.close(); + } + } +} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthMissingClientConfigTest.java ---------------------------------------------------------------------- diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthMissingClientConfigTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthMissingClientConfigTest.java new file mode 100644 index 0000000..98be0be --- /dev/null +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslAuthMissingClientConfigTest.java @@ -0,0 +1,97 @@ +/** + * 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.io.FileWriter; +import java.io.IOException; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.Watcher.Event.KeeperState; +import org.apache.zookeeper.ZooDefs.Ids; +import org.apache.zookeeper.client.ZooKeeperSaslClient; +import org.junit.Assert; +import org.junit.Test; + +public class SaslAuthMissingClientConfigTest extends ClientBase { + static { + System.setProperty("zookeeper.authProvider.1","org.apache.zookeeper.server.auth.SASLAuthenticationProvider"); + // This configuration section 'MyZookeeperClient', is missing from the JAAS configuration. + // As a result, SASL authentication should fail, which is tested by this test (testAuth()). + System.setProperty(ZooKeeperSaslClient.LOGIN_CONTEXT_NAME_KEY, "MyZookeeperClient"); + + try { + File tmpDir = createTmpDir(); + File saslConfFile = new File(tmpDir, "jaas.conf"); + FileWriter fwriter = new FileWriter(saslConfFile); + + fwriter.write("" + + "Server {\n" + + " org.apache.zookeeper.server.auth.DigestLoginModule required\n" + + " user_myuser=\"mypassword\";\n" + + "};\n" + + "Client {\n" + /* this 'Client' section has the correct password, but we're not configured + to use it - we're configured instead by the above + System.setProperty(...LOGIN_CONTEXT_NAME_KEY...) to + use the (nonexistent) 'MyZookeeperClient' section. */ + " org.apache.zookeeper.server.auth.DigestLoginModule required\n" + + " username=\"myuser\"\n" + + " password=\"mypassword\";\n" + + "};\n"); + 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 AtomicInteger authFailed = new AtomicInteger(0); + + 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); + Assert.fail("Should have gotten exception."); + } catch (KeeperException e) { + // ok, exception as expected. + LOG.info("Got exception as expected: " + e); + } + finally { + zk.close(); + } + } +} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslClientTest.java ---------------------------------------------------------------------- diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslClientTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslClientTest.java new file mode 100644 index 0000000..8213abc --- /dev/null +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SaslClientTest.java @@ -0,0 +1,62 @@ +/** + * 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.apache.zookeeper.ZKTestCase; +import org.apache.zookeeper.client.ZooKeeperSaslClient; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; + +public class SaslClientTest extends ZKTestCase { + + private String existingPropertyValue = null; + + @Before + public void setUp() { + existingPropertyValue = System.getProperty(ZooKeeperSaslClient.ENABLE_CLIENT_SASL_KEY); + } + + @After + public void tearDown() { + // Restore the System property if it was set previously + if (existingPropertyValue != null) { + System.setProperty(ZooKeeperSaslClient.ENABLE_CLIENT_SASL_KEY, existingPropertyValue); + } + } + + @Test + public void testSaslClientDisabled() { + System.clearProperty(ZooKeeperSaslClient.ENABLE_CLIENT_SASL_KEY); + Assert.assertTrue("SASL client disabled", ZooKeeperSaslClient.isEnabled()); + + for (String value : Arrays.asList("true", "TRUE")) { + System.setProperty(ZooKeeperSaslClient.ENABLE_CLIENT_SASL_KEY, value); + Assert.assertTrue("SASL client disabled", ZooKeeperSaslClient.isEnabled()); + } + + for (String value : Arrays.asList("false", "FALSE")) { + System.setProperty(ZooKeeperSaslClient.ENABLE_CLIENT_SASL_KEY, value); + Assert.assertFalse("SASL client disabled", ZooKeeperSaslClient.isEnabled()); + } + } +} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/SessionInvalidationTest.java ---------------------------------------------------------------------- diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/SessionInvalidationTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SessionInvalidationTest.java new file mode 100644 index 0000000..3a0b2ee --- /dev/null +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SessionInvalidationTest.java @@ -0,0 +1,105 @@ +/** + * 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.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + +import junit.framework.Assert; + +import org.apache.jute.BinaryOutputArchive; +import org.apache.zookeeper.ZooDefs; +import org.apache.zookeeper.ZooDefs.Ids; +import org.apache.zookeeper.ZooDefs.OpCode; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.proto.ConnectRequest; +import org.apache.zookeeper.proto.CreateRequest; +import org.apache.zookeeper.proto.RequestHeader; +import org.junit.Test; + +public class SessionInvalidationTest extends ClientBase { + /** + * Test solution for ZOOKEEPER-1208. Verify that operations are not + * accepted after a close session. + * + * We're using our own marshalling here in order to force an operation + * after the session is closed (ZooKeeper.class will not allow this). Also + * by filling the pipe with operations it increases the likelyhood that + * the server will process the create before FinalRequestProcessor + * removes the session from the tracker. + */ + @Test + public void testCreateAfterCloseShouldFail() throws Exception { + for (int i = 0; i < 10; i++) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + BinaryOutputArchive boa = BinaryOutputArchive.getArchive(baos); + + // open a connection + boa.writeInt(44, "len"); + ConnectRequest conReq = new ConnectRequest(0, 0, 30000, 0, new byte[16]); + conReq.serialize(boa, "connect"); + + // close connection + boa.writeInt(8, "len"); + RequestHeader h = new RequestHeader(1, ZooDefs.OpCode.closeSession); + h.serialize(boa, "header"); + + // create ephemeral znode + boa.writeInt(52, "len"); // We'll fill this in later + RequestHeader header = new RequestHeader(2, OpCode.create); + header.serialize(boa, "header"); + CreateRequest createReq = new CreateRequest("/foo" + i, new byte[0], + Ids.OPEN_ACL_UNSAFE, 1); + createReq.serialize(boa, "request"); + baos.close(); + + System.out.println("Length:" + baos.toByteArray().length); + + String hp[] = hostPort.split(":"); + Socket sock = new Socket(hp[0], Integer.parseInt(hp[1])); + InputStream resultStream = null; + try { + OutputStream outstream = sock.getOutputStream(); + byte[] data = baos.toByteArray(); + outstream.write(data); + outstream.flush(); + + resultStream = sock.getInputStream(); + byte[] b = new byte[10000]; + int len; + while ((len = resultStream.read(b)) >= 0) { + // got results + System.out.println("gotlen:" + len); + } + } finally { + if (resultStream != null) { + resultStream.close(); + } + sock.close(); + } + } + + ZooKeeper zk = createClient(); + Assert.assertEquals(1, zk.getChildren("/", false).size()); + + zk.close(); + } +} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/SessionTest.java ---------------------------------------------------------------------- diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/SessionTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SessionTest.java new file mode 100644 index 0000000..891b0f0 --- /dev/null +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SessionTest.java @@ -0,0 +1,394 @@ +/** + * 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.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.zookeeper.AsyncCallback; +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.PortAssignment; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.Watcher.Event.EventType; +import org.apache.zookeeper.Watcher.Event.KeeperState; +import org.apache.zookeeper.ZKTestCase; +import org.apache.zookeeper.ZooDefs.Ids; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.data.Stat; +import org.apache.zookeeper.server.ServerCnxnFactory; +import org.apache.zookeeper.server.ZooKeeperServer; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; + +public class SessionTest extends ZKTestCase { + protected static final Logger LOG = LoggerFactory.getLogger(SessionTest.class); + + private static final String HOSTPORT = "127.0.0.1:" + + PortAssignment.unique(); + + private ServerCnxnFactory serverFactory; + private ZooKeeperServer zs; + + private CountDownLatch startSignal; + + File tmpDir; + + private final int TICK_TIME = 3000; + + @Before + public void setUp() throws Exception { + if (tmpDir == null) { + tmpDir = ClientBase.createTmpDir(); + } + + ClientBase.setupTestEnv(); + zs = new ZooKeeperServer(tmpDir, tmpDir, TICK_TIME); + + final int PORT = Integer.parseInt(HOSTPORT.split(":")[1]); + serverFactory = ServerCnxnFactory.createFactory(PORT, -1); + serverFactory.startup(zs); + + Assert.assertTrue("waiting for server up", + ClientBase.waitForServerUp(HOSTPORT, + CONNECTION_TIMEOUT)); + } + + @After + public void tearDown() throws Exception { + serverFactory.shutdown(); + zs.shutdown(); + Assert.assertTrue("waiting for server down", + ClientBase.waitForServerDown(HOSTPORT, + CONNECTION_TIMEOUT)); + } + + private static class CountdownWatcher implements Watcher { + volatile CountDownLatch clientConnected = new CountDownLatch(1); + + public void process(WatchedEvent event) { + if (event.getState() == KeeperState.SyncConnected) { + clientConnected.countDown(); + } + } + } + + private DisconnectableZooKeeper createClient() + throws IOException, InterruptedException + { + CountdownWatcher watcher = new CountdownWatcher(); + return createClient(CONNECTION_TIMEOUT, watcher); + } + + private DisconnectableZooKeeper createClient(int timeout) + throws IOException, InterruptedException + { + CountdownWatcher watcher = new CountdownWatcher(); + return createClient(timeout, watcher); + } + + private DisconnectableZooKeeper createClient(int timeout, + CountdownWatcher watcher) + throws IOException, InterruptedException + { + DisconnectableZooKeeper zk = + new DisconnectableZooKeeper(HOSTPORT, timeout, watcher); + if(!watcher.clientConnected.await(timeout, TimeUnit.MILLISECONDS)) { + Assert.fail("Unable to connect to server"); + } + + return zk; + } + +// FIXME this test is Assert.failing due to client close race condition fixing in separate patch for ZOOKEEPER-63 +// /** +// * this test checks to see if the sessionid that was created for the +// * first zookeeper client can be reused for the second one immidiately +// * after the first client closes and the new client resues them. +// * @throws IOException +// * @throws InterruptedException +// * @throws KeeperException +// */ +// public void testSessionReuse() throws IOException, InterruptedException { +// ZooKeeper zk = createClient(); +// +// long sessionId = zk.getSessionId(); +// byte[] passwd = zk.getSessionPasswd(); +// zk.close(); +// +// zk.close(); +// +// LOG.info("Closed first session"); +// +// startSignal = new CountDownLatch(1); +// zk = new ZooKeeper(HOSTPORT, CONNECTION_TIMEOUT, this, +// sessionId, passwd); +// startSignal.await(); +// +// LOG.info("Opened reuse"); +// +// Assert.assertEquals(sessionId, zk.getSessionId()); +// +// zk.close(); +// } + + private class MyWatcher implements Watcher { + private String name; + public MyWatcher(String name) { + this.name = name; + } + public void process(WatchedEvent event) { + LOG.info(name + " event:" + event.getState() + " " + + event.getType() + " " + event.getPath()); + if (event.getState() == KeeperState.SyncConnected + && startSignal != null && startSignal.getCount() > 0) + { + startSignal.countDown(); + } + } + } + + /** + * This test verifies that when the session id is reused, and the original + * client is disconnected, but not session closed, that the server + * will remove ephemeral nodes created by the original session. + */ + @Test + public void testSession() + throws IOException, InterruptedException, KeeperException + { + DisconnectableZooKeeper zk = createClient(); + zk.create("/e", new byte[0], Ids.OPEN_ACL_UNSAFE, + CreateMode.EPHEMERAL); + LOG.info("zk with session id 0x" + Long.toHexString(zk.getSessionId()) + + " was destroyed!"); + + // disconnect the client by killing the socket, not sending the + // session disconnect to the server as usual. This allows the test + // to verify disconnect handling + zk.disconnect(); + + Stat stat = new Stat(); + startSignal = new CountDownLatch(1); + zk = new DisconnectableZooKeeper(HOSTPORT, CONNECTION_TIMEOUT, + new MyWatcher("testSession"), zk.getSessionId(), + zk.getSessionPasswd()); + startSignal.await(); + + LOG.info("zk with session id 0x" + Long.toHexString(zk.getSessionId()) + + " was created!"); + zk.getData("/e", false, stat); + LOG.info("After get data /e"); + zk.close(); + + zk = createClient(); + Assert.assertEquals(null, zk.exists("/e", false)); + LOG.info("before close zk with session id 0x" + + Long.toHexString(zk.getSessionId()) + "!"); + zk.close(); + try { + zk.getData("/e", false, stat); + Assert.fail("Should have received a SessionExpiredException"); + } catch(KeeperException.SessionExpiredException e) {} + + AsyncCallback.DataCallback cb = new AsyncCallback.DataCallback() { + String status = "not done"; + public void processResult(int rc, String p, Object c, byte[] b, Stat s) { + synchronized(this) { status = KeeperException.Code.get(rc).toString(); this.notify(); } + } + public String toString() { return status; } + }; + zk.getData("/e", false, cb, null); + synchronized(cb) { + if (cb.toString().equals("not done")) { + cb.wait(1000); + } + } + Assert.assertEquals(KeeperException.Code.SESSIONEXPIRED.toString(), cb.toString()); + } + + /** + * Make sure that we cannot have two connections with the same + * session id. + * + * @throws IOException + * @throws InterruptedException + * @throws KeeperException + */ + @Test + public void testSessionMove() throws Exception { + String hostPorts[] = HOSTPORT.split(","); + DisconnectableZooKeeper zk = new DisconnectableZooKeeper(hostPorts[0], + CONNECTION_TIMEOUT, new MyWatcher("0")); + zk.create("/sessionMoveTest", new byte[0], Ids.OPEN_ACL_UNSAFE, + CreateMode.EPHEMERAL); + // we want to loop through the list twice + for(int i = 0; i < hostPorts.length*2; i++) { + zk.dontReconnect(); + // This should stomp the zk handle + DisconnectableZooKeeper zknew = new DisconnectableZooKeeper( + hostPorts[(i+1)%hostPorts.length], + CONNECTION_TIMEOUT, + new MyWatcher(Integer.toString(i+1)), + zk.getSessionId(), + zk.getSessionPasswd()); + final int result[] = new int[1]; + result[0] = Integer.MAX_VALUE; + zknew.sync("/", new AsyncCallback.VoidCallback() { + public void processResult(int rc, String path, Object ctx) { + synchronized(result) { result[0] = rc; result.notify(); } + } + }, null); + synchronized(result) { + if(result[0] == Integer.MAX_VALUE) { + result.wait(5000); + } + } + LOG.info(hostPorts[(i+1)%hostPorts.length] + " Sync returned " + result[0]); + Assert.assertTrue(result[0] == KeeperException.Code.OK.intValue()); + zknew.setData("/", new byte[1], -1); + try { + zk.setData("/", new byte[1], -1); + Assert.fail("Should have lost the connection"); + } catch(KeeperException.ConnectionLossException e) { + LOG.info("Got connection loss exception as expected"); + } + //zk.close(); + zk = zknew; + } + zk.close(); + } + /** + * This test makes sure that duplicate state changes are not communicated + * to the client watcher. For example we should not notify state as + * "disconnected" if the watch has already been disconnected. In general + * we don't consider a dup state notification if the event type is + * not "None" (ie non-None communicates an event). + */ + @Test + public void testSessionStateNoDupStateReporting() + throws IOException, InterruptedException, KeeperException + { + final int TIMEOUT = 3000; + DupWatcher watcher = new DupWatcher(); + ZooKeeper zk = createClient(TIMEOUT, watcher); + + // shutdown the server + serverFactory.shutdown(); + + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + // ignore + } + + // verify that the size is just 2 - ie connect then disconnect + // if the client attempts reconnect and we are not handling current + // state correctly (ie eventing on duplicate disconnects) then we'll + // see a disconnect for each Assert.failed connection attempt + Assert.assertEquals(2, watcher.states.size()); + + zk.close(); + } + + /** + * Verify access to the negotiated session timeout. + */ + @Test + public void testSessionTimeoutAccess() throws Exception { + // validate typical case - requested == negotiated + DisconnectableZooKeeper zk = createClient(TICK_TIME * 4); + Assert.assertEquals(TICK_TIME * 4, zk.getSessionTimeout()); + // make sure tostring works in both cases + LOG.info(zk.toString()); + zk.close(); + LOG.info(zk.toString()); + + // validate lower limit + zk = createClient(TICK_TIME); + Assert.assertEquals(TICK_TIME * 2, zk.getSessionTimeout()); + LOG.info(zk.toString()); + zk.close(); + LOG.info(zk.toString()); + + // validate upper limit + zk = createClient(TICK_TIME * 30); + Assert.assertEquals(TICK_TIME * 20, zk.getSessionTimeout()); + LOG.info(zk.toString()); + zk.close(); + LOG.info(zk.toString()); + } + + private class DupWatcher extends CountdownWatcher { + public LinkedList states = new LinkedList(); + public void process(WatchedEvent event) { + super.process(event); + if (event.getType() == EventType.None) { + states.add(event); + } + } + } + + @Test + public void testMinMaxSessionTimeout() throws Exception { + // override the defaults + final int MINSESS = 20000; + final int MAXSESS = 240000; + { + ZooKeeperServer zs = ClientBase.getServer(serverFactory); + zs.setMinSessionTimeout(MINSESS); + zs.setMaxSessionTimeout(MAXSESS); + } + + // validate typical case - requested == negotiated + int timeout = 120000; + DisconnectableZooKeeper zk = createClient(timeout); + Assert.assertEquals(timeout, zk.getSessionTimeout()); + // make sure tostring works in both cases + LOG.info(zk.toString()); + zk.close(); + LOG.info(zk.toString()); + + // validate lower limit + zk = createClient(MINSESS/2); + Assert.assertEquals(MINSESS, zk.getSessionTimeout()); + LOG.info(zk.toString()); + zk.close(); + LOG.info(zk.toString()); + + // validate upper limit + zk = createClient(MAXSESS * 2); + Assert.assertEquals(MAXSESS, zk.getSessionTimeout()); + LOG.info(zk.toString()); + zk.close(); + LOG.info(zk.toString()); + } +} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/SessionTimeoutTest.java ---------------------------------------------------------------------- diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/SessionTimeoutTest.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SessionTimeoutTest.java new file mode 100644 index 0000000..09badae --- /dev/null +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SessionTimeoutTest.java @@ -0,0 +1,129 @@ +/** + * 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.apache.zookeeper.CreateMode; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.TestableZooKeeper; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.ZooDefs; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.data.Stat; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +public class SessionTimeoutTest extends ClientBase { + protected static final Logger LOG = LoggerFactory.getLogger(SessionTimeoutTest.class); + + private TestableZooKeeper zk; + + @Before + public void setUp() throws Exception { + super.setUp(); + zk = createClient(); + } + + @Test + public void testSessionExpiration() throws InterruptedException, + KeeperException { + final CountDownLatch expirationLatch = new CountDownLatch(1); + Watcher watcher = new Watcher() { + @Override + public void process(WatchedEvent event) { + if ( event.getState() == Event.KeeperState.Expired ) { + expirationLatch.countDown(); + } + } + }; + zk.exists("/foo", watcher); + + zk.getTestable().injectSessionExpiration(); + Assert.assertTrue(expirationLatch.await(5, TimeUnit.SECONDS)); + + boolean gotException = false; + try { + zk.exists("/foo", false); + Assert.fail("Should have thrown a SessionExpiredException"); + } catch (KeeperException.SessionExpiredException e) { + // correct + gotException = true; + } + Assert.assertTrue(gotException); + } + + /** + * Make sure ephemerals get cleaned up when session disconnects. + */ + @Test + public void testSessionDisconnect() throws KeeperException, InterruptedException, IOException { + zk.create("/sdisconnect", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, + CreateMode.EPHEMERAL); + assertNotNull("Ephemeral node has not been created", zk.exists("/sdisconnect", null)); + + zk.close(); + + zk = createClient(); + assertNull("Ephemeral node shouldn't exist after client disconnect", zk.exists("/sdisconnect", null)); + } + + /** + * Make sure ephemerals are kept when session restores. + */ + @Test + public void testSessionRestore() throws KeeperException, InterruptedException, IOException { + zk.create("/srestore", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, + CreateMode.EPHEMERAL); + assertNotNull("Ephemeral node has not been created", zk.exists("/srestore", null)); + + zk.disconnect(); + zk.close(); + + zk = createClient(); + assertNotNull("Ephemeral node should be present when session is restored", zk.exists("/srestore", null)); + } + + /** + * Make sure ephemerals are kept when server restarts. + */ + @Test + public void testSessionSurviveServerRestart() throws Exception { + zk.create("/sdeath", new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, + CreateMode.EPHEMERAL); + assertNotNull("Ephemeral node has not been created", zk.exists("/sdeath", null)); + + zk.disconnect(); + stopServer(); + startServer(); + zk = createClient(); + + assertNotNull("Ephemeral node should be present when server restarted", zk.exists("/sdeath", null)); + } +} http://git-wip-us.apache.org/repos/asf/zookeeper/blob/7291e47c/zookeeper-server/src/test/java/org/apache/zookeeper/test/SledgeHammer.java ---------------------------------------------------------------------- diff --git a/zookeeper-server/src/test/java/org/apache/zookeeper/test/SledgeHammer.java b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SledgeHammer.java new file mode 100644 index 0000000..614a93d --- /dev/null +++ b/zookeeper-server/src/test/java/org/apache/zookeeper/test/SledgeHammer.java @@ -0,0 +1,115 @@ +/** + * 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.Collections; +import java.util.List; + +import org.apache.zookeeper.CreateMode; +import org.apache.zookeeper.KeeperException; +import org.apache.zookeeper.WatchedEvent; +import org.apache.zookeeper.Watcher; +import org.apache.zookeeper.ZooKeeper; +import org.apache.zookeeper.ZooDefs.Ids; +import org.apache.zookeeper.data.Stat; + +public class SledgeHammer extends Thread implements Watcher { + ZooKeeper zk; + + int count; + + int readsPerWrite; + + public SledgeHammer(String hosts, int count, int readsPerWrite) + throws IOException { + zk = new ZooKeeper(hosts, 10000, this); + this.count = count; + this.readsPerWrite = readsPerWrite; + } + + public void run() { + try { + Stat stat = new Stat(); + String path = zk.create("/hammers/hammer-", new byte[0], + Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL); + byte tag[] = (path + " was here!").getBytes(); + synchronized (this) { + String startPath = "/hammers/start"; + System.out.println("Waiting for " + startPath); + while (zk.exists(startPath, true) == null) { + wait(); + } + System.out.println("Running"); + } + for (int i = 0; i < count; i++) { + try { + System.out.print(i + "\r"); + List childs = + zk.getChildren("/hammers", false); + Collections.shuffle(childs); + for (String s : childs) { + if (s.startsWith("hammer-")) { + s = "/hammers/" + s; + zk.setData(s, tag, -1); + for (int j = 0; j < readsPerWrite; j++) { + zk.getData(s, false, stat); + } + break; + } + } + } catch (KeeperException.ConnectionLossException e) { + // ignore connection loss + } catch (KeeperException e) { + e.printStackTrace(); + } + } + System.out.println(); + zk.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * @param args + * @throws IOException + * @throws KeeperException + * @throws NumberFormatException + */ + public static void main(String[] args) throws NumberFormatException, + IOException { + if (args.length != 3) { + System.err + .println("USAGE: SledgeHammer zookeeper_server reps reads_per_rep"); + System.exit(3); + } + SledgeHammer h = new SledgeHammer(args[0], Integer.parseInt(args[1]), + Integer.parseInt(args[2])); + h.start(); + System.exit(0); + } + + public void process(WatchedEvent event) { + synchronized (this) { + notifyAll(); + } + } + +}