233 lines
8.9 KiB
Java
233 lines
8.9 KiB
Java
package controllers;
|
|
|
|
import static java.time.temporal.ChronoUnit.SECONDS;
|
|
import static org.junit.Assert.assertEquals;
|
|
import static play.mvc.Http.Status.SERVICE_UNAVAILABLE;
|
|
|
|
import akka.Done;
|
|
import akka.actor.ActorSystem;
|
|
import akka.stream.ActorMaterializer;
|
|
import akka.stream.javadsl.Sink;
|
|
import akka.util.ByteString;
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.time.Duration;
|
|
import java.util.OptionalInt;
|
|
import java.util.concurrent.CompletionStage;
|
|
import java.util.concurrent.CountDownLatch;
|
|
import java.util.concurrent.ExecutionException;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.TimeoutException;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
import java.util.stream.IntStream;
|
|
import org.apache.http.HttpStatus;
|
|
import org.junit.Before;
|
|
import org.junit.Test;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import play.Application;
|
|
import play.inject.guice.GuiceApplicationBuilder;
|
|
import play.libs.concurrent.Futures;
|
|
import play.libs.ws.WSClient;
|
|
import play.libs.ws.WSResponse;
|
|
import play.libs.ws.ahc.AhcCurlRequestLogger;
|
|
import play.mvc.Result;
|
|
import play.mvc.Results;
|
|
import play.test.WithServer;
|
|
|
|
public class HomeControllerTest extends WithServer {
|
|
|
|
private final Logger log = LoggerFactory.getLogger(HomeControllerTest.class);
|
|
private String url;
|
|
private int port;
|
|
|
|
@Override
|
|
protected Application provideApplication() {
|
|
return new GuiceApplicationBuilder().build();
|
|
}
|
|
|
|
@Before
|
|
public void setup() {
|
|
OptionalInt optHttpsPort = testServer.getRunningHttpsPort();
|
|
if (optHttpsPort.isPresent()) {
|
|
port = optHttpsPort.getAsInt();
|
|
url = "https://localhost:" + port;
|
|
} else {
|
|
port = testServer.getRunningHttpPort()
|
|
.getAsInt();
|
|
url = "http://localhost:" + port;
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void givenASingleGetRequestWhenResponseThenBlockWithCompletableAndLog()
|
|
throws Exception {
|
|
WSClient ws = play.test.WSTestClient.newClient(port);
|
|
WSResponse wsResponse = ws.url(url)
|
|
.setRequestFilter(new AhcCurlRequestLogger())
|
|
.addHeader("key", "value")
|
|
.addQueryParameter("num", "" + 1)
|
|
.get()
|
|
.toCompletableFuture()
|
|
.get();
|
|
|
|
log.debug("Thread#" + Thread.currentThread()
|
|
.getId() + " Request complete: Response code = "
|
|
+ wsResponse.getStatus()
|
|
+ " | Response: " + wsResponse.getBody() + " | Current Time:"
|
|
+ System.currentTimeMillis());
|
|
assert (HttpStatus.SC_OK == wsResponse.getStatus());
|
|
}
|
|
|
|
@Test
|
|
public void givenASingleGetRequestWhenResponseThenLog() throws Exception {
|
|
CountDownLatch latch = new CountDownLatch(1);
|
|
WSClient ws = play.test.WSTestClient.newClient(port);
|
|
ws.url(url)
|
|
.setRequestFilter(new AhcCurlRequestLogger())
|
|
.addHeader("key", "value")
|
|
.addQueryParameter("num", "" + 1)
|
|
.get()
|
|
.thenAccept(r -> {
|
|
log.debug("Thread#" + Thread.currentThread()
|
|
.getId() + " Request complete: Response code = "
|
|
+ r.getStatus()
|
|
+ " | Response: " + r.getBody() + " | Current Time:" + System.currentTimeMillis());
|
|
latch.countDown();
|
|
});
|
|
|
|
log.debug(
|
|
"Waiting for requests to be completed. Current Time: " + System.currentTimeMillis());
|
|
latch.await(5, TimeUnit.SECONDS );
|
|
assertEquals(0, latch.getCount());
|
|
log.debug("All requests have been completed. Exiting test.");
|
|
}
|
|
|
|
@Test
|
|
public void givenASinglePostRequestWhenResponseThenLog() throws Exception {
|
|
CountDownLatch latch = new CountDownLatch(1);
|
|
WSClient ws = play.test.WSTestClient.newClient(port);
|
|
ws.url(url)
|
|
.setContentType("application/x-www-form-urlencoded")
|
|
.post("key1=value1&key2=value2")
|
|
.thenAccept(r -> {
|
|
log.debug("Thread#" + Thread.currentThread()
|
|
.getId() + " Request complete: Response code = "
|
|
+ r.getStatus()
|
|
+ " | Response: " + r.getBody() + " | Current Time:" + System.currentTimeMillis());
|
|
latch.countDown();
|
|
});
|
|
|
|
log.debug(
|
|
"Waiting for requests to be completed. Current Time: " + System.currentTimeMillis());
|
|
latch.await(5, TimeUnit.SECONDS );
|
|
assertEquals(0, latch.getCount());
|
|
log.debug("All requests have been completed. Exiting test.");
|
|
}
|
|
|
|
@Test
|
|
public void givenMultipleRequestsWhenResponseThenLog() throws Exception {
|
|
CountDownLatch latch = new CountDownLatch(100);
|
|
WSClient ws = play.test.WSTestClient.newClient(port);
|
|
IntStream.range(0, 100)
|
|
.parallel()
|
|
.forEach(num ->
|
|
ws.url(url)
|
|
.setRequestFilter(new AhcCurlRequestLogger())
|
|
.addHeader("key", "value")
|
|
.addQueryParameter("num", "" + num)
|
|
.get()
|
|
.thenAccept(r -> {
|
|
log.debug(
|
|
"Thread#" + num + " Request complete: Response code = " + r.getStatus()
|
|
+ " | Response: " + r.getBody() + " | Current Time:"
|
|
+ System.currentTimeMillis());
|
|
latch.countDown();
|
|
})
|
|
);
|
|
|
|
log.debug(
|
|
"Waiting for requests to be completed. Current Time: " + System.currentTimeMillis());
|
|
latch.await(5, TimeUnit.SECONDS );
|
|
assertEquals(0, latch.getCount());
|
|
log.debug("All requests have been completed. Exiting test.");
|
|
}
|
|
|
|
@Test
|
|
public void givenLongResponseWhenTimeoutThenHandle() throws Exception {
|
|
CountDownLatch latch = new CountDownLatch(1);
|
|
WSClient ws = play.test.WSTestClient.newClient(port);
|
|
Futures futures = app.injector()
|
|
.instanceOf(Futures.class);
|
|
CompletionStage<Result> f = futures.timeout(
|
|
ws.url(url)
|
|
.setRequestTimeout(Duration.of(1, SECONDS))
|
|
.get()
|
|
.thenApply(result -> {
|
|
try {
|
|
Thread.sleep(2000L);
|
|
return Results.ok();
|
|
} catch (InterruptedException e) {
|
|
return Results.status(
|
|
SERVICE_UNAVAILABLE);
|
|
}
|
|
}), 1L, TimeUnit.SECONDS
|
|
);
|
|
CompletionStage<Object> res = f.handleAsync((result, e) -> {
|
|
if (e != null) {
|
|
log.error("Exception thrown", e);
|
|
latch.countDown();
|
|
return e.getCause();
|
|
} else {
|
|
return result;
|
|
}
|
|
});
|
|
res.thenAccept(result -> assertEquals(TimeoutException.class, result));
|
|
|
|
log.debug(
|
|
"Waiting for requests to be completed. Current Time: " + System.currentTimeMillis());
|
|
latch.await(5, TimeUnit.SECONDS );
|
|
assertEquals(0, latch.getCount());
|
|
log.debug("All requests have been completed. Exiting test.");
|
|
}
|
|
|
|
@Test
|
|
public void givenMultigigabyteResponseConsumeWithStreams() throws Exception {
|
|
CountDownLatch latch = new CountDownLatch(1);
|
|
final ActorSystem system = ActorSystem.create();
|
|
final ActorMaterializer materializer = ActorMaterializer.create(system);
|
|
final Path path = Files.createTempFile("tmp_", ".out");
|
|
|
|
WSClient ws = play.test.WSTestClient.newClient(port);
|
|
log.info("Starting test server on url: " + url);
|
|
ws.url(url)
|
|
.stream()
|
|
.thenAccept(
|
|
response -> {
|
|
try {
|
|
OutputStream outputStream = java.nio.file.Files.newOutputStream(path);
|
|
Sink<ByteString, CompletionStage<Done>> outputWriter =
|
|
Sink.foreach(bytes -> {
|
|
log.info("Reponse: " + bytes.utf8String());
|
|
outputStream.write(bytes.toArray());
|
|
});
|
|
|
|
response.getBodyAsSource()
|
|
.runWith(outputWriter, materializer);
|
|
|
|
} catch (IOException e) {
|
|
log.error("An error happened while opening the output stream", e);
|
|
}
|
|
})
|
|
.whenComplete((value, error) -> latch.countDown());
|
|
|
|
log.debug(
|
|
"Waiting for requests to be completed. Current Time: " + System.currentTimeMillis());
|
|
latch.await(5, TimeUnit.SECONDS );
|
|
assertEquals(0, latch.getCount());
|
|
log.debug("All requests have been completed. Exiting test.");
|
|
}
|
|
}
|