// Copyright 2016 Twitter. All rights reserved.
//
// 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.twitter.heron.statemgr.zookeeper;
import java.net.InetSocketAddress;
import java.time.Duration;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.twitter.heron.common.basics.Pair;
import com.twitter.heron.spi.common.Config;
import com.twitter.heron.spi.common.Key;
import com.twitter.heron.spi.utils.NetworkUtils;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@RunWith(PowerMockRunner.class)
@PrepareForTest(NetworkUtils.class)
public class ZkUtilsTest {
/**
* Test setupZkTunnel
*/
@Test
public void testSetupZkTunnel() throws Exception {
String host0 = "host0";
int port0 = 12;
InetSocketAddress address0 =
NetworkUtils.getInetSocketAddress(String.format("%s:%d", host0, port0));
String host1 = "host1";
int port1 = 13;
InetSocketAddress address1 =
NetworkUtils.getInetSocketAddress(String.format("%s:%d", host1, port1));
String host2 = "host2";
int port2 = 9049;
InetSocketAddress address2 =
NetworkUtils.getInetSocketAddress(String.format("%s:%d", host2, port2));
String tunnelHost = "tunnelHost";
int tunnelPort = 9519;
InetSocketAddress tunnelAddress =
NetworkUtils.getInetSocketAddress(String.format("%s:%d", tunnelHost, tunnelPort));
// Original connection String
String connectionString = String.format("%s:%d, %s:%d, %s:%d ",
host0, port0, host1, port1, host2, port2);
Config config = mock(Config.class);
when(config.getStringValue(Key.STATEMGR_CONNECTION_STRING))
.thenReturn(connectionString);
NetworkUtils.TunnelConfig tunnelConfig =
NetworkUtils.TunnelConfig.build(config, NetworkUtils.HeronSystem.STATE_MANAGER);
Process process = mock(Process.class);
// Mock the invocation of establishSSHTunnelIfNeeded
// address0 and address1 are directly reachable
// address2 are reachable after tunneling
PowerMockito.spy(NetworkUtils.class);
PowerMockito.doReturn(new Pair<>(address0, process))
.when(NetworkUtils.class, "establishSSHTunnelIfNeeded",
eq(address0), anyString(), any(NetworkUtils.TunnelType.class), any(Duration.class),
anyInt(), any(Duration.class), anyInt());
PowerMockito.doReturn(new Pair<>(address1, process))
.when(NetworkUtils.class, "establishSSHTunnelIfNeeded",
eq(address1), anyString(), any(NetworkUtils.TunnelType.class), any(Duration.class),
anyInt(), any(Duration.class), anyInt());
PowerMockito.doReturn(new Pair<>(tunnelAddress, process))
.when(NetworkUtils.class, "establishSSHTunnelIfNeeded",
eq(address2), anyString(), any(NetworkUtils.TunnelType.class), any(Duration.class),
anyInt(), any(Duration.class), anyInt());
Pair<String, List<Process>> ret = ZkUtils.setupZkTunnel(config, tunnelConfig);
// Assert with expected results
String expectedConnectionString =
String.format("%s,%s,%s",
address0.toString(), address1.toString(), tunnelAddress.toString());
assertEquals(expectedConnectionString, ret.first);
assertEquals(3, ret.second.size());
for (Process p : ret.second) {
assertEquals(process, p);
}
}
}