@Test public void channelRead_does_not_explode_if_metricsListener_is_null() throws Exception { // given RequestStateCleanerHandler handlerNoMetrics = new RequestStateCleanerHandler( null, incompleteHttpCallTimeoutMillis, distributedTracingConfigMock ); // when handlerNoMetrics.channelRead(ctxMock, msgMockFirstChunkOnly); // then verify(stateMock).cleanStateForNewRequest(); verifyZeroInteractions(metricsListenerMock); }
@Test public void constructor_sets_fields_as_expected() { // when RequestStateCleanerHandler handler = new RequestStateCleanerHandler( metricsListenerMock, incompleteHttpCallTimeoutMillis, distributedTracingConfigMock ); // then assertThat(handler.metricsListener).isSameAs(metricsListenerMock); assertThat(handler.incompleteHttpCallTimeoutMillis).isEqualTo(incompleteHttpCallTimeoutMillis); assertThat(handler.distributedTracingConfig).isSameAs(distributedTracingConfigMock); }
@Test public void channelRead_does_not_remove_IdleChannelTimeoutHandler_if_it_is_not_in_the_pipeline() throws Exception { // given doReturn(null).when(pipelineMock).get(IDLE_CHANNEL_TIMEOUT_HANDLER_NAME); // when handler.channelRead(ctxMock, msgMockFirstChunkOnly); // then verify(pipelineMock).get(IDLE_CHANNEL_TIMEOUT_HANDLER_NAME); verify(pipelineMock, never()).remove(idleChannelTimeoutHandlerMock); }
@Before public void beforeMethod() { stateMock = mock(HttpProcessingState.class); proxyRouterProcessingStateMock = mock(ProxyRouterProcessingState.class); ctxMock = mock(ChannelHandlerContext.class); channelMock = mock(Channel.class); pipelineMock = mock(ChannelPipeline.class); stateAttrMock = mock(Attribute.class); proxyRouterProcessingStateAttrMock = mock(Attribute.class); metricsListenerMock = mock(MetricsListener.class); distributedTracingConfigMock = mock(DistributedTracingConfig.class); msgMockFirstChunkOnly = mock(HttpRequest.class); msgMockFullRequest = mock(FullHttpRequest.class); msgMockLastChunkOnly = mock(LastHttpContent.class); idleChannelTimeoutHandlerMock = mock(IdleChannelTimeoutHandler.class); doReturn(channelMock).when(ctxMock).channel(); doReturn(pipelineMock).when(ctxMock).pipeline(); doReturn(idleChannelTimeoutHandlerMock).when(pipelineMock).get(IDLE_CHANNEL_TIMEOUT_HANDLER_NAME); doReturn(stateAttrMock).when(channelMock).attr(ChannelAttributes.HTTP_PROCESSING_STATE_ATTRIBUTE_KEY); doReturn(stateMock).when(stateAttrMock).get(); doReturn(proxyRouterProcessingStateAttrMock).when(channelMock).attr(ChannelAttributes.PROXY_ROUTER_PROCESSING_STATE_ATTRIBUTE_KEY); doReturn(proxyRouterProcessingStateMock).when(proxyRouterProcessingStateAttrMock).get(); handler = new RequestStateCleanerHandler( metricsListenerMock, incompleteHttpCallTimeoutMillis, distributedTracingConfigMock ); }
@Test public void channelRead_does_nothing_if_msg_is_not_HttpRequest_or_LastHttpContent() throws Exception { // given HttpMessage ignoredMsgMock = mock(HttpMessage.class); // when handler.channelRead(ctxMock, ignoredMsgMock); // then verify(ctxMock).fireChannelRead(ignoredMsgMock); // the normal continuation behavior from the super class. verifyNoMoreInteractions(ctxMock); // nothing else should have happened related to the ctx. verifyZeroInteractions(stateMock); verifyZeroInteractions(metricsListenerMock); }
@Test public void channelRead_replaces_IncompleteHttpCallTimeoutHandler_if_one_already_exists() throws Exception { // given long timeoutMillis = 42; RequestStateCleanerHandler handlerToUse = new RequestStateCleanerHandler( null, timeoutMillis, distributedTracingConfigMock ); IncompleteHttpCallTimeoutHandler alreadyExistingHandler = mock(IncompleteHttpCallTimeoutHandler.class); doReturn(alreadyExistingHandler).when(pipelineMock).get(INCOMPLETE_HTTP_CALL_TIMEOUT_HANDLER_NAME); doReturn(null).when(pipelineMock).get(IDLE_CHANNEL_TIMEOUT_HANDLER_NAME); // when handlerToUse.channelRead(ctxMock, msgMockFirstChunkOnly); // then // The normal happy path addition of the timeout handler should not have occurred. verify(pipelineMock, never()).addFirst(eq(INCOMPLETE_HTTP_CALL_TIMEOUT_HANDLER_NAME), any(ChannelHandler.class)); // Instead, the existing handler should have been replaced. ArgumentCaptor<ChannelHandler> handlerArgCaptor = ArgumentCaptor.forClass(ChannelHandler.class); verify(pipelineMock).replace(eq(alreadyExistingHandler), eq(INCOMPLETE_HTTP_CALL_TIMEOUT_HANDLER_NAME), handlerArgCaptor.capture()); assertThat(handlerArgCaptor.getValue()).isInstanceOf(IncompleteHttpCallTimeoutHandler.class); IncompleteHttpCallTimeoutHandler handlerAdded = (IncompleteHttpCallTimeoutHandler)handlerArgCaptor.getValue(); assertThat(handlerAdded.idleTimeoutMillis).isEqualTo(timeoutMillis); }
new RequestStateCleanerHandler( metricsListener, incompleteHttpCallTimeoutMillis,
@Test public void channelRead_cleans_the_state_and_starts_metrics_request_and_removes_any_existing_IdleChannelTimeoutHandler() throws Exception { // when handler.channelRead(ctxMock, msgMockFirstChunkOnly); // then verify(stateMock).cleanStateForNewRequest(); verify(metricsListenerMock).onEvent(ServerMetricsEvent.REQUEST_RECEIVED, stateMock); verify(pipelineMock).get(IDLE_CHANNEL_TIMEOUT_HANDLER_NAME); verify(pipelineMock).remove(idleChannelTimeoutHandlerMock); }
RequestStateCleanerHandler handlerToUse = new RequestStateCleanerHandler( null, timeoutMillis, distributedTracingConfigMock ); handlerToUse.channelRead(ctxMock, msg);
new RequestStateCleanerHandler( metricsListener, incompleteHttpCallTimeoutMillis,
@DataProvider(value = { "true", "false" }) @Test public void channelRead_removes_IncompleteHttpCallTimeoutHandler_gracefully_on_last_chunk_only_messages( boolean handlerExistsInPipeline ) throws Exception { // given IncompleteHttpCallTimeoutHandler existingHandler = (handlerExistsInPipeline) ? mock(IncompleteHttpCallTimeoutHandler.class) : null; doReturn(existingHandler).when(pipelineMock).get(INCOMPLETE_HTTP_CALL_TIMEOUT_HANDLER_NAME); // when handler.channelRead(ctxMock, msgMockLastChunkOnly); // then verify(pipelineMock).get(INCOMPLETE_HTTP_CALL_TIMEOUT_HANDLER_NAME); if (handlerExistsInPipeline) verify(pipelineMock).remove(INCOMPLETE_HTTP_CALL_TIMEOUT_HANDLER_NAME); else verifyNoMoreInteractions(pipelineMock); }
handler.channelRead(ctxMock, msgMockFirstChunkOnly);