/* * 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.control.ProtocolException; import com.navercorp.pinpoint.rpc.packet.ControlHandshakePacket; import com.navercorp.pinpoint.rpc.packet.ControlHandshakeResponsePacket; import com.navercorp.pinpoint.rpc.packet.HandshakePropertyType; import com.navercorp.pinpoint.rpc.packet.HandshakeResponseCode; import com.navercorp.pinpoint.rpc.packet.HandshakeResponseType; import com.navercorp.pinpoint.rpc.packet.PingPacket; import com.navercorp.pinpoint.rpc.packet.RequestPacket; import com.navercorp.pinpoint.rpc.packet.ResponsePacket; import com.navercorp.pinpoint.rpc.packet.SendPacket; 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.Collections; import java.util.Map; /** * @author koo.taejin */ public class ControlPacketServerTest { 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 registerAgentTest1() throws Exception { PinpointServerAcceptor serverAcceptor = PinpointRPCTestUtils.createPinpointServerFactory(bindPort, new SimpleListener()); Socket socket = null; try { socket = new Socket("127.0.0.1", bindPort); sendAndReceiveSimplePacket(socket); int code= sendAndReceiveRegisterPacket(socket); Assert.assertEquals(2, code); sendAndReceiveSimplePacket(socket); } finally { PinpointRPCTestUtils.close(socket); PinpointRPCTestUtils.close(serverAcceptor); } } // Test for being possible to send messages in case of success of registering packet ( return code : 0) @Test public void registerAgentTest2() throws Exception { PinpointServerAcceptor serverAcceptor = PinpointRPCTestUtils.createPinpointServerFactory(bindPort, new SimpleListener()); Socket socket = null; try { socket = new Socket("127.0.0.1", bindPort); sendAndReceiveSimplePacket(socket); int code= sendAndReceiveRegisterPacket(socket, PinpointRPCTestUtils.getParams()); Assert.assertEquals(0, code); sendAndReceiveSimplePacket(socket); } finally { PinpointRPCTestUtils.close(socket); PinpointRPCTestUtils.close(serverAcceptor); } } // when failure of registering and retrying to register, confirm to return same code ( return code : 2 @Test public void registerAgentTest3() throws Exception { PinpointServerAcceptor serverAcceptor = PinpointRPCTestUtils.createPinpointServerFactory(bindPort, new SimpleListener()); Socket socket = null; try { socket = new Socket("127.0.0.1", bindPort); int code = sendAndReceiveRegisterPacket(socket); Assert.assertEquals(2, code); code = sendAndReceiveRegisterPacket(socket); Assert.assertEquals(2, code); sendAndReceiveSimplePacket(socket); } finally { PinpointRPCTestUtils.close(socket); PinpointRPCTestUtils.close(serverAcceptor); } } // after success of registering, when success message are sent repeatedly. // test 1) confirm to return success code, 2) confirm to return already success code. @Test public void registerAgentTest4() throws Exception { PinpointServerAcceptor serverAcceptor = PinpointRPCTestUtils.createPinpointServerFactory(bindPort, new SimpleListener()); Socket socket = null; try { socket = new Socket("127.0.0.1", bindPort); sendAndReceiveSimplePacket(socket); int code = sendAndReceiveRegisterPacket(socket, PinpointRPCTestUtils.getParams()); Assert.assertEquals(0, code); sendAndReceiveSimplePacket(socket); code = sendAndReceiveRegisterPacket(socket, PinpointRPCTestUtils.getParams()); Assert.assertEquals(1, code); sendAndReceiveSimplePacket(socket); } finally { PinpointRPCTestUtils.close(socket); PinpointRPCTestUtils.close(serverAcceptor); } } private int sendAndReceiveRegisterPacket(Socket socket) throws ProtocolException, IOException { return sendAndReceiveRegisterPacket(socket, Collections.<String, Object>emptyMap()); } 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 SimpleListener implements ServerMessageListener { @Override public void handleSend(SendPacket sendPacket, PinpointSocket pinpointSocket) { logger.debug("handleSend packet:{}, remote:{}", sendPacket, pinpointSocket.getRemoteAddress()); } @Override public void handleRequest(RequestPacket requestPacket, PinpointSocket pinpointSocket) { logger.debug("handleRequest packet:{}, remote:{}", requestPacket, pinpointSocket.getRemoteAddress()); pinpointSocket.response(requestPacket, requestPacket.getPayload()); } @Override public HandshakeResponseCode handleHandshake(Map properties) { if (properties == null) { return HandshakeResponseType.ProtocolError.PROTOCOL_ERROR; } boolean hasRequiredKeys = HandshakePropertyType.hasRequiredKeys(properties); if (!hasRequiredKeys) { return HandshakeResponseType.PropertyError.PROPERTY_ERROR; } return HandshakeResponseType.Success.DUPLEX_COMMUNICATION; } @Override public void handlePing(PingPacket pingPacket, PinpointServer pinpointServer) { } } }