// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.jdisc.handler;
import com.google.common.util.concurrent.MoreExecutors;
import com.yahoo.jdisc.Request;
import com.yahoo.jdisc.Response;
import com.yahoo.jdisc.application.ContainerBuilder;
import com.yahoo.jdisc.test.TestDriver;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
/**
* @author Simon Thoresen Hult
*/
public class RequestDispatchTestCase {
@Test
public void requireThatRequestCanBeDispatched() throws Exception {
final TestDriver driver = TestDriver.newSimpleApplicationInstanceWithoutOsgi();
final List writtenContent = Arrays.asList(ByteBuffer.allocate(6), ByteBuffer.allocate(9));
ReadableContentChannel receivedContent = new ReadableContentChannel();
ContainerBuilder builder = driver.newContainerBuilder();
Response response = new Response(Response.Status.OK);
builder.serverBindings().bind("http://localhost/", new MyRequestHandler(receivedContent, response));
driver.activateContainer(builder);
RequestDispatch dispatch = new RequestDispatch() {
@Override
protected Request newRequest() {
return new Request(driver, URI.create("http://localhost/"));
}
@Override
protected Iterable requestContent() {
return writtenContent;
}
};
dispatch.dispatch();
assertFalse(dispatch.isDone());
assertSame(writtenContent.get(0), receivedContent.read());
assertFalse(dispatch.isDone());
assertSame(writtenContent.get(1), receivedContent.read());
assertFalse(dispatch.isDone());
assertNull(receivedContent.read());
assertTrue(dispatch.isDone());
assertSame(response, dispatch.get(600, TimeUnit.SECONDS));
assertTrue(driver.close());
}
@Test
public void requireThatStreamCanBeConnected() throws IOException {
TestDriver driver = TestDriver.newSimpleApplicationInstanceWithoutOsgi();
ContainerBuilder builder = driver.newContainerBuilder();
ReadableContentChannel content = new ReadableContentChannel();
MyRequestHandler requestHandler = new MyRequestHandler(content, new Response(Response.Status.OK));
builder.serverBindings().bind("http://localhost/", requestHandler);
driver.activateContainer(builder);
OutputStream out = new FastContentOutputStream(driver.newRequestDispatch("http://localhost/", new FutureResponse()).connect());
out.write(6);
out.write(9);
out.close();
InputStream in = content.toStream();
assertEquals(6, in.read());
assertEquals(9, in.read());
assertEquals(-1, in.read());
assertTrue(driver.close());
}
@Test
public void requireThatCancelIsUnsupported() {
TestDriver driver = TestDriver.newSimpleApplicationInstanceWithoutOsgi();
RequestDispatch dispatch = driver.newRequestDispatch("http://localhost/", new FutureResponse());
assertFalse(dispatch.isCancelled());
try {
dispatch.cancel(true);
fail();
} catch (UnsupportedOperationException e) {
}
assertFalse(dispatch.isCancelled());
try {
dispatch.cancel(false);
fail();
} catch (UnsupportedOperationException e) {
}
assertFalse(dispatch.isCancelled());
assertTrue(driver.close());
}
@Test
public void requireThatDispatchHandlesConnectException() {
TestDriver driver = TestDriver.newSimpleApplicationInstanceWithoutOsgi();
ContainerBuilder builder = driver.newContainerBuilder();
builder.serverBindings().bind("http://localhost/", new AbstractRequestHandler() {
@Override
public ContentChannel handleRequest(Request request, ResponseHandler handler) {
throw new RuntimeException();
}
});
driver.activateContainer(builder);
try {
driver.newRequestDispatch("http://localhost/", new FutureResponse()).dispatch();
fail();
} catch (RuntimeException e) {
}
assertTrue(driver.close());
}
@Test
public void requireThatDispatchHandlesWriteException() {
final TestDriver driver = TestDriver.newSimpleApplicationInstanceWithoutOsgi();
ContainerBuilder builder = driver.newContainerBuilder();
Response response = new Response(Response.Status.OK);
builder.serverBindings().bind("http://localhost/", new MyRequestHandler(new ContentChannel() {
@Override
public void write(ByteBuffer buf, CompletionHandler handler) {
throw new RuntimeException();
}
@Override
public void close(CompletionHandler handler) {
handler.completed();
}
}, response));
driver.activateContainer(builder);
try {
new RequestDispatch() {
@Override
protected Request newRequest() {
return new Request(driver, URI.create("http://localhost/"));
}
@Override
protected Iterable requestContent() {
return Arrays.asList(ByteBuffer.allocate(69));
}
}.dispatch();
fail();
} catch (RuntimeException e) {
}
assertTrue(driver.close());
}
@Test
public void requireThatDispatchHandlesCloseException() {
final TestDriver driver = TestDriver.newSimpleApplicationInstanceWithoutOsgi();
ContainerBuilder builder = driver.newContainerBuilder();
Response response = new Response(Response.Status.OK);
builder.serverBindings().bind("http://localhost/", new MyRequestHandler(new ContentChannel() {
@Override
public void write(ByteBuffer buf, CompletionHandler handler) {
handler.completed();
}
@Override
public void close(CompletionHandler handler) {
throw new RuntimeException();
}
}, response));
driver.activateContainer(builder);
try {
new RequestDispatch() {
@Override
protected Request newRequest() {
return new Request(driver, URI.create("http://localhost/"));
}
@Override
protected Iterable requestContent() {
return Arrays.asList(ByteBuffer.allocate(69));
}
}.dispatch();
fail();
} catch (RuntimeException e) {
}
assertTrue(driver.close());
}
@Test
public void requireThatDispatchCanBeListenedTo() throws InterruptedException {
final TestDriver driver = TestDriver.newSimpleApplicationInstanceWithoutOsgi();
ContainerBuilder builder = driver.newContainerBuilder();
ReadableContentChannel requestContent = new ReadableContentChannel();
MyRequestHandler requestHandler = new MyRequestHandler(requestContent, null);
builder.serverBindings().bind("http://localhost/", requestHandler);
driver.activateContainer(builder);
RunnableLatch listener = new RunnableLatch();
new RequestDispatch() {
@Override
protected Request newRequest() {
return new Request(driver, URI.create("http://localhost/"));
}
}.dispatch().addListener(listener, MoreExecutors.directExecutor());
assertFalse(listener.await(100, TimeUnit.MILLISECONDS));
ContentChannel responseContent = ResponseDispatch.newInstance(Response.Status.OK)
.connect(requestHandler.responseHandler);
assertFalse(listener.await(100, TimeUnit.MILLISECONDS));
assertNull(requestContent.read());
assertTrue(listener.await(600, TimeUnit.SECONDS));
responseContent.close(null);
assertTrue(driver.close());
}
private static class MyRequestHandler extends AbstractRequestHandler {
final ContentChannel content;
final Response response;
ResponseHandler responseHandler;
MyRequestHandler(ContentChannel content, Response response) {
this.content = content;
this.response = response;
}
@Override
public ContentChannel handleRequest(Request request, ResponseHandler handler) {
if (response != null) {
ResponseDispatch.newInstance(response).dispatch(handler);
} else {
responseHandler = handler;
}
return content;
}
}
}