/*
* Copyright 2014 NAVER Corp.
*
* 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.navercorp.pinpoint.rpc.server;
import com.navercorp.pinpoint.rpc.PinpointSocket;
import com.navercorp.pinpoint.rpc.TestAwaitTaskUtils;
import com.navercorp.pinpoint.rpc.TestAwaitUtils;
import com.navercorp.pinpoint.rpc.client.PinpointClient;
import com.navercorp.pinpoint.rpc.client.PinpointClientFactory;
import com.navercorp.pinpoint.rpc.client.PinpointClientHandshaker;
import com.navercorp.pinpoint.rpc.packet.HandshakePropertyType;
import com.navercorp.pinpoint.rpc.util.PinpointRPCTestUtils;
import com.navercorp.pinpoint.rpc.util.TimerFactory;
import org.jboss.netty.util.Timer;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.SocketUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class HandshakeTest {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private static Timer timer = null;
private static int bindPort;
private final TestAwaitUtils awaitUtils = new TestAwaitUtils(10, 500);
@BeforeClass
public static void setUp() throws IOException {
timer = TimerFactory.createHashedWheelTimer(HandshakeTest.class.getSimpleName(), 100, TimeUnit.MILLISECONDS, 512);
bindPort = SocketUtils.findAvailableTcpPort();
}
@AfterClass
public static void tearDown() {
if (timer != null) {
timer.stop();
}
}
// simple test
@Test
public void handshakeTest1() throws InterruptedException {
final PinpointServerAcceptor serverAcceptor = PinpointRPCTestUtils.createPinpointServerFactory(bindPort, SimpleServerMessageListener.DUPLEX_INSTANCE);
PinpointClientFactory clientFactory1 = PinpointRPCTestUtils.createClientFactory(PinpointRPCTestUtils.getParams(), PinpointRPCTestUtils.createEchoClientListener());
PinpointClientFactory clientFactory2 = PinpointRPCTestUtils.createClientFactory(PinpointRPCTestUtils.getParams(), null);
try {
PinpointClient client = clientFactory1.connect("127.0.0.1", bindPort);
PinpointClient client2 = clientFactory2.connect("127.0.0.1", bindPort);
awaitUtils.await(new TestAwaitTaskUtils() {
@Override
public boolean checkCompleted() {
List<PinpointSocket> writableServerList = serverAcceptor.getWritableSocketList();
return writableServerList.size() == 2;
}
});
List<PinpointSocket> writableServerList = serverAcceptor.getWritableSocketList();
if (writableServerList.size() != 2) {
Assert.fail();
}
PinpointRPCTestUtils.close(client, client2);
} finally {
clientFactory1.release();
clientFactory2.release();
PinpointRPCTestUtils.close(serverAcceptor);
}
}
@Test
public void handshakeTest2() throws InterruptedException {
final PinpointServerAcceptor serverAcceptor = PinpointRPCTestUtils.createPinpointServerFactory(bindPort, SimpleServerMessageListener.DUPLEX_INSTANCE);
Map<String, Object> params = PinpointRPCTestUtils.getParams();
PinpointClientFactory clientFactory1 = PinpointRPCTestUtils.createClientFactory(PinpointRPCTestUtils.getParams(), PinpointRPCTestUtils.createEchoClientListener());
try {
PinpointClient client = clientFactory1.connect("127.0.0.1", bindPort);
awaitUtils.await(new TestAwaitTaskUtils() {
@Override
public boolean checkCompleted() {
List<PinpointSocket> writableServerList = serverAcceptor.getWritableSocketList();
return writableServerList.size() == 1;
}
});
PinpointSocket writableServer = getWritableServer("application", "agent", (Long) params.get(HandshakePropertyType.START_TIMESTAMP.getName()), serverAcceptor.getWritableSocketList());
Assert.assertNotNull(writableServer);
writableServer = getWritableServer("application", "agent", (Long) params.get(HandshakePropertyType.START_TIMESTAMP.getName()) + 1, serverAcceptor.getWritableSocketList());
Assert.assertNull(writableServer);
PinpointRPCTestUtils.close(client);
} finally {
clientFactory1.release();
PinpointRPCTestUtils.close(serverAcceptor);
}
}
@Test
public void testExecuteCompleteWithoutStart() {
int retryInterval = 100;
int maxHandshakeCount = 10;
PinpointClientHandshaker handshaker = new PinpointClientHandshaker(timer, retryInterval, maxHandshakeCount);
handshaker.handshakeComplete(null);
Assert.assertEquals(null, handshaker.getHandshakeResult());
Assert.assertTrue(handshaker.isFinished());
}
@Test
public void testExecuteAbortWithoutStart() {
int retryInterval = 100;
int maxHandshakeCount = 10;
PinpointClientHandshaker handshaker = new PinpointClientHandshaker(timer, retryInterval, maxHandshakeCount);
handshaker.handshakeAbort();
Assert.assertTrue(handshaker.isFinished());
}
private PinpointSocket getWritableServer(String applicationName, String agentId, long startTimeMillis, List<PinpointSocket> writableServerList) {
if (applicationName == null) {
return null;
}
if (agentId == null) {
return null;
}
if (startTimeMillis <= 0) {
return null;
}
List<PinpointSocket> result = new ArrayList<PinpointSocket>();
for (PinpointSocket writableServer : writableServerList) {
if (writableServer instanceof PinpointServer) {
Map agentProperties = ((PinpointServer)writableServer).getChannelProperties();
if (!applicationName.equals(agentProperties.get(HandshakePropertyType.APPLICATION_NAME.getName()))) {
continue;
}
if (!agentId.equals(agentProperties.get(HandshakePropertyType.AGENT_ID.getName()))) {
continue;
}
if (startTimeMillis != (Long) agentProperties.get(HandshakePropertyType.START_TIMESTAMP.getName())) {
continue;
}
result.add(writableServer);
}
}
if (result.isEmpty()) {
return null;
}
if (result.size() == 1) {
return result.get(0);
} else {
logger.warn("Ambiguous Channel Context {}, {}, {} (Valid Agent list={}).", applicationName, agentId, startTimeMillis, result);
return null;
}
}
}