aurora-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From zma...@apache.org
Subject [01/37] aurora git commit: Import of Twitter Commons.
Date Tue, 25 Aug 2015 18:19:15 GMT
Repository: aurora
Updated Branches:
  refs/heads/master cb84ed249 -> 86a547b92


http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/zookeeper/ZooKeeperMapTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/zookeeper/ZooKeeperMapTest.java b/commons/src/test/java/com/twitter/common/zookeeper/ZooKeeperMapTest.java
new file mode 100644
index 0000000..1170778
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/zookeeper/ZooKeeperMapTest.java
@@ -0,0 +1,421 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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 com.twitter.common.zookeeper;
+
+import java.util.AbstractMap.SimpleEntry;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.data.ACL;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.twitter.common.base.Command;
+import com.twitter.common.collections.Pair;
+import com.twitter.common.zookeeper.ZooKeeperMap.Listener;
+import com.twitter.common.zookeeper.testing.BaseZooKeeperTest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class ZooKeeperMapTest extends BaseZooKeeperTest {
+
+  private static final List<ACL> ACL = ZooDefs.Ids.OPEN_ACL_UNSAFE;
+  private static final Function<byte[], String> BYTES_TO_STRING =
+      new Function<byte[], String>() {
+        @Override
+        public String apply(byte[] from) {
+          return new String(from);
+        }};
+
+  private static class TestListener implements ZooKeeperMap.Listener<String> {
+    private final BlockingQueue<Pair<String, String>> queue =
+        new LinkedBlockingQueue<Pair<String, String>>();
+
+    public Pair<String, String> waitForUpdate() throws InterruptedException {
+      return queue.take();
+    }
+
+    @Override
+    public void nodeChanged(String name, String value) {
+      queue.offer(Pair.of(name, value));
+    }
+
+    @Override
+    public void nodeRemoved(String name) {
+      queue.offer(Pair.of(name, (String) null));
+    }
+  }
+
+  private ZooKeeperClient zkClient;
+  private BlockingQueue<Pair<String, String>> entryChanges;
+
+  @Before
+  public void mySetUp() throws Exception {
+    zkClient = createZkClient();
+    entryChanges = new LinkedBlockingQueue<Pair<String, String>>();
+  }
+
+  @Test(expected = KeeperException.NoNodeException.class)
+  public void testMissingPath() throws Exception {
+    makeMap("/twitter/doesnt/exist");
+  }
+
+  @Test(expected = KeeperException.class)
+  public void testZooKeeperUnavailableAtConstruction() throws Exception {
+    final String parentPath = "/twitter/path";
+    ZooKeeperUtils.ensurePath(zkClient, ACL, parentPath);
+
+    shutdownNetwork();  // Make zk unavailable.
+
+    makeUninitializedMap(parentPath);
+  }
+
+  @Test(expected = KeeperException.class)
+  public void testZooKeeperUnavailableAtInit() throws Exception {
+    final String parentPath = "/twitter/path";
+    ZooKeeperUtils.ensurePath(zkClient, ACL, parentPath);
+    ZooKeeperMap<String> zkMap = makeUninitializedMap(parentPath);
+
+    shutdownNetwork();  // Make zk unavailable.
+
+    zkMap.init();
+  }
+
+  @Test
+  public void testInitialization() throws Exception {
+    final String parentPath = "/twitter/path";
+    final String node = "node";
+    final String nodePath = parentPath + "/" + node;
+    final String data = "abcdefg";
+
+    ZooKeeperUtils.ensurePath(zkClient, ACL, parentPath);
+    zkClient.get().create(nodePath, data.getBytes(), ACL, CreateMode.PERSISTENT);
+    ZooKeeperMap<String> zkMap = makeUninitializedMap(parentPath);
+
+    // Map should be empty before initialization
+    assertTrue(zkMap.isEmpty());
+
+    zkMap.init();
+
+    // Now that we've initialized, the data should be synchronously reflected.
+    assertFalse(zkMap.isEmpty());
+    assertEquals(1, zkMap.size());
+    assertEquals(data, zkMap.get(node));
+  }
+
+  @Test
+  public void testEmptyStaticMap() throws Exception {
+    final String parentPath = "/twitter/path";
+    ZooKeeperUtils.ensurePath(zkClient, ACL, parentPath);
+    Map<String, String> zkMap = makeMap(parentPath);
+
+    assertEquals(0, zkMap.size());
+    assertTrue(zkMap.isEmpty());
+  }
+
+  @Test
+  public void testStaticMapWithValues() throws Exception {
+    final String parentPath = "/twitter/path";
+    final String node1 = "node1";
+    final String node2 = "node2";
+    final String nodePath1 = parentPath + "/" + node1;
+    final String nodePath2 = parentPath + "/" + node2;
+    final String data1 = "hello World!";
+    final String data2 = "evrver232&$";
+    ZooKeeperUtils.ensurePath(zkClient, ACL, parentPath);
+    zkClient.get().create(nodePath1, data1.getBytes(), ACL, CreateMode.PERSISTENT);
+    zkClient.get().create(nodePath2, data2.getBytes(), ACL, CreateMode.PERSISTENT);
+
+    Map<String, String> zkMap = makeMap(parentPath);
+
+    // Test all java.util.Map operations that are implemented.
+    assertTrue(zkMap.containsKey(node1));
+    assertTrue(zkMap.containsKey(node2));
+    assertTrue(zkMap.containsValue(data1));
+    assertTrue(zkMap.containsValue(data2));
+    assertEquals(ImmutableSet.of(new SimpleEntry<String, String>(node1, data1),
+        new SimpleEntry<String, String>(node2, data2)), zkMap.entrySet());
+    assertEquals(data1, zkMap.get(node1));
+    assertEquals(data2, zkMap.get(node2));
+    assertFalse(zkMap.isEmpty());
+    assertEquals(ImmutableSet.of(node1, node2),
+        zkMap.keySet());
+    assertEquals(2, zkMap.size());
+  }
+
+  @Test
+  public void testChangingChildren() throws Exception {
+    final String parentPath = "/twitter/path";
+    final String node1 = "node1";
+    final String node2 = "node2";
+    final String nodePath1 = parentPath + "/" + node1;
+    final String nodePath2 = parentPath + "/" + node2;
+    final String data1 = "wefwe";
+    final String data2 = "rtgrtg";
+
+    ZooKeeperUtils.ensurePath(zkClient, ACL, parentPath);
+    zkClient.get().create(nodePath1, data1.getBytes(), ACL, CreateMode.PERSISTENT);
+
+    Map<String, String> zkMap = makeMap(parentPath);
+    assertEquals(1, zkMap.size());
+    assertEquals(data1, zkMap.get(node1));
+    assertEquals(null, zkMap.get(node2));
+
+    // Make sure the map is updated when a child is added.
+    zkClient.get().create(nodePath2, data2.getBytes(), ACL, CreateMode.PERSISTENT);
+    waitForEntryChange(node2, data2);
+    assertEquals(2, zkMap.size());
+    assertEquals(data1, zkMap.get(node1));
+    assertEquals(data2, zkMap.get(node2));
+
+    // Make sure the map is updated when a child is deleted.
+    zkClient.get().delete(nodePath1, -1);
+    waitForEntryChange(node1, null);
+    assertEquals(1, zkMap.size());
+    assertEquals(null, zkMap.get(node1));
+    assertEquals(data2, zkMap.get(node2));
+  }
+
+  @Test
+  public void testChangingChildValues() throws Exception {
+    final String parentPath = "/twitter/path";
+    final String node = "node";
+    final String nodePath = parentPath + "/" + node;
+
+    final String data1 = "";
+    final String data2 = "abc";
+    final String data3 = "lalala";
+
+    ZooKeeperUtils.ensurePath(zkClient, ACL, parentPath);
+    zkClient.get().create(nodePath, data1.getBytes(), ACL, CreateMode.PERSISTENT);
+
+    TestListener testListener = new TestListener();
+    Map<String, String> zkMap = makeMap(parentPath, testListener);
+
+    assertEquals(Pair.of(node, data1), testListener.waitForUpdate());
+
+    assertEquals(1, zkMap.size());
+    assertEquals(data1, zkMap.get(node));
+
+    zkClient.get().setData(nodePath, data2.getBytes(), -1);
+    waitForEntryChange(node, data2);
+    assertEquals(1, zkMap.size());
+
+    assertEquals(Pair.of(node, data2), testListener.waitForUpdate());
+
+    zkClient.get().setData(nodePath, data3.getBytes(), -1);
+    waitForEntryChange(node, data3);
+    assertEquals(1, zkMap.size());
+
+    assertEquals(Pair.of(node, data3), testListener.waitForUpdate());
+  }
+
+  @Test
+  public void testRemoveParentNode() throws Exception {
+    final String parentPath = "/twitter/path";
+    final String node = "node";
+    final String nodePath = parentPath + "/" + node;
+    final String data = "testdata";
+
+    ZooKeeperUtils.ensurePath(zkClient, ACL, parentPath);
+    zkClient.get().create(nodePath, data.getBytes(), ACL, CreateMode.PERSISTENT);
+
+    TestListener testListener = new TestListener();
+    Map<String, String> zkMap = makeMap(parentPath, testListener);
+    assertEquals(1, zkMap.size());
+    assertEquals(data, zkMap.get(node));
+
+    assertEquals(Pair.of(node, data), testListener.waitForUpdate());
+
+    zkClient.get().delete(nodePath, -1);
+    zkClient.get().delete(parentPath, -1);
+
+    assertEquals(Pair.of(node, null), testListener.waitForUpdate());
+
+    waitForEntryChange(node, null);
+    assertEquals(0, zkMap.size());
+    assertTrue(zkMap.isEmpty());
+
+    // Recreate our node, make sure the map observes it.
+    ZooKeeperUtils.ensurePath(zkClient, ACL, parentPath);
+    zkClient.get().create(nodePath, data.getBytes(), ACL, CreateMode.PERSISTENT);
+    waitForEntryChange(node, data);
+  }
+
+  @Test
+  public void testSessionExpireLogic() throws Exception {
+    final String parentPath = "/twitter/path";
+    final String node1 = "node1";
+    final String nodePath1 = parentPath + "/" + node1;
+    final String data1 = "testdata";
+
+    ZooKeeperUtils.ensurePath(zkClient, ACL, parentPath);
+    zkClient.get().create(nodePath1, data1.getBytes(), ACL, CreateMode.PERSISTENT);
+
+    Map<String, String> zkMap = makeMap(parentPath);
+    assertEquals(1, zkMap.size());
+    assertEquals(data1, zkMap.get(node1));
+
+    expireSession(zkClient);
+    assertEquals(1, zkMap.size());
+    assertEquals(data1, zkMap.get(node1));
+
+    final String node2 = "node2";
+    final String nodePath2 = parentPath + "/" + node2;
+    final String data2 = "testdata2";
+    zkClient = createZkClient();
+    zkClient.get().create(nodePath2, data2.getBytes(), ACL, CreateMode.PERSISTENT);
+
+    waitForEntryChange(node2, data2);
+    assertEquals(2, zkMap.size());
+    assertEquals(data2, zkMap.get(node2));
+  }
+
+  @Test
+  public void testStaticCreate() throws Exception {
+    String parentPath = "/twitter/path";
+    String node = "node";
+    String nodePath = parentPath + "/" + node;
+    String data = "DaTa";
+
+    ZooKeeperUtils.ensurePath(zkClient, ACL, parentPath);
+    zkClient.get().create(nodePath, data.getBytes(), ACL, CreateMode.PERSISTENT);
+
+    Map<String, String> zkMap = ZooKeeperMap.create(zkClient, parentPath, BYTES_TO_STRING);
+    assertEquals(1, zkMap.size());
+    assertEquals(data, zkMap.get(node));
+  }
+
+  private static void checkUnsupported(Command test) {
+    try {
+      test.execute();
+      fail("Expected UnsupportedOperationException to be thrown.");
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+  }
+
+  @Test
+  public void testReadOnly() throws Exception {
+    String parentPath = "/twitter/path";
+    final String node = "node";
+    String nodePath = parentPath + "/" + node;
+    String data = "DaTa";
+
+    ZooKeeperUtils.ensurePath(zkClient, ACL, parentPath);
+    zkClient.get().create(nodePath, data.getBytes(), ACL, CreateMode.PERSISTENT);
+
+    final Map<String, String> zkMap = ZooKeeperMap.create(zkClient, parentPath, BYTES_TO_STRING);
+    checkUnsupported(new Command() {
+      @Override public void execute() {
+        zkMap.clear();
+      }
+    });
+    checkUnsupported(new Command() {
+      @Override public void execute() {
+        zkMap.remove(node);
+      }
+    });
+    checkUnsupported(new Command() {
+      @Override public void execute() {
+        zkMap.put("othernode", "othervalue");
+      }
+    });
+    checkUnsupported(new Command() {
+      @Override public void execute() {
+        zkMap.putAll(ImmutableMap.of("othernode", "othervalue"));
+      }
+    });
+    checkUnsupported(new Command() {
+      @Override public void execute() {
+        zkMap.keySet().iterator().remove();
+      }
+    });
+    checkUnsupported(new Command() {
+      @Override public void execute() {
+        zkMap.values().iterator().remove();
+      }
+    });
+    checkUnsupported(new Command() {
+      @Override public void execute() {
+        zkMap.entrySet().iterator().remove();
+      }
+    });
+
+    // Ensure contents didn't change
+    assertEquals(1, zkMap.size());
+    assertEquals(data, zkMap.get(node));
+  }
+
+  private void waitForEntryChange(String key, String value) throws Exception {
+    Pair<String, String> expectedEntry = Pair.of(key, value);
+    while (true) {
+      Pair<String, String> nextEntry = entryChanges.take();
+      if (expectedEntry.equals(nextEntry)) {
+        return;
+      }
+    }
+  }
+
+  private Map<String, String> makeMap(String path) throws Exception {
+    return makeMap(path, ZooKeeperMap.<String>noopListener());
+  }
+
+  private Map<String, String> makeMap(String path, ZooKeeperMap.Listener<String>
listener)
+      throws Exception {
+
+    ZooKeeperMap<String> zkMap = makeUninitializedMap(path, listener);
+    zkMap.init();
+    return zkMap;
+  }
+
+  private ZooKeeperMap<String> makeUninitializedMap(String path) throws Exception {
+    return makeUninitializedMap(path, ZooKeeperMap.<String>noopListener());
+  }
+
+  private ZooKeeperMap<String> makeUninitializedMap(String path, Listener<String>
listener)
+      throws Exception {
+
+    return new ZooKeeperMap<String>(zkClient, path, BYTES_TO_STRING, listener) {
+      @Override void putEntry(String key, String value) {
+        super.putEntry(key, value);
+        recordEntryChange(key);
+      }
+
+      @Override void removeEntry(String key) {
+        super.removeEntry(key);
+        recordEntryChange(key);
+      }
+
+      private void recordEntryChange(String key) {
+        entryChanges.offer(Pair.of(key, get(key)));
+      }
+    };
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/zookeeper/ZooKeeperNodeTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/zookeeper/ZooKeeperNodeTest.java b/commons/src/test/java/com/twitter/common/zookeeper/ZooKeeperNodeTest.java
new file mode 100644
index 0000000..f1ce3f3
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/zookeeper/ZooKeeperNodeTest.java
@@ -0,0 +1,284 @@
+package com.twitter.common.zookeeper;
+
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.KeeperException.NoNodeException;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.ZooKeeper;
+import org.apache.zookeeper.data.ACL;
+import org.apache.zookeeper.data.Stat;
+import org.easymock.Capture;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.twitter.common.base.Closure;
+import com.twitter.common.base.Closures;
+import com.twitter.common.base.Command;
+import com.twitter.common.testing.easymock.EasyMockTest;
+import com.twitter.common.zookeeper.ZooKeeperNode.NodeDeserializer;
+import com.twitter.common.zookeeper.testing.BaseZooKeeperTest;
+
+import static org.easymock.EasyMock.aryEq;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.isA;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+
+public class ZooKeeperNodeTest {
+  public static class LightWeightTests extends EasyMockTest {
+    private ZooKeeperClient zooKeeperClient;
+    private ZooKeeper zk;
+    private NodeDeserializer<String> deserializer;
+    private Closure<String> dataUpdateListener;
+    private ZooKeeperNode<String> node;
+
+    @Before
+    public void setUp() {
+      zooKeeperClient = createMock(ZooKeeperClient.class);
+      zk = createMock(ZooKeeper.class);
+      deserializer = createMock(new Clazz<NodeDeserializer<String>>() { });
+      dataUpdateListener = createMock(new Clazz<Closure<String>>() { });
+      node = new ZooKeeperNode<String>(zooKeeperClient, "/foo", deserializer, dataUpdateListener);
+    }
+
+    @Test
+    public void testWatchersReused() throws Exception {
+      // 1st init with initial no node exception
+      expect(zooKeeperClient.registerExpirationHandler(isA(Command.class))).andReturn(null);
+      expect(zooKeeperClient.get()).andReturn(zk);
+      Capture<Watcher> dataWatcher1 = createCapture();
+      expect(zk.getData(eq("/foo"), capture(dataWatcher1), isA(Stat.class)))
+          .andThrow(new NoNodeException()); // Force an existence watch to be set
+      dataUpdateListener.execute(null);
+
+      expect(zooKeeperClient.get()).andReturn(zk);
+      Capture<Watcher> existenceWatcher1 = createCapture();
+      expect(zk.exists(eq("/foo"), capture(existenceWatcher1))).andReturn(new Stat());
+
+      expect(zooKeeperClient.get()).andReturn(zk);
+      Capture<Watcher> dataWatcher2 = createCapture();
+      expect(zk.getData(eq("/foo"), capture(dataWatcher2), isA(Stat.class)))
+          .andReturn("bob".getBytes());
+      expect(deserializer.deserialize(aryEq("bob".getBytes()), isA(Stat.class))).andReturn("fred");
+      dataUpdateListener.execute("fred");
+
+      // 2nd init with initial no node exception
+      expect(zooKeeperClient.registerExpirationHandler(isA(Command.class))).andReturn(null);
+      expect(zooKeeperClient.get()).andReturn(zk);
+      Capture<Watcher> dataWatcher3 = createCapture();
+      expect(zk.getData(eq("/foo"), capture(dataWatcher3), isA(Stat.class)))
+          .andThrow(new NoNodeException()); // Force an existence watch to be set
+      dataUpdateListener.execute(null);
+
+      expect(zooKeeperClient.get()).andReturn(zk);
+      Capture<Watcher> existenceWatcher2 = createCapture();
+      expect(zk.exists(eq("/foo"), capture(existenceWatcher2))).andReturn(new Stat());
+
+      expect(zooKeeperClient.get()).andReturn(zk);
+      Capture<Watcher> dataWatcher4 = createCapture();
+      expect(zk.getData(eq("/foo"), capture(dataWatcher4), isA(Stat.class)))
+          .andReturn("bip".getBytes());
+      expect(deserializer.deserialize(aryEq("bip".getBytes()), isA(Stat.class))).andReturn("frog");
+      dataUpdateListener.execute("frog");
+
+      control.replay();
+
+      node.init();
+      node.init();
+
+      assertSame(dataWatcher1.getValue(), dataWatcher2.getValue());
+      assertSame(dataWatcher2.getValue(), dataWatcher3.getValue());
+      assertSame(dataWatcher3.getValue(), dataWatcher4.getValue());
+
+      assertSame(existenceWatcher1.getValue(), existenceWatcher2.getValue());
+    }
+  }
+
+  public static class HeavyWeightTests extends BaseZooKeeperTest {
+
+    private static final List<ACL> ACL = ZooDefs.Ids.OPEN_ACL_UNSAFE;
+
+    private ZooKeeperClient zkClient;
+
+    private static class Listener<T> implements Closure<T> {
+      // We use AtomicReference as a wrapper since LinkedBlockingQueue does not allow null
values.
+      private final BlockingQueue<AtomicReference<T>> queue =
+          new LinkedBlockingQueue<AtomicReference<T>>();
+
+      public void execute(T item) {
+        queue.offer(new AtomicReference<T>(item));
+      }
+
+      public T waitForUpdate() throws InterruptedException {
+        return queue.take().get();
+      }
+    }
+
+    private String nodePath;
+
+    @Before
+    public void mySetUp() throws Exception {
+      zkClient = createZkClient();
+      ZooKeeperUtils.ensurePath(zkClient, ACL, "/twitter");
+      nodePath = "/twitter/node";
+    }
+
+    @Test
+    public void testZooKeeperUnavailableAtConstruction() throws Exception {
+      shutdownNetwork();  // Make zk unavailable.
+
+      // Should be fine.
+      makeUninitializedNode(nodePath, Closures.<String>noop());
+    }
+
+    @Test(expected = KeeperException.class)
+    public void testZooKeeperUnavailableAtInit() throws Exception {
+      ZooKeeperNode zkNode = makeUninitializedNode(nodePath, Closures.<String>noop());
+
+      shutdownNetwork();  // Make zk unavailable.
+
+      zkNode.init();
+    }
+
+    @Test
+    public void testInitialization() throws Exception {
+      String data = "abcdefg";
+      zkClient.get().create(nodePath, data.getBytes(), ACL, CreateMode.PERSISTENT);
+      ZooKeeperNode zkNode = makeUninitializedNode(nodePath, Closures.<String>noop());
+
+      // get() should return null before initialization
+      assertEquals(null, zkNode.get());
+
+      zkNode.init();
+
+      // Now that init has been called, the data should be synchronously reflected.
+      assertEquals(data, zkNode.get());
+    }
+
+    @Test
+    public void testInitialEmptyNode() throws Exception {
+      Listener<String> listener = new Listener<String>();
+      ZooKeeperNode<String> zkNode = makeUninitializedNode(nodePath, listener);
+
+      assertEquals(null, zkNode.get());
+      zkNode.init();
+      assertEquals(null, listener.waitForUpdate());
+
+      String data = "abcdefg";
+      zkClient.get().create(nodePath, data.getBytes(), ACL, CreateMode.PERSISTENT);
+      assertEquals(data, listener.waitForUpdate());
+    }
+
+    @Test
+    public void testChangingData() throws Exception {
+      String data1 = "test_data";
+      zkClient.get().create(nodePath, data1.getBytes(), ACL, CreateMode.PERSISTENT);
+      Listener<String> listener = new Listener<String>();
+      TestDeserializer deserializer = new TestDeserializer();
+      makeNode(deserializer, nodePath, listener);
+
+      assertEquals(data1, listener.waitForUpdate());
+      assertNotNull(deserializer.getStat());
+      assertEquals(0, deserializer.getStat().getVersion());
+      String data2 = "BLAH";
+      zkClient.get().setData(nodePath, data2.getBytes(), -1);
+      assertEquals(data2, listener.waitForUpdate());
+      assertEquals(1, deserializer.getStat().getVersion());
+    }
+
+    @Test
+    public void testRemoveNode() throws Exception {
+      String data = "testdata";
+      zkClient.get().create(nodePath, data.getBytes(), ACL, CreateMode.PERSISTENT);
+      Listener<String> listener = new Listener<String>();
+      TestDeserializer deserializer = new TestDeserializer();
+      makeNode(deserializer, nodePath, listener);
+
+      assertEquals(data, listener.waitForUpdate());
+      assertNotNull(deserializer.getStat());
+      assertEquals(0, deserializer.getStat().getVersion());
+
+      zkClient.get().delete(nodePath, -1);
+      assertEquals(null, listener.waitForUpdate());
+      assertEquals(0, deserializer.getStat().getVersion());
+
+      zkClient.get().create(nodePath, data.getBytes(), ACL, CreateMode.PERSISTENT);
+      assertEquals(data, listener.waitForUpdate());
+      assertEquals(0, deserializer.getStat().getVersion());
+    }
+
+    @Test
+    public void testSessionExpireLogic() throws Exception {
+      String data1 = "testdata";
+      zkClient.get().create(nodePath, data1.getBytes(), ACL, CreateMode.PERSISTENT);
+      Listener<String> listener = new Listener<String>();
+      TestDeserializer deserializer = new TestDeserializer();
+      makeNode(deserializer, nodePath, listener);
+
+      assertEquals(data1, listener.waitForUpdate());
+      assertNotNull(deserializer.getStat());
+      assertEquals(0, deserializer.getStat().getVersion());
+
+      expireSession(zkClient);
+      assertEquals(data1, listener.waitForUpdate());
+
+      String data2 = "avewf";
+      zkClient = createZkClient();
+      zkClient.get().setData(nodePath, data2.getBytes(), -1);
+      assertEquals(data2, listener.waitForUpdate());
+      assertEquals(1, deserializer.getStat().getVersion());
+    }
+
+    @Test
+    public void testStaticCreate() throws Exception {
+      String data = "stuff";
+      zkClient.get().create(nodePath, data.getBytes(), ACL, CreateMode.PERSISTENT);
+      ZooKeeperNode<String> zkNode = ZooKeeperNode.create(zkClient, nodePath, new TestDeserializer());
+      assertEquals(data, zkNode.get());
+    }
+
+    private ZooKeeperNode<String> makeNode(TestDeserializer deserializer, String path,
+        Closure<String> listener) throws Exception {
+      ZooKeeperNode<String> zkNode = makeUninitializedNode(deserializer, path, listener);
+      zkNode.init();
+      return zkNode;
+    }
+
+    private ZooKeeperNode<String> makeUninitializedNode(String path, Closure<String>
listener)
+        throws Exception {
+      return makeUninitializedNode(new TestDeserializer(), path, listener);
+    }
+
+    private ZooKeeperNode<String> makeUninitializedNode(
+        ZooKeeperNode.NodeDeserializer<String> deserializer, String path, Closure<String>
listener)
+        throws Exception {
+      // we test deserializertionWithPair primarily because it is deserializertionally a
proper
+      // superset of deserializertionWithByteArray
+      return new ZooKeeperNode<String>(zkClient, path, deserializer, listener);
+    }
+
+    // helper to test Stat population and retrieval
+    private static final class TestDeserializer implements ZooKeeperNode.NodeDeserializer<String>
{
+      private Stat stat = null;
+
+      @Override
+      public String deserialize(byte[] data, Stat stat) {
+        this.stat = stat;
+        return new String(data);
+      }
+
+      Stat getStat() {
+        return stat;
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/zookeeper/ZooKeeperUtilsTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/zookeeper/ZooKeeperUtilsTest.java b/commons/src/test/java/com/twitter/common/zookeeper/ZooKeeperUtilsTest.java
new file mode 100644
index 0000000..1feba27
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/zookeeper/ZooKeeperUtilsTest.java
@@ -0,0 +1,141 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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 com.twitter.common.zookeeper;
+
+import com.google.common.base.Charsets;
+import com.twitter.common.zookeeper.testing.BaseZooKeeperTest;
+import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.KeeperException.BadVersionException;
+import org.apache.zookeeper.KeeperException.NoAuthException;
+import org.apache.zookeeper.ZooDefs;
+import org.apache.zookeeper.data.Stat;
+import org.junit.Test;
+
+import static com.google.common.testing.junit4.JUnitAsserts.assertNotEqual;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * @author John Sirois
+ */
+public class ZooKeeperUtilsTest extends BaseZooKeeperTest {
+  @Test
+  public void testEnsurePath() throws Exception {
+    ZooKeeperClient zkClient = createZkClient();
+    zkClient.get().addAuthInfo("digest", "client1:boo".getBytes(Charsets.UTF_8));
+
+    assertNull(zkClient.get().exists("/foo", false));
+    ZooKeeperUtils.ensurePath(zkClient, ZooDefs.Ids.CREATOR_ALL_ACL, "/foo/bar/baz");
+
+    zkClient = createZkClient();
+    zkClient.get().addAuthInfo("digest", "client2:bap".getBytes(Charsets.UTF_8));
+
+    // Anyone can check for existence in ZK
+    assertNotNull(zkClient.get().exists("/foo", false));
+    assertNotNull(zkClient.get().exists("/foo/bar", false));
+    assertNotNull(zkClient.get().exists("/foo/bar/baz", false));
+
+    try {
+      zkClient.get().delete("/foo/bar/baz", -1 /* delete no matter what */);
+      fail("Expected CREATOR_ALL_ACL to be applied to created path and client2 mutations
to be "
+           + "rejected");
+    } catch (NoAuthException e) {
+      // expected
+    }
+  }
+
+  @Test
+  public void testMagicVersionNumberAllowsUnconditionalUpdate() throws Exception {
+    String nodePath = "/foo";
+    ZooKeeperClient zkClient = createZkClient();
+
+    zkClient.get().create(nodePath, "init".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
+        CreateMode.PERSISTENT);
+
+    Stat initStat = new Stat();
+    byte[] initialData = zkClient.get().getData(nodePath, false, initStat);
+    assertArrayEquals("init".getBytes(), initialData);
+
+    // bump the version
+    Stat rev1Stat = zkClient.get().setData(nodePath, "rev1".getBytes(), initStat.getVersion());
+
+    try {
+      zkClient.get().setData(nodePath, "rev2".getBytes(), initStat.getVersion());
+      fail("expected correct version to be required");
+    } catch (BadVersionException e) {
+      // expected
+    }
+
+    // expect using the correct version to work
+    Stat rev2Stat = zkClient.get().setData(nodePath, "rev2".getBytes(), rev1Stat.getVersion());
+    assertNotEqual(ZooKeeperUtils.ANY_VERSION, rev2Stat.getVersion());
+
+    zkClient.get().setData(nodePath, "force-write".getBytes(), ZooKeeperUtils.ANY_VERSION);
+    Stat forceWriteStat = new Stat();
+    byte[] forceWriteData = zkClient.get().getData(nodePath, false, forceWriteStat);
+    assertArrayEquals("force-write".getBytes(), forceWriteData);
+
+    assertTrue(forceWriteStat.getVersion() > rev2Stat.getVersion());
+    assertNotEqual(ZooKeeperUtils.ANY_VERSION, forceWriteStat.getVersion());
+  }
+
+  @Test
+  public void testNormalizingPath() throws Exception {
+    assertEquals("/", ZooKeeperUtils.normalizePath("/"));
+    assertEquals("/foo", ZooKeeperUtils.normalizePath("/foo/"));
+    assertEquals("/foo/bar", ZooKeeperUtils.normalizePath("/foo//bar"));
+    assertEquals("/foo/bar", ZooKeeperUtils.normalizePath("//foo/bar"));
+    assertEquals("/foo/bar", ZooKeeperUtils.normalizePath("/foo/bar/"));
+    assertEquals("/foo/bar", ZooKeeperUtils.normalizePath("/foo/bar//"));
+    assertEquals("/foo/bar", ZooKeeperUtils.normalizePath("/foo/bar"));
+  }
+
+  @Test
+  public void testLenientPaths() {
+    assertEquals("/", ZooKeeperUtils.normalizePath("///"));
+    assertEquals("/a/group", ZooKeeperUtils.normalizePath("/a/group"));
+    assertEquals("/a/group", ZooKeeperUtils.normalizePath("/a/group/"));
+    assertEquals("/a/group", ZooKeeperUtils.normalizePath("/a//group"));
+    assertEquals("/a/group", ZooKeeperUtils.normalizePath("/a//group//"));
+
+    try {
+      ZooKeeperUtils.normalizePath("a/group");
+      fail("Relative paths should not be allowed.");
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+
+    try {
+      ZooKeeperUtils.normalizePath("/a/./group");
+      fail("Relative paths should not be allowed.");
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+
+    try {
+      ZooKeeperUtils.normalizePath("/a/../group");
+      fail("Relative paths should not be allowed.");
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/java/com/twitter/common/zookeeper/guice/ServerSetModuleTest.java
----------------------------------------------------------------------
diff --git a/commons/src/test/java/com/twitter/common/zookeeper/guice/ServerSetModuleTest.java
b/commons/src/test/java/com/twitter/common/zookeeper/guice/ServerSetModuleTest.java
new file mode 100644
index 0000000..a9c8575
--- /dev/null
+++ b/commons/src/test/java/com/twitter/common/zookeeper/guice/ServerSetModuleTest.java
@@ -0,0 +1,63 @@
+package com.twitter.common.zookeeper.guice;
+
+import java.util.Set;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.util.Providers;
+
+import org.easymock.EasyMock;
+import org.easymock.IMocksControl;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.twitter.common.application.ShutdownRegistry;
+import com.twitter.common.application.ShutdownRegistry.ShutdownRegistryImpl;
+import com.twitter.common.application.modules.LifecycleModule.ServiceRunner;
+import com.twitter.common.application.modules.LocalServiceRegistry;
+import com.twitter.common.zookeeper.ServerSet;
+import com.twitter.common.zookeeper.ZooKeeperClient;
+import com.twitter.common.zookeeper.testing.BaseZooKeeperTest;
+
+public class ServerSetModuleTest extends BaseZooKeeperTest {
+
+  private IMocksControl control;
+
+  private ServerSet serverSet;
+  private ShutdownRegistry shutdownRegistry;
+  private ZooKeeperClient zooKeeperClient;
+  private LocalServiceRegistry localServiceRegistry;
+
+  @Before
+  public void mySetUp() {
+    control = EasyMock.createControl();
+    serverSet = control.createMock(ServerSet.class);
+
+    shutdownRegistry = new ShutdownRegistryImpl();
+    zooKeeperClient = createZkClient();
+    Set<ServiceRunner> localServices = ImmutableSet.of();
+    localServiceRegistry = new LocalServiceRegistry(Providers.of(localServices), shutdownRegistry);
+  }
+
+  @After
+  public void verify() {
+    control.verify();
+  }
+
+  @Test
+  public void testInjection() {
+    control.replay();
+
+    Guice.createInjector(ImmutableList.of(ServerSetModule.builder().build(), new AbstractModule()
{
+      @Override protected void configure() {
+        bind(ServerSet.class).toInstance(serverSet);
+        bind(ZooKeeperClient.class).toInstance(zooKeeperClient);
+        bind(ShutdownRegistry.class).toInstance(shutdownRegistry);
+        bind(LocalServiceRegistry.class).toInstance(localServiceRegistry);
+      }
+    }));
+  }
+}

http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/test/resources/com/twitter/common/util/templating/template.st
----------------------------------------------------------------------
diff --git a/commons/src/test/resources/com/twitter/common/util/templating/template.st b/commons/src/test/resources/com/twitter/common/util/templating/template.st
new file mode 100644
index 0000000..c4cc8dc
--- /dev/null
+++ b/commons/src/test/resources/com/twitter/common/util/templating/template.st
@@ -0,0 +1,7 @@
+$header$
+
+$items:{ item |
+  The $item.name$ costs \$$item.price$.
+}$
+
+$footer$

http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/settings.gradle
----------------------------------------------------------------------
diff --git a/settings.gradle b/settings.gradle
index 6180227..b097e2f 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -12,4 +12,4 @@
  * limitations under the License.
  */
 rootProject.name = 'aurora'
-include 'api', 'buildSrc'
+include 'api', 'buildSrc', 'commons-args', 'commons'


Mime
View raw message