/* * Copyright 2014-2016 CyberVision, Inc. * * 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 org.kaaproject.kaa.server.common.zk; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import org.apache.curator.RetryPolicy; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.retry.ExponentialBackoffRetry; import org.apache.curator.test.TestingCluster; import org.apache.curator.test.Timing; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.kaaproject.kaa.server.common.zk.bootstrap.BootstrapNode; import org.kaaproject.kaa.server.common.zk.bootstrap.BootstrapNodeListener; import org.kaaproject.kaa.server.common.zk.control.ControlNode; import org.kaaproject.kaa.server.common.zk.gen.BootstrapNodeInfo; import org.kaaproject.kaa.server.common.zk.gen.ConnectionInfo; import org.kaaproject.kaa.server.common.zk.gen.ControlNodeInfo; import org.kaaproject.kaa.server.common.zk.gen.TransportMetaData; import org.kaaproject.kaa.server.common.zk.gen.VersionConnectionInfoPair; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class BootstrapNodeIT { static final int TCP_ID = 73; static final int HTTP_ID = 42; private static final String UTF_8 = "UTF-8"; private static final String BOOTSTRAP_NODE_HOST = "192.168.0.202"; private static final String CONTROL_NODE_HOST = "192.168.0.1"; private CuratorFramework zkClient; private TestingCluster cluster; static List<TransportMetaData> getHttpAndTcpTransportMD() { List<TransportMetaData> supportedTransports = new ArrayList<>(); try { supportedTransports.add(getHttpTransportMD()); supportedTransports.add(getTcpTransportMD()); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return supportedTransports; } static TransportMetaData getTcpTransportMD() throws UnsupportedEncodingException { TransportMetaData tcp = new TransportMetaData(); tcp.setId(TCP_ID); tcp.setMaxSupportedVersion(2); tcp.setMinSupportedVersion(2); tcp.setConnectionInfo(Collections.singletonList(new VersionConnectionInfoPair(2, ByteBuffer.wrap("tcp".getBytes(UTF_8))))); return tcp; } static TransportMetaData getHttpTransportMD() throws UnsupportedEncodingException { TransportMetaData http = new TransportMetaData(); http.setId(HTTP_ID); http.setMaxSupportedVersion(1); http.setMinSupportedVersion(1); http.setConnectionInfo(Collections.singletonList(new VersionConnectionInfoPair(1, ByteBuffer.wrap("http".getBytes(UTF_8))))); return http; } @Before public void beforeTest() { try { cluster = new TestingCluster(3); cluster.start(); zkClient = CuratorFrameworkFactory.newClient(cluster.getConnectString(), buildDefaultRetryPolicy()); zkClient.start(); } catch (Exception e) { System.err.println("Unable to initialize cluster before test! " + e); } } @After public void afterTest() { try { zkClient.close(); cluster.close(); } catch (Exception e) { System.err.println("Unable to shutdown cluster after test! " + e); } } @Test public void boostrapListenerTest() throws Exception { Timing timing = new Timing(); ControlNodeInfo controlNodeInfo = buildControlNodeInfo(); BootstrapNodeInfo bootstrapNodeInfo = buildBootstrapNodeInfo(); ControlNode controlNode = new ControlNode(controlNodeInfo, zkClient); BootstrapNodeListener mockListener = mock(BootstrapNodeListener.class); controlNode.addListener(mockListener); controlNode.start(); BootstrapNode bootstrapNode = new BootstrapNode(bootstrapNodeInfo, zkClient); bootstrapNode.start(); timing.sleepABit(); verify(mockListener).onNodeAdded(bootstrapNodeInfo); List<TransportMetaData> transports = bootstrapNodeInfo.getTransports(); transports.remove(getHttpTransportMD()); bootstrapNode.updateNodeData(bootstrapNodeInfo); timing.sleepABit(); verify(mockListener).onNodeUpdated(bootstrapNodeInfo); bootstrapNode.close(); timing.sleepABit(); verify(mockListener).onNodeRemoved(bootstrapNodeInfo); bootstrapNode.close(); assertTrue(controlNode.removeListener(mockListener)); assertFalse(controlNode.removeListener(mockListener)); controlNode.close(); } @Test public void outdatedRemovalTest() throws Exception { Timing timing = new Timing(); ControlNodeInfo controlNodeInfo = buildControlNodeInfo(); BootstrapNodeInfo bootstrapNodeInfo = buildBootstrapNodeInfo(); ControlNode controlNode = new ControlNode(controlNodeInfo, zkClient); BootstrapNodeListener mockListener = mock(BootstrapNodeListener.class); controlNode.addListener(mockListener); controlNode.start(); BootstrapNode bootstrapNode = new BootstrapNode(bootstrapNodeInfo, zkClient); bootstrapNode.start(); timing.sleepABit(); verify(mockListener).onNodeAdded(bootstrapNodeInfo); BootstrapNodeInfo bootstrapNodeInfoWithGreaterTimeStarted = buildBootstrapNodeInfo(); BootstrapNode bootstrapNodeWithGreaterTimeStarted = new BootstrapNode(bootstrapNodeInfoWithGreaterTimeStarted, zkClient); bootstrapNodeWithGreaterTimeStarted.start(); timing.sleepABit(); bootstrapNode.close(); timing.sleepABit(); verify(mockListener, never()).onNodeRemoved(bootstrapNodeInfo); bootstrapNodeWithGreaterTimeStarted.close(); timing.sleepABit(); verify(mockListener).onNodeRemoved(bootstrapNodeInfoWithGreaterTimeStarted); controlNode.close(); } private RetryPolicy buildDefaultRetryPolicy() { return new ExponentialBackoffRetry(100, 1); } private BootstrapNodeInfo buildBootstrapNodeInfo() { BootstrapNodeInfo nodeInfo = new BootstrapNodeInfo(); ByteBuffer testKeyData = ByteBuffer.wrap(new byte[]{10, 11, 12, 45, 34, 23, 67, 89, 66, 12}); nodeInfo.setConnectionInfo(new ConnectionInfo(BOOTSTRAP_NODE_HOST, 1000, testKeyData)); nodeInfo.setTimeStarted(System.currentTimeMillis()); nodeInfo.setTransports(getHttpAndTcpTransportMD()); return nodeInfo; } private ControlNodeInfo buildControlNodeInfo() { ControlNodeInfo controlNodeInfo = new ControlNodeInfo(); controlNodeInfo.setConnectionInfo(new ConnectionInfo(CONTROL_NODE_HOST, 1000, null)); controlNodeInfo.setBootstrapServerCount(3); controlNodeInfo.setOperationsServerCount(4); return controlNodeInfo; } }