FileDocCategorySizeDatePackage
HttpsURLConnectionTest.javaAPI DocAndroid 1.5 API61422Wed May 06 22:41:04 BST 2009org.apache.harmony.luni.tests.internal.net.www.protocol.https

HttpsURLConnectionTest.java

/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.harmony.luni.tests.internal.net.www.protocol.https;

import dalvik.annotation.AndroidOnly;
import dalvik.annotation.KnownFailure;
import dalvik.annotation.TestTargetClass; 
import dalvik.annotation.TestTargets;
import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetNew;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.net.Proxy;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.util.Arrays;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import junit.framework.TestCase;

/**
 * Implementation independent test for HttpsURLConnection.
 * The test needs certstore file placed in system classpath 
 * and named as "key_store." + the type of the
 * default KeyStore installed in the system in lower case.
 * <br>
 * For example: if default KeyStore type in the system is BKS
 * (i.e. java.security file sets up the property keystore.type=BKS),
 * thus classpath should point to the directory with "key_store.bks"
 * file.
 * <br>
 * This certstore file should contain self-signed certificate
 * generated by keytool utility in a usual way.
 * <br>
 * The password to the certstore should be "password" (without quotes).
 */
@TestTargetClass(HttpsURLConnection.class)
public class HttpsURLConnectionTest extends TestCase {

    // the password to the store
    private static final String KS_PASSWORD = "password";

    // turn on/off logging
    private static final boolean DO_LOG = false;

    // read/connection timeout value
    private static final int TIMEOUT = 5000;

    // OK response code
    private static final int OK_CODE = 200;

    // Not Found response code
    private static final int NOT_FOUND_CODE = 404;

    // Proxy authentication required response code
    private static final int AUTHENTICATION_REQUIRED_CODE = 407;

    // fields keeping the system values of corresponding properties
    private static String systemKeyStoreType;

    private static String systemKeyStore;

    private static String systemKeyStorePassword;

    private static String systemTrustStoreType;

    private static String systemTrustStore;

    private static String systemTrustStorePassword;
    
    private static File store;
    
    static {
        try {
            store = File.createTempFile("key_store", "bks");
        } catch (Exception e) {
            // ignore
        }
    }

