@Test
    public void testHttpsEndpointIdentification() throws Exception {
        TestUtils.assumeExtendedTrustManagerAvailable();

        KeyStore.PrivateKeyEntry pke = TestKeyStore.getServerHostname().getPrivateKey("RSA", "RSA");
        X509Certificate[] chain = (X509Certificate[]) pke.getCertificateChain();
        X509Certificate root = chain[2];
        TrustManagerImpl tmi = (TrustManagerImpl) trustManager(root);

        String goodHostname = TestKeyStore.CERT_HOSTNAME;
        String badHostname = "definitelywrong.nopenopenope";

        try {
            SSLParameters params = new SSLParameters();

            // Without endpoint identification this should pass despite the mismatched hostname
            params.setEndpointIdentificationAlgorithm(null);

            List<X509Certificate> certs = tmi.getTrustedChainForServer(chain, "RSA",
                    new FakeSSLSocket(new FakeSSLSession(badHostname, chain), params));
            assertEquals(Arrays.asList(chain), certs);

            // Turn on endpoint identification
            params.setEndpointIdentificationAlgorithm("HTTPS");

            try {
                tmi.getTrustedChainForServer(chain, "RSA",
                        new FakeSSLSocket(new FakeSSLSession(badHostname, chain), params));
                fail();
            } catch (CertificateException expected) {
            }

            certs = tmi.getTrustedChainForServer(chain, "RSA",
                    new FakeSSLSocket(new FakeSSLSession(goodHostname, chain), params));
            assertEquals(Arrays.asList(chain), certs);

            // Override the global default hostname verifier with a Conscrypt-specific one that
            // always passes.  Both scenarios should pass.
            Conscrypt.setHostnameVerifier(tmi, new ConscryptHostnameVerifier() {
                @Override
                public boolean verify(X509Certificate[] certificates, String s, SSLSession sslSession) {
                    return true;
                }
            });

            certs = tmi.getTrustedChainForServer(chain, "RSA",
                    new FakeSSLSocket(new FakeSSLSession(badHostname, chain), params));
            assertEquals(Arrays.asList(chain), certs);

            certs = tmi.getTrustedChainForServer(chain, "RSA",
                    new FakeSSLSocket(new FakeSSLSession(goodHostname, chain), params));
            assertEquals(Arrays.asList(chain), certs);

            // Now set an instance-specific verifier on the trust manager.  The bad hostname should
            // fail again.
            Conscrypt.setHostnameVerifier(tmi, Conscrypt.wrapHostnameVerifier(new TestHostnameVerifier()));

            try {
                tmi.getTrustedChainForServer(chain, "RSA",
                        new FakeSSLSocket(new FakeSSLSession(badHostname, chain), params));
                fail();
            } catch (CertificateException expected) {
            }

            certs = tmi.getTrustedChainForServer(chain, "RSA",
                    new FakeSSLSocket(new FakeSSLSession(goodHostname, chain), params));
            assertEquals(Arrays.asList(chain), certs);

            // Remove the instance-specific verifier, and both should pass again.
            Conscrypt.setHostnameVerifier(tmi, null);

            try {
                tmi.getTrustedChainForServer(chain, "RSA",
                        new FakeSSLSocket(new FakeSSLSession(badHostname, chain), params));
                fail();
            } catch (CertificateException expected) {
            }

            certs = tmi.getTrustedChainForServer(chain, "RSA",
                    new FakeSSLSocket(new FakeSSLSession(goodHostname, chain), params));
            assertEquals(Arrays.asList(chain), certs);
        } finally {
            Conscrypt.setDefaultHostnameVerifier(null);
        }
    }
Ensure that our non-standard behavior of learning to trust new
intermediate CAs does not regress. http://b/3404902
common/src/test/java/org/conscrypt/TrustManagerImplTest.java