/** * Copyright 2011 LiveRamp * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.liveramp.hank.coordinator.zk; import com.liveramp.hank.coordinator.Coordinator; import com.liveramp.hank.coordinator.Host; import com.liveramp.hank.coordinator.HostCommand; import com.liveramp.hank.coordinator.HostState; import com.liveramp.hank.coordinator.PartitionServerAddress; import com.liveramp.hank.coordinator.mock.MockCoordinator; import com.liveramp.hank.test.ZkTestCase; import com.liveramp.hank.util.Condition; import com.liveramp.hank.util.WaitUntil; import com.liveramp.hank.zookeeper.ZkPath; import org.junit.Before; import org.junit.Test; import java.util.Collections; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class TestZkRing extends ZkTestCase { private static Coordinator coordinator; @Before public void setUp() throws Exception { create(ZkPath.append(getRoot(), "ring-group-one")); TestZkRing.coordinator = new MockCoordinator(); } private static final PartitionServerAddress LOCALHOST = PartitionServerAddress.parse("localhost:1"); private static final PartitionServerAddress LOCALHOST2 = PartitionServerAddress.parse("localhost:2"); private final String ring_group_root = ZkPath.append(getRoot(), "ring-group-one"); private final String ring_root = ZkPath.append(getRoot(), "ring-group-one/ring-1"); @Test public void testCreate() throws Exception { ZkRing ring = ZkRing.create(getZk(), coordinator, ring_group_root, 1, null, null); assertEquals("ring number", 1, ring.getRingNumber()); assertEquals("number of hosts", 0, ring.getHosts().size()); ring.close(); } @Test public void testLoad() throws Exception { ZkRing ring = ZkRing.create(getZk(), coordinator, ring_group_root, 1, null, null); ring.close(); ring = new ZkRing(getZk(), ZkPath.append(ring_group_root, "ring-1"), null, coordinator, null); assertEquals("ring number", 1, ring.getRingNumber()); assertEquals("number of hosts", 0, ring.getHosts().size()); ring.close(); } @Test public void testHosts() throws Exception { final ZkRing ring = ZkRing.create(getZk(), coordinator, ring_group_root, 1, null, null); assertEquals(0, ring.getHosts().size()); Host host = ring.addHost(LOCALHOST, Collections.<String>emptyList()); assertEquals(LOCALHOST, host.getAddress()); WaitUntil.orDie(new Condition() { @Override public boolean test() { return !ring.getHosts().isEmpty(); } }); assertEquals(Collections.singleton(host), ring.getHosts()); assertEquals(LOCALHOST, ring.getHostByAddress(LOCALHOST).getAddress()); ring.close(); // assure that hosts reload well, too final ZkRing sameRing = new ZkRing(getZk(), ring_root, null, coordinator, null); assertEquals(1, sameRing.getHosts().size()); assertEquals(Collections.singleton(host), sameRing.getHosts()); assertEquals(LOCALHOST, sameRing.getHostByAddress(LOCALHOST).getAddress()); // Rename that host sameRing.getHostByAddress(LOCALHOST).setAddress(LOCALHOST2); WaitUntil.orDie(new Condition() { @Override public boolean test() { return sameRing.getHostByAddress(LOCALHOST2) != null && LOCALHOST2.equals(sameRing.getHostByAddress(LOCALHOST2).getAddress()); } }); assertEquals(LOCALHOST2, sameRing.getHostByAddress(LOCALHOST2).getAddress()); assertNull(sameRing.getHostByAddress(LOCALHOST)); assertTrue(sameRing.removeHost(LOCALHOST2)); assertNull(sameRing.getHostByAddress(LOCALHOST2)); assertFalse(sameRing.removeHost(LOCALHOST2)); ring.close(); } @Test public void testListenersPreservedWhenHostAdded() throws Exception { ZkRing ring = ZkRing.create(getZk(), coordinator, ZkPath.append(getRoot(), "ring-group-one"), 1, null, null); Host h1 = ring.addHost(new PartitionServerAddress("localhost", 1), Collections.<String>emptyList()); MockHostCommandQueueChangeListener l1 = new MockHostCommandQueueChangeListener(); h1.setCommandQueueChangeListener(l1); final MockHostStateChangeListener l2 = new MockHostStateChangeListener(); h1.setStateChangeListener(l2); ring.addHost(new PartitionServerAddress("localhost", 2), Collections.<String>emptyList()); h1.setState(HostState.UPDATING); WaitUntil.orDie(new Condition() { @Override public boolean test() { return HostState.UPDATING == l2.calledWith; } }); assertEquals(HostState.UPDATING, l2.calledWith); h1.enqueueCommand(HostCommand.EXECUTE_UPDATE); l1.waitForNotification(); assertEquals(h1, l1.calledWith); } @Test public void testDelete() throws Exception { ZkRing ring = ZkRing.create(getZk(), coordinator, ZkPath.append(getRoot(), "ring-group-one"), 1, null, null); ring.delete(); assertTrue(getZk().exists(ZkPath.append(getRoot(), "ring-group-one/ring-1"), null) == null); } }