use of com.linkedin.r2.testutils.server.HttpServerBuilder in project rest.li by linkedin.
the class TestHttpNettyStreamClient method testSlowReaderTimeout.
/**
* Tests slow EntityStream {@link Reader} implementation should be subject to streaming timeout even
* if the entire response entity can be buffered in memory.
*
* @throws Exception
*/
@Test(dataProvider = "slowReaderTimeoutClientProvider")
public void testSlowReaderTimeout(AbstractNettyStreamClient client) throws Exception {
// Sets the response size to be greater than zero but smaller than the in-memory buffer for HTTP/1.1
// and smaller than the receiving window size for HTTP/2 so the receiver will not block sender
Server server = new HttpServerBuilder().responseSize(R2Constants.DEFAULT_DATA_CHUNK_SIZE).build();
StreamRequest request = new StreamRequestBuilder(new URI(URL)).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.emptyStream());
final CountDownLatch responseLatch = new CountDownLatch(1);
final CountDownLatch streamLatch = new CountDownLatch(1);
final AtomicReference<TransportResponse<StreamResponse>> atomicTransportResponse = new AtomicReference<>();
final AtomicReference<Throwable> atomicThrowable = new AtomicReference<>();
try {
server.start();
client.streamRequest(request, new RequestContext(), new HashMap<>(), response -> {
atomicTransportResponse.set(response);
responseLatch.countDown();
// Sets a reader that does not consume any byte
response.getResponse().getEntityStream().setReader(new Reader() {
@Override
public void onInit(ReadHandle rh) {
}
@Override
public void onDataAvailable(ByteString data) {
}
@Override
public void onDone() {
}
@Override
public void onError(Throwable e) {
atomicThrowable.set(e);
streamLatch.countDown();
}
});
});
} finally {
responseLatch.await(5, TimeUnit.SECONDS);
streamLatch.await(5, TimeUnit.SECONDS);
server.stop();
}
TransportResponse<StreamResponse> transportResponse = atomicTransportResponse.get();
Assert.assertNotNull(transportResponse, "Expected to receive a response");
Assert.assertFalse(transportResponse.hasError(), "Expected to receive a response without error");
Assert.assertNotNull(transportResponse.getResponse());
Assert.assertNotNull(transportResponse.getResponse().getEntityStream());
Throwable throwable = atomicThrowable.get();
Assert.assertNotNull(throwable, "Expected onError invoked with TimeoutException");
Assert.assertTrue(throwable instanceof RemoteInvocationException);
Assert.assertNotNull(throwable.getCause());
Assert.assertTrue(throwable.getCause() instanceof TimeoutException);
}
use of com.linkedin.r2.testutils.server.HttpServerBuilder in project rest.li by linkedin.
the class TestHttp2NettyStreamClient method testChannelReusedAfterStreamingTimeout.
/**
* When a request fails due to {@link TimeoutException}, connection should not be destroyed.
* @throws Exception
*/
@Test(timeOut = TEST_TIMEOUT, retryAnalyzer = SingleRetry.class)
public void testChannelReusedAfterStreamingTimeout() throws Exception {
final HttpServerBuilder.HttpServerStatsProvider statsProvider = new HttpServerBuilder.HttpServerStatsProvider();
final HttpServerBuilder serverBuilder = new HttpServerBuilder();
final Server server = serverBuilder.serverStatsProvider(statsProvider).stopTimeout(0).build();
final HttpClientBuilder clientBuilder = new HttpClientBuilder(_eventLoop, _scheduler);
final Http2NettyStreamClient client = clientBuilder.setRequestTimeout(1000).buildHttp2StreamClient();
final TransportResponse<StreamResponse> response1;
final TransportResponse<StreamResponse> response2;
try {
server.start();
final StreamRequestBuilder builder1 = new StreamRequestBuilder(new URI(URL));
final StreamRequest request1 = builder1.setMethod(METHOD).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new ByteStringWriter(ByteString.copy(new byte[REQUEST_SIZE]))));
final FutureTransportCallback<StreamResponse> callback1 = new FutureTransportCallback<>();
client.streamRequest(request1, new RequestContext(), new HashMap<>(), callback1);
response1 = callback1.get();
Assert.assertNotNull(response1);
Assert.assertFalse(response1.hasError());
response1.getResponse().getEntityStream().setReader(new TimeoutReader());
final StreamRequestBuilder builder2 = new StreamRequestBuilder(new URI(URL));
final StreamRequest request2 = builder2.setMethod(METHOD).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new ByteStringWriter(ByteString.copy(new byte[REQUEST_SIZE]))));
final FutureTransportCallback<StreamResponse> callback2 = new FutureTransportCallback<>();
client.streamRequest(request2, new RequestContext(), new HashMap<>(), callback2);
response2 = callback2.get();
} finally {
server.stop();
}
// The 2nd request should succeed
Assert.assertNotNull(response2);
Assert.assertFalse(response2.hasError());
response2.getResponse().getEntityStream().setReader(new DrainReader());
// The server should have seen 3 requests but establishes only 1 connection with the client
Assert.assertEquals(statsProvider.requestCount(), 3);
Assert.assertEquals(statsProvider.clientConnections().size(), 1);
}
use of com.linkedin.r2.testutils.server.HttpServerBuilder in project rest.li by linkedin.
the class TestHttp2NettyStreamClient method testMaxConcurrentStreamExhaustion.
/**
* When the maximum number of concurrent streams is exhausted, the client is expected to throw
* an {@link StreamException} immediately.
*/
@Test(timeOut = TEST_TIMEOUT)
public void testMaxConcurrentStreamExhaustion() throws Exception {
final HttpServerBuilder serverBuilder = new HttpServerBuilder();
final Server server = serverBuilder.maxConcurrentStreams(0).build();
final HttpClientBuilder clientBuilder = new HttpClientBuilder(_eventLoop, _scheduler);
final Http2NettyStreamClient client = clientBuilder.buildHttp2StreamClient();
final FutureTransportCallback<StreamResponse> callback = new FutureTransportCallback<>();
final TransportResponse<StreamResponse> response;
try {
server.start();
// Sends the stream request
final StreamRequestBuilder builder = new StreamRequestBuilder(new URI(URL));
final StreamRequest request = builder.setMethod(METHOD).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new ByteStringWriter(ByteString.copy(new byte[REQUEST_SIZE]))));
client.streamRequest(request, new RequestContext(), new HashMap<>(), callback);
response = callback.get();
} finally {
server.stop();
}
Assert.assertNotNull(response);
Assert.assertTrue(response.hasError());
Assert.assertNotNull(response.getError());
ExceptionTestUtil.verifyCauseChain(response.getError(), Http2Exception.StreamException.class);
}
use of com.linkedin.r2.testutils.server.HttpServerBuilder in project rest.li by linkedin.
the class TestHttp2NettyStreamClient method testChannelReusedAfterRequestTimeout.
/**
* When a request fails due to {@link TimeoutException}, connection should not be destroyed.
* @throws Exception
*/
@Test(timeOut = TEST_TIMEOUT)
public void testChannelReusedAfterRequestTimeout() throws Exception {
final HttpServerBuilder.HttpServerStatsProvider statsProvider = new HttpServerBuilder.HttpServerStatsProvider();
final HttpServerBuilder serverBuilder = new HttpServerBuilder();
final Server server = serverBuilder.serverStatsProvider(statsProvider).stopTimeout(0).build();
final HttpClientBuilder clientBuilder = new HttpClientBuilder(_eventLoop, _scheduler);
final Http2NettyStreamClient client = clientBuilder.setRequestTimeout(1000).buildHttp2StreamClient();
final TransportResponse<StreamResponse> response1;
final TransportResponse<StreamResponse> response2;
try {
server.start();
final StreamRequestBuilder builder1 = new StreamRequestBuilder(new URI(URL));
final StreamRequest request1 = builder1.setMethod(METHOD).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new TimeoutWriter()));
final FutureTransportCallback<StreamResponse> callback1 = new FutureTransportCallback<>();
client.streamRequest(request1, new RequestContext(), new HashMap<>(), callback1);
response1 = callback1.get();
final StreamRequestBuilder builder2 = new StreamRequestBuilder(new URI(URL));
final StreamRequest request2 = builder2.setMethod(METHOD).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new ByteStringWriter(ByteString.copy(new byte[REQUEST_SIZE]))));
final FutureTransportCallback<StreamResponse> callback2 = new FutureTransportCallback<>();
client.streamRequest(request2, new RequestContext(), new HashMap<>(), callback2);
response2 = callback2.get();
} finally {
server.stop();
}
// The 1st request should be failed with timeout
Assert.assertNotNull(response1);
Assert.assertTrue(response1.hasError());
Assert.assertNotNull(response1.getError());
ExceptionTestUtil.verifyCauseChain(response1.getError(), TimeoutException.class);
// The 2nd request should succeed
Assert.assertNotNull(response2);
Assert.assertFalse(response2.hasError());
response2.getResponse().getEntityStream().setReader(new DrainReader());
// The server should have seen 2 requests but establishes only 1 connection with the client
Assert.assertEquals(statsProvider.requestCount(), 3);
Assert.assertEquals(statsProvider.clientConnections().size(), 1);
}
use of com.linkedin.r2.testutils.server.HttpServerBuilder in project rest.li by linkedin.
the class TestEarlyUpgrade method testEarlyUpgrade.
/**
* The aim is having the pool upgrading the http1 connection to http2 even before a request comes in
*/
@Test
public void testEarlyUpgrade() throws Exception {
ChannelPoolManagerFactoryImpl channelPoolManagerFactory = new ChannelPoolManagerFactoryImpl(_eventLoopGroup, _scheduler, SSL_SESSION_RESUMPTION_ENABLED, _newPipelineEnabled, HttpClientFactory.DEFAULT_CHANNELPOOL_WAITER_TIMEOUT, HttpClientFactory.DEFAULT_CONNECT_TIMEOUT, HttpClientFactory.DEFAULT_SSL_HANDSHAKE_TIMEOUT);
ChannelPoolManagerKey key = new ChannelPoolManagerKeyBuilder().setMinPoolSize(1).build();
ChannelPoolManager channelPoolManager = channelPoolManagerFactory.buildHttp2Stream(key);
HttpServerBuilder.HttpServerStatsProvider httpServerStatsProvider = new HttpServerBuilder.HttpServerStatsProvider();
Server server = new HttpServerBuilder().serverStatsProvider(httpServerStatsProvider).build();
try {
server.start();
InetAddress inetAddress = InetAddress.getByName("localhost");
final SocketAddress address = new InetSocketAddress(inetAddress, HttpServerBuilder.HTTP_PORT);
// since min pool size is 1, it automatically creates a channel
channelPoolManager.getPoolForAddress(address);
// We need the assertWithTimeout because, even if we get the channel,
// it doesn't mean it connected to the server yet
AssertionMethods.assertWithTimeout(2000, // it is expected 1 connection to be opened and 1 option request
() -> Assert.assertEquals(httpServerStatsProvider.clientConnections().size(), 1));
Assert.assertEquals(httpServerStatsProvider.requestCount(), 1);
} finally {
server.stop();
}
FutureCallback<None> futureCallback = new FutureCallback<>();
channelPoolManager.shutdown(futureCallback, () -> {
}, () -> {
}, 5);
futureCallback.get(5, TimeUnit.SECONDS);
}
Aggregations