net.sf.katta.protocol.InteractionProtocolTest.java Source code

Java tutorial

Introduction

Here is the source code for net.sf.katta.protocol.InteractionProtocolTest.java

Source

/**
 * Copyright 2008 the original author or authors.
 *
 * 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 net.sf.katta.protocol;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

import net.sf.katta.AbstractZkTest;
import net.sf.katta.master.Master;
import net.sf.katta.node.Node;
import net.sf.katta.node.monitor.MetricsRecord;
import net.sf.katta.operation.OperationId;
import net.sf.katta.operation.master.AbstractIndexOperation;
import net.sf.katta.operation.master.MasterOperation;
import net.sf.katta.operation.node.NodeOperation;
import net.sf.katta.protocol.metadata.IndexMetaData;
import net.sf.katta.protocol.metadata.NodeMetaData;
import net.sf.katta.protocol.metadata.IndexMetaData.Shard;
import net.sf.katta.testutil.Mocks;
import net.sf.katta.testutil.mockito.WaitingAnswer;
import net.sf.katta.util.ZkConfiguration.PathDef;

import org.I0Itec.zkclient.Gateway;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.util.ZkPathUtil;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.proto.WatcherEvent;
import org.junit.Test;
import org.mockito.InOrder;

public class InteractionProtocolTest extends AbstractZkTest {

    @Test(timeout = 7000)
    public void testLifecycle() throws Exception {
        int GATEWAY_PORT = 2190;
        Gateway gateway = new Gateway(GATEWAY_PORT, _zk.getServerPort());
        gateway.start();
        ZkClient zkClient = new ZkClient("localhost:" + GATEWAY_PORT);

        InteractionProtocol protocol = new InteractionProtocol(zkClient, _zk.getZkConf());
        final AtomicInteger connectCount = new AtomicInteger();
        final AtomicInteger disconnectCount = new AtomicInteger();
        final Object mutex = new Object();

        protocol.registerComponent(new ConnectedComponent() {
            @Override
            public void disconnect() {
                disconnectCount.incrementAndGet();
                synchronized (mutex) {
                    mutex.notifyAll();
                }
            }

            @Override
            public void reconnect() {
                connectCount.incrementAndGet();
                synchronized (mutex) {
                    mutex.notifyAll();
                }
            }
        });
        synchronized (mutex) {
            gateway.stop();
            mutex.wait();
            gateway.start();
            mutex.wait();
            gateway.stop();
            mutex.wait();
            gateway.start();
            mutex.wait();
        }
        zkClient.close();
        assertEquals(2, connectCount.get());
        assertEquals(2, connectCount.get());
        gateway.stop();
    }

    @Test(timeout = 7000)
    public void testNodeQueue() throws Exception {
        Node node = mock(Node.class);
        String nodeName = "node1";
        when(node.getName()).thenReturn(nodeName);

        InteractionProtocol protocol = _zk.getInteractionProtocol();
        NodeQueue nodeQueue = protocol.publishNode(node, new NodeMetaData());

        NodeOperation nodeOperation1 = mock(NodeOperation.class, withSettings().serializable().name("a"));
        NodeOperation nodeOperation2 = mock(NodeOperation.class, withSettings().serializable().name("b"));
        OperationId operation1Id = protocol.addNodeOperation(nodeName, nodeOperation1);
        OperationId operation2Id = protocol.addNodeOperation(nodeName, nodeOperation2);

        assertTrue(protocol.isNodeOperationQueued(operation1Id));
        assertTrue(protocol.isNodeOperationQueued(operation2Id));
        assertEquals(nodeOperation1.toString(), nodeQueue.remove().toString());
        assertEquals(nodeOperation2.toString(), nodeQueue.remove().toString());
        assertTrue(nodeQueue.isEmpty());
        assertFalse(protocol.isNodeOperationQueued(operation1Id));
        assertFalse(protocol.isNodeOperationQueued(operation2Id));
    }

    @Test(timeout = 7000)
    public void testPublishMaster() throws Exception {
        Master master1 = mock(Master.class);
        Master master2 = mock(Master.class);
        when(master1.getMasterName()).thenReturn("master1");
        when(master2.getMasterName()).thenReturn("master2");
        MasterOperation operation = mock(MasterOperation.class);
        _protocol.addMasterOperation(operation);

        MasterQueue queue = _protocol.publishMaster(master1);
        assertNotNull(queue);
        assertNotNull(_protocol.getMasterMD());
        assertEquals(1, queue.size());
        assertNotNull(queue.peek());

        // same again
        queue = _protocol.publishMaster(master1);
        assertNotNull(queue);
        assertNotNull(_protocol.getMasterMD());

        // second master
        queue = _protocol.publishMaster(master2);
        assertNull(queue);
        assertNotNull(_protocol.getMasterMD());
    }

    @Test(timeout = 7000)
    public void testPublishNode() throws Exception {
        Node node = Mocks.mockNode();
        assertNull(_protocol.getNodeMD(node.getName()));
        NodeQueue queue = _protocol.publishNode(node, new NodeMetaData(node.getName()));
        assertNotNull(queue);
        assertNotNull(_protocol.getNodeMD(node.getName()));

        // test operation
        NodeOperation operation = mock(NodeOperation.class);
        OperationId operationId = _protocol.addNodeOperation(node.getName(), operation);
        assertEquals(1, queue.size());
        assertNotNull(queue.peek());
        assertEquals(node.getName(), operationId.getNodeName());
    }

    @Test(timeout = 7000)
    public void testExplainStructure() throws Exception {
        _protocol.explainStructure();
        System.out.println("----------------");
        _protocol.showStructure(false);
        System.out.println("----------------");
        _protocol.showStructure(true);
    }

    @Test(timeout = 7000)
    public void testUnregisterListenersOnUnregisterComponent() throws Exception {
        ConnectedComponent component = mock(ConnectedComponent.class);
        _protocol.registerComponent(component);

        IAddRemoveListener childListener = mock(IAddRemoveListener.class);
        IZkDataListener dataListener = mock(IZkDataListener.class);
        _protocol.registerChildListener(component, PathDef.NODES_LIVE, childListener);
        _protocol.registerDataListener(component, PathDef.NODES_LIVE, "node1", dataListener);

        _zk.getZkClient().createPersistent(_zk.getZkConf().getZkPath(PathDef.NODES_LIVE, "node1"));
        Thread.sleep(500);
        verify(childListener).added("node1");
        verify(dataListener).handleDataChange(anyString(), any());
        verifyNoMoreInteractions(childListener, dataListener);

        _protocol.unregisterComponent(component);
        _zk.getZkClient().delete(_zk.getZkConf().getZkPath(PathDef.NODES_LIVE, "node1"));
        Thread.sleep(500);
        verifyNoMoreInteractions(childListener, dataListener);
        // ephemerals should be removed
        // listeners nshould be removed
    }

    @Test(timeout = 7000)
    public void testDeleteEphemeraksOnUnregisterComponent() throws Exception {
        Master master = mock(Master.class);
        _protocol.publishMaster(master);
        assertNotNull(_protocol.getMasterMD());

        _protocol.unregisterComponent(master);
        assertNull(_protocol.getMasterMD());
    }

    @Test(timeout = 7000)
    public void testChildListener() throws Exception {
        ConnectedComponent component = mock(ConnectedComponent.class);
        IAddRemoveListener listener = mock(IAddRemoveListener.class);
        PathDef pathDef = PathDef.NODES_LIVE;

        _zk.getZkClient().createPersistent(_zk.getZkConf().getZkPath(pathDef, "node1"));
        List<String> existingChilds = _protocol.registerChildListener(component, pathDef, listener);
        assertEquals(1, existingChilds.size());
        assertTrue(existingChilds.contains("node1"));

        _zk.getZkClient().createPersistent(_zk.getZkConf().getZkPath(pathDef, "node2"));
        _zk.getZkClient().delete(_zk.getZkConf().getZkPath(pathDef, "node1"));

        Thread.sleep(500);
        InOrder inOrder = inOrder(listener);
        inOrder.verify(listener).added("node2");
        inOrder.verify(listener).removed("node1");
        verifyNoMoreInteractions(listener);
    }

    @Test(timeout = 70000)
    public void testDataListener() throws Exception {
        ConnectedComponent component = mock(ConnectedComponent.class);
        IZkDataListener listener = mock(IZkDataListener.class);
        PathDef pathDef = PathDef.INDICES_METADATA;
        String zkPath = _zk.getZkConf().getZkPath(pathDef, "index1");

        Long serializable = new Long(1);
        _zk.getZkClient().createPersistent(zkPath, serializable);
        _protocol.registerDataListener(component, pathDef, "index1", listener);

        serializable = new Long(2);
        _zk.getZkClient().writeData(zkPath, serializable);
        Thread.sleep(500);
        verify(listener).handleDataChange(zkPath, serializable);

        _zk.getZkClient().delete(zkPath);
        Thread.sleep(500);
        verify(listener).handleDataDeleted(zkPath);
        verifyNoMoreInteractions(listener);
    }

    @Test(timeout = 70000)
    public void testIndexManagement() throws Exception {
        IndexMetaData indexMD = new IndexMetaData("index1", "indexPath", 2);
        indexMD.getShards()
                .add(new Shard(AbstractIndexOperation.createShardName(indexMD.getName(), "path1"), "path1"));
        Node node = Mocks.mockNode();

        assertNull(_protocol.getIndexMD("index1"));
        assertEquals(0, _protocol.getIndices().size());

        // publish index
        _protocol.publishIndex(indexMD);
        _protocol.publishShard(node, indexMD.getShards().iterator().next().getName());
        assertNotNull(_protocol.getIndexMD("index1"));
        assertEquals(1, _protocol.getIndices().size());
        assertEquals(indexMD.getReplicationLevel(), _protocol.getIndexMD(indexMD.getName()).getReplicationLevel());

        // update index
        indexMD.setReplicationLevel(3);
        _protocol.updateIndexMD(indexMD);
        assertEquals(indexMD.getReplicationLevel(), _protocol.getIndexMD(indexMD.getName()).getReplicationLevel());

        _protocol.showStructure(false);
        _protocol.unpublishIndex(indexMD.getName());
        _protocol.showStructure(false);
        assertNull(_protocol.getIndexMD("index1"));
        assertEquals(0, _protocol.getIndices().size());

        String string = ZkPathUtil.toString(_protocol._zkClient);
        Set<Shard> shards = indexMD.getShards();
        for (Shard shard : shards) {
            assertFalse(string.contains(shard.getName()));
        }
    }

    @Test(timeout = 7000)
    public void testShardManagement() throws Exception {
        Node node1 = Mocks.mockNode();
        Node node2 = Mocks.mockNode();
        Map<String, String> shardMD = new HashMap<String, String>();
        shardMD.put("a", "1");

        assertEquals(0, _protocol.getShardNodes("shard1").size());

        // publish shard
        _protocol.publishShard(node1, "shard1");
        assertEquals(1, _protocol.getShardNodes("shard1").size());
        assertEquals(1, _protocol.getNodeShards(node1.getName()).size());
        assertEquals(0, _protocol.getNodeShards(node2.getName()).size());

        // publish shard on 2nd node
        _protocol.publishShard(node2, "shard1");
        assertEquals(2, _protocol.getShardNodes("shard1").size());
        assertEquals(1, _protocol.getNodeShards(node1.getName()).size());
        assertEquals(1, _protocol.getNodeShards(node2.getName()).size());

        // remove shard on first node
        _protocol.unpublishShard(node1, "shard1");
        assertEquals(1, _protocol.getShardNodes("shard1").size());
        assertEquals(0, _protocol.getNodeShards(node1.getName()).size());
        assertEquals(1, _protocol.getNodeShards(node2.getName()).size());

        // publish 2nd shard
        _protocol.publishShard(node1, "shard2");
        assertEquals(1, _protocol.getShardNodes("shard1").size());
        assertEquals(1, _protocol.getShardNodes("shard2").size());
        assertEquals(1, _protocol.getNodeShards(node1.getName()).size());
        assertEquals(1, _protocol.getNodeShards(node2.getName()).size());

        // remove one shard completely
        _protocol.unpublishShard(node1, "shard2");

        Map<String, List<String>> shard2NodesMap = _protocol.getShard2NodesMap(Arrays.asList("shard1"));
        assertEquals(1, shard2NodesMap.size());
        assertEquals(1, shard2NodesMap.get("shard1").size());
    }

    @Test(timeout = 7000)
    public void testMetrics() throws Exception {
        String nodeName1 = "node1";
        assertNull(_protocol.getMetric(nodeName1));
        _protocol.setMetric(nodeName1, new MetricsRecord(nodeName1));
        assertNotNull(_protocol.getMetric(nodeName1));

        String nodeName2 = "node2";
        _protocol.setMetric(nodeName2, new MetricsRecord(nodeName1));
        assertNotSame(_protocol.getMetric(nodeName1).getServerId(), _protocol.getMetric(nodeName2).getServerId());
    }

    @Test
    /**see KATTA-125*/
    public void testConcurrentModification() throws Exception {
        ConnectedComponent component1 = mock(ConnectedComponent.class);
        WaitingAnswer waitingAnswer = new WaitingAnswer();
        doAnswer(waitingAnswer).when(component1).disconnect();
        _protocol = _zk.createInteractionProtocol();
        _protocol.registerComponent(component1);
        WatchedEvent expiredEvent = new WatchedEvent(
                new WatcherEvent(EventType.None.getIntValue(), KeeperState.Expired.getIntValue(), null));
        _protocol.getZkClient().process(new WatchedEvent(
                new WatcherEvent(EventType.None.getIntValue(), KeeperState.SyncConnected.getIntValue(), null)));
        _protocol.getZkClient().process(expiredEvent);
        // verify(component1).disconnect();

        ConnectedComponent component2 = mock(ConnectedComponent.class, "2ndComp");
        _protocol.registerComponent(component2);
        _protocol.unregisterComponent(component2);
        waitingAnswer.release();
        _protocol.disconnect();
    }
}