/* * Copyright 2015 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.collector.rpc.handler; import com.navercorp.pinpoint.collector.cluster.route.ResponseEvent; import com.navercorp.pinpoint.collector.dao.AgentEventDao; import com.navercorp.pinpoint.common.server.bo.AgentEventBo; import com.navercorp.pinpoint.common.server.util.AgentEventMessageSerializer; import com.navercorp.pinpoint.common.server.util.AgentEventType; import com.navercorp.pinpoint.common.util.BytesUtils; import com.navercorp.pinpoint.rpc.packet.HandshakePropertyType; import com.navercorp.pinpoint.rpc.server.PinpointServer; import com.navercorp.pinpoint.thrift.dto.command.TCommandEcho; import com.navercorp.pinpoint.thrift.dto.command.TCommandThreadDumpResponse; import com.navercorp.pinpoint.thrift.dto.command.TCommandTransfer; import com.navercorp.pinpoint.thrift.dto.command.TCommandTransferResponse; import com.navercorp.pinpoint.thrift.dto.command.TRouteResult; import com.navercorp.pinpoint.thrift.io.DeserializerFactory; import com.navercorp.pinpoint.thrift.io.HeaderTBaseDeserializer; import org.apache.thrift.TBase; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; import org.mockito.runners.MockitoJUnitRunner; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Executor; import static org.junit.Assert.*; import static org.mockito.Mockito.*; /** * @author HyunGil Jeong */ @RunWith(MockitoJUnitRunner.class) public class AgentEventHandlerTest { // FIX guava 19.0.0 update error. MoreExecutors.sameThreadExecutor(); change final class @Spy private Executor executor = new DirectExecutor(); @Mock private PinpointServer pinpointServer; @Mock private AgentEventDao agentEventDao; @Mock private AgentEventMessageSerializer agentEventMessageSerializer; @Mock private DeserializerFactory<HeaderTBaseDeserializer> deserializerFactory; @InjectMocks private AgentEventHandler agentEventHandler = new AgentEventHandler(); private static final String TEST_AGENT_ID = "TEST_AGENT"; private static final long TEST_START_TIMESTAMP = System.currentTimeMillis(); private static final long TEST_EVENT_TIMESTAMP = TEST_START_TIMESTAMP + 10; private static final Map<Object, Object> TEST_CHANNEL_PROPERTIES = createTestChannelProperties(); @Before public void setUp() { when(this.pinpointServer.getChannelProperties()).thenReturn(TEST_CHANNEL_PROPERTIES); } @Test public void handler_should_handle_events_with_empty_message_body() throws Exception { // given final AgentEventType expectedEventType = AgentEventType.AGENT_CONNECTED; ArgumentCaptor<AgentEventBo> argCaptor = ArgumentCaptor.forClass(AgentEventBo.class); // when this.agentEventHandler.handleEvent(this.pinpointServer, TEST_EVENT_TIMESTAMP, expectedEventType); verify(this.agentEventDao, times(1)).insert(argCaptor.capture()); // then AgentEventBo actualAgentEventBo = argCaptor.getValue(); assertEquals(TEST_AGENT_ID, actualAgentEventBo.getAgentId()); assertEquals(TEST_START_TIMESTAMP, actualAgentEventBo.getStartTimestamp()); assertEquals(TEST_EVENT_TIMESTAMP, actualAgentEventBo.getEventTimestamp()); assertEquals(expectedEventType, actualAgentEventBo.getEventType()); assertNull(actualAgentEventBo.getEventBody()); } @Test public void handler_should_handle_serialization_of_messages_appropriately() throws Exception { // given final AgentEventType expectedEventType = AgentEventType.OTHER; final String expectedMessageBody = "test event message"; final byte[] expectedMessageBodyBytes = BytesUtils.toBytes(expectedMessageBody); ArgumentCaptor<AgentEventBo> argCaptor = ArgumentCaptor.forClass(AgentEventBo.class); when(this.agentEventMessageSerializer.serialize(expectedEventType, expectedMessageBody)).thenReturn( expectedMessageBodyBytes); // when this.agentEventHandler.handleEvent(this.pinpointServer, TEST_EVENT_TIMESTAMP, expectedEventType, expectedMessageBody); verify(this.agentEventDao, times(1)).insert(argCaptor.capture()); // then AgentEventBo actualAgentEventBo = argCaptor.getValue(); assertEquals(TEST_AGENT_ID, actualAgentEventBo.getAgentId()); assertEquals(TEST_START_TIMESTAMP, actualAgentEventBo.getStartTimestamp()); assertEquals(TEST_EVENT_TIMESTAMP, actualAgentEventBo.getEventTimestamp()); assertEquals(expectedEventType, actualAgentEventBo.getEventType()); assertEquals(expectedMessageBodyBytes, actualAgentEventBo.getEventBody()); } @Test @SuppressWarnings({ "rawtypes", "unchecked" }) public void handler_should_handle_serialization_of_request_events() throws Exception { // given final AgentEventType expectedEventType = AgentEventType.USER_THREAD_DUMP; final TCommandThreadDumpResponse expectedThreadDumpResponse = new TCommandThreadDumpResponse(); final byte[] expectedThreadDumpResponseBody = new byte[0]; final TCommandTransfer tCommandTransfer = new TCommandTransfer(); tCommandTransfer.setAgentId(TEST_AGENT_ID); tCommandTransfer.setStartTime(TEST_START_TIMESTAMP); final TCommandTransferResponse tCommandTransferResponse = new TCommandTransferResponse(); tCommandTransferResponse.setRouteResult(TRouteResult.OK); tCommandTransferResponse.setPayload(expectedThreadDumpResponseBody); final ResponseEvent responseEvent = new ResponseEvent(tCommandTransfer, null, 0, tCommandTransferResponse); ArgumentCaptor<AgentEventBo> argCaptor = ArgumentCaptor.forClass(AgentEventBo.class); HeaderTBaseDeserializer deserializer = mock(HeaderTBaseDeserializer.class); when(this.deserializerFactory.createDeserializer()).thenReturn(deserializer); when(deserializer.deserialize(expectedThreadDumpResponseBody)).thenReturn((TBase)expectedThreadDumpResponse); // when this.agentEventHandler.handleResponseEvent(responseEvent, TEST_EVENT_TIMESTAMP); // then verify(this.agentEventDao, atLeast(1)).insert(argCaptor.capture()); AgentEventBo actualAgentEventBo = argCaptor.getValue(); assertEquals(TEST_AGENT_ID, actualAgentEventBo.getAgentId()); assertEquals(TEST_START_TIMESTAMP, actualAgentEventBo.getStartTimestamp()); assertEquals(TEST_EVENT_TIMESTAMP, actualAgentEventBo.getEventTimestamp()); assertEquals(expectedEventType, actualAgentEventBo.getEventType()); assertArrayEquals(expectedThreadDumpResponseBody, actualAgentEventBo.getEventBody()); } @Test @SuppressWarnings({ "rawtypes", "unchecked" }) public void handler_should_ignore_request_events_with_unsupported_message_types() throws Exception { // given final TCommandEcho mismatchingResponse = new TCommandEcho(); final byte[] mismatchingResponseBody = new byte[0]; final TCommandTransfer tCommandTransfer = new TCommandTransfer(); tCommandTransfer.setAgentId(TEST_AGENT_ID); tCommandTransfer.setStartTime(TEST_START_TIMESTAMP); final TCommandTransferResponse tCommandTransferResponse = new TCommandTransferResponse(); tCommandTransferResponse.setRouteResult(TRouteResult.OK); tCommandTransferResponse.setPayload(mismatchingResponseBody); final ResponseEvent responseEvent = new ResponseEvent(tCommandTransfer, null, 0, tCommandTransferResponse); ArgumentCaptor<AgentEventBo> argCaptor = ArgumentCaptor.forClass(AgentEventBo.class); HeaderTBaseDeserializer deserializer = mock(HeaderTBaseDeserializer.class); when(this.deserializerFactory.createDeserializer()).thenReturn(deserializer); when(deserializer.deserialize(mismatchingResponseBody)).thenReturn((TBase)mismatchingResponse); // when this.agentEventHandler.handleResponseEvent(responseEvent, TEST_EVENT_TIMESTAMP); // then verify(this.agentEventDao, never()).insert(argCaptor.capture()); } private static Map<Object, Object> createTestChannelProperties() { return createChannelProperties(TEST_AGENT_ID, TEST_START_TIMESTAMP); } private static Map<Object, Object> createChannelProperties(String agentId, long startTimestamp) { Map<Object, Object> map = new HashMap<>(); map.put(HandshakePropertyType.AGENT_ID.getName(), agentId); map.put(HandshakePropertyType.START_TIMESTAMP.getName(), startTimestamp); return map; } }