package test.r2.integ;
import com.linkedin.common.callback.Callback;
import com.linkedin.common.callback.FutureCallback;
import com.linkedin.common.util.None;
import com.linkedin.r2.message.RequestContext;
import com.linkedin.r2.message.rest.RestRequest;
import com.linkedin.r2.message.rest.RestResponse;
import com.linkedin.r2.message.rest.RestResponseBuilder;
import com.linkedin.r2.message.rest.RestStatus;
import com.linkedin.r2.message.stream.StreamException;
import com.linkedin.r2.message.stream.StreamRequest;
import com.linkedin.r2.message.stream.StreamRequestBuilder;
import com.linkedin.r2.message.stream.StreamResponse;
import com.linkedin.r2.message.stream.StreamResponseBuilder;
import com.linkedin.r2.message.stream.entitystream.DrainReader;
import com.linkedin.r2.message.stream.entitystream.EntityStreams;
import com.linkedin.r2.sample.Bootstrap;
import com.linkedin.r2.transport.common.Client;
import com.linkedin.r2.transport.common.TransportClientFactory;
import com.linkedin.r2.transport.common.bridge.client.TransportClientAdapter;
import com.linkedin.r2.transport.common.bridge.common.TransportCallback;
import com.linkedin.r2.transport.common.bridge.common.TransportResponseImpl;
import com.linkedin.r2.transport.common.bridge.server.TransportDispatcher;
import com.linkedin.r2.transport.http.client.HttpClientFactory;
import com.linkedin.r2.transport.http.common.HttpProtocolVersion;
import com.linkedin.r2.transport.http.server.HttpServer;
import com.linkedin.r2.transport.http.server.HttpServerFactory;
import junit.framework.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.io.IOException;
import java.net.URI;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author Zhenkai Zhu
*/
public class TestJetty404
{
protected static final int PORT = 8099;
protected HttpServer _server;
protected TransportClientFactory _clientFactory;
protected Client _client;
@BeforeClass
public void setup() throws IOException
{
_clientFactory = new HttpClientFactory();
_client = new TransportClientAdapter(_clientFactory.getClient(Collections.<String, String>emptyMap()), true);
_server = new HttpServerFactory().createH2cServer(PORT, "/correct-path", 50, new TransportDispatcher()
{
@Override
public void handleRestRequest(RestRequest req, Map<String, String> wireAttrs,
RequestContext requestContext, TransportCallback<RestResponse> callback)
{
callback.onResponse(TransportResponseImpl.success(new RestResponseBuilder().build()));
}
@Override
public void handleStreamRequest(StreamRequest req, Map<String, String> wireAttrs, RequestContext requestContext, TransportCallback<StreamResponse> callback)
{
req.getEntityStream().setReader(new DrainReader());
callback.onResponse(TransportResponseImpl.success(new StreamResponseBuilder().build(EntityStreams.emptyStream())));
}
}, true);
_server.start();
}
// make sure jetty's default behavior will read all the request bytes in case of 404
@Test
public void testJetty404() throws Exception
{
BytesWriter writer = new BytesWriter(200 * 1024, (byte)100);
final AtomicReference<Throwable> exRef = new AtomicReference<Throwable>();
final CountDownLatch latch = new CountDownLatch(1);
_client.streamRequest(new StreamRequestBuilder(Bootstrap.createHttpURI(PORT, URI.create("/wrong-path")))
.build(EntityStreams.newEntityStream(writer)), new Callback<StreamResponse>()
{
@Override
public void onError(Throwable e)
{
exRef.set(e);
latch.countDown();
}
@Override
public void onSuccess(StreamResponse result)
{
latch.countDown();
}
});
latch.await(5000, TimeUnit.MILLISECONDS);
Assert.assertTrue(writer.isDone());
Throwable ex = exRef.get();
Assert.assertTrue(ex instanceof StreamException);
StreamResponse response = ((StreamException) ex).getResponse();
Assert.assertEquals(response.getStatus(), RestStatus.NOT_FOUND);
response.getEntityStream().setReader(new DrainReader());
}
@AfterClass
public void tearDown() throws Exception
{
final FutureCallback<None> clientShutdownCallback = new FutureCallback<None>();
_client.shutdown(clientShutdownCallback);
clientShutdownCallback.get();
final FutureCallback<None> factoryShutdownCallback = new FutureCallback<None>();
_clientFactory.shutdown(factoryShutdownCallback);
factoryShutdownCallback.get();
if (_server != null) {
_server.stop();
_server.waitForStop();
}
}
}