    /**
     * Checks that HttpsURLConnection's default SSLSocketFactory is operable.
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL_COMPLETE,
        notes = "Verifies that HttpsURLConnection's default SSLSocketFactory is operable.",
        method = "getDefaultSSLSocketFactory",
        args = {}
    )
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testGetDefaultSSLSocketFactory() throws Exception {
        // set up the properties defining the default values needed by SSL stuff
        setUpStoreProperties();

        try {
            SSLSocketFactory defaultSSLSF = HttpsURLConnection
                    .getDefaultSSLSocketFactory();
            ServerSocket ss = new ServerSocket(0);
            Socket s = defaultSSLSF
                    .createSocket("localhost", ss.getLocalPort());
            ss.accept();
            s.close();
            ss.close();
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Checks if HTTPS connection performs initial SSL handshake with the
     * server working over SSL, sends encrypted HTTP request,
     * and receives expected HTTP response. After HTTPS session if finished
     * test checks connection state parameters established by
     * HttpsURLConnection.
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL_COMPLETE,
        notes = "Verifies  if HTTPS connection performs initial SSL handshake with the server working over SSL, sends encrypted HTTP request, and receives expected HTTP response.",
        method = "setDefaultHostnameVerifier",
        args = {javax.net.ssl.HostnameVerifier.class}
    )
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testHttpsConnection() throws Throwable {
        // set up the properties defining the default values needed by SSL stuff
        setUpStoreProperties();

        try {
            // create the SSL server socket acting as a server
            SSLContext ctx = getContext();
            ServerSocket ss = ctx.getServerSocketFactory()
                    .createServerSocket(0);

            // create the HostnameVerifier to check hostname verification
            TestHostnameVerifier hnv = new TestHostnameVerifier();
            HttpsURLConnection.setDefaultHostnameVerifier(hnv);

            // create url connection to be tested
            URL url = new URL("https://localhost:" + ss.getLocalPort());
            HttpsURLConnection connection = (HttpsURLConnection) url
                    .openConnection();

            // perform the interaction between the peers
            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);

            // check the connection state
            checkConnectionStateParameters(connection, peerSocket);

            // should silently exit
            connection.connect();
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Tests the behaviour of HTTPS connection in case of unavailability
     * of requested resource.
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies the behaviour of HTTPS connection in case of unavailability of requested resource.",
            method = "setDoInput",
            args = {boolean.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies the behaviour of HTTPS connection in case of unavailability of requested resource.",
            method = "setConnectTimeout",
            args = {int.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies the behaviour of HTTPS connection in case of unavailability of requested resource.",
            method = "setReadTimeout",
            args = {int.class}
        )
    })
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testHttpsConnection_Not_Found_Response() throws Throwable {
        // set up the properties defining the default values needed by SSL stuff
        setUpStoreProperties();

        try {
            // create the SSL server socket acting as a server
            SSLContext ctx = getContext();
            ServerSocket ss = ctx.getServerSocketFactory()
                    .createServerSocket(0);

            // create the HostnameVerifier to check hostname verification
            TestHostnameVerifier hnv = new TestHostnameVerifier();
            HttpsURLConnection.setDefaultHostnameVerifier(hnv);

            // create url connection to be tested
            URL url = new URL("https://localhost:" + ss.getLocalPort());
            HttpsURLConnection connection = (HttpsURLConnection) url
                    .openConnection();

            try {
                doInteraction(connection, ss, NOT_FOUND_CODE);
                fail("Expected exception was not thrown.");
            } catch (FileNotFoundException e) {
                if (DO_LOG) {
                    System.out.println("Expected exception was thrown: "
                            + e.getMessage());
                }
            }

            // should silently exit
            connection.connect();
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Tests possibility to set up the default SSLSocketFactory
     * to be used by HttpsURLConnection.
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL_COMPLETE,
        notes = "Verifies possibility to set up the default SSLSocketFactory to be used by HttpsURLConnection.",
        method = "setDefaultSSLSocketFactory",
        args = {javax.net.ssl.SSLSocketFactory.class}
    )
    @AndroidOnly("we only have a .bks key store in the test resources")
    @KnownFailure("End to end test fails. No response data is transferred from server to client")
    public void testSetDefaultSSLSocketFactory() throws Throwable {
        // create the SSLServerSocket which will be used by server side
        SSLContext ctx = getContext();
        SSLServerSocket ss = (SSLServerSocket) ctx.getServerSocketFactory()
                .createServerSocket(0);

        SSLSocketFactory socketFactory = (SSLSocketFactory) ctx
                .getSocketFactory();
        // set up the factory as default
        HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
        // check the result
        assertSame("Default SSLSocketFactory differs from expected",
                socketFactory, HttpsURLConnection.getDefaultSSLSocketFactory());

        // create the HostnameVerifier to check hostname verification
        TestHostnameVerifier hnv = new TestHostnameVerifier();
        HttpsURLConnection.setDefaultHostnameVerifier(hnv);

        // create HttpsURLConnection to be tested
        URL url = new URL("https://localhost:" + ss.getLocalPort());
        HttpsURLConnection connection = (HttpsURLConnection) url
                .openConnection();

        TestHostnameVerifier hnv_late = new TestHostnameVerifier();
        // late initialization: should not be used for created connection
        HttpsURLConnection.setDefaultHostnameVerifier(hnv_late);

        // perform the interaction between the peers
        SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
        // check the connection state
        checkConnectionStateParameters(connection, peerSocket);
        // check the verification process
        assertTrue("Hostname verification was not done", hnv.verified);
        assertFalse(
                "Hostname verification should not be done by this verifier",
                hnv_late.verified);
        // check the used SSLSocketFactory
        assertSame("Default SSLSocketFactory should be used",
                HttpsURLConnection.getDefaultSSLSocketFactory(), connection
                        .getSSLSocketFactory());

        // should silently exit
        connection.connect();
    }

    /**
     * Tests possibility to set up the SSLSocketFactory
     * to be used by HttpsURLConnection.
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL_COMPLETE,
        notes = "Verifies possibility to set up the SSLSocketFactory to be used by HttpsURLConnection.",
        method = "setSSLSocketFactory",
        args = {javax.net.ssl.SSLSocketFactory.class}
    )
    @AndroidOnly("we only have a .bks key store in the test resources")
    @KnownFailure("End to end test fails. No response data is transferred from server to client")
    public void testSetSSLSocketFactory() throws Throwable {
        // create the SSLServerSocket which will be used by server side
        SSLContext ctx = getContext();
        SSLServerSocket ss = (SSLServerSocket) ctx.getServerSocketFactory()
                .createServerSocket(0);

        // create the HostnameVerifier to check hostname verification
        TestHostnameVerifier hnv = new TestHostnameVerifier();
        HttpsURLConnection.setDefaultHostnameVerifier(hnv);

        // create HttpsURLConnection to be tested
        URL url = new URL("https://localhost:" + ss.getLocalPort());
        HttpsURLConnection connection = (HttpsURLConnection) url
                .openConnection();

        SSLSocketFactory socketFactory = (SSLSocketFactory) ctx
                .getSocketFactory();
        connection.setSSLSocketFactory(socketFactory);

        TestHostnameVerifier hnv_late = new TestHostnameVerifier();
        // late initialization: should not be used for created connection
        HttpsURLConnection.setDefaultHostnameVerifier(hnv_late);

        // perform the interaction between the peers
        SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
        // check the connection state
        checkConnectionStateParameters(connection, peerSocket);
        // check the verification process
        assertTrue("Hostname verification was not done", hnv.verified);
        assertFalse(
                "Hostname verification should not be done by this verifier",
                hnv_late.verified);
        // check the used SSLSocketFactory
        assertNotSame("Default SSLSocketFactory should not be used",
                HttpsURLConnection.getDefaultSSLSocketFactory(), connection
                        .getSSLSocketFactory());
        assertSame("Result differs from expected", socketFactory, connection
                .getSSLSocketFactory());

        // should silently exit
        connection.connect();
    }

    /**
     * Tests the behaviour of HttpsURLConnection in case of retrieving
     * of the connection state parameters before connection has been made.
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies the behaviour of HttpsURLConnection in case of retrieving of the connection state parameters before connection has been made.",
            method = "getCipherSuite",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies the behaviour of HttpsURLConnection in case of retrieving of the connection state parameters before connection has been made.",
            method = "getPeerPrincipal",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies the behaviour of HttpsURLConnection in case of retrieving of the connection state parameters before connection has been made.",
            method = "getLocalPrincipal",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies the behaviour of HttpsURLConnection in case of retrieving of the connection state parameters before connection has been made.",
            method = "getServerCertificates",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies the behaviour of HttpsURLConnection in case of retrieving of the connection state parameters before connection has been made.",
            method = "getLocalCertificates",
            args = {}
        )
    })
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testUnconnectedStateParameters() throws Throwable {
        // create HttpsURLConnection to be tested
        URL url = new URL("https://localhost:55555");
        HttpsURLConnection connection = (HttpsURLConnection) url
                .openConnection();

        try {
            connection.getCipherSuite();
            fail("Expected IllegalStateException was not thrown");
        } catch (IllegalStateException e) {}
        try {
            connection.getPeerPrincipal();
            fail("Expected IllegalStateException was not thrown");
        } catch (IllegalStateException e) {}
        try {
            connection.getLocalPrincipal();
            fail("Expected IllegalStateException was not thrown");
        } catch (IllegalStateException e) {}

        try {
            connection.getServerCertificates();
            fail("Expected IllegalStateException was not thrown");
        } catch (IllegalStateException e) {}
        try {
            connection.getLocalCertificates();
            fail("Expected IllegalStateException was not thrown");
        } catch (IllegalStateException e) {}
    }

    /**
     * Tests if setHostnameVerifier() method replaces default verifier.
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL_COMPLETE,
        notes = "Verifies if setHostnameVerifier() method replaces default verifier.",
        method = "setHostnameVerifier",
        args = {javax.net.ssl.HostnameVerifier.class}
    )
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testSetHostnameVerifier() throws Throwable {
        // setting up the properties pointing to the key/trust stores
        setUpStoreProperties();

        try {
            // create the SSLServerSocket which will be used by server side
            SSLServerSocket ss = (SSLServerSocket) getContext()
                    .getServerSocketFactory().createServerSocket(0);

            // create the HostnameVerifier to check that Hostname verification
            // is done
            TestHostnameVerifier hnv = new TestHostnameVerifier();
            HttpsURLConnection.setDefaultHostnameVerifier(hnv);

            // create HttpsURLConnection to be tested
            URL url = new URL("https://localhost:" + ss.getLocalPort());
            HttpsURLConnection connection = (HttpsURLConnection) url
                    .openConnection();

            TestHostnameVerifier hnv_late = new TestHostnameVerifier();
            // replace default verifier
            connection.setHostnameVerifier(hnv_late);

            // perform the interaction between the peers and check the results
            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
            assertTrue("Hostname verification was not done", hnv_late.verified);
            assertFalse(
                    "Hostname verification should not be done by this verifier",
                    hnv.verified);
            checkConnectionStateParameters(connection, peerSocket);

            // should silently exit
            connection.connect();
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Tests the behaviour in case of sending the data to the server.
     */
    @TestTargetNew(
        level = TestLevel.PARTIAL,
        notes = "Verifies the behaviour in case of sending the data to the server.",
        method = "setDoOutput",
        args = {boolean.class}
    )
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void test_doOutput() throws Throwable {
        // setting up the properties pointing to the key/trust stores
        setUpStoreProperties();

        try {
            // create the SSLServerSocket which will be used by server side
            SSLServerSocket ss = (SSLServerSocket) getContext()
                    .getServerSocketFactory().createServerSocket(0);

            // create the HostnameVerifier to check that Hostname verification
            // is done
            TestHostnameVerifier hnv = new TestHostnameVerifier();
            HttpsURLConnection.setDefaultHostnameVerifier(hnv);

            // create HttpsURLConnection to be tested
            URL url = new URL("https://localhost:" + ss.getLocalPort());
            HttpsURLConnection connection = (HttpsURLConnection) url
                    .openConnection();
            connection.setDoOutput(true);

            // perform the interaction between the peers and check the results
            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
            checkConnectionStateParameters(connection, peerSocket);

            // should silently exit
            connection.connect();
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Tests HTTPS connection process made through the proxy server.
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server.",
            method = "setDoInput",
            args = {boolean.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server.",
            method = "setConnectTimeout",
            args = {int.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server.",
            method = "setReadTimeout",
            args = {int.class}
        )
    })
    @KnownFailure("Handshake fails.")
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testProxyConnection() throws Throwable {
        // setting up the properties pointing to the key/trust stores
        setUpStoreProperties();

        try {
            // create the SSLServerSocket which will be used by server side
            ServerSocket ss = new ServerSocket(0);

            // create the HostnameVerifier to check that Hostname verification
            // is done
            TestHostnameVerifier hnv = new TestHostnameVerifier();
            HttpsURLConnection.setDefaultHostnameVerifier(hnv);

            // create HttpsURLConnection to be tested
            URL url = new URL("https://requested.host:55556/requested.data");
            HttpsURLConnection connection = (HttpsURLConnection) url
                    .openConnection(new Proxy(Proxy.Type.HTTP,
                            new InetSocketAddress("localhost", ss
                                    .getLocalPort())));

            // perform the interaction between the peers and check the results
            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
            checkConnectionStateParameters(connection, peerSocket);

            // should silently exit
            connection.connect();
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Tests HTTPS connection process made through the proxy server.
     * Proxy server needs authentication.
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication.",
            method = "setDoInput",
            args = {boolean.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication.",
            method = "setConnectTimeout",
            args = {int.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication.",
            method = "setReadTimeout",
            args = {int.class}
        )
    })
    @KnownFailure("Handshake fails.")
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testProxyAuthConnection() throws Throwable {
        // setting up the properties pointing to the key/trust stores
        setUpStoreProperties();

        try {
            // create the SSLServerSocket which will be used by server side
            ServerSocket ss = new ServerSocket(0);

            // create the HostnameVerifier to check that Hostname verification
            // is done
            TestHostnameVerifier hnv = new TestHostnameVerifier();
            HttpsURLConnection.setDefaultHostnameVerifier(hnv);

            Authenticator.setDefault(new Authenticator() {

                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication("user", "password"
                            .toCharArray());
                }
            });

            // create HttpsURLConnection to be tested
            URL url = new URL("https://requested.host:55555/requested.data");
            HttpsURLConnection connection = (HttpsURLConnection) url
                    .openConnection(new Proxy(Proxy.Type.HTTP,
                            new InetSocketAddress("localhost", ss
                                    .getLocalPort())));

            // perform the interaction between the peers and check the results
            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
            checkConnectionStateParameters(connection, peerSocket);

            // should silently exit
            connection.connect();
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Tests HTTPS connection process made through the proxy server.
     * 2 HTTPS connections are opened for one URL. For the first time
     * the connection is opened through one proxy,
     * for the second time through another.
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies HTTPS connection process made through the proxy server.",
            method = "getCipherSuite",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies HTTPS connection process made through the proxy server.",
            method = "getLocalPrincipal",
            args = {}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL_COMPLETE,
            notes = "Verifies HTTPS connection process made through the proxy server.",
            method = "getPeerPrincipal",
            args = {}
        )
    })
    @KnownFailure("Handshake fails.")
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testConsequentProxyConnection() throws Throwable {
        // setting up the properties pointing to the key/trust stores
        setUpStoreProperties();

        try {
            // create the SSLServerSocket which will be used by server side
            ServerSocket ss = new ServerSocket(0);

            // create the HostnameVerifier to check that Hostname verification
            // is done
            TestHostnameVerifier hnv = new TestHostnameVerifier();
            HttpsURLConnection.setDefaultHostnameVerifier(hnv);

            // create HttpsURLConnection to be tested
            URL url = new URL("https://requested.host:55555/requested.data");
            HttpsURLConnection connection = (HttpsURLConnection) url
                    .openConnection(new Proxy(Proxy.Type.HTTP,
                            new InetSocketAddress("localhost", ss
                                    .getLocalPort())));

            // perform the interaction between the peers and check the results
            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss);
            checkConnectionStateParameters(connection, peerSocket);

            // create another SSLServerSocket which will be used by server side
            ss = new ServerSocket(0);

            connection = (HttpsURLConnection) url.openConnection(new Proxy(
                    Proxy.Type.HTTP, new InetSocketAddress("localhost", ss
                            .getLocalPort())));

            // perform the interaction between the peers and check the results
            peerSocket = (SSLSocket) doInteraction(connection, ss);
            checkConnectionStateParameters(connection, peerSocket);
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Tests HTTPS connection process made through the proxy server.
     * Proxy server needs authentication.
     * Client sends data to the server.
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication. Client sends data to the server.",
            method = "setDoInput",
            args = {boolean.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication. Client sends data to the server.",
            method = "setConnectTimeout",
            args = {int.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication. Client sends data to the server.",
            method = "setReadTimeout",
            args = {int.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication. Client sends data to the server.",
            method = "setDoOutput",
            args = {boolean.class}
        )
    })
    @KnownFailure("Handshake fails.")
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testProxyAuthConnection_doOutput() throws Throwable {
        // setting up the properties pointing to the key/trust stores
        setUpStoreProperties();

        try {
            // create the SSLServerSocket which will be used by server side
            ServerSocket ss = new ServerSocket(0);

            // create the HostnameVerifier to check that Hostname verification
            // is done
            TestHostnameVerifier hnv = new TestHostnameVerifier();
            HttpsURLConnection.setDefaultHostnameVerifier(hnv);

            Authenticator.setDefault(new Authenticator() {

                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication("user", "password"
                            .toCharArray());
                }
            });

            // create HttpsURLConnection to be tested
            URL url = new URL("https://requested.host:55554/requested.data");
            HttpsURLConnection connection = (HttpsURLConnection) url
                    .openConnection(new Proxy(Proxy.Type.HTTP,
                            new InetSocketAddress("localhost", ss
                                    .getLocalPort())));
            connection.setDoOutput(true);

            // perform the interaction between the peers and check the results
            SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss,
                    OK_CODE, true);
            checkConnectionStateParameters(connection, peerSocket);
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Tests HTTPS connection process made through the proxy server.
     * Proxy server needs authentication but client fails to authenticate
     * (Authenticator was not set up in the system).
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication but client fails to authenticate (Authenticator was not set up in the system).",
            method = "setDoInput",
            args = {boolean.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication but client fails to authenticate (Authenticator was not set up in the system).",
            method = "setConnectTimeout",
            args = {int.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies HTTPS connection process made through the proxy server. Proxy server needs authentication but client fails to authenticate (Authenticator was not set up in the system).",
            method = "setReadTimeout",
            args = {int.class}
        )
    })
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testProxyAuthConnectionFailed() throws Throwable {
        // setting up the properties pointing to the key/trust stores
        setUpStoreProperties();

        try {
            // create the SSLServerSocket which will be used by server side
            ServerSocket ss = new ServerSocket(0);

            // create the HostnameVerifier to check that Hostname verification
            // is done
            TestHostnameVerifier hnv = new TestHostnameVerifier();
            HttpsURLConnection.setDefaultHostnameVerifier(hnv);

            // create HttpsURLConnection to be tested
            URL url = new URL("https://requested.host:55555/requested.data");
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection(new Proxy(Proxy.Type.HTTP,
                            new InetSocketAddress("localhost", ss
                                    .getLocalPort())));

            // perform the interaction between the peers and check the results
            try {
                doInteraction(connection, ss, AUTHENTICATION_REQUIRED_CODE,
                        true);
            } catch (IOException e) {
                // SSL Tunnelling failed
                if (DO_LOG) {
                    System.out.println("Got expected IOException: "
                            + e.getMessage());
                }
            }
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    /**
     * Tests the behaviour of HTTPS connection in case of unavailability
     * of requested resource.
     */
    @TestTargets({
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies the behaviour of HTTPS connection in case of unavailability of requested resource.",
            method = "setDoInput",
            args = {boolean.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies the behaviour of HTTPS connection in case of unavailability of requested resource.",
            method = "setConnectTimeout",
            args = {int.class}
        ),
        @TestTargetNew(
            level = TestLevel.PARTIAL,
            notes = "Verifies the behaviour of HTTPS connection in case of unavailability of requested resource.",
            method = "setReadTimeout",
            args = {int.class}
        )
    })
    @KnownFailure("Handshake fails.")
    @AndroidOnly("we only have a .bks key store in the test resources")
    public void testProxyConnection_Not_Found_Response() throws Throwable {
        // setting up the properties pointing to the key/trust stores
        setUpStoreProperties();

        try {
            // create the SSLServerSocket which will be used by server side
            ServerSocket ss = new ServerSocket(0);

            // create the HostnameVerifier to check that Hostname verification
            // is done
            TestHostnameVerifier hnv = new TestHostnameVerifier();
            HttpsURLConnection.setDefaultHostnameVerifier(hnv);

            // create HttpsURLConnection to be tested
            URL url = new URL("https://localhost:" + ss.getLocalPort());
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection(new Proxy(Proxy.Type.HTTP,
                            new InetSocketAddress("localhost", ss
                                    .getLocalPort())));

            try {
                doInteraction(connection, ss, NOT_FOUND_CODE); // NOT FOUND
                fail("Expected exception was not thrown.");
            } catch (FileNotFoundException e) {
                if (DO_LOG) {
                    System.out.println("Expected exception was thrown: "
                            + e.getMessage());
                }
            }
        } finally {
            // roll the properties back to system values
            tearDownStoreProperties();
        }
    }

    // ---------------------------------------------------------------------
    // ------------------------ Staff Methods ------------------------------
    // ---------------------------------------------------------------------

    /**
     * Log the name of the test case to be executed.
     */
    public void setUp() throws Exception {
        if (DO_LOG) {
            System.out.println();
            System.out.println("------------------------");
            System.out.println("------ " + getName());
            System.out.println("------------------------");
        }
        
        if (store != null) {
            String ksFileName = "org/apache/harmony/luni/tests/key_store."
                    + KeyStore.getDefaultType().toLowerCase();
            InputStream in = getClass().getClassLoader()
                    .getResourceAsStream(ksFileName);
            FileOutputStream out = new FileOutputStream(store);
            BufferedInputStream bufIn = new BufferedInputStream(in, 8192);
            while (bufIn.available() > 0) {
                byte[] buf = new byte[128];
                int read = bufIn.read(buf);
                out.write(buf, 0, read);
            }
            bufIn.close();
            out.close();
        } else {
            fail("couldn't set up key store");
        }
    }

    public void tearDown() {
        if (store != null) {
            store.delete();
        }
    }
    
    /**
     * Checks the HttpsURLConnection getter's values and compares
     * them with actual corresponding values of remote peer.
     */
    public static void checkConnectionStateParameters(
            HttpsURLConnection clientConnection, SSLSocket serverPeer)
            throws Exception {
        SSLSession session = serverPeer.getSession();

        assertEquals(session.getCipherSuite(), clientConnection
                .getCipherSuite());

        assertEquals(session.getLocalPrincipal(), clientConnection
                .getPeerPrincipal());

        assertEquals(session.getPeerPrincipal(), clientConnection
                .getLocalPrincipal());

        Certificate[] serverCertificates = clientConnection
                .getServerCertificates();
        Certificate[] localCertificates = session.getLocalCertificates();
        assertTrue("Server certificates differ from expected", Arrays.equals(
                serverCertificates, localCertificates));

        localCertificates = clientConnection.getLocalCertificates();
        serverCertificates = session.getPeerCertificates();
        assertTrue("Local certificates differ from expected", Arrays.equals(
                serverCertificates, localCertificates));
    }

    /**
     * Returns the file name of the key/trust store. The key store file 
     * (named as "key_store." + extension equals to the default KeyStore
     * type installed in the system in lower case) is searched in classpath.
     * @throws AssertionFailedError if property was not set 
     * or file does not exist.
     */
    private static String getKeyStoreFileName() {
        return store.getAbsolutePath();
    }

    /**
     * Builds and returns the context used for secure socket creation.
     */
    private static SSLContext getContext() throws Exception {
        String type = KeyStore.getDefaultType();
        SSLContext ctx;

        String keyStore = getKeyStoreFileName();
        File keyStoreFile = new File(keyStore);

        FileInputStream fis = new FileInputStream(keyStoreFile);

        KeyStore ks = KeyStore.getInstance(type);
        ks.load(fis, KS_PASSWORD.toCharArray());

        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
                .getDefaultAlgorithm());
        kmf.init(ks, KS_PASSWORD.toCharArray());

        TrustManagerFactory tmf = TrustManagerFactory
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(ks);

        ctx = SSLContext.getInstance("TLSv1");
        ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        return ctx;
    }

    /**
     * Sets up the properties pointing to the key store and trust store
     * and used as default values by JSSE staff. This is needed to test
     * HTTPS behaviour in the case of default SSL Socket Factories.
     */
    private static void setUpStoreProperties() throws Exception {
        String type = KeyStore.getDefaultType();

        systemKeyStoreType = System.getProperty("javax.net.ssl.keyStoreType");
        systemKeyStore = System.getProperty("javax.net.ssl.keyStore");
        systemKeyStorePassword = System
                .getProperty("javax.net.ssl.keyStorePassword");

        systemTrustStoreType = System
                .getProperty("javax.net.ssl.trustStoreType");
        systemTrustStore = System.getProperty("javax.net.ssl.trustStore");
        systemTrustStorePassword = System
                .getProperty("javax.net.ssl.trustStorePassword");

        System.setProperty("javax.net.ssl.keyStoreType", type);
        System.setProperty("javax.net.ssl.keyStore", getKeyStoreFileName());
        System.setProperty("javax.net.ssl.keyStorePassword", KS_PASSWORD);

        System.setProperty("javax.net.ssl.trustStoreType", type);
        System.setProperty("javax.net.ssl.trustStore", getKeyStoreFileName());
        System.setProperty("javax.net.ssl.trustStorePassword", KS_PASSWORD);
    }

    /**
     * Rolls back the values of system properties.
     */
    private static void tearDownStoreProperties() {
        if (systemKeyStoreType == null) {
            System.clearProperty("javax.net.ssl.keyStoreType");
        } else {
            System
                    .setProperty("javax.net.ssl.keyStoreType",
                            systemKeyStoreType);
        }
        if (systemKeyStore == null) {
            System.clearProperty("javax.net.ssl.keyStore");
        } else {
            System.setProperty("javax.net.ssl.keyStore", systemKeyStore);
        }
        if (systemKeyStorePassword == null) {
            System.clearProperty("javax.net.ssl.keyStorePassword");
        } else {
            System.setProperty("javax.net.ssl.keyStorePassword",
                    systemKeyStorePassword);
        }

        if (systemTrustStoreType == null) {
            System.clearProperty("javax.net.ssl.trustStoreType");
        } else {
            System.setProperty("javax.net.ssl.trustStoreType",
                    systemTrustStoreType);
        }
        if (systemTrustStore == null) {
            System.clearProperty("javax.net.ssl.trustStore");
        } else {
            System.setProperty("javax.net.ssl.trustStore", systemTrustStore);
        }
        if (systemTrustStorePassword == null) {
            System.clearProperty("javax.net.ssl.trustStorePassword");
        } else {
            System.setProperty("javax.net.ssl.trustStorePassword",
                    systemTrustStorePassword);
        }
    }

    /**
     * Performs interaction between client's HttpURLConnection and
     * servers side (ServerSocket).
     */
    public static Socket doInteraction(
            final HttpURLConnection clientConnection,
            final ServerSocket serverSocket) throws Throwable {
        return doInteraction(clientConnection, serverSocket, OK_CODE, false);
    }

    /**
     * Performs interaction between client's HttpURLConnection and
     * servers side (ServerSocket). Server will response with specified
     * response code.
     */
    public static Socket doInteraction(
            final HttpURLConnection clientConnection,
            final ServerSocket serverSocket, final int responseCode)
            throws Throwable {
        return doInteraction(clientConnection, serverSocket, responseCode,
                false);
    }

    /**
     * Performs interaction between client's HttpURLConnection and
     * servers side (ServerSocket). Server will response with specified
     * response code.
     * @param doAuthentication specifies 
     * if the server needs client authentication.
     */
    public static Socket doInteraction(
            final HttpURLConnection clientConnection,
            final ServerSocket serverSocket, final int responseCode,
            final boolean doAuthentication) throws Throwable {

        // set up the connection
        clientConnection.setDoInput(true);
        clientConnection.setConnectTimeout(TIMEOUT);
        clientConnection.setReadTimeout(TIMEOUT);

        ServerWork server = new ServerWork(serverSocket, responseCode,
                doAuthentication);

        ClientConnectionWork client = new ClientConnectionWork(clientConnection);

        server.start();
        client.start();

        client.join();
        server.join();

        if (client.thrown != null) {
            if (responseCode != OK_CODE) { // not OK response expected
                // it is probably expected exception, keep it as is
                throw client.thrown;
            }
            if ((client.thrown instanceof SocketTimeoutException)
                    && (server.thrown != null)) {
                // server's exception is more informative in this case
                throw new Exception(server.thrown);
            } else {
                throw new Exception(client.thrown);
            }
        }
        if (server.thrown != null) {
            throw server.thrown;
        }
        return server.peerSocket;
    }

    /**
     * The host name verifier used in test.
     */
    static class TestHostnameVerifier implements HostnameVerifier {

        boolean verified = false;

        public boolean verify(String hostname, SSLSession session) {
            if (DO_LOG) {
                System.out.println("***> verification " + hostname + " "
                        + session.getPeerHost());
            }
            verified = true;
            return true;
        }
    }

    /**
     * The base class for mock Client and Server.
     */
    static class Work extends Thread {

        /**
         * The header of OK HTTP response.
         */
        static final String responseHead = "HTTP/1.1 200 OK\n";

        /**
         * The content of the response.
         */
        static final String plainResponseContent = "<HTML>\n"
                + "<HEAD><TITLE>Plain Response Content</TITLE></HEAD>\n"
                + "</HTML>";

        /**
         * The tail of the response.
         */
        static final String plainResponseTail = "Content-type: text/html\n"
                + "Content-length: " + plainResponseContent.length() + "\n\n"
                + plainResponseContent;

        /**
         * The response message to be sent in plain (HTTP) format.
         */
        static final String plainResponse = responseHead + plainResponseTail;

        /**
         * The content of the response to be sent during HTTPS session.
         */
        static final String httpsResponseContent = "<HTML>\n"
                + "<HEAD><TITLE>HTTPS Response Content</TITLE></HEAD>\n"
                + "</HTML>";

        /**
         * The tail of the response to be sent during HTTPS session.
         */
        static final String httpsResponseTail = "Content-type: text/html\n"
                + "Content-length: " + httpsResponseContent.length() + "\n\n"
                + httpsResponseContent;

        /**
         * The response requiring client's proxy authentication.
         */
        static final String respAuthenticationRequired = "HTTP/1.0 407 Proxy authentication required\n"
                + "Proxy-authenticate: Basic realm=\"localhost\"\n\n";

        /**
         * The data to be posted by client to the server.
         */
        static final String clientsData = "_.-^ Client's Data ^-._";

        /**
         * The exception thrown during peers interaction.
         */
        protected Throwable thrown;

        /**
         * The print stream used for debug log.
         * If it is null debug info will not be printed.
         */
        private PrintStream out = new PrintStream(System.out);

        /**
         * Prints log message.
         */
        public synchronized void log(String message) {
            if (DO_LOG && (out != null)) {
                System.out.println("[" + getName() + "]: " + message);
            }
        }
    }

    /**
     * The class used for server side works.
     */
    static class ServerWork extends Work {

        // the server socket used for connection
        private ServerSocket serverSocket;

        // the socket connected with client peer
        private Socket peerSocket;

        // indicates if the server acts as proxy server
        private boolean actAsProxy;

        // indicates if the server needs proxy authentication
        private boolean needProxyAuthentication;

        // response code to be send to the client peer
        private int responseCode;

        /**
         * Creates the thread acting as a server side.
         */
        public ServerWork(ServerSocket serverSocket) {
            // the server does not require proxy authentication
            // and sends OK_CODE (OK) response code
            this(serverSocket, OK_CODE, false);
        }

        /**
         * Creates the thread acting as a server side.
         * @param serverSocket the server socket to be used during connection
         * @param responseCode the response code to be sent to the client
         * @param needProxyAuthentication
         * indicates if the server needs proxy authentication
         */
        public ServerWork(ServerSocket serverSocket, int responseCode,
                boolean needProxyAuthentication) {
            this.serverSocket = serverSocket;
            this.responseCode = responseCode;
            this.needProxyAuthentication = needProxyAuthentication;
            // will act as a proxy server if the specified server socket
            // is not a secure server socket
            if (serverSocket instanceof SSLServerSocket) {
                // demand client to send its certificate
                ((SSLServerSocket) serverSocket).setNeedClientAuth(true);
                // work as a HTTPS server, not as HTTP proxy
                this.actAsProxy = false;
            } else {
                this.actAsProxy = true;
            }
            this.actAsProxy = !(serverSocket instanceof SSLServerSocket);
            setName(this.actAsProxy ? "Proxy Server" : "Server");
        }

        /**
         * Closes the connection.
         */
        public void closeSocket(Socket socket) {
            try {
                socket.getInputStream().close();
            } catch (IOException e) {}
            try {
                socket.getOutputStream().close();
            } catch (IOException e) {}
            try {
                socket.close();
            } catch (IOException e) {}
        }

        /**
         * Performs the actual server work.
         * If some exception occurs during the work it will be
         * stored in the <code>thrown</code> field.
         */
        public void run() {
            // the buffer used for reading the messages
            byte[] buff = new byte[2048];
            // the number of bytes read into the buffer
            int num;
            try {
                // configure the server socket to avoid blocking
                serverSocket.setSoTimeout(TIMEOUT);
                // accept client connection
                peerSocket = serverSocket.accept();
                // configure the client connection to avoid blocking
                peerSocket.setSoTimeout(TIMEOUT);
                log("Client connection ACCEPTED");

                InputStream is = peerSocket.getInputStream();
                OutputStream os = peerSocket.getOutputStream();

                num = is.read(buff);
                String message = new String(buff, 0, num);
                log("Got request:\n" + message);
                log("------------------");

                if (!actAsProxy) {
                    // Act as Server (not Proxy) side
                    if (message.startsWith("POST")) {
                        // client connection sent some data
                        log("try to read client data");
                        num = is.read(buff);
                        message = new String(buff, 0, num);
                        log("client's data: '" + message + "'");
                        // check the received data
                        assertEquals(clientsData, message);
                    }
                    // just send the response
                    os
                            .write(("HTTP/1.1 " + responseCode + "\n" + httpsResponseTail)
                                    .getBytes());
                    os.flush();
                    os.close();
                    // and return
                    log("Work is DONE !actAsProxy");
                    return;
                }

                // Do proxy work
                if (needProxyAuthentication) {
                    log("Authentication required ...");
                    // send Authentication Request
                    os.write(respAuthenticationRequired.getBytes());
                    // read response
                    num = is.read(buff);
                    if (num == -1) {
                        // this connection was closed, 
                        // do clean up and create new one:
                        closeSocket(peerSocket);
                        peerSocket = serverSocket.accept();
                        peerSocket.setSoTimeout(TIMEOUT);
                        log("New client connection ACCEPTED");
                        is = peerSocket.getInputStream();
                        os = peerSocket.getOutputStream();
                        num = is.read(buff);
                    }
                    message = new String(buff, 0, num);
                    log("Got authenticated request:\n" + message);
                    log("------------------");
                    // check provided authorization credentials
                    assertTrue("Received message does not contain "
                            + "authorization credentials", message
                            .toLowerCase().indexOf("proxy-authorization:") > 0);
                }

                // The content of this response will reach proxied HTTPUC
                // but will not reach proxied HTTPSUC
                // In case of HTTP connection it will be the final message,
                // in case of HTTPS connection this message will just indicate
                // that connection with remote host has been done
                // (i.e. SSL tunnel has been established).
                os.write(plainResponse.getBytes());
                log("Sent OK RESPONSE");

                if (message.startsWith("CONNECT")) { // request for SSL tunnel
                    log("Perform SSL Handshake...");
                    // create sslSocket acting as a remote server peer
                    SSLSocket sslSocket = (SSLSocket) getContext()
                            .getSocketFactory().createSocket(peerSocket,
                                    "localhost", peerSocket.getPort(), true); // do autoclose
                    sslSocket.setUseClientMode(false);
                    // demand client authentication
                    sslSocket.setNeedClientAuth(true);
                    sslSocket.startHandshake();
                    peerSocket = sslSocket;
                    is = peerSocket.getInputStream();
                    os = peerSocket.getOutputStream();

                    // read the HTTP request sent by secure connection
                    // (HTTPS request)
                    num = is.read(buff);
                    message = new String(buff, 0, num);
                    log("[Remote Server] Request from SSL tunnel:\n" + message);
                    log("------------------");

                    if (message.startsWith("POST")) {
                        // client connection sent some data
                        log("[Remote Server] try to read client data");
                        num = is.read(buff);
                        message = new String(buff, 0, num);
                        log("[Remote Server] client's data: '" + message + "'");
                        // check the received data
                        assertEquals(clientsData, message);
                    }

                    log("[Remote Server] Sending the response by SSL tunnel..");
                    // send the response with specified response code
                    os
                            .write(("HTTP/1.1 " + responseCode + "\n" + httpsResponseTail)
                                    .getBytes());
                }
                log("Work is DONE actAsProxy");
            } catch (Throwable e) {
                if (DO_LOG) {
                    e.printStackTrace();
                }
                thrown = e;
            } finally {
                closeSocket(peerSocket);
                try {
                    serverSocket.close();
                } catch (IOException e) {}
            }
        }
    }

    /**
     * The class used for client side works. It could be used to test
     * both HttpURLConnection and HttpsURLConnection.
     */
    static class ClientConnectionWork extends Work {

        // connection to be used to contact the server side
        private HttpURLConnection connection;

        /**
         * Creates the thread acting as a client side.
         * @param connection connection to be used to contact the server side
         */
        public ClientConnectionWork(HttpURLConnection connection) {
            this.connection = connection;
            setName("Client Connection");
            log("Created over connection: " + connection.getClass());
        }

        /**
         * Performs the actual client work.
         * If some exception occurs during the work it will be
         * stored in the <code>thrown<code> field.
         */
        public void run() {
            try {
                log("Opening the connection..");
                connection.connect();
                log("Connection has been ESTABLISHED, using proxy: "
                        + connection.usingProxy());
                if (connection.getDoOutput()) {
                    // connection configured to post data, do so
                    connection.getOutputStream().write(clientsData.getBytes());
                }
                // read the content of HTTP(s) response
                InputStream is = connection.getInputStream();
                log("Input Stream obtained");
                byte[] buff = new byte[2048];
                int num = 0;
                int byt = 0;
                while ((num < buff.length) && (is.available() > 0)
                        && ((byt = is.read()) != -1)) {
                    buff[num++] = (byte) byt;
                }
                String message = new String(buff, 0, num);
                log("Got content:\n" + message);
                log("------------------");
                log("Response code: " + connection.getResponseCode());

                if (connection instanceof HttpsURLConnection) {
                    assertEquals(httpsResponseContent, message);
                } else {
                    assertEquals(plainResponseContent, message);
                }
            } catch (Throwable e) {
                if (DO_LOG) {
                    e.printStackTrace();
                }
                thrown = e;
            }
        }
    }
}