diff --git a/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/EchoHandler.java b/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/EchoHandler.java deleted file mode 100644 index b5bf612848..0000000000 --- a/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/EchoHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2002-2015 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.http.server.reactive; - -import reactor.core.publisher.Mono; - -/** - * @author Arjen Poutsma - */ -public class EchoHandler implements HttpHandler { - - @Override - public Mono handle(ServerHttpRequest request, ServerHttpResponse response) { - return response.setBody(request.getBody()); - } -} diff --git a/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/EchoHandlerIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/EchoHandlerIntegrationTests.java index 5a27960114..00c030795e 100644 --- a/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/EchoHandlerIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/EchoHandlerIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -20,13 +20,13 @@ import java.net.URI; import java.util.Random; import org.junit.Test; +import reactor.core.publisher.Mono; import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; public class EchoHandlerIntegrationTests extends AbstractHttpHandlerIntegrationTests { @@ -43,7 +43,7 @@ public class EchoHandlerIntegrationTests extends AbstractHttpHandlerIntegrationT @Test - public void echoBytes() throws Exception { + public void echo() throws Exception { RestTemplate restTemplate = new RestTemplate(); byte[] body = randomBytes(); @@ -53,36 +53,6 @@ public class EchoHandlerIntegrationTests extends AbstractHttpHandlerIntegrationT assertArrayEquals(body, response.getBody()); } - @Test - public void echoString() throws Exception { - RestTemplate restTemplate = new RestTemplate(); - - String body = randomString(); - RequestEntity request = RequestEntity.post(new URI("http://localhost:" + port)).body(body); - ResponseEntity response = restTemplate.exchange(request, String.class); - - assertEquals(body, response.getBody()); - } - - private String randomString() { - StringBuilder builder = new StringBuilder(); - int i = 1; - while (builder.length() < REQUEST_SIZE) { - builder.append(randomChar()); - if (i % 5 == 0) { - builder.append(' '); - } - if (i % 80 == 0) { - builder.append('\n'); - } - i++; - } - return builder.toString(); - } - - private char randomChar() { - return (char) (rnd.nextInt(26) + 'a'); - } private byte[] randomBytes() { byte[] buffer = new byte[REQUEST_SIZE]; @@ -90,4 +60,14 @@ public class EchoHandlerIntegrationTests extends AbstractHttpHandlerIntegrationT return buffer; } + /** + * @author Arjen Poutsma + */ + public static class EchoHandler implements HttpHandler { + + @Override + public Mono handle(ServerHttpRequest request, ServerHttpResponse response) { + return response.setBody(request.getBody()); + } + } } diff --git a/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/RandomHandler.java b/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/RandomHandler.java deleted file mode 100644 index 14b17ec1c2..0000000000 --- a/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/RandomHandler.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2002-2016 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.http.server.reactive; - -import java.util.Random; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import reactor.core.publisher.Mono; - -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DefaultDataBufferAllocator; - -import static org.junit.Assert.assertEquals; - -/** - * @author Arjen Poutsma - */ -public class RandomHandler implements HttpHandler { - - private static final Log logger = LogFactory.getLog(RandomHandler.class); - - public static final int RESPONSE_SIZE = 4096 * 3; - - private final Random rnd = new Random(); - - @Override - public Mono handle(ServerHttpRequest request, ServerHttpResponse response) { - - request.getBody().subscribe(new Subscriber() { - private Subscription s; - - private int requestSize = 0; - - @Override - public void onSubscribe(Subscription s) { - this.s = s; - s.request(Long.MAX_VALUE); - } - - @Override - public void onNext(DataBuffer bytes) { - requestSize += bytes.readableByteCount(); - } - - @Override - public void onError(Throwable t) { - logger.error(t); - - } - - @Override - public void onComplete() { - logger.debug("Complete"); - assertEquals(RandomHandlerIntegrationTests.REQUEST_SIZE, requestSize); - } - }); - - response.getHeaders().setContentLength(RESPONSE_SIZE); - byte[] randomBytes = randomBytes(); - DataBuffer buffer = - new DefaultDataBufferAllocator().allocateBuffer(randomBytes.length); - buffer.write(randomBytes); - return response.setBody(Mono.just(buffer)); - } - - private byte[] randomBytes() { - byte[] buffer = new byte[RESPONSE_SIZE]; - rnd.nextBytes(buffer); - return buffer; - } - -} diff --git a/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/RandomHandlerIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/RandomHandlerIntegrationTests.java index d7925d3ca0..7e92d620df 100644 --- a/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/RandomHandlerIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/RandomHandlerIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -20,29 +20,48 @@ import java.net.URI; import java.util.Random; import org.junit.Test; +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferAllocator; +import org.springframework.core.io.buffer.DefaultDataBufferAllocator; import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; +import org.springframework.http.server.reactive.boot.ReactorHttpServer; import org.springframework.web.client.RestTemplate; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assume.assumeFalse; public class RandomHandlerIntegrationTests extends AbstractHttpHandlerIntegrationTests { public static final int REQUEST_SIZE = 4096 * 3; - private Random rnd = new Random(); + public static final int RESPONSE_SIZE = 1024 * 4; + + private final Random rnd = new Random(); + + private final RandomHandler handler = new RandomHandler(); + + private final DataBufferAllocator allocator = new DefaultDataBufferAllocator(); @Override protected RandomHandler createHttpHandler() { - return new RandomHandler(); + return handler; } @Test - public void random() throws Exception { + public void random() throws Throwable { + // TODO: fix Reactor support + assumeFalse(server instanceof ReactorHttpServer); + RestTemplate restTemplate = new RestTemplate(); byte[] body = randomBytes(); @@ -50,9 +69,17 @@ public class RandomHandlerIntegrationTests extends AbstractHttpHandlerIntegratio ResponseEntity response = restTemplate.exchange(request, byte[].class); assertNotNull(response.getBody()); - assertEquals(RandomHandler.RESPONSE_SIZE, + assertEquals(RESPONSE_SIZE, response.getHeaders().getContentLength()); - assertEquals(RandomHandler.RESPONSE_SIZE, response.getBody().length); + assertEquals(RESPONSE_SIZE, response.getBody().length); + + while (!handler.requestComplete) { + Thread.sleep(100); + } + if (handler.requestError != null) { + throw handler.requestError; + } + assertEquals(REQUEST_SIZE, handler.requestSize); } @@ -62,4 +89,67 @@ public class RandomHandlerIntegrationTests extends AbstractHttpHandlerIntegratio return buffer; } + private class RandomHandler implements HttpHandler { + + public static final int CHUNKS = 16; + + private volatile boolean requestComplete; + + private int requestSize; + + private Throwable requestError; + + @Override + public Mono handle(ServerHttpRequest request, ServerHttpResponse response) { + requestError = null; + + request.getBody().subscribe(new Subscriber() { + + @Override + public void onSubscribe(Subscription s) { + requestComplete = false; + requestSize = 0; + requestError = null; + s.request(Long.MAX_VALUE); + } + + @Override + public void onNext(DataBuffer bytes) { + requestSize += bytes.readableByteCount(); + } + + @Override + public void onError(Throwable t) { + requestComplete = true; + requestError = t; + } + + @Override + public void onComplete() { + requestComplete = true; + } + }); + + response.getHeaders().setContentLength(RESPONSE_SIZE); + return response.setBody(multipleChunks()); + } + + private Publisher singleChunk() { + return Mono.just(randomBuffer(RESPONSE_SIZE)); + } + + private Publisher multipleChunks() { + int chunkSize = RESPONSE_SIZE / CHUNKS; + return Flux.range(1, CHUNKS).map(integer -> randomBuffer(chunkSize)); + } + + private DataBuffer randomBuffer(int size) { + byte[] bytes = new byte[size]; + rnd.nextBytes(bytes); + DataBuffer buffer = allocator.allocateBuffer(size); + buffer.write(bytes); + return buffer; + } + + } } diff --git a/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/XmlHandler.java b/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/XmlHandler.java deleted file mode 100644 index 3b72aed9d9..0000000000 --- a/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/XmlHandler.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2002-2016 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.http.server.reactive; - -import java.io.InputStream; -import java.io.OutputStream; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.Marshaller; -import javax.xml.bind.Unmarshaller; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import org.springframework.core.io.buffer.DataBuffer; -import org.springframework.core.io.buffer.DefaultDataBufferAllocator; -import org.springframework.core.io.buffer.support.DataBufferUtils; -import org.springframework.http.MediaType; - -import static org.junit.Assert.fail; - -/** - * @author Arjen Poutsma - */ -public class XmlHandler implements HttpHandler { - - private static final Log logger = LogFactory.getLog(XmlHandler.class); - - @Override - public Mono handle(ServerHttpRequest request, - ServerHttpResponse response) { - try { - JAXBContext jaxbContext = JAXBContext.newInstance(XmlHandlerIntegrationTests.Person.class); - Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - Marshaller marshaller = jaxbContext.createMarshaller(); - - Runnable r = () -> { - try { - InputStream bis = DataBufferUtils.toInputStream(request.getBody()); - - XmlHandlerIntegrationTests.Person johnDoe = - (XmlHandlerIntegrationTests.Person) unmarshaller.unmarshal(bis); - - logger.info("Read: " + johnDoe); - - } - catch (Exception e) { - logger.error(e, e); - } - }; - - Thread t = new Thread(r); - t.start(); - - response.getHeaders().setContentType(MediaType.APPLICATION_XML); - XmlHandlerIntegrationTests.Person janeDoe = new XmlHandlerIntegrationTests.Person("Jane Doe"); - - DataBuffer buffer = new DefaultDataBufferAllocator().allocateBuffer(); - OutputStream bos = buffer.asOutputStream(); - marshaller.marshal(janeDoe, bos); - bos.close(); - - return response.setBody(Flux.just(buffer)); - } - catch (Exception ex) { - logger.error(ex, ex); - fail(ex.getMessage()); - return null; - } - } -} diff --git a/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/XmlHandlerIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/XmlHandlerIntegrationTests.java index c805886bf1..b286a8273b 100644 --- a/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/XmlHandlerIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/http/server/reactive/XmlHandlerIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -16,39 +16,123 @@ package org.springframework.http.server.reactive; +import java.io.InputStream; +import java.io.OutputStream; import java.net.URI; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.Marshaller; +import javax.xml.bind.Unmarshaller; import javax.xml.bind.annotation.XmlRootElement; import org.junit.Test; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DefaultDataBufferAllocator; +import org.springframework.core.io.buffer.support.DataBufferUtils; +import org.springframework.http.MediaType; import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; +import org.springframework.http.server.reactive.boot.ReactorHttpServer; +import org.springframework.http.server.reactive.boot.RxNettyHttpServer; import org.springframework.web.client.RestTemplate; +import static org.junit.Assert.assertEquals; +import static org.junit.Assume.assumeFalse; + /** * @author Arjen Poutsma */ public class XmlHandlerIntegrationTests extends AbstractHttpHandlerIntegrationTests { + private final XmlHandler handler = new XmlHandler(); + @Override protected HttpHandler createHttpHandler() { - return new XmlHandler(); + return handler; } @Test public void xml() throws Exception { + // TODO: fix Reactor and RxNetty support + assumeFalse(server instanceof ReactorHttpServer || + server instanceof RxNettyHttpServer); + RestTemplate restTemplate = new RestTemplate(); Person johnDoe = new Person("John Doe"); + Person janeDoe = new Person("Jane Doe"); RequestEntity request = RequestEntity.post(new URI("http://localhost:" + port)).body( johnDoe); ResponseEntity response = restTemplate.exchange(request, Person.class); - System.out.println(response.getBody()); + assertEquals(janeDoe, response.getBody()); + + while (!handler.requestComplete) { + Thread.sleep(100); + } + if (handler.requestError != null) { + throw handler.requestError; + } + assertEquals(johnDoe, handler.requestPerson); + + } + + private static class XmlHandler implements HttpHandler { + + private volatile boolean requestComplete = false; + + private Person requestPerson; + + private Exception requestError; + + + @Override + public Mono handle(ServerHttpRequest request, ServerHttpResponse response) { + requestError = null; + try { + JAXBContext jaxbContext = JAXBContext.newInstance(Person.class); + Marshaller marshaller = jaxbContext.createMarshaller(); + + Runnable r = () -> { + try { + InputStream bis = + DataBufferUtils.toInputStream(request.getBody()); + + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + requestPerson = (Person) unmarshaller.unmarshal(bis); + + } + catch (Exception ex) { + requestError = ex; + } + finally { + requestComplete = true; + } + }; + + Thread t = new Thread(r); + t.start(); + + response.getHeaders().setContentType(MediaType.APPLICATION_XML); + Person janeDoe = new Person("Jane Doe"); + + DataBuffer buffer = new DefaultDataBufferAllocator().allocateBuffer(); + OutputStream bos = buffer.asOutputStream(); + marshaller.marshal(janeDoe, bos); + bos.close(); + + return response.setBody(Flux.just(buffer)); + } + catch (Exception ex) { + return Mono.error(ex); + } + } } @XmlRootElement - static class Person { + private static class Person { private String name; @@ -82,4 +166,5 @@ public class XmlHandlerIntegrationTests extends AbstractHttpHandlerIntegrationTe return name; } } + } diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/method/annotation/RequestMappingIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/method/annotation/RequestMappingIntegrationTests.java index bd75c45429..250dcc6645 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/method/annotation/RequestMappingIntegrationTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/method/annotation/RequestMappingIntegrationTests.java @@ -25,7 +25,6 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; -import org.junit.Ignore; import org.junit.Test; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; @@ -170,8 +169,6 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati } @Test - @Ignore - //FIXME Fail with Jetty and Tomcat public void streamResult() throws Exception { RestTemplate restTemplate = new RestTemplate(); @@ -468,7 +465,13 @@ public class RequestMappingIntegrationTests extends AbstractHttpHandlerIntegrati @RequestMapping("/stream-result") public Publisher stringStreamResponseBody() { - return Flux.interval(Duration.ofMillis(100)).take(5); + /* + TODO: replace the following line with: + return Flux.interval(Duration.ofMillis(100)).take(5); + to make the build last shorter. Unfortunately, this hangs the build as of + 20160317. + */ + return Flux.interval(Duration.ofSeconds(1)).take(5); } @RequestMapping("/raw-flux")