/*
* 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.client;
import com.navercorp.pinpoint.rpc.Future;
import com.navercorp.pinpoint.rpc.PinpointSocketException;
import com.navercorp.pinpoint.rpc.ResponseMessage;
import com.navercorp.pinpoint.rpc.TestAwaitTaskUtils;
import com.navercorp.pinpoint.rpc.TestAwaitUtils;
import com.navercorp.pinpoint.rpc.TestByteUtils;
import com.navercorp.pinpoint.rpc.server.PinpointServerAcceptor;
import com.navercorp.pinpoint.rpc.server.SimpleServerMessageListener;
import com.navercorp.pinpoint.rpc.util.PinpointRPCTestUtils;
import org.junit.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.SocketUtils;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author emeroad
*/
//@Ignore
public class ReconnectTest {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private static int bindPort;
private static PinpointClientFactory clientFactory;
private final TestAwaitUtils awaitUtils = new TestAwaitUtils(100, 1000);
@BeforeClass
public static void setUp() throws IOException {
bindPort = SocketUtils.findAvailableTcpPort();
clientFactory = new DefaultPinpointClientFactory();
clientFactory.setReconnectDelay(200);
clientFactory.setPingDelay(100);
clientFactory.setTimeoutMillis(200);
}
@AfterClass
public static void tearDown() {
if (clientFactory != null) {
clientFactory.release();
}
}
@Test
public void reconnect() throws IOException, InterruptedException {
PinpointServerAcceptor serverAcceptor = PinpointRPCTestUtils.createPinpointServerFactory(bindPort, SimpleServerMessageListener.DUPLEX_ECHO_INSTANCE);
final AtomicBoolean reconnectPerformed = new AtomicBoolean(false);
PinpointServerAcceptor newServerAcceptor = null;
try {
PinpointClient client = clientFactory.connect("localhost", bindPort);
client.addPinpointClientReconnectEventListener(new PinpointClientReconnectEventListener() {
@Override
public void reconnectPerformed(PinpointClient client) {
reconnectPerformed.set(true);
}
});
PinpointRPCTestUtils.close(serverAcceptor);
logger.debug("server.close");
assertClientDisconnected(client);
newServerAcceptor = PinpointRPCTestUtils.createPinpointServerFactory(bindPort, SimpleServerMessageListener.DUPLEX_ECHO_INSTANCE);
logger.debug("bind server");
assertClientConnected(client);
logger.debug("request server");
byte[] randomByte = TestByteUtils.createRandomByte(10);
byte[] response = PinpointRPCTestUtils.request(client, randomByte);
Assert.assertArrayEquals(randomByte, response);
PinpointRPCTestUtils.close(client);
} finally {
PinpointRPCTestUtils.close(newServerAcceptor);
}
Assert.assertTrue(reconnectPerformed.get());
}
// it takes very long time.
// @Test
@Ignore
public void reconnectStressTest() throws IOException, InterruptedException {
int count = 3;
ThreadMXBean tbean = ManagementFactory.getThreadMXBean();
int threadCount = tbean.getThreadCount();
for (int i = 0; i < count; i++) {
logger.debug((i + 1) + "th's start.");
PinpointServerAcceptor serverAcceptor = PinpointRPCTestUtils.createPinpointServerFactory(bindPort, SimpleServerMessageListener.DUPLEX_ECHO_INSTANCE);
PinpointClient client = clientFactory.connect("localhost", bindPort);
PinpointRPCTestUtils.close(serverAcceptor);
logger.debug("server.close");
assertClientDisconnected(client);
serverAcceptor = PinpointRPCTestUtils.createPinpointServerFactory(bindPort, SimpleServerMessageListener.DUPLEX_ECHO_INSTANCE);
logger.debug("bind server");
assertClientConnected(client);
logger.debug("request server");
byte[] randomByte = TestByteUtils.createRandomByte(10);
byte[] response = PinpointRPCTestUtils.request(client, randomByte);
Assert.assertArrayEquals(randomByte, response);
PinpointRPCTestUtils.close(client);
PinpointRPCTestUtils.close(serverAcceptor);
}
Thread.sleep(10000);
Assert.assertEquals(threadCount, tbean.getThreadCount());
}
@Test
public void scheduledConnect() throws IOException, InterruptedException {
final PinpointClientFactory clientFactory = new DefaultPinpointClientFactory();
clientFactory.setReconnectDelay(200);
PinpointClient client = null;
PinpointServerAcceptor serverAcceptor = null;
try {
client = clientFactory.scheduledConnect("localhost", bindPort);
serverAcceptor = PinpointRPCTestUtils.createPinpointServerFactory(bindPort, SimpleServerMessageListener.DUPLEX_ECHO_INSTANCE);
assertClientConnected(client);
logger.debug("request server");
byte[] randomByte = TestByteUtils.createRandomByte(10);
byte[] response = PinpointRPCTestUtils.request(client, randomByte);
Assert.assertArrayEquals(randomByte, response);
} finally {
PinpointRPCTestUtils.close(client);
clientFactory.release();
PinpointRPCTestUtils.close(serverAcceptor);
}
}
@Test
public void scheduledConnectAndClosed() throws IOException, InterruptedException {
PinpointClient client = clientFactory.scheduledConnect("localhost", bindPort);
logger.debug("close");
PinpointRPCTestUtils.close(client);
}
@Test
public void scheduledConnectDelayAndClosed() throws IOException, InterruptedException {
PinpointClient client = clientFactory.scheduledConnect("localhost", bindPort);
Thread.sleep(2000);
logger.debug("close pinpoint client");
PinpointRPCTestUtils.close(client);
}
@Test
public void scheduledConnectStateTest() {
PinpointClient client = clientFactory.scheduledConnect("localhost", bindPort);
client.send(new byte[10]);
try {
Future future = client.sendAsync(new byte[10]);
future.await();
future.getResult();
Assert.fail();
} catch (PinpointSocketException e) {
}
try {
client.sendSync(new byte[10]);
Assert.fail();
} catch (PinpointSocketException e) {
}
try {
PinpointRPCTestUtils.request(client, new byte[10]);
Assert.fail();
} catch (PinpointSocketException e) {
}
PinpointRPCTestUtils.close(client);
}
@Test
public void serverFirstClose() throws IOException, InterruptedException {
// when abnormal case in which server has been closed first, confirm that a socket should be closed properly.
PinpointServerAcceptor serverAcceptor = PinpointRPCTestUtils.createPinpointServerFactory(bindPort);
PinpointClient client = clientFactory.connect("127.0.0.1", bindPort);
byte[] randomByte = TestByteUtils.createRandomByte(10);
Future<ResponseMessage> response = client.request(randomByte);
response.await();
try {
response.getResult();
} catch (Exception e) {
logger.debug("timeout.", e);
}
// close server by force
PinpointRPCTestUtils.close(serverAcceptor);
assertClientDisconnected(client);
PinpointRPCTestUtils.close(client);
}
@Test
public void serverCloseAndWrite() throws IOException, InterruptedException {
// when abnormal case in which server has been closed first, confirm that a client socket should be closed properly.
PinpointServerAcceptor serverAcceptor = PinpointRPCTestUtils.createPinpointServerFactory(bindPort);
PinpointClient client = clientFactory.connect("127.0.0.1", bindPort);
// just close server and request
PinpointRPCTestUtils.close(serverAcceptor);
byte[] randomByte = TestByteUtils.createRandomByte(10);
Future<ResponseMessage> response = client.request(randomByte);
response.await();
try {
response.getResult();
Assert.fail("expected exception");
} catch (Exception e) {
}
assertClientDisconnected(client);
PinpointRPCTestUtils.close(client);
}
private void assertClientDisconnected(final PinpointClient client) {
boolean pass = awaitUtils.await(new TestAwaitTaskUtils() {
@Override
public boolean checkCompleted() {
return !client.isConnected();
}
});
Assert.assertTrue(pass);
}
private void assertClientConnected(final PinpointClient client) {
boolean pass = awaitUtils.await(new TestAwaitTaskUtils() {
@Override
public boolean checkCompleted() {
return client.isConnected();
}
});
Assert.assertTrue(pass);
}
}