diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultEntityResponseBuilderTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultEntityResponseBuilderTests.java new file mode 100644 index 000000000000..130c0c50141e --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultEntityResponseBuilderTests.java @@ -0,0 +1,208 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * 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 org.springframework.web.servlet.function; + +import java.io.IOException; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Set; +import javax.servlet.ServletException; +import javax.servlet.http.Cookie; + +import org.junit.Test; + +import org.springframework.http.CacheControl; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.mock.web.test.MockHttpServletRequest; +import org.springframework.mock.web.test.MockHttpServletResponse; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.servlet.ModelAndView; + +import static org.junit.Assert.*; + +/** + * @author Arjen Poutsma + */ +public class DefaultEntityResponseBuilderTests { + + static final ServerResponse.Context EMPTY_CONTEXT = new ServerResponse.Context() { + @Override + public List> messageConverters() { + return Collections.emptyList(); + } + + }; + + @Test + public void fromObject() { + String body = "foo"; + EntityResponse response = EntityResponse.fromObject(body).build(); + assertSame(body, response.entity()); + } + + @Test + public void status() { + String body = "foo"; + EntityResponse result = + EntityResponse.fromObject(body).status(HttpStatus.CREATED).build(); + + assertEquals(HttpStatus.CREATED, result.statusCode()); + } + + @Test + public void allow() { + String body = "foo"; + EntityResponse result = + EntityResponse.fromObject(body).allow(HttpMethod.GET).build(); + Set expected = EnumSet.of(HttpMethod.GET); + assertEquals(expected, result.headers().getAllow()); + } + + @Test + public void contentLength() { + String body = "foo"; + EntityResponse result = EntityResponse.fromObject(body).contentLength(42).build(); + assertEquals(42, result.headers().getContentLength()); + } + + @Test + public void contentType() { + String body = "foo"; + EntityResponse + result = + EntityResponse.fromObject(body).contentType(MediaType.APPLICATION_JSON).build(); + + assertEquals(MediaType.APPLICATION_JSON, result.headers().getContentType()); + } + + @Test + public void etag() { + String body = "foo"; + EntityResponse result = EntityResponse.fromObject(body).eTag("foo").build(); + + assertEquals("\"foo\"", result.headers().getETag()); + } + + @Test + public void lastModified() { + ZonedDateTime now = ZonedDateTime.now(); + String body = "foo"; + EntityResponse result = EntityResponse.fromObject(body).lastModified(now).build(); + long expected = now.toInstant().toEpochMilli() / 1000; + assertEquals(expected, result.headers().getLastModified() / 1000); + } + + @Test + public void cacheControlTag() { + String body = "foo"; + EntityResponse result = + EntityResponse.fromObject(body).cacheControl(CacheControl.noCache()).build(); + assertEquals("no-cache", result.headers().getCacheControl()); + } + + @Test + public void varyBy() { + String body = "foo"; + EntityResponse result = EntityResponse.fromObject(body).varyBy("foo").build(); + List expected = Collections.singletonList("foo"); + assertEquals(expected, result.headers().getVary()); + } + + @Test + public void header() { + String body = "foo"; + EntityResponse result = EntityResponse.fromObject(body).header("foo", "bar").build(); + assertEquals("bar", result.headers().getFirst("foo")); + } + + @Test + public void headers() { + String body = "foo"; + HttpHeaders headers = new HttpHeaders(); + headers.set("foo", "bar"); + EntityResponse result = EntityResponse.fromObject(body).headers(headers).build(); + assertEquals(headers, result.headers()); + } + + @Test + public void cookie() { + Cookie cookie = new Cookie("name", "value"); + EntityResponse result = + EntityResponse.fromObject("foo").cookie(cookie) + .build(); + assertTrue(result.cookies().get("name").contains(cookie)); + } + + @Test + public void cookies() { + MultiValueMap newCookies = new LinkedMultiValueMap<>(); + newCookies.add("name", new Cookie("name", "value")); + EntityResponse result = + EntityResponse.fromObject("foo").cookies(cookies -> cookies.addAll(newCookies)) + .build(); + assertEquals(newCookies, result.cookies()); + } + + @Test + public void notModifiedEtag() throws Exception { + String etag = "\"foo\""; + EntityResponse entityResponse = EntityResponse.fromObject("bar") + .eTag(etag) + .build(); + + MockHttpServletRequest mockRequest = new MockHttpServletRequest("GET", "http://example.com"); + mockRequest.addHeader(HttpHeaders.IF_NONE_MATCH, etag); + + MockHttpServletResponse mockResponse = new MockHttpServletResponse(); + + ModelAndView mav = entityResponse.writeTo(mockRequest, mockResponse, EMPTY_CONTEXT); + assertNull(mav); + + assertEquals(HttpStatus.NOT_MODIFIED.value(), mockResponse.getStatus()); + } + + + @Test + public void notModifiedLastModified() throws ServletException, IOException { + ZonedDateTime now = ZonedDateTime.now(); + ZonedDateTime oneMinuteBeforeNow = now.minus(1, ChronoUnit.MINUTES); + + EntityResponse entityResponse = EntityResponse.fromObject("bar") + .lastModified(oneMinuteBeforeNow) + .build(); + + MockHttpServletRequest mockRequest = new MockHttpServletRequest("GET", "http://example.com"); + mockRequest.addHeader(HttpHeaders.IF_MODIFIED_SINCE, DateTimeFormatter.RFC_1123_DATE_TIME.format(now)); + + MockHttpServletResponse mockResponse = new MockHttpServletResponse(); + + ModelAndView mav = entityResponse.writeTo(mockRequest, mockResponse, EMPTY_CONTEXT); + assertNull(mav); + + assertEquals(HttpStatus.NOT_MODIFIED.value(), mockResponse.getStatus()); + } + +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultRenderingResponseTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultRenderingResponseTests.java new file mode 100644 index 000000000000..223768417c07 --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultRenderingResponseTests.java @@ -0,0 +1,190 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * 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 org.springframework.web.servlet.function; + +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import javax.servlet.http.Cookie; + +import org.junit.Test; + +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.mock.web.test.MockHttpServletRequest; +import org.springframework.mock.web.test.MockHttpServletResponse; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.servlet.ModelAndView; + +import static org.junit.Assert.*; + +/** + * @author Arjen Poutsma + */ +public class DefaultRenderingResponseTests { + + static final ServerResponse.Context EMPTY_CONTEXT = new ServerResponse.Context() { + @Override + public List> messageConverters() { + return Collections.emptyList(); + } + + }; + + @Test + public void create() throws Exception { + String name = "foo"; + RenderingResponse result = RenderingResponse.create(name).build(); + + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + ModelAndView mav = result.writeTo(request, response, EMPTY_CONTEXT); + + assertEquals(name, mav.getViewName()); + } + + @Test + public void status() throws Exception { + HttpStatus status = HttpStatus.I_AM_A_TEAPOT; + RenderingResponse result = RenderingResponse.create("foo").status(status).build(); + + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + ModelAndView mav = result.writeTo(request, response, EMPTY_CONTEXT); + assertNotNull(mav); + assertEquals(status.value(), response.getStatus()); + } + + @Test + public void headers() throws Exception { + HttpHeaders headers = new HttpHeaders(); + headers.set("foo", "bar"); + RenderingResponse result = RenderingResponse.create("foo").headers(headers).build(); + + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + ModelAndView mav = result.writeTo(request, response, EMPTY_CONTEXT); + assertNotNull(mav); + + assertEquals("bar", response.getHeader("foo")); + } + + @Test + public void modelAttribute() throws Exception { + RenderingResponse result = RenderingResponse.create("foo") + .modelAttribute("foo", "bar").build(); + + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + ModelAndView mav = result.writeTo(request, response, EMPTY_CONTEXT); + assertNotNull(mav); + + assertEquals("bar", mav.getModel().get("foo")); + } + + + @Test + public void modelAttributeConventions() throws Exception { + RenderingResponse result = RenderingResponse.create("foo") + .modelAttribute("bar").build(); + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + ModelAndView mav = result.writeTo(request, response, EMPTY_CONTEXT); + assertNotNull(mav); + assertEquals("bar", mav.getModel().get("string")); + } + + @Test + public void modelAttributes() throws Exception { + Map model = Collections.singletonMap("foo", "bar"); + RenderingResponse result = RenderingResponse.create("foo") + .modelAttributes(model).build(); + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + ModelAndView mav = result.writeTo(request, response, EMPTY_CONTEXT); + assertNotNull(mav); + assertEquals("bar", mav.getModel().get("foo")); + } + + @Test + public void modelAttributesConventions() throws Exception { + RenderingResponse result = RenderingResponse.create("foo") + .modelAttributes("bar").build(); + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + ModelAndView mav = result.writeTo(request, response, EMPTY_CONTEXT); + assertNotNull(mav); + assertEquals("bar", mav.getModel().get("string")); + } + + @Test + public void cookies() throws Exception { + MultiValueMap newCookies = new LinkedMultiValueMap<>(); + newCookies.add("name", new Cookie("name", "value")); + RenderingResponse result = + RenderingResponse.create("foo").cookies(cookies -> cookies.addAll(newCookies)).build(); + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + ModelAndView mav = result.writeTo(request, response, EMPTY_CONTEXT); + assertNotNull(mav); + assertEquals(1, response.getCookies().length); + assertEquals("name", response.getCookies()[0].getName()); + assertEquals("value", response.getCookies()[0].getValue()); + } + + @Test + public void notModifiedEtag() throws Exception { + String etag = "\"foo\""; + RenderingResponse result = RenderingResponse.create("bar") + .header(HttpHeaders.ETAG, etag) + .build(); + + MockHttpServletRequest request = new MockHttpServletRequest("GET", "http://example.com"); + request.addHeader(HttpHeaders.IF_NONE_MATCH, etag); + MockHttpServletResponse response = new MockHttpServletResponse(); + + ModelAndView mav = result.writeTo(request, response, EMPTY_CONTEXT); + assertNull(mav); + assertEquals(HttpStatus.NOT_MODIFIED.value(), response.getStatus()); + } + + + @Test + public void notModifiedLastModified() throws Exception { + ZonedDateTime now = ZonedDateTime.now(); + ZonedDateTime oneMinuteBeforeNow = now.minus(1, ChronoUnit.MINUTES); + + RenderingResponse result = RenderingResponse.create("bar") + .header(HttpHeaders.LAST_MODIFIED, DateTimeFormatter.RFC_1123_DATE_TIME.format(oneMinuteBeforeNow)) + .build(); + + MockHttpServletRequest request = new MockHttpServletRequest("GET", "http://example.com"); + request.addHeader(HttpHeaders.IF_MODIFIED_SINCE,DateTimeFormatter.RFC_1123_DATE_TIME.format(now)); + MockHttpServletResponse response = new MockHttpServletResponse(); + + ModelAndView mav = result.writeTo(request, response, EMPTY_CONTEXT); + assertNull(mav); + assertEquals(HttpStatus.NOT_MODIFIED.value(), response.getStatus()); + } + + +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultServerRequestBuilderTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultServerRequestBuilderTests.java new file mode 100644 index 000000000000..1fcbfab05ad7 --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultServerRequestBuilderTests.java @@ -0,0 +1,76 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * 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 org.springframework.web.servlet.function; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import javax.servlet.ServletException; +import javax.servlet.http.Cookie; + +import org.junit.Test; + +import org.springframework.http.HttpMethod; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.mock.web.test.MockHttpServletRequest; + +import static org.junit.Assert.*; + +/** + * @author Arjen Poutsma + */ +public class DefaultServerRequestBuilderTests { + + private final List> messageConverters = Collections.singletonList( + new StringHttpMessageConverter()); + + @Test + public void from() throws ServletException, IOException { + MockHttpServletRequest request = new MockHttpServletRequest("POST", "http://example.com"); + request.addHeader("foo", "bar"); + + ServerRequest other = ServerRequest.create(request, messageConverters); + + ServerRequest result = ServerRequest.from(other) + .method(HttpMethod.HEAD) + .header("foo", "bar") + .headers(httpHeaders -> httpHeaders.set("baz", "qux")) + .cookie("foo", "bar") + .cookies(cookies -> cookies.set("baz", new Cookie("baz", "qux"))) + .attribute("foo", "bar") + .attributes(attributes -> attributes.put("baz", "qux")) + .body("baz") + .build(); + + assertEquals(HttpMethod.HEAD, result.method()); + assertEquals(2, result.headers().asHttpHeaders().size()); + assertEquals("bar", result.headers().asHttpHeaders().getFirst("foo")); + assertEquals("qux", result.headers().asHttpHeaders().getFirst("baz")); + assertEquals(2, result.cookies().size()); + assertEquals("bar", result.cookies().getFirst("foo").getValue()); + assertEquals("qux", result.cookies().getFirst("baz").getValue()); + assertEquals(2, result.attributes().size()); + assertEquals("bar", result.attributes().get("foo")); + assertEquals("qux", result.attributes().get("baz")); + + String body = result.body(String.class); + assertEquals("baz", body); + } + + +} \ No newline at end of file diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultServerRequestTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultServerRequestTests.java new file mode 100644 index 000000000000..04cdc228a566 --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultServerRequestTests.java @@ -0,0 +1,296 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * 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 org.springframework.web.servlet.function; + +import java.net.InetSocketAddress; +import java.net.URI; +import java.nio.charset.Charset; +import java.security.Principal; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.OptionalLong; +import javax.servlet.http.Cookie; + +import org.junit.Test; + +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpRange; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.mock.web.test.MockHttpServletRequest; +import org.springframework.mock.web.test.MockHttpSession; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.HttpMediaTypeNotSupportedException; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.Assert.*; + +/** + * @author Arjen Poutsma + * @since 5.1 + */ +public class DefaultServerRequestTests { + + private final List> messageConverters = Collections.singletonList( + new StringHttpMessageConverter()); + + @Test + public void method() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("HEAD", "/"); + DefaultServerRequest request = + new DefaultServerRequest(servletRequest, this.messageConverters); + + assertEquals(HttpMethod.HEAD, request.method()); + } + + @Test + public void uri() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + servletRequest.setServerName("example.com"); + servletRequest.setScheme("https"); + servletRequest.setServerPort(443); + + DefaultServerRequest request = + new DefaultServerRequest(servletRequest, this.messageConverters); + + assertEquals(URI.create("https://example.com/"), request.uri()); + } + + @Test + public void uriBuilder() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path"); + servletRequest.setQueryString("a=1"); + + DefaultServerRequest request = + new DefaultServerRequest(servletRequest, this.messageConverters); + + URI result = request.uriBuilder().build(); + assertEquals("http", result.getScheme()); + assertEquals("localhost", result.getHost()); + assertEquals(-1, result.getPort()); + assertEquals("/path", result.getPath()); + assertEquals("a=1", result.getQuery()); + } + + @Test + public void attribute() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + servletRequest.setAttribute("foo", "bar"); + + DefaultServerRequest request = + new DefaultServerRequest(servletRequest, this.messageConverters); + + assertEquals(Optional.of("bar"), request.attribute("foo")); + } + + @Test + public void params() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + servletRequest.setParameter("foo", "bar"); + + DefaultServerRequest request = + new DefaultServerRequest(servletRequest, this.messageConverters); + + assertEquals(Optional.of("bar"), request.param("foo")); + } + + @Test + public void emptyQueryParam() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + servletRequest.setParameter("foo", ""); + + DefaultServerRequest request = + new DefaultServerRequest(servletRequest, this.messageConverters); + + assertEquals(Optional.of(""), request.param("foo")); + } + + @Test + public void absentQueryParam() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + servletRequest.setParameter("foo", ""); + + DefaultServerRequest request = + new DefaultServerRequest(servletRequest, this.messageConverters); + + assertEquals(Optional.empty(), request.param("bar")); + } + + @Test + public void pathVariable() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + Map pathVariables = Collections.singletonMap("foo", "bar"); + servletRequest + .setAttribute(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE, pathVariables); + + DefaultServerRequest request = new DefaultServerRequest(servletRequest, + this.messageConverters); + + assertEquals("bar", request.pathVariable("foo")); + } + + @Test(expected = IllegalArgumentException.class) + public void pathVariableNotFound() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + Map pathVariables = Collections.singletonMap("foo", "bar"); + servletRequest + .setAttribute(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE, pathVariables); + + DefaultServerRequest request = new DefaultServerRequest(servletRequest, + this.messageConverters); + + request.pathVariable("baz"); + } + + @Test + public void pathVariables() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + Map pathVariables = Collections.singletonMap("foo", "bar"); + servletRequest + .setAttribute(RouterFunctions.URI_TEMPLATE_VARIABLES_ATTRIBUTE, pathVariables); + + DefaultServerRequest request = new DefaultServerRequest(servletRequest, + this.messageConverters); + + assertEquals(pathVariables, request.pathVariables()); + } + + @Test + public void header() { + HttpHeaders httpHeaders = new HttpHeaders(); + List accept = + Collections.singletonList(MediaType.APPLICATION_JSON); + httpHeaders.setAccept(accept); + List acceptCharset = Collections.singletonList(UTF_8); + httpHeaders.setAcceptCharset(acceptCharset); + long contentLength = 42L; + httpHeaders.setContentLength(contentLength); + MediaType contentType = MediaType.TEXT_PLAIN; + httpHeaders.setContentType(contentType); + InetSocketAddress host = InetSocketAddress.createUnresolved("localhost", 80); + httpHeaders.setHost(host); + List range = Collections.singletonList(HttpRange.createByteRange(0, 42)); + httpHeaders.setRange(range); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + httpHeaders.forEach(servletRequest::addHeader); + servletRequest.setContentType(MediaType.TEXT_PLAIN_VALUE); + + DefaultServerRequest request = new DefaultServerRequest(servletRequest, + this.messageConverters); + + ServerRequest.Headers headers = request.headers(); + assertEquals(accept, headers.accept()); + assertEquals(acceptCharset, headers.acceptCharset()); + assertEquals(OptionalLong.of(contentLength), headers.contentLength()); + assertEquals(Optional.of(contentType), headers.contentType()); + assertEquals(httpHeaders, headers.asHttpHeaders()); + } + + @Test + public void cookies() { + Cookie cookie = new Cookie("foo", "bar"); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + servletRequest.setCookies(cookie); + + DefaultServerRequest request = new DefaultServerRequest(servletRequest, + this.messageConverters); + + MultiValueMap expected = new LinkedMultiValueMap<>(); + expected.add("foo", cookie); + + assertEquals(expected, request.cookies()); + + } + + @Test + public void bodyClass() throws Exception { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + servletRequest.setContentType(MediaType.TEXT_PLAIN_VALUE); + servletRequest.setContent("foo".getBytes(UTF_8)); + + DefaultServerRequest request = new DefaultServerRequest(servletRequest, + this.messageConverters); + + String result = request.body(String.class); + assertEquals("foo", result); + } + + @Test + public void bodyParameterizedTypeReference() throws Exception { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + servletRequest.setContentType(MediaType.TEXT_PLAIN_VALUE); + servletRequest.setContent("foo".getBytes(UTF_8)); + + DefaultServerRequest request = new DefaultServerRequest(servletRequest, + this.messageConverters); + + String result = request.body(new ParameterizedTypeReference() {}); + assertEquals("foo", result); + } + + @Test(expected = HttpMediaTypeNotSupportedException.class) + public void bodyUnacceptable() throws Exception { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + servletRequest.setContentType(MediaType.TEXT_PLAIN_VALUE); + servletRequest.setContent("foo".getBytes(UTF_8)); + + DefaultServerRequest request = + new DefaultServerRequest(servletRequest, Collections.emptyList()); + + request.body(String.class); + } + + @Test + public void session() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + MockHttpSession session = new MockHttpSession(); + servletRequest.setSession(session); + + DefaultServerRequest request = new DefaultServerRequest(servletRequest, + this.messageConverters); + + assertEquals(session, request.session()); + + } + + @Test + public void principal() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + Principal principal = new Principal() { + @Override + public String getName() { + return "foo"; + } + }; + servletRequest.setUserPrincipal(principal); + + DefaultServerRequest request = new DefaultServerRequest(servletRequest, + this.messageConverters); + + assertEquals(principal, request.principal().get()); + + } + +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultServerResponseBuilderTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultServerResponseBuilderTests.java new file mode 100644 index 000000000000..a388b6116943 --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/DefaultServerResponseBuilderTests.java @@ -0,0 +1,327 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * 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 org.springframework.web.servlet.function; + +import java.net.URI; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import javax.servlet.http.Cookie; + +import org.junit.Test; +import org.reactivestreams.Publisher; +import reactor.core.publisher.Mono; + +import org.springframework.http.CacheControl; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.mock.web.test.MockHttpServletRequest; +import org.springframework.mock.web.test.MockHttpServletResponse; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.servlet.ModelAndView; + +import static org.junit.Assert.*; + +/** + * @author Arjen Poutsma + */ +public class DefaultServerResponseBuilderTests { + + static final ServerResponse.Context EMPTY_CONTEXT = new ServerResponse.Context() { + @Override + public List> messageConverters() { + return Collections.emptyList(); + + } + + }; + + @Test + public void status() { + ServerResponse response = ServerResponse.status(HttpStatus.CREATED).build(); + assertEquals(HttpStatus.CREATED, response.statusCode()); + } + + @Test + public void from() { + ServerResponse other = ServerResponse.ok().header("foo", "bar").build(); + ServerResponse result = ServerResponse.from(other).build(); + assertEquals(HttpStatus.OK, result.statusCode()); + assertEquals("bar", result.headers().getFirst("foo")); + } + + + @Test + public void ok() { + ServerResponse response = ServerResponse.ok().build(); + + assertEquals(HttpStatus.OK, response.statusCode()); + } + + @Test + public void created() { + URI location = URI.create("http://example.com"); + ServerResponse response = ServerResponse.created(location).build(); + assertEquals(HttpStatus.CREATED, response.statusCode()); + assertEquals(location, response.headers().getLocation()); + } + + @Test + public void accepted() { + ServerResponse response = ServerResponse.accepted().build(); + assertEquals(HttpStatus.ACCEPTED, response.statusCode()); + } + + @Test + public void noContent() { + ServerResponse response = ServerResponse.noContent().build(); + assertEquals(HttpStatus.NO_CONTENT, response.statusCode()); + } + + @Test + public void seeOther() { + URI location = URI.create("http://example.com"); + ServerResponse response = ServerResponse.seeOther(location).build(); + assertEquals(HttpStatus.SEE_OTHER, response.statusCode()); + assertEquals(location, response.headers().getLocation()); + } + + @Test + public void temporaryRedirect() { + URI location = URI.create("http://example.com"); + ServerResponse response = ServerResponse.temporaryRedirect(location).build(); + assertEquals(HttpStatus.TEMPORARY_REDIRECT, response.statusCode()); + assertEquals(location, response.headers().getLocation()); + } + + @Test + public void permanentRedirect() { + URI location = URI.create("http://example.com"); + ServerResponse response = ServerResponse.permanentRedirect(location).build(); + assertEquals(HttpStatus.PERMANENT_REDIRECT, response.statusCode()); + assertEquals(location, response.headers().getLocation()); + } + + @Test + public void badRequest() { + ServerResponse response = ServerResponse.badRequest().build(); + assertEquals(HttpStatus.BAD_REQUEST, response.statusCode()); + } + + @Test + public void notFound() { + ServerResponse response = ServerResponse.notFound().build(); + assertEquals(HttpStatus.NOT_FOUND, response.statusCode()); + } + + @Test + public void unprocessableEntity() { + ServerResponse response = ServerResponse.unprocessableEntity().build(); + assertEquals(HttpStatus.UNPROCESSABLE_ENTITY, response.statusCode()); + } + + @Test + public void allow() { + ServerResponse response = ServerResponse.ok().allow(HttpMethod.GET).build(); + assertEquals(EnumSet.of(HttpMethod.GET), response.headers().getAllow()); + } + + @Test + public void contentLength() { + ServerResponse response = ServerResponse.ok().contentLength(42).build(); + assertEquals(42L, response.headers().getContentLength()); + } + + @Test + public void contentType() { + ServerResponse response = ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).build(); + assertEquals(MediaType.APPLICATION_JSON, response.headers().getContentType()); + } + + @Test + public void eTag() { + ServerResponse response = ServerResponse.ok().eTag("foo").build(); + assertEquals("\"foo\"", response.headers().getETag()); + } + + @Test + public void lastModified() { + ZonedDateTime now = ZonedDateTime.now(); + ServerResponse response = ServerResponse.ok().lastModified(now).build(); + long expected = now.toInstant().toEpochMilli() / 1000; + assertEquals(expected, response.headers().getLastModified() / 1000); + } + + @Test + public void cacheControlTag() { + ServerResponse response = ServerResponse.ok().cacheControl(CacheControl.noCache()).build(); + assertEquals("no-cache", response.headers().getCacheControl()); + } + + @Test + public void varyBy() { + ServerResponse response = ServerResponse.ok().varyBy("foo").build(); + List expected = Collections.singletonList("foo"); + assertEquals(expected, response.headers().getVary()); + } + + + @Test + public void statusCode() { + HttpStatus statusCode = HttpStatus.ACCEPTED; + ServerResponse response = ServerResponse.status(statusCode).build(); + assertEquals(statusCode, response.statusCode()); + } + + @Test + public void headers() { + HttpHeaders newHeaders = new HttpHeaders(); + newHeaders.set("foo", "bar"); + ServerResponse response = ServerResponse.ok() + .headers(headers -> headers.addAll(newHeaders)) + .build(); + assertEquals(newHeaders, response.headers()); + } + + @Test + public void cookies() { + MultiValueMap newCookies = new LinkedMultiValueMap<>(); + newCookies.add("name", new Cookie("name", "value")); + ServerResponse response = ServerResponse.ok() + .cookies(cookies -> cookies.addAll(newCookies)) + .build(); + assertEquals(newCookies, response.cookies()); + } + + @Test + public void build() throws Exception { + Cookie cookie = new Cookie("name", "value"); + ServerResponse response = ServerResponse.status(HttpStatus.CREATED) + .header("MyKey", "MyValue") + .cookie(cookie) + .build(); + + MockHttpServletRequest mockRequest = new MockHttpServletRequest("GET", "http://example.com"); + MockHttpServletResponse mockResponse = new MockHttpServletResponse(); + + ModelAndView mav = response.writeTo(mockRequest, mockResponse, EMPTY_CONTEXT); + assertNull(mav); + + assertEquals(HttpStatus.CREATED.value(), mockResponse.getStatus()); + assertEquals("MyValue", mockResponse.getHeader("MyKey")); + assertEquals("value", mockResponse.getCookie("name").getValue()); + } + + @Test + public void notModifiedEtag() throws Exception { + String etag = "\"foo\""; + ServerResponse response = ServerResponse.ok() + .eTag(etag) + .body("bar"); + + MockHttpServletRequest mockRequest = new MockHttpServletRequest("GET", "http://example.com"); + mockRequest.addHeader(HttpHeaders.IF_NONE_MATCH, etag); + + MockHttpServletResponse mockResponse = new MockHttpServletResponse(); + ModelAndView mav = response.writeTo(mockRequest, mockResponse, EMPTY_CONTEXT); + assertNull(mav); + + assertEquals(HttpStatus.NOT_MODIFIED.value(), mockResponse.getStatus()); + } + + @Test + public void notModifiedLastModified() throws Exception { + ZonedDateTime now = ZonedDateTime.now(); + ZonedDateTime oneMinuteBeforeNow = now.minus(1, ChronoUnit.MINUTES); + + ServerResponse response = ServerResponse.ok() + .lastModified(oneMinuteBeforeNow) + .body("bar"); + + MockHttpServletRequest mockRequest = new MockHttpServletRequest("GET", "http://example.com"); + mockRequest.addHeader(HttpHeaders.IF_MODIFIED_SINCE, DateTimeFormatter.RFC_1123_DATE_TIME.format(now)); + + MockHttpServletResponse mockResponse = new MockHttpServletResponse(); + ModelAndView mav = response.writeTo(mockRequest, mockResponse, EMPTY_CONTEXT); + assertNull(mav); + + assertEquals(HttpStatus.NOT_MODIFIED.value(), mockResponse.getStatus()); + } + + @Test + public void body() throws Exception { + String body = "foo"; + ServerResponse response = ServerResponse.ok().body(body); + + MockHttpServletRequest mockRequest = new MockHttpServletRequest("GET", "http://example.com"); + MockHttpServletResponse mockResponse = new MockHttpServletResponse(); + ServerResponse.Context context = () -> Collections.singletonList(new StringHttpMessageConverter()); + + ModelAndView mav = response.writeTo(mockRequest, mockResponse, context); + assertNull(mav); + + assertEquals(body, mockResponse.getContentAsString()); + } + + @Test + public void asyncBodyCompletionStage() throws Exception { + String body = "foo"; + CompletionStage completionStage = CompletableFuture.completedFuture(body); + ServerResponse response = ServerResponse.ok().asyncBody(completionStage); + + MockHttpServletRequest mockRequest = new MockHttpServletRequest("GET", "http://example.com"); + MockHttpServletResponse mockResponse = new MockHttpServletResponse(); + mockRequest.setAsyncSupported(true); + + ServerResponse.Context context = () -> Collections.singletonList(new StringHttpMessageConverter()); + + ModelAndView mav = response.writeTo(mockRequest, mockResponse, context); + assertNull(mav); + + + assertEquals(body, mockResponse.getContentAsString()); + } + + @Test + public void asyncBodyPublisher() throws Exception { + String body = "foo"; + Publisher publisher = Mono.just(body); + ServerResponse response = ServerResponse.ok().asyncBody(publisher); + + MockHttpServletRequest mockRequest = new MockHttpServletRequest("GET", "http://example.com"); + MockHttpServletResponse mockResponse = new MockHttpServletResponse(); + mockRequest.setAsyncSupported(true); + + ServerResponse.Context context = () -> Collections.singletonList(new StringHttpMessageConverter()); + + ModelAndView mav = response.writeTo(mockRequest, mockResponse, context); + assertNull(mav); + + assertEquals(body, mockResponse.getContentAsString()); + } + +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/PathResourceLookupFunctionTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/PathResourceLookupFunctionTests.java new file mode 100644 index 000000000000..bde5fc65a508 --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/PathResourceLookupFunctionTests.java @@ -0,0 +1,120 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * 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 org.springframework.web.servlet.function; + +import java.io.File; +import java.util.Collections; +import java.util.Optional; +import java.util.function.Function; + +import org.junit.Test; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.mock.web.test.MockHttpServletRequest; + +import static org.junit.Assert.*; + +/** + * @author Arjen Poutsma + */ +public class PathResourceLookupFunctionTests { + + @Test + public void normal() throws Exception { + ClassPathResource location = + new ClassPathResource("org/springframework/web/servlet/function/"); + + PathResourceLookupFunction function = + new PathResourceLookupFunction("/resources/**", location); + + MockHttpServletRequest servletRequest = + new MockHttpServletRequest("GET", "/resources/response.txt"); + ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList()); + + Optional result = function.apply(request); + assertTrue(result.isPresent()); + + File expected = new ClassPathResource("response.txt", getClass()).getFile(); + assertEquals(expected, result.get().getFile()); + } + + @Test + public void subPath() throws Exception { + ClassPathResource location = + new ClassPathResource("org/springframework/web/servlet/function/"); + + PathResourceLookupFunction function = + new PathResourceLookupFunction("/resources/**", location); + + MockHttpServletRequest servletRequest = + new MockHttpServletRequest("GET", "/resources/child/response.txt"); + ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList()); + + Optional result = function.apply(request); + assertTrue(result.isPresent()); + + File expected = + new ClassPathResource("org/springframework/web/servlet/function/child/response.txt") + .getFile(); + assertEquals(expected, result.get().getFile()); + } + + @Test + public void notFound() { + ClassPathResource location = + new ClassPathResource("org/springframework/web/reactive/function/server/"); + + PathResourceLookupFunction function = + new PathResourceLookupFunction("/resources/**", location); + + MockHttpServletRequest servletRequest = + new MockHttpServletRequest("GET", "/resources/foo.txt"); + ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList()); + + Optional result = function.apply(request); + assertFalse(result.isPresent()); + } + + @Test + public void composeResourceLookupFunction() throws Exception { + ClassPathResource defaultResource = new ClassPathResource("response.txt", getClass()); + + Function> lookupFunction = + new PathResourceLookupFunction("/resources/**", + new ClassPathResource("org/springframework/web/servlet/function/")); + + Function> customLookupFunction = + lookupFunction.andThen((Optional optionalResource) -> { + if (optionalResource.isPresent()) { + return optionalResource; + } + else { + return Optional.of(defaultResource); + } + }); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/resources/foo"); + ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList()); + + Optional result = customLookupFunction.apply(request); + assertTrue(result.isPresent()); + + assertEquals(defaultResource.getFile(), result.get().getFile()); + } + +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RequestPredicateTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RequestPredicateTests.java new file mode 100644 index 000000000000..83e53e05f418 --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RequestPredicateTests.java @@ -0,0 +1,76 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * 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 org.springframework.web.servlet.function; + +import java.util.Collections; + +import org.junit.Before; +import org.junit.Test; + +import org.springframework.mock.web.test.MockHttpServletRequest; + +import static org.junit.Assert.*; + +/** + * @author Arjen Poutsma + */ +public class RequestPredicateTests { + + private ServerRequest request; + + @Before + public void createRequest() { + this.request = new DefaultServerRequest(new MockHttpServletRequest(), + Collections.emptyList()); + } + + @Test + public void and() { + RequestPredicate predicate1 = request -> true; + RequestPredicate predicate2 = request -> true; + RequestPredicate predicate3 = request -> false; + + assertTrue(predicate1.and(predicate2).test(request)); + assertTrue(predicate2.and(predicate1).test(request)); + assertFalse(predicate1.and(predicate3).test(request)); + } + + @Test + public void negate() { + RequestPredicate predicate = request -> false; + RequestPredicate negated = predicate.negate(); + + assertTrue(negated.test(request)); + + predicate = request -> true; + negated = predicate.negate(); + + assertFalse(negated.test(request)); + } + + @Test + public void or() { + RequestPredicate predicate1 = request -> true; + RequestPredicate predicate2 = request -> false; + RequestPredicate predicate3 = request -> false; + + assertTrue(predicate1.or(predicate2).test(request)); + assertTrue(predicate2.or(predicate1).test(request)); + assertFalse(predicate2.or(predicate3).test(request)); + } + +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RequestPredicatesTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RequestPredicatesTests.java new file mode 100644 index 000000000000..89633b6d2c66 --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RequestPredicatesTests.java @@ -0,0 +1,230 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * 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 org.springframework.web.servlet.function; + +import java.util.Collections; +import java.util.function.Function; + +import org.junit.Test; + +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.mock.web.test.MockHttpServletRequest; +import org.springframework.web.util.pattern.PathPatternParser; + +import static java.util.Collections.emptyList; +import static org.junit.Assert.*; +import static org.springframework.http.MediaType.TEXT_XML_VALUE; + +/** + * @author Arjen Poutsma + */ +public class RequestPredicatesTests { + + @Test + public void all() { + RequestPredicate predicate = RequestPredicates.all(); + MockHttpServletRequest servletRequest = new MockHttpServletRequest(); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + assertTrue(predicate.test(request)); + } + + + @Test + public void method() { + HttpMethod httpMethod = HttpMethod.GET; + RequestPredicate predicate = RequestPredicates.method(httpMethod); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "http://example.com"); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + assertTrue(predicate.test(request)); + + servletRequest.setMethod("POST"); + assertFalse(predicate.test(request)); + } + + @Test + public void methods() { + RequestPredicate predicate = RequestPredicates.methods(HttpMethod.GET, HttpMethod.HEAD); + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "http://example.com"); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + assertTrue(predicate.test(request)); + + servletRequest.setMethod("HEAD"); + assertTrue(predicate.test(request)); + + servletRequest.setMethod("POST"); + assertFalse(predicate.test(request)); + } + + @Test + public void allMethods() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path"); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + + RequestPredicate predicate = RequestPredicates.GET("/p*"); + assertTrue(predicate.test(request)); + + predicate = RequestPredicates.HEAD("/p*"); + servletRequest.setMethod("HEAD"); + assertTrue(predicate.test(request)); + + predicate = RequestPredicates.POST("/p*"); + servletRequest.setMethod("POST"); + assertTrue(predicate.test(request)); + + predicate = RequestPredicates.PUT("/p*"); + servletRequest.setMethod("PUT"); + assertTrue(predicate.test(request)); + + predicate = RequestPredicates.PATCH("/p*"); + servletRequest.setMethod("PATCH"); + assertTrue(predicate.test(request)); + + predicate = RequestPredicates.DELETE("/p*"); + servletRequest.setMethod("DELETE"); + assertTrue(predicate.test(request)); + + predicate = RequestPredicates.OPTIONS("/p*"); + servletRequest.setMethod("OPTIONS"); + assertTrue(predicate.test(request)); + } + + @Test + public void path() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path"); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + RequestPredicate predicate = RequestPredicates.path("/p*"); + assertTrue(predicate.test(request)); + + servletRequest = new MockHttpServletRequest("GET", "/foo"); + request = new DefaultServerRequest(servletRequest, emptyList()); + assertFalse(predicate.test(request)); + } + + @Test + public void pathEncoded() { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/foo%20bar"); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + + RequestPredicate predicate = RequestPredicates.path("/foo bar"); + assertTrue(predicate.test(request)); + + servletRequest = new MockHttpServletRequest(); + request = new DefaultServerRequest(servletRequest, emptyList()); + assertFalse(predicate.test(request)); + } + + @Test + public void pathPredicates() { + PathPatternParser parser = new PathPatternParser(); + parser.setCaseSensitive(false); + Function pathPredicates = RequestPredicates.pathPredicates(parser); + + RequestPredicate predicate = pathPredicates.apply("/P*"); + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path"); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + assertTrue(predicate.test(request)); + } + + + @Test + public void headers() { + String name = "MyHeader"; + String value = "MyValue"; + RequestPredicate predicate = + RequestPredicates.headers( + headers -> headers.header(name).equals(Collections.singletonList(value))); + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path"); + servletRequest.addHeader(name, value); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + assertTrue(predicate.test(request)); + + servletRequest = new MockHttpServletRequest(); + request = new DefaultServerRequest(servletRequest, emptyList()); + assertFalse(predicate.test(request)); + } + + @Test + public void contentType() { + MediaType json = MediaType.APPLICATION_JSON; + RequestPredicate predicate = RequestPredicates.contentType(json); + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path"); + servletRequest.setContentType(json.toString()); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + + assertTrue(predicate.test(request)); + + servletRequest = new MockHttpServletRequest(); + request = new DefaultServerRequest(servletRequest, emptyList()); + assertFalse(predicate.test(request)); + } + + @Test + public void accept() { + MediaType json = MediaType.APPLICATION_JSON; + RequestPredicate predicate = RequestPredicates.accept(json); + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path"); + servletRequest.addHeader("Accept", json.toString()); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + assertTrue(predicate.test(request)); + + servletRequest = new MockHttpServletRequest(); + servletRequest.addHeader("Accept", TEXT_XML_VALUE); + request = new DefaultServerRequest(servletRequest, emptyList()); + assertFalse(predicate.test(request)); + } + + @Test + public void pathExtension() { + RequestPredicate predicate = RequestPredicates.pathExtension("txt"); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/file.txt"); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + assertTrue(predicate.test(request)); + + servletRequest = new MockHttpServletRequest("GET", "/FILE.TXT"); + request = new DefaultServerRequest(servletRequest, emptyList()); + assertTrue(predicate.test(request)); + + predicate = RequestPredicates.pathExtension("bar"); + assertFalse(predicate.test(request)); + + servletRequest = new MockHttpServletRequest("GET", "/file.foo"); + request = new DefaultServerRequest(servletRequest, emptyList()); + assertFalse(predicate.test(request)); + } + + @Test + public void param() { + RequestPredicate predicate = RequestPredicates.param("foo", "bar"); + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/path"); + servletRequest.addParameter("foo", "bar"); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + assertTrue(predicate.test(request)); + + predicate = RequestPredicates.param("foo", s -> s.equals("bar")); + assertTrue(predicate.test(request)); + + predicate = RequestPredicates.param("foo", "baz"); + assertFalse(predicate.test(request)); + + predicate = RequestPredicates.param("foo", s -> s.equals("baz")); + assertFalse(predicate.test(request)); + } + +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/ResourceHandlerFunctionTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/ResourceHandlerFunctionTests.java new file mode 100644 index 000000000000..b548f0b4138f --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/ResourceHandlerFunctionTests.java @@ -0,0 +1,136 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * 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 org.springframework.web.servlet.function; + +import java.io.IOException; +import java.nio.file.Files; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import javax.servlet.ServletException; + +import org.junit.Before; +import org.junit.Test; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.ResourceHttpMessageConverter; +import org.springframework.mock.web.test.MockHttpServletRequest; +import org.springframework.mock.web.test.MockHttpServletResponse; +import org.springframework.web.servlet.ModelAndView; + +import static org.junit.Assert.*; + +/** + * @author Arjen Poutsma + */ +public class ResourceHandlerFunctionTests { + + private final Resource resource = new ClassPathResource("response.txt", getClass()); + + private final ResourceHandlerFunction handlerFunction = new ResourceHandlerFunction(this.resource); + + private ServerResponse.Context context; + + private ResourceHttpMessageConverter messageConverter; + + @Before + public void createContext() { + this.messageConverter = new ResourceHttpMessageConverter(); + this.context = new ServerResponse.Context() { + @Override + public List> messageConverters() { + return Collections.singletonList(messageConverter); + } + + }; + } + + + @Test + public void get() throws IOException, ServletException { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/"); + ServerRequest request = new DefaultServerRequest(servletRequest, Collections.singletonList(messageConverter)); + + ServerResponse response = this.handlerFunction.handle(request); + assertEquals(HttpStatus.OK, response.statusCode()); + assertTrue(response instanceof EntityResponse); + @SuppressWarnings("unchecked") + EntityResponse entityResponse = (EntityResponse) response; + assertEquals(this.resource, entityResponse.entity()); + + MockHttpServletResponse servletResponse = new MockHttpServletResponse(); + ModelAndView mav = response.writeTo(servletRequest, servletResponse, this.context); + assertNull(mav); + + assertEquals(200, servletResponse.getStatus()); + byte[] expectedBytes = Files.readAllBytes(this.resource.getFile().toPath()); + byte[] actualBytes = servletResponse.getContentAsByteArray(); + assertArrayEquals(expectedBytes, actualBytes); + assertEquals(MediaType.TEXT_PLAIN_VALUE, servletResponse.getContentType()); + assertEquals(this.resource.contentLength(),servletResponse.getContentLength()); + } + + @Test + public void head() throws IOException, ServletException { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("HEAD", "/"); + ServerRequest request = new DefaultServerRequest(servletRequest, Collections.singletonList(messageConverter)); + + ServerResponse response = this.handlerFunction.handle(request); + assertEquals(HttpStatus.OK, response.statusCode()); + assertTrue(response instanceof EntityResponse); + @SuppressWarnings("unchecked") + EntityResponse entityResponse = (EntityResponse) response; + assertEquals(this.resource.getFilename(), entityResponse.entity().getFilename()); + + + MockHttpServletResponse servletResponse = new MockHttpServletResponse(); + ModelAndView mav = response.writeTo(servletRequest, servletResponse, this.context); + assertNull(mav); + + assertEquals(200, servletResponse.getStatus()); + byte[] actualBytes = servletResponse.getContentAsByteArray(); + assertEquals(0, actualBytes.length); + assertEquals(MediaType.TEXT_PLAIN_VALUE, servletResponse.getContentType()); + assertEquals(this.resource.contentLength(),servletResponse.getContentLength()); + } + + + @Test + public void options() throws ServletException, IOException { + MockHttpServletRequest servletRequest = new MockHttpServletRequest("OPTIONS", "/"); + ServerRequest request = new DefaultServerRequest(servletRequest, Collections.singletonList(messageConverter)); + + ServerResponse response = this.handlerFunction.handle(request); + assertEquals(HttpStatus.OK, response.statusCode()); + assertEquals(EnumSet.of(HttpMethod.GET, HttpMethod.HEAD, HttpMethod.OPTIONS), response.headers().getAllow()); + + MockHttpServletResponse servletResponse = new MockHttpServletResponse(); + ModelAndView mav = response.writeTo(servletRequest, servletResponse, this.context); + assertNull(mav); + + assertEquals(200, servletResponse.getStatus()); + assertEquals("GET,HEAD,OPTIONS", servletResponse.getHeader("Allow")); + byte[] actualBytes = servletResponse.getContentAsByteArray(); + assertEquals(0, actualBytes.length); + } + +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RouterFunctionBuilderTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RouterFunctionBuilderTests.java new file mode 100644 index 000000000000..ad9f9f0b4c32 --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RouterFunctionBuilderTests.java @@ -0,0 +1,188 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * 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 org.springframework.web.servlet.function; + +import java.util.Optional; +import java.util.concurrent.atomic.AtomicInteger; + +import org.junit.Test; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.mock.web.test.MockHttpServletRequest; + +import static java.util.Collections.emptyList; +import static org.junit.Assert.*; + +/** + * @author Arjen Poutsma + */ +public class RouterFunctionBuilderTests { + + @Test + public void route() { + RouterFunction route = RouterFunctions.route() + .GET("/foo", request -> ServerResponse.ok().build()) + .POST("/", RequestPredicates.contentType(MediaType.TEXT_PLAIN), + request -> ServerResponse.noContent().build()) + .build(); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/foo"); + ServerRequest fooRequest = new DefaultServerRequest(servletRequest, emptyList()); + + Optional responseStatus = route.route(fooRequest) + .map(handlerFunction -> handle(handlerFunction, fooRequest)) + .map(ServerResponse::statusCode) + .map(HttpStatus::value); + assertEquals(200, responseStatus.get().intValue()); + + servletRequest = new MockHttpServletRequest("POST", "/"); + servletRequest.setContentType("text/plain"); + ServerRequest barRequest = new DefaultServerRequest(servletRequest, emptyList()); + + responseStatus = route.route(barRequest) + .map(handlerFunction -> handle(handlerFunction, barRequest)) + .map(ServerResponse::statusCode) + .map(HttpStatus::value); + assertEquals(204, responseStatus.get().intValue()); + + servletRequest = new MockHttpServletRequest("POST", "/"); + ServerRequest invalidRequest = new DefaultServerRequest(servletRequest, emptyList()); + + responseStatus = route.route(invalidRequest) + .map(handlerFunction -> handle(handlerFunction, invalidRequest)) + .map(ServerResponse::statusCode) + .map(HttpStatus::value); + + assertFalse(responseStatus.isPresent()); + + } + + private static ServerResponse handle(HandlerFunction handlerFunction, + ServerRequest request) { + try { + return handlerFunction.handle(request); + } + catch (Exception e) { + fail(e.getMessage()); + return null; + } + } + + @Test + public void resources() { + Resource resource = new ClassPathResource("/org/springframework/web/servlet/function/"); + assertTrue(resource.exists()); + + RouterFunction route = RouterFunctions.route() + .resources("/resources/**", resource) + .build(); + + MockHttpServletRequest servletRequest = + new MockHttpServletRequest("GET", "/resources/response.txt"); + ServerRequest resourceRequest = new DefaultServerRequest(servletRequest, emptyList()); + + Optional responseStatus = route.route(resourceRequest) + .map(handlerFunction -> handle(handlerFunction, resourceRequest)) + .map(ServerResponse::statusCode) + .map(HttpStatus::value); + assertEquals(200, responseStatus.get().intValue()); + + servletRequest = new MockHttpServletRequest("POST", "/resources/foo.txt"); + ServerRequest invalidRequest = new DefaultServerRequest(servletRequest, emptyList()); + + responseStatus = route.route(invalidRequest) + .map(handlerFunction -> handle(handlerFunction, invalidRequest)) + .map(ServerResponse::statusCode) + .map(HttpStatus::value); + assertFalse(responseStatus.isPresent()); + } + + @Test + public void nest() { + RouterFunction route = RouterFunctions.route() + .path("/foo", builder -> + builder.path("/bar", + () -> RouterFunctions.route() + .GET("/baz", request -> ServerResponse.ok().build()) + .build())) + .build(); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/foo/bar/baz"); + ServerRequest fooRequest = new DefaultServerRequest(servletRequest, emptyList()); + + Optional responseStatus = route.route(fooRequest) + .map(handlerFunction -> handle(handlerFunction, fooRequest)) + .map(ServerResponse::statusCode) + .map(HttpStatus::value); + assertEquals(200, responseStatus.get().intValue()); + } + + @Test + public void filters() { + AtomicInteger filterCount = new AtomicInteger(); + + RouterFunction route = RouterFunctions.route() + .GET("/foo", request -> ServerResponse.ok().build()) + .GET("/bar", request -> { + throw new IllegalStateException(); + }) + .before(request -> { + int count = filterCount.getAndIncrement(); + assertEquals(0, count); + return request; + }) + .after((request, response) -> { + int count = filterCount.getAndIncrement(); + assertEquals(3, count); + return response; + }) + .filter((request, next) -> { + int count = filterCount.getAndIncrement(); + assertEquals(1, count); + ServerResponse responseMono = next.handle(request); + count = filterCount.getAndIncrement(); + assertEquals(2, count); + return responseMono; + }) + .onError(IllegalStateException.class, + (e, request) -> ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR) + .build()) + .build(); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/foo"); + ServerRequest fooRequest = new DefaultServerRequest(servletRequest, emptyList()); + + Optional fooResponse = route.route(fooRequest) + .map(handlerFunction -> handle(handlerFunction, fooRequest)); + assertEquals(4, filterCount.get()); + + filterCount.set(0); + + servletRequest = new MockHttpServletRequest("GET", "/bar"); + ServerRequest barRequest = new DefaultServerRequest(servletRequest, emptyList()); + + Optional responseStatus = route.route(barRequest) + .map(handlerFunction -> handle(handlerFunction, barRequest)) + .map(ServerResponse::statusCode) + .map(HttpStatus::value); + assertEquals(500, responseStatus.get().intValue()); + } + +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RouterFunctionTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RouterFunctionTests.java new file mode 100644 index 000000000000..01ffcf6aa943 --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RouterFunctionTests.java @@ -0,0 +1,125 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * 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 org.springframework.web.servlet.function; + +import java.util.Optional; + +import org.junit.Test; + +import org.springframework.mock.web.test.MockHttpServletRequest; + +import static java.util.Collections.emptyList; +import static org.junit.Assert.*; + +/** + * @author Arjen Poutsma + */ +@SuppressWarnings("unchecked") +public class RouterFunctionTests { + + @Test + public void and() { + HandlerFunction handlerFunction = request -> ServerResponse.ok().build(); + RouterFunction routerFunction1 = request -> Optional.empty(); + RouterFunction routerFunction2 = request -> Optional.of(handlerFunction); + + RouterFunction result = routerFunction1.and(routerFunction2); + assertNotNull(result); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest(); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + + Optional> resultHandlerFunction = result.route(request); + assertTrue(resultHandlerFunction.isPresent()); + assertEquals(handlerFunction, resultHandlerFunction.get()); + } + + + @Test + public void andOther() { + HandlerFunction handlerFunction = request -> ServerResponse.ok().body("42"); + RouterFunction routerFunction1 = request -> Optional.empty(); + RouterFunction routerFunction2 = request -> Optional.of(handlerFunction); + + RouterFunction result = routerFunction1.andOther(routerFunction2); + assertNotNull(result); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest(); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + + Optional> resultHandlerFunction = result.route(request); + assertTrue(resultHandlerFunction.isPresent()); + assertEquals(handlerFunction, resultHandlerFunction.get()); + } + + + @Test + public void andRoute() { + RouterFunction routerFunction1 = request -> Optional.empty(); + RequestPredicate requestPredicate = request -> true; + + RouterFunction result = routerFunction1.andRoute(requestPredicate, this::handlerMethod); + assertNotNull(result); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest(); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + + Optional> resultHandlerFunction = result.route(request); + assertTrue(resultHandlerFunction.isPresent()); + } + + + @Test + public void filter() { + String string = "42"; + HandlerFunction> handlerFunction = + request -> EntityResponse.fromObject(string).build(); + RouterFunction> routerFunction = + request -> Optional.of(handlerFunction); + + HandlerFilterFunction, EntityResponse> filterFunction = + (request, next) -> { + String stringResponse = next.handle(request).entity(); + Integer intResponse = Integer.parseInt(stringResponse); + return EntityResponse.fromObject(intResponse).build(); + }; + + RouterFunction> result = routerFunction.filter(filterFunction); + assertNotNull(result); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest(); + ServerRequest request = new DefaultServerRequest(servletRequest, emptyList()); + + Optional> resultHandlerFunction = result.route(request) + .map(hf -> { + try { + return hf.handle(request); + } + catch (Exception e) { + fail(e.getMessage()); + return null; + } + }); + assertTrue(resultHandlerFunction.isPresent()); + assertEquals(42, (int)resultHandlerFunction.get().entity()); + } + + + private ServerResponse handlerMethod(ServerRequest request) { + return ServerResponse.ok().body("42"); + } +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RouterFunctionsTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RouterFunctionsTests.java new file mode 100644 index 000000000000..509bf3b53dbe --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/RouterFunctionsTests.java @@ -0,0 +1,104 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * 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 org.springframework.web.servlet.function; + +import java.util.Collections; +import java.util.Optional; + +import org.junit.Test; + +import org.springframework.mock.web.test.MockHttpServletRequest; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +/** + * @author Arjen Poutsma + */ +@SuppressWarnings("unchecked") +public class RouterFunctionsTests { + + @Test + public void routeMatch() { + HandlerFunction handlerFunction = request -> ServerResponse.ok().build(); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest(); + ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList()); + RequestPredicate requestPredicate = mock(RequestPredicate.class); + when(requestPredicate.test(request)).thenReturn(true); + + RouterFunction + result = RouterFunctions.route(requestPredicate, handlerFunction); + assertNotNull(result); + + Optional> resultHandlerFunction = result.route(request); + assertTrue(resultHandlerFunction.isPresent()); + assertEquals(handlerFunction, resultHandlerFunction.get()); + } + + @Test + public void routeNoMatch() { + HandlerFunction handlerFunction = request -> ServerResponse.ok().build(); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest(); + ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList()); + RequestPredicate requestPredicate = mock(RequestPredicate.class); + when(requestPredicate.test(request)).thenReturn(false); + + RouterFunction result = RouterFunctions.route(requestPredicate, handlerFunction); + assertNotNull(result); + + Optional> resultHandlerFunction = result.route(request); + assertFalse(resultHandlerFunction.isPresent()); + } + + @Test + public void nestMatch() { + HandlerFunction handlerFunction = request -> ServerResponse.ok().build(); + RouterFunction routerFunction = request -> Optional.of(handlerFunction); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest(); + ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList()); + RequestPredicate requestPredicate = mock(RequestPredicate.class); + when(requestPredicate.nest(request)).thenReturn(Optional.of(request)); + + RouterFunction result = RouterFunctions.nest(requestPredicate, routerFunction); + assertNotNull(result); + + Optional> resultHandlerFunction = result.route(request); + assertTrue(resultHandlerFunction.isPresent()); + assertEquals(handlerFunction, resultHandlerFunction.get()); + } + + @Test + public void nestNoMatch() { + HandlerFunction handlerFunction = request -> ServerResponse.ok().build(); + RouterFunction routerFunction = request -> Optional.of(handlerFunction); + + MockHttpServletRequest servletRequest = new MockHttpServletRequest(); + ServerRequest request = new DefaultServerRequest(servletRequest, Collections.emptyList()); + RequestPredicate requestPredicate = mock(RequestPredicate.class); + when(requestPredicate.nest(request)).thenReturn(Optional.empty()); + + RouterFunction result = RouterFunctions.nest(requestPredicate, routerFunction); + assertNotNull(result); + + Optional> resultHandlerFunction = result.route(request); + assertFalse(resultHandlerFunction.isPresent()); + } + +} diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/function/ToStringVisitorTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/ToStringVisitorTests.java new file mode 100644 index 000000000000..9ffa430f5a24 --- /dev/null +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/function/ToStringVisitorTests.java @@ -0,0 +1,113 @@ +/* + * Copyright 2002-2019 the original author or authors. + * + * 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 org.springframework.web.servlet.function; + +import org.junit.Test; + +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; + +import static org.junit.Assert.*; +import static org.springframework.web.servlet.function.RequestPredicates.GET; +import static org.springframework.web.servlet.function.RequestPredicates.accept; +import static org.springframework.web.servlet.function.RequestPredicates.contentType; +import static org.springframework.web.servlet.function.RequestPredicates.method; +import static org.springframework.web.servlet.function.RequestPredicates.methods; +import static org.springframework.web.servlet.function.RequestPredicates.param; +import static org.springframework.web.servlet.function.RequestPredicates.path; +import static org.springframework.web.servlet.function.RequestPredicates.pathExtension; +import static org.springframework.web.servlet.function.RouterFunctions.route; + +/** + * @author Arjen Poutsma + */ +public class ToStringVisitorTests { + + @Test + public void nested() { + HandlerFunction handler = new SimpleHandlerFunction(); + RouterFunction routerFunction = route() + .path("/foo", builder -> { + builder.path("/bar", () -> route() + .GET("/baz", handler) + .build()); + }) + .build(); + + ToStringVisitor visitor = new ToStringVisitor(); + routerFunction.accept(visitor); + String result = visitor.toString(); + + String expected = "/foo => {\n" + + " /bar => {\n" + + " (GET && /baz) -> \n" + + " }\n" + + "}"; + assertEquals(expected, result); + } + + @Test + public void predicates() { + testPredicate(methods(HttpMethod.GET), "GET"); + testPredicate(methods(HttpMethod.GET, HttpMethod.POST), "[GET, POST]"); + + testPredicate(path("/foo"), "/foo"); + + testPredicate(pathExtension("foo"), "*.foo"); + + testPredicate(contentType(MediaType.APPLICATION_JSON), "Content-Type: application/json"); + testPredicate(contentType(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN), "Content-Type: [application/json, text/plain]"); + + testPredicate(accept(MediaType.APPLICATION_JSON), "Accept: application/json"); + + testPredicate(param("foo", "bar"), "?foo == bar"); + + testPredicate(method(HttpMethod.GET).and(path("/foo")), "(GET && /foo)"); + + testPredicate(method(HttpMethod.GET).or(path("/foo")), "(GET || /foo)"); + + testPredicate(method(HttpMethod.GET).negate(), "!(GET)"); + + testPredicate(GET("/foo") + .or(contentType(MediaType.TEXT_PLAIN)) + .and(accept(MediaType.APPLICATION_JSON).negate()), + "(((GET && /foo) || Content-Type: text/plain) && !(Accept: application/json))"); + } + + private void testPredicate(RequestPredicate predicate, String expected) { + ToStringVisitor visitor = new ToStringVisitor(); + predicate.accept(visitor); + String result = visitor.toString(); + + assertEquals(expected, result); + } + + + private static class SimpleHandlerFunction implements HandlerFunction { + + @Override + public ServerResponse handle(ServerRequest request) { + return ServerResponse.ok().build(); + } + + @Override + public String toString() { + return ""; + } + } + +} diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/function/child/response.txt b/spring-webmvc/src/test/resources/org/springframework/web/servlet/function/child/response.txt new file mode 100644 index 000000000000..4888e525763d --- /dev/null +++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/function/child/response.txt @@ -0,0 +1,2 @@ +Hello World +This is a sample response text file. diff --git a/spring-webmvc/src/test/resources/org/springframework/web/servlet/function/response.txt b/spring-webmvc/src/test/resources/org/springframework/web/servlet/function/response.txt new file mode 100644 index 000000000000..4888e525763d --- /dev/null +++ b/spring-webmvc/src/test/resources/org/springframework/web/servlet/function/response.txt @@ -0,0 +1,2 @@ +Hello World +This is a sample response text file.