@Test
  public void testEstablishRouteViaProxyTunnelRetryOnAuthChallengeNonPersistentConnection()
      throws Exception {
    final AuthState authState = new AuthState();
    final HttpRoute route = new HttpRoute(target, null, proxy, true);
    final HttpClientContext context = new HttpClientContext();
    final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
    final HttpResponse response1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 401, "Huh?");
    final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3}));
    response1.setEntity(EntityBuilder.create().setStream(instream1).build());
    final HttpResponse response2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");

    Mockito.when(managedConn.isOpen()).thenReturn(Boolean.TRUE);
    Mockito.when(
            proxyAuthStrategy.isAuthenticationRequested(
                Mockito.eq(proxy), Mockito.same(response1), Mockito.<HttpClientContext>any()))
        .thenReturn(Boolean.TRUE);
    Mockito.when(
            reuseStrategy.keepAlive(Mockito.<HttpResponse>any(), Mockito.<HttpClientContext>any()))
        .thenReturn(Boolean.FALSE);
    Mockito.when(
            requestExecutor.execute(
                Mockito.<HttpRequest>any(),
                Mockito.<HttpClientConnection>any(),
                Mockito.<HttpClientContext>any()))
        .thenReturn(response1, response2);

    mainClientExec.establishRoute(authState, managedConn, route, request, context);

    Mockito.verify(connManager).connect(managedConn, route, 0, context);
    Mockito.verify(connManager).routeComplete(managedConn, route, context);
    Mockito.verify(instream1, Mockito.never()).close();
    Mockito.verify(managedConn).close();
  }
  @Before
  public void setup() throws Exception {
    MockitoAnnotations.initMocks(this);
    mainClientExec =
        new MainClientExec(
            requestExecutor,
            connManager,
            reuseStrategy,
            keepAliveStrategy,
            proxyHttpProcessor,
            targetAuthStrategy,
            proxyAuthStrategy,
            userTokenHandler);
    target = new HttpHost("foo", 80);
    proxy = new HttpHost("bar", 8888);

    Mockito.when(connManager.requestConnection(Mockito.<HttpRoute>any(), Mockito.any()))
        .thenReturn(connRequest);
    Mockito.when(connRequest.get(Mockito.anyLong(), Mockito.<TimeUnit>any()))
        .thenReturn(managedConn);
    final Map<String, Header> challenges = new HashMap<String, Header>();
    challenges.put("basic", new BasicHeader(AUTH.WWW_AUTH, "Basic realm=test"));
    final AuthOption authOption =
        new AuthOption(new BasicScheme(), new UsernamePasswordCredentials("user:pass"));
    Mockito.when(
            targetAuthStrategy.getChallenges(
                Mockito.eq(target), Mockito.<HttpResponse>any(), Mockito.<HttpClientContext>any()))
        .thenReturn(challenges);
    Mockito.when(
            targetAuthStrategy.getChallenges(
                Mockito.eq(target), Mockito.<HttpResponse>any(), Mockito.<HttpClientContext>any()))
        .thenReturn(challenges);
    Mockito.when(
            targetAuthStrategy.select(
                Mockito.same(challenges),
                Mockito.eq(target),
                Mockito.<HttpResponse>any(),
                Mockito.<HttpClientContext>any()))
        .thenReturn(new LinkedList<AuthOption>(Arrays.asList(authOption)));
    Mockito.when(
            proxyAuthStrategy.getChallenges(
                Mockito.eq(proxy), Mockito.<HttpResponse>any(), Mockito.<HttpClientContext>any()))
        .thenReturn(challenges);
    Mockito.when(
            proxyAuthStrategy.getChallenges(
                Mockito.eq(proxy), Mockito.<HttpResponse>any(), Mockito.<HttpClientContext>any()))
        .thenReturn(challenges);
    Mockito.when(
            proxyAuthStrategy.select(
                Mockito.same(challenges),
                Mockito.eq(proxy),
                Mockito.<HttpResponse>any(),
                Mockito.<HttpClientContext>any()))
        .thenReturn(new LinkedList<AuthOption>(Arrays.asList(authOption)));
  }
  @Test
  public void testExecEntityEnclosingRequestRetryOnAuthChallenge() throws Exception {
    final HttpRoute route = new HttpRoute(target);
    final HttpRequestWrapper request = HttpRequestWrapper.wrap(new HttpGet("http://bar/test"));
    final HttpResponse response1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 401, "Huh?");
    final InputStream instream1 = Mockito.spy(new ByteArrayInputStream(new byte[] {1, 2, 3}));
    response1.setEntity(EntityBuilder.create().setStream(instream1).build());
    final HttpResponse response2 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
    final InputStream instream2 = Mockito.spy(new ByteArrayInputStream(new byte[] {2, 3, 4}));
    response2.setEntity(EntityBuilder.create().setStream(instream2).build());

    final AuthState proxyAuthState = new AuthState();
    proxyAuthState.setState(AuthProtocolState.SUCCESS);
    proxyAuthState.update(new NTLMScheme(), new NTCredentials("user:pass"));

    final HttpClientContext context = new HttpClientContext();
    context.setAttribute(HttpClientContext.PROXY_AUTH_STATE, proxyAuthState);

    Mockito.when(managedConn.isOpen()).thenReturn(Boolean.TRUE);
    Mockito.when(managedConn.isStale()).thenReturn(Boolean.FALSE);
    Mockito.when(
            requestExecutor.execute(
                Mockito.same(request),
                Mockito.<HttpClientConnection>any(),
                Mockito.<HttpClientContext>any()))
        .thenReturn(response1, response2);
    Mockito.when(
            reuseStrategy.keepAlive(Mockito.<HttpResponse>any(), Mockito.<HttpClientContext>any()))
        .thenReturn(Boolean.FALSE);
    Mockito.when(
            targetAuthStrategy.isAuthenticationRequested(
                Mockito.eq(target), Mockito.same(response1), Mockito.<HttpClientContext>any()))
        .thenReturn(Boolean.TRUE);

    final CloseableHttpResponse finalResponse =
        mainClientExec.execute(route, request, context, execAware);
    Mockito.verify(requestExecutor, Mockito.times(2)).execute(request, managedConn, context);
    Mockito.verify(managedConn).close();
    Mockito.verify(instream2, Mockito.never()).close();

    Assert.assertNotNull(finalResponse);
    Assert.assertEquals(200, finalResponse.getStatusLine().getStatusCode());
    Assert.assertNull(proxyAuthState.getAuthScheme());
    Assert.assertNull(proxyAuthState.getCredentials());
  }
  @Test(expected = NonRepeatableRequestException.class)
  public void testExecEntityEnclosingRequest() throws Exception {
    final HttpRoute route = new HttpRoute(target);
    final HttpClientContext context = new HttpClientContext();
    final HttpPost post = new HttpPost("http://bar/test");
    final InputStream instream0 = new ByteArrayInputStream(new byte[] {1, 2, 3});
    post.setEntity(EntityBuilder.create().setStream(instream0).build());
    final HttpRequestWrapper request = HttpRequestWrapper.wrap(post);

    final HttpResponse response1 = new BasicHttpResponse(HttpVersion.HTTP_1_1, 401, "Huh?");
    final InputStream instream1 = new ByteArrayInputStream(new byte[] {1, 2, 3});
    response1.setEntity(EntityBuilder.create().setStream(instream1).build());

    Mockito.when(managedConn.isOpen()).thenReturn(Boolean.TRUE);
    Mockito.when(managedConn.isStale()).thenReturn(Boolean.FALSE);
    Mockito.when(
            requestExecutor.execute(
                Mockito.same(request),
                Mockito.<HttpClientConnection>any(),
                Mockito.<HttpClientContext>any()))
        .thenAnswer(
            new Answer<HttpResponse>() {

              @Override
              public HttpResponse answer(final InvocationOnMock invocationOnMock) throws Throwable {
                final Object[] args = invocationOnMock.getArguments();
                final HttpEntityEnclosingRequest requestEE = (HttpEntityEnclosingRequest) args[0];
                requestEE.getEntity().writeTo(new ByteArrayOutputStream());
                return response1;
              }
            });
    Mockito.when(
            reuseStrategy.keepAlive(Mockito.<HttpResponse>any(), Mockito.<HttpClientContext>any()))
        .thenReturn(Boolean.TRUE);
    Mockito.when(
            targetAuthStrategy.isAuthenticationRequested(
                Mockito.eq(target), Mockito.same(response1), Mockito.<HttpClientContext>any()))
        .thenReturn(Boolean.TRUE);

    mainClientExec.execute(route, request, context, execAware);
  }