package jenkins.plugins.asynchttpclient;

import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.ListenableFuture;
import com.ning.http.client.RequestBuilder;
import com.ning.http.client.Response;
import hudson.ProxyConfiguration;
import hudson.model.FreeStyleProject;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Random;
import java.util.concurrent.ExecutionException;

import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.TrustManagerFactory;
import jenkins.model.Jenkins;
import org.junit.AssumptionViolatedException;
import org.junit.Rule;
import org.junit.Test;
import org.jvnet.hudson.test.JenkinsRule;
import sun.security.provider.certpath.SunCertPathBuilderException;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeThat;

public class AHCTest {

    @Rule
    public JenkinsRule j = new JenkinsRule();

    @Test
    public void closeCausesRecycle() {
        assertThat(AHC.instance(), notNullValue());
        AHC.instance().close();
        assertThat(AHC.instance(), notNullValue());
        assertThat(AHC.instance(), hasProperty("closed", is(false)));
    }

    @Test
    public void worksOnJenkinsClasspath() throws Exception {
        final Random entropy = new Random();
        final String jobName = String.format("Random job name %d", entropy.nextLong());
        final String systemMessage = String.format("Random system message %d", entropy.nextLong());
        j.jenkins.setSystemMessage(systemMessage);
        j.getInstance().createProject(j.getInstance().getDescriptorByType(FreeStyleProject.DescriptorImpl.class),
                jobName);
        final ListenableFuture<Response> response =
                AHC.instance().executeRequest(new RequestBuilder("GET").setUrl(j.getURL().toURI().toString()).build());
        assertThat(response.get().getResponseBody(), allOf(
                containsString(Jenkins.getVersion().toString()),
                containsString(systemMessage),
                containsString(jobName)
        ));
    }

    @Test(expected=SunCertPathBuilderException.class)
    public void failsOnSelfSignedCertificate() throws Throwable {
        try {
            ProxyConfiguration proxy = Jenkins.getInstance().proxy;
            URL url = new URL("https://letsencrypt.org");
            HttpURLConnection connection = (HttpURLConnection)
                    (proxy == null ? url.openConnection() : url.openConnection(proxy.createProxy("self-signed.badssl.com")));
            connection.setRequestMethod("HEAD");
            connection.setConnectTimeout(30000);
            connection.connect();
            throw new AssumptionViolatedException("The certificate for self-signed.badssl.com is not trusted");
        } catch (SSLHandshakeException e) {
            // yeah we have a test
        } catch (SocketTimeoutException e) {
            throw new AssumptionViolatedException("We can connect to self-signed.badssl.com", e);
        }
        AsyncHttpClient ahc = AHC.instance();
        ListenableFuture<Response> response = ahc.prepareGet("https://self-signed.badssl.com/").execute();
        try {
            response.get();
        } catch (ExecutionException e) {
            // walk the cause stack to get the real cause
            throw e.getCause().getCause().getCause().getCause().getCause();
        }
        fail("Self Signed certificate accepted");
    }


    @Test(expected=SunCertPathBuilderException.class)
    public void failsOnExpiredCertificate() throws Throwable {
        try {
            ProxyConfiguration proxy = Jenkins.getInstance().proxy;
            URL url = new URL("https://letsencrypt.org");
            HttpURLConnection connection = (HttpURLConnection)
                    (proxy == null ? url.openConnection() : url.openConnection(proxy.createProxy("expired.badssl.com")));
            connection.setRequestMethod("HEAD");
            connection.setConnectTimeout(30000);
            connection.connect();
            throw new AssumptionViolatedException("The certificate for expired.badssl.com is expired");
        } catch (SSLHandshakeException e) {
            // yeah we have a test
        } catch (SocketTimeoutException e) {
            throw new AssumptionViolatedException("We can connect to expired.badssl.com", e);
        }
        AsyncHttpClient ahc = AHC.instance();
        ListenableFuture<Response> response = ahc.prepareGet("https://expired.badssl.com/").execute();
        try {
            response.get();
        } catch (ExecutionException e) {
            // walk the cause stack to get the real cause
            throw e.getCause().getCause().getCause().getCause().getCause();
        }
        fail("Expired certificate accepted");
    }

    @Test
    public void acceptGoodCertificate() throws Throwable {
        try {
            ProxyConfiguration proxy = Jenkins.getInstance().proxy;
            URL url = new URL("https://letsencrypt.org");
            HttpURLConnection connection = (HttpURLConnection)
                    (proxy == null ? url.openConnection() : url.openConnection(proxy.createProxy("letsencrypt.org")));
            connection.setRequestMethod("HEAD");
            connection.setConnectTimeout(30000);
            connection.connect();
        } catch (SSLHandshakeException e) {
            throw new AssumptionViolatedException("The Root CA for letsencrypt.org is in the JVM trust store", e);
        } catch (SocketTimeoutException e) {
            throw new AssumptionViolatedException("We can connect to letsencrypt.org", e);
        }
        AsyncHttpClient ahc = AHC.instance();
        ListenableFuture<Response> response = ahc.prepareGet("https://letsencrypt.org").execute();
        assertTrue(response.get().hasResponseStatus());
    }
}

@@ -742,11 +742,12 @@
 ort 
-sun
+java
 .sec
@@ -756,29 +756,13 @@
 ity.
-provider.certpath.Sun
+cert.
 Cert
@@ -2153,35 +2153,32 @@
  @Test(expected=
-Sun
 CertPathBuilderE
@@ -3525,11 +3525,8 @@
 ted=
-Sun
 Cert

Use public parent CertPathBuilderException instead of SunCertPathBuilderException