/*
* 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.common.SocketStateCode;
import com.navercorp.pinpoint.rpc.control.ProtocolException;
import com.navercorp.pinpoint.rpc.packet.*;
import com.navercorp.pinpoint.rpc.server.handler.ServerStateChangeEventHandler;
import com.navercorp.pinpoint.rpc.util.ControlMessageEncodingUtils;
import com.navercorp.pinpoint.rpc.util.MapUtils;
import com.navercorp.pinpoint.rpc.util.PinpointRPCTestUtils;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
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.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.Map;
/**
* @author koo.taejin
*/
public class EventHandlerTest {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private static int bindPort;
@BeforeClass
public static void setUp() throws IOException {
bindPort = SocketUtils.findAvailableTcpPort();
}
// Test for being possible to send messages in case of failure of registering packet ( return code : 2, lack of parameter)
@Test
public void registerAgentSuccessTest() throws Exception {
EventHandler eventHandler = new EventHandler();
PinpointServerAcceptor serverAcceptor = new PinpointServerAcceptor();
serverAcceptor.addStateChangeEventHandler(eventHandler);
serverAcceptor.setMessageListener(SimpleServerMessageListener.DUPLEX_ECHO_INSTANCE);
serverAcceptor.bind("127.0.0.1", bindPort);
Socket socket = null;
try {
socket = new Socket("127.0.0.1", bindPort);
sendAndReceiveSimplePacket(socket);
Assert.assertEquals(eventHandler.getCode(), SocketStateCode.RUN_WITHOUT_HANDSHAKE);
int code = sendAndReceiveRegisterPacket(socket, PinpointRPCTestUtils.getParams());
Assert.assertEquals(eventHandler.getCode(), SocketStateCode.RUN_DUPLEX);
sendAndReceiveSimplePacket(socket);
} finally {
if (socket != null) {
socket.close();
}
PinpointRPCTestUtils.close(serverAcceptor);
}
}
@Test
public void registerAgentFailTest() throws Exception {
ThrowExceptionEventHandler eventHandler = new ThrowExceptionEventHandler();
PinpointServerAcceptor serverAcceptor = new PinpointServerAcceptor();
serverAcceptor.addStateChangeEventHandler(eventHandler);
serverAcceptor.setMessageListener(SimpleServerMessageListener.DUPLEX_ECHO_INSTANCE);
serverAcceptor.bind("127.0.0.1", bindPort);
Socket socket = null;
try {
socket = new Socket("127.0.0.1", bindPort);
sendAndReceiveSimplePacket(socket);
Assert.assertTrue(eventHandler.getErrorCount() > 0);
} finally {
if (socket != null) {
socket.close();
}
PinpointRPCTestUtils.close(serverAcceptor);
}
}
private int sendAndReceiveRegisterPacket(Socket socket, Map<String, Object> properties) throws ProtocolException, IOException {
sendRegisterPacket(socket.getOutputStream(), properties);
ControlHandshakeResponsePacket packet = receiveRegisterConfirmPacket(socket.getInputStream());
Map<Object, Object> result = (Map<Object, Object>) ControlMessageEncodingUtils.decode(packet.getPayload());
return MapUtils.getInteger(result, "code", -1);
}
private void sendAndReceiveSimplePacket(Socket socket) throws ProtocolException, IOException {
sendSimpleRequestPacket(socket.getOutputStream());
ResponsePacket responsePacket = readSimpleResponsePacket(socket.getInputStream());
Assert.assertNotNull(responsePacket);
}
private void sendRegisterPacket(OutputStream outputStream, Map<String, Object> properties) throws ProtocolException, IOException {
byte[] payload = ControlMessageEncodingUtils.encode(properties);
ControlHandshakePacket packet = new ControlHandshakePacket(1, payload);
ByteBuffer bb = packet.toBuffer().toByteBuffer(0, packet.toBuffer().writerIndex());
sendData(outputStream, bb.array());
}
private void sendSimpleRequestPacket(OutputStream outputStream) throws ProtocolException, IOException {
RequestPacket packet = new RequestPacket(new byte[0]);
packet.setRequestId(10);
ByteBuffer bb = packet.toBuffer().toByteBuffer(0, packet.toBuffer().writerIndex());
sendData(outputStream, bb.array());
}
private void sendData(OutputStream outputStream, byte[] payload) throws IOException {
outputStream.write(payload);
outputStream.flush();
}
private ControlHandshakeResponsePacket receiveRegisterConfirmPacket(InputStream inputStream) throws ProtocolException, IOException {
byte[] payload = readData(inputStream);
ChannelBuffer cb = ChannelBuffers.wrappedBuffer(payload);
short packetType = cb.readShort();
ControlHandshakeResponsePacket packet = ControlHandshakeResponsePacket.readBuffer(packetType, cb);
return packet;
}
private ResponsePacket readSimpleResponsePacket(InputStream inputStream) throws ProtocolException, IOException {
byte[] payload = readData(inputStream);
ChannelBuffer cb = ChannelBuffers.wrappedBuffer(payload);
short packetType = cb.readShort();
ResponsePacket packet = ResponsePacket.readBuffer(packetType, cb);
return packet;
}
private byte[] readData(InputStream inputStream) throws IOException {
int availableSize = 0;
for (int i = 0; i < 3; i++) {
availableSize = inputStream.available();
if (availableSize > 0) {
break;
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
byte[] payload = new byte[availableSize];
inputStream.read(payload);
return payload;
}
class EventHandler implements ServerStateChangeEventHandler {
private SocketStateCode code;
@Override
public void eventPerformed(PinpointServer pinpointServer, SocketStateCode stateCode) {
this.code = stateCode;
}
@Override
public void exceptionCaught(PinpointServer pinpointServer, SocketStateCode stateCode, Throwable e) {
}
public SocketStateCode getCode() {
return code;
}
}
class ThrowExceptionEventHandler implements ServerStateChangeEventHandler {
private int errorCount = 0;
@Override
public void eventPerformed(PinpointServer pinpointServer, SocketStateCode stateCode) throws Exception {
throw new Exception("always error.");
}
@Override
public void exceptionCaught(PinpointServer pinpointServer, SocketStateCode stateCode, Throwable e) {
errorCount++;
}
public int getErrorCount() {
return errorCount;
}
}
}