@Test
  public void testProxyRequestFailureInTheMiddleOfProxyingBigContent() throws Exception {
    final long proxyTimeout = 1000;
    int outputBufferSize = 1024;
    Map<String, String> proxyParams = new HashMap<>();
    proxyParams.put("timeout", String.valueOf(proxyTimeout));
    proxyParams.put("outputBufferSize", String.valueOf(outputBufferSize));
    prepareProxy(proxyParams);

    final CountDownLatch chunk1Latch = new CountDownLatch(1);
    final byte[] chunk1 = new byte[outputBufferSize];
    new Random().nextBytes(chunk1);
    final int chunk2 = 'w';
    prepareServer(
        new HttpServlet() {
          @Override
          protected void service(HttpServletRequest request, HttpServletResponse response)
              throws ServletException, IOException {
            ServletOutputStream output = response.getOutputStream();
            output.write(chunk1);
            response.flushBuffer();

            // Wait for the client to receive this chunk.
            await(chunk1Latch, 5000);

            // Send second chunk, must not be received by proxy.
            output.write(chunk2);
          }

          private boolean await(CountDownLatch latch, long ms) throws IOException {
            try {
              return latch.await(ms, TimeUnit.MILLISECONDS);
            } catch (InterruptedException x) {
              throw new InterruptedIOException();
            }
          }
        });

    HttpClient client = prepareClient();
    InputStreamResponseListener listener = new InputStreamResponseListener();
    int port = serverConnector.getLocalPort();
    client.newRequest("localhost", port).send(listener);

    Response response = listener.get(5, TimeUnit.SECONDS);
    Assert.assertEquals(200, response.getStatus());

    InputStream input = listener.getInputStream();
    for (int i = 0; i < chunk1.length; ++i) Assert.assertEquals(chunk1[i] & 0xFF, input.read());

    TimeUnit.MILLISECONDS.sleep(2 * proxyTimeout);

    chunk1Latch.countDown();

    try {
      // Make sure the proxy does not receive chunk2.
      input.read();
      Assert.fail();
    } catch (EOFException x) {
      // Expected
    }

    HttpDestinationOverHTTP destination =
        (HttpDestinationOverHTTP) client.getDestination("http", "localhost", port);
    Assert.assertEquals(0, destination.getConnectionPool().getIdleConnections().size());
  }
  @Test
  public void testProxyRequestFailureInTheMiddleOfProxyingSmallContent() throws Exception {
    final long proxyTimeout = 1000;
    Map<String, String> proxyParams = new HashMap<>();
    proxyParams.put("timeout", String.valueOf(proxyTimeout));
    prepareProxy(proxyParams);

    final CountDownLatch chunk1Latch = new CountDownLatch(1);
    final int chunk1 = 'q';
    final int chunk2 = 'w';
    prepareServer(
        new HttpServlet() {
          @Override
          protected void service(HttpServletRequest request, HttpServletResponse response)
              throws ServletException, IOException {
            ServletOutputStream output = response.getOutputStream();
            output.write(chunk1);
            response.flushBuffer();

            // Wait for the client to receive this chunk.
            await(chunk1Latch, 5000);

            // Send second chunk, must not be received by proxy.
            output.write(chunk2);
          }

          private boolean await(CountDownLatch latch, long ms) throws IOException {
            try {
              return latch.await(ms, TimeUnit.MILLISECONDS);
            } catch (InterruptedException x) {
              throw new InterruptedIOException();
            }
          }
        });

    HttpClient client = prepareClient();
    InputStreamResponseListener listener = new InputStreamResponseListener();
    int port = serverConnector.getLocalPort();
    client.newRequest("localhost", port).send(listener);

    // Make the proxy request fail; given the small content, the
    // proxy-to-client response is not committed yet so it will be reset.
    TimeUnit.MILLISECONDS.sleep(2 * proxyTimeout);

    Response response = listener.get(5, TimeUnit.SECONDS);
    Assert.assertEquals(504, response.getStatus());

    // Make sure there is no content, as the proxy-to-client response has been reset.
    InputStream input = listener.getInputStream();
    Assert.assertEquals(-1, input.read());

    chunk1Latch.countDown();

    // Result succeeds because a 504 is a valid HTTP response.
    Result result = listener.await(5, TimeUnit.SECONDS);
    Assert.assertTrue(result.isSucceeded());

    // Make sure the proxy does not receive chunk2.
    Assert.assertEquals(-1, input.read());

    HttpDestinationOverHTTP destination =
        (HttpDestinationOverHTTP) client.getDestination("http", "localhost", port);
    Assert.assertEquals(0, destination.getConnectionPool().getIdleConnections().size());
  }