@Test public void doChannelRead_HttpRequest_under_max_global_request_size_processed_successfully() { // given doReturn(null).when(endpointMock).maxRequestSizeInBytesOverride(); maxRequestSizeInBytes = 101; httpHeaders.set(CONTENT_LENGTH, 100); handlerSpy = spy(new RoutingHandler(endpoints, maxRequestSizeInBytes)); // when PipelineContinuationBehavior result = handlerSpy.doChannelRead(ctxMock, msg); // then assertThat(result).isEqualTo(PipelineContinuationBehavior.CONTINUE); }
@Test(expected = PathNotFound404Exception.class) public void findSingleEndpointForExecution_throws_PathNotFound404Exception_if_no_matching_path() { // given doReturn(Optional.empty()).when(matcherMock).matchesPath(any(RequestInfo.class)); // expect handlerSpy.findSingleEndpointForExecution(requestInfoMock); }
@Test public void argsAreEligibleForLinkingAndUnlinkingDistributedTracingInfo_returns_false() { assertThat(handlerSpy.argsAreEligibleForLinkingAndUnlinkingDistributedTracingInfo(null,null,null,null)).isFalse(); }
@Test public void doChannelRead_calls_findSingleEndpointForExecution_then_sets_path_params_and_endpoint_on_state_then_returns_CONTINUE_if_msg_is_HttpRequest() { // given doReturn(Arrays.asList(defaultPath)).when(matcherMock).matchingPathTemplates(); HttpRequest msg = mock(HttpRequest.class); // when PipelineContinuationBehavior result = handlerSpy.doChannelRead(ctxMock, msg); // then verify(handlerSpy).findSingleEndpointForExecution(requestInfoMock); verify(requestInfoMock).setPathParamsBasedOnPathTemplate(defaultPath); verify(stateMock).setEndpointForExecution(endpointMock, defaultPath); assertThat(result).isEqualTo(PipelineContinuationBehavior.CONTINUE); }
@Test(expected = IllegalArgumentException.class) public void constructor_throws_IllegalArgumentException_if_arg_is_null() { // expect new RoutingHandler(null, maxRequestSizeInBytes); }
@Override public PipelineContinuationBehavior doChannelRead(ChannelHandlerContext ctx, Object msg) { if (msg instanceof HttpRequest) { HttpProcessingState state = ChannelAttributes.getHttpProcessingStateForChannel(ctx).get(); RequestInfo request = handlerUtils.createRequestInfoFromNettyHttpRequestAndHandleStateSetupIfNecessary( (HttpRequest)msg, state ); // If the Netty HttpRequest is invalid, we shouldn't do any endpoint routing. handlerUtils.throwExceptionIfNotSuccessfullyDecoded((HttpRequest) msg); // The HttpRequest is valid, so continue with the endpoint routing. Pair<Endpoint<?>, String> endpointForExecution = findSingleEndpointForExecution(request); request.setPathParamsBasedOnPathTemplate(endpointForExecution.getRight()); state.setEndpointForExecution(endpointForExecution.getLeft(), endpointForExecution.getRight()); throwExceptionIfContentLengthHeaderIsLargerThanConfiguredMaxRequestSize( (HttpRequest) msg, endpointForExecution.getLeft() ); } return PipelineContinuationBehavior.CONTINUE; }
@Test public void doChannelRead_does_nothing_if_msg_is_not_HttpRequest() { // given String pathTemplate = "/some/path/with/{id}"; Collection<String> pathTemplates = new ArrayList<String>() {{ add(pathTemplate); }}; doReturn(pathTemplates).when(matcherMock).matchingPathTemplates(); HttpObject msg = mock(HttpObject.class); // when PipelineContinuationBehavior result = handlerSpy.doChannelRead(ctxMock, msg); // then verify(handlerSpy).doChannelRead(ctxMock, msg); verifyNoMoreInteractions(handlerSpy); verifyNoMoreInteractions(requestInfoMock); verifyNoMoreInteractions(stateMock); assertThat(result).isEqualTo(PipelineContinuationBehavior.CONTINUE); }
@Test(expected = IllegalArgumentException.class) public void constructor_throws_IllegalArgumentException_if_arg_is_empty() { // expect new RoutingHandler(Collections.emptyList(), maxRequestSizeInBytes); }
@Override public PipelineContinuationBehavior doChannelRead(ChannelHandlerContext ctx, Object msg) { if (msg instanceof HttpRequest) { HttpProcessingState state = ChannelAttributes.getHttpProcessingStateForChannel(ctx).get(); RequestInfo request = handlerUtils.createRequestInfoFromNettyHttpRequestAndHandleStateSetupIfNecessary( (HttpRequest)msg, state ); // If the Netty HttpRequest is invalid, we shouldn't do any endpoint routing. handlerUtils.throwExceptionIfNotSuccessfullyDecoded((HttpRequest) msg); // The HttpRequest is valid, so continue with the endpoint routing. Pair<Endpoint<?>, String> endpointForExecution = findSingleEndpointForExecution(request); request.setPathParamsBasedOnPathTemplate(endpointForExecution.getRight()); state.setEndpointForExecution(endpointForExecution.getLeft(), endpointForExecution.getRight()); throwExceptionIfContentLengthHeaderIsLargerThanConfiguredMaxRequestSize( (HttpRequest) msg, endpointForExecution.getLeft() ); } return PipelineContinuationBehavior.CONTINUE; }
@Test public void doChannelRead_HttpRequest_throws_exception_when_failed_decoder_result() { // given HttpRequest msgMock = mock(HttpRequest.class); Throwable decoderFailureCauseMock = mock(Throwable.class); DecoderResult decoderResult = DecoderResult.failure(decoderFailureCauseMock); doReturn(decoderResult).when(msgMock).decoderResult(); doReturn(null).when(stateMock).getRequestInfo(); // when Throwable thrownException = Assertions.catchThrowable(() -> handlerSpy.doChannelRead(ctxMock, msgMock)); // then assertThat(thrownException).isExactlyInstanceOf(InvalidHttpRequestException.class); assertThat(thrownException.getCause()).isSameAs(decoderFailureCauseMock); }
@Test public void doChannelRead_HttpRequest_throws_exception_when_content_length_header_greater_than_configured_global_request_limit() { // given doReturn(null).when(endpointMock).maxRequestSizeInBytesOverride(); maxRequestSizeInBytes = 10; httpHeaders.set(CONTENT_LENGTH, 100); handlerSpy = spy(new RoutingHandler(endpoints, maxRequestSizeInBytes)); // when Throwable thrownException = Assertions.catchThrowable(() -> handlerSpy.doChannelRead(ctxMock, msg)); // then assertThat(thrownException).isExactlyInstanceOf(RequestTooBigException.class); assertThat(thrownException.getMessage()).isEqualTo("Content-Length header value exceeded configured max request size of 10"); }
@Before public void beforeMethod() { stateMock = mock(HttpProcessingState.class); ctxMock = mock(ChannelHandlerContext.class); channelMock = mock(Channel.class); stateAttrMock = mock(Attribute.class); requestInfoMock = mock(RequestInfo.class); endpointMock = mock(StandardEndpoint.class); matcherMock = mock(Matcher.class); endpoints = new ArrayList<>(Collections.singleton(endpointMock)); httpHeaders = new DefaultHttpHeaders(); maxRequestSizeInBytes = 10; msg = mock(HttpRequest.class); doReturn(channelMock).when(ctxMock).channel(); doReturn(stateAttrMock).when(channelMock).attr(ChannelAttributes.HTTP_PROCESSING_STATE_ATTRIBUTE_KEY); doReturn(stateMock).when(stateAttrMock).get(); doReturn(endpointMock).when(stateMock).getEndpointForExecution(); doReturn(matcherMock).when(endpointMock).requestMatcher(); doReturn(Optional.of(defaultPath)).when(matcherMock).matchesPath(any(RequestInfo.class)); doReturn(true).when(matcherMock).matchesMethod(any(RequestInfo.class)); doReturn(requestInfoMock).when(stateMock).getRequestInfo(); doReturn(httpHeaders).when(msg).headers(); handlerSpy = spy(new RoutingHandler(endpoints, maxRequestSizeInBytes)); }
@Test(expected = MultipleMatchingEndpointsException.class) public void findSingleEndpointForExecution_throws_MultipleMatchingEndpointsException_if_multiple_endpoints_fully_match() { // given doReturn(Optional.of(defaultPath)).when(matcherMock).matchesPath(any(RequestInfo.class)); doReturn(true).when(matcherMock).matchesMethod(any(RequestInfo.class)); Endpoint<?> alsoMatchingEndpointMock = mock(Endpoint.class); doReturn(matcherMock).when(alsoMatchingEndpointMock).requestMatcher(); endpoints.add(alsoMatchingEndpointMock); // when handlerSpy.findSingleEndpointForExecution(requestInfoMock); }
PipelineContinuationBehavior result = handlerSpy.doChannelRead(ctxMock, msgMock);
@DataProvider(value = { "99", "100" }) @Test public void doChannelRead_HttpRequest_does_not_throw_TooLongFrameException_if_content_length_is_less_than_endpoint_overridden_value( int maxRequestSize ) { // given doReturn(100).when(endpointMock).maxRequestSizeInBytesOverride(); httpHeaders.set(CONTENT_LENGTH, 100); handlerSpy = spy(new RoutingHandler(endpoints, maxRequestSize)); // when PipelineContinuationBehavior result = handlerSpy.doChannelRead(ctxMock, msg); // then assertThat(result).isEqualTo(PipelineContinuationBehavior.CONTINUE); }
@Test public void constructor_sets_fields_based_on_incoming_args() { // when RoutingHandler theHandler = new RoutingHandler(endpoints, maxRequestSizeInBytes); // then Collection<Endpoint<?>> actualEndpoints = (Collection<Endpoint<?>>) Whitebox.getInternalState(theHandler, "endpoints"); assertThat(actualEndpoints).isSameAs(endpoints); }
@Test(expected = MethodNotAllowed405Exception.class) public void findSingleEndpointForExecution_throws_MethodNotAllowed405Exception_if_path_matches_but_method_does_not() { // given doReturn(Optional.of(defaultPath)).when(matcherMock).matchesPath(any(RequestInfo.class)); doReturn(false).when(matcherMock).matchesMethod(any(RequestInfo.class)); // expect handlerSpy.findSingleEndpointForExecution(requestInfoMock); }
@DataProvider(value = { "99", "101" }) @Test public void doChannelRead_HttpRequest_endpoint_overridden_max_request_size_throws_exception(int maxRequestSize) { // given doReturn(100).when(endpointMock).maxRequestSizeInBytesOverride(); httpHeaders.set(CONTENT_LENGTH, 101); handlerSpy = spy(new RoutingHandler(endpoints, maxRequestSize)); // when Throwable thrownException = Assertions.catchThrowable(() -> handlerSpy.doChannelRead(ctxMock, msg)); // then assertThat(thrownException).isExactlyInstanceOf(RequestTooBigException.class); assertThat(thrownException.getMessage()).isEqualTo("Content-Length header value exceeded configured max request size of 100"); }
p.addLast(ROUTING_HANDLER_NAME, new RoutingHandler(endpoints, maxRequestSizeInBytes));
@Test public void findSingleEndpointForExecution_returns_matching_endpoint() { // given doReturn(Optional.of(defaultPath)).when(matcherMock).matchesPath(any(RequestInfo.class)); doReturn(true).when(matcherMock).matchesMethod(any(RequestInfo.class)); // when Pair<Endpoint<?>, String> result = handlerSpy.findSingleEndpointForExecution(requestInfoMock); // then assertThat(result.getKey()).isSameAs(endpointMock); assertThat(result.getValue()).isSameAs(defaultPath); }