1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.luni.tests.internal.net.www.protocol.https;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
2076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fullerimport com.google.mockwebserver.Dispatcher;
2176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fullerimport com.google.mockwebserver.MockResponse;
2276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fullerimport com.google.mockwebserver.MockWebServer;
2376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fullerimport com.google.mockwebserver.RecordedRequest;
2476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fullerimport com.google.mockwebserver.SocketPolicy;
2576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.BufferedInputStream;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.File;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.FileInputStream;
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.FileNotFoundException;
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.FileOutputStream;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.OutputStream;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.Authenticator;
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.InetSocketAddress;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.PasswordAuthentication;
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.Proxy;
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.ServerSocket;
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.Socket;
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URL;
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.KeyStore;
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.Certificate;
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Arrays;
4476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fullerimport java.util.Collections;
4576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fullerimport java.util.LinkedList;
4676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
47507154fd78b95c46be07a52aedd92a45e3783a62Jesse Wilsonimport javax.net.ssl.HostnameVerifier;
48507154fd78b95c46be07a52aedd92a45e3783a62Jesse Wilsonimport javax.net.ssl.HttpsURLConnection;
49f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstromimport javax.net.ssl.KeyManager;
50507154fd78b95c46be07a52aedd92a45e3783a62Jesse Wilsonimport javax.net.ssl.KeyManagerFactory;
51507154fd78b95c46be07a52aedd92a45e3783a62Jesse Wilsonimport javax.net.ssl.SSLContext;
52507154fd78b95c46be07a52aedd92a45e3783a62Jesse Wilsonimport javax.net.ssl.SSLSession;
53507154fd78b95c46be07a52aedd92a45e3783a62Jesse Wilsonimport javax.net.ssl.SSLSocketFactory;
54f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstromimport javax.net.ssl.TrustManager;
55507154fd78b95c46be07a52aedd92a45e3783a62Jesse Wilsonimport javax.net.ssl.TrustManagerFactory;
56507154fd78b95c46be07a52aedd92a45e3783a62Jesse Wilsonimport junit.framework.TestCase;
57f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstromimport libcore.java.security.TestKeyStore;
58f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstromimport libcore.javax.net.ssl.TestTrustManager;
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Implementation independent test for HttpsURLConnection.
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class HttpsURLConnectionTest extends TestCase {
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
6576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    private static final String POST_METHOD = "POST";
6676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
6776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    private static final String GET_METHOD = "GET";
6876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
6976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    /**
7076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * Data to be posted by client to the server when the method is POST.
7176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     */
7276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    private static final String POST_DATA = "_.-^ Client's Data ^-._";
7376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
7476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    /**
7576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * The content of the response to be sent during HTTPS session.
7676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     */
7776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    private static final String RESPONSE_CONTENT
7876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            = "<HTML>\n"
7976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            + "<HEAD><TITLE>HTTPS Response Content</TITLE></HEAD>\n"
8076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            + "</HTML>";
8176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // the password to the store
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final String KS_PASSWORD = "password";
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // turn on/off logging
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final boolean DO_LOG = false;
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // read/connection timeout value
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int TIMEOUT = 5000;
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // OK response code
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int OK_CODE = 200;
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Not Found response code
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int NOT_FOUND_CODE = 404;
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Proxy authentication required response code
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int AUTHENTICATION_REQUIRED_CODE = 407;
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static File store;
101f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static {
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            store = File.createTempFile("key_store", "bks");
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (Exception e) {
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // ignore
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Checks that HttpsURLConnection's default SSLSocketFactory is operable.
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void testGetDefaultSSLSocketFactory() throws Exception {
11476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set up the properties pointing to the key/trust stores
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setUpStoreProperties();
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
117f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        SSLSocketFactory defaultSSLSF = HttpsURLConnection.getDefaultSSLSocketFactory();
118d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        ServerSocket ss = new ServerSocket(0);
119f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        Socket s = defaultSSLSF.createSocket("localhost", ss.getLocalPort());
120d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        ss.accept();
121d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        s.close();
122d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        ss.close();
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void testHttpsConnection() throws Throwable {
12676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set up the properties pointing to the key/trust stores
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setUpStoreProperties();
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
129d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        SSLContext ctx = getContext();
130d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
13176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
13276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
13376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
13476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // create a webserver to check and respond to requests
13576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SingleRequestDispatcher dispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
13676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        MockWebServer webServer = createWebServer(ctx, dispatcher);
137d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
138d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // create url connection to be tested
13976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        URL url = webServer.getUrl("/");
140f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
141f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        connection.setSSLSocketFactory(ctx.getSocketFactory());
142d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
143d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // perform the interaction between the peers
14476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        executeClientRequest(connection, false /* doOutput */);
145d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
14676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        checkConnectionStateParameters(connection, dispatcher.getLastRequest());
147d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
148d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // should silently exit
149d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        connection.connect();
15076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
15176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        webServer.shutdown();
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
15576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * Tests the behaviour of HTTPS connection in case of unavailability of requested resource.
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void testHttpsConnection_Not_Found_Response() throws Throwable {
15876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set up the properties pointing to the key/trust stores
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setUpStoreProperties();
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
161d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        SSLContext ctx = getContext();
162d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
16376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
16476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
16576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
16676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // create a webserver to check and respond to requests
16776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SingleRequestDispatcher dispatcher =
16876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                new SingleRequestDispatcher(GET_METHOD, NOT_FOUND_CODE);
16976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        MockWebServer webServer = createWebServer(ctx, dispatcher);
170d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
171d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // create url connection to be tested
17276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        URL url = webServer.getUrl("/");
173f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
174f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        connection.setSSLSocketFactory(ctx.getSocketFactory());
175d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
17776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            executeClientRequest(connection, false /* doOutput */);
178d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson            fail("Expected exception was not thrown.");
179d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        } catch (FileNotFoundException e) {
180d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson            if (DO_LOG) {
181f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom                System.out.println("Expected exception was thrown: " + e.getMessage());
182f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom                e.printStackTrace();
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
185d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
186d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // should silently exit
187d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        connection.connect();
18876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
18976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        webServer.shutdown();
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
19376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * Tests possibility to set up the default SSLSocketFactory to be used by HttpsURLConnection.
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void testSetDefaultSSLSocketFactory() throws Throwable {
19676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set up the properties pointing to the key/trust stores
19776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        setUpStoreProperties();
19876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SSLContext ctx = getContext();
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SSLSocketFactory socketFactory = ctx.getSocketFactory();
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // set up the factory as default
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // check the result
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        assertSame("Default SSLSocketFactory differs from expected",
20676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                socketFactory, HttpsURLConnection.getDefaultSSLSocketFactory());
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set the initial default host name verifier.
20976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        TestHostnameVerifier initialHostnameVerifier = new TestHostnameVerifier();
21076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        HttpsURLConnection.setDefaultHostnameVerifier(initialHostnameVerifier);
21176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
21276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // create a webserver to check and respond to requests
21376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SingleRequestDispatcher dispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
21476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        MockWebServer webServer = createWebServer(ctx, dispatcher);
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // create HttpsURLConnection to be tested
21776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        URL url = webServer.getUrl("/");
218f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
22076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // late initialization: this HostnameVerifier should not be used for created connection
22176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        TestHostnameVerifier lateHostnameVerifier = new TestHostnameVerifier();
22276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        HttpsURLConnection.setDefaultHostnameVerifier(lateHostnameVerifier);
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // perform the interaction between the peers
22576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        executeClientRequest(connection, false /* doOutput */);
22676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        checkConnectionStateParameters(connection, dispatcher.getLastRequest());
22776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // check the verification process
22976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        assertTrue("Hostname verification was not done", initialHostnameVerifier.verified);
230f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        assertFalse("Hostname verification should not be done by this verifier",
23176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                lateHostnameVerifier.verified);
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // check the used SSLSocketFactory
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        assertSame("Default SSLSocketFactory should be used",
23476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                HttpsURLConnection.getDefaultSSLSocketFactory(),
23576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                connection.getSSLSocketFactory());
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
23776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        webServer.shutdown();
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
24176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * Tests
24276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * {@link javax.net.ssl.HttpsURLConnection#setSSLSocketFactory(javax.net.ssl.SSLSocketFactory)}.
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void testSetSSLSocketFactory() throws Throwable {
24576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set up the properties pointing to the key/trust stores
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SSLContext ctx = getContext();
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
24876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set the initial default host name verifier.
24976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        TestHostnameVerifier hostnameVerifier = new TestHostnameVerifier();
25076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
25176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
25276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // create a webserver to check and respond to requests
25376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SingleRequestDispatcher dispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
25476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        MockWebServer webServer = createWebServer(ctx, dispatcher);
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // create HttpsURLConnection to be tested
25776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        URL url = webServer.getUrl("/");
258f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
26076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // late initialization: should not be used for the created connection.
26176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SSLSocketFactory socketFactory = ctx.getSocketFactory();
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        connection.setSSLSocketFactory(socketFactory);
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // late initialization: should not be used for created connection
26576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        TestHostnameVerifier lateHostnameVerifier = new TestHostnameVerifier();
26676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        HttpsURLConnection.setDefaultHostnameVerifier(lateHostnameVerifier);
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // perform the interaction between the peers
26976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        executeClientRequest(connection, false /* doOutput */);
27076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        checkConnectionStateParameters(connection, dispatcher.getLastRequest());
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // check the verification process
27276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        assertTrue("Hostname verification was not done", hostnameVerifier.verified);
273f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        assertFalse("Hostname verification should not be done by this verifier",
27476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                lateHostnameVerifier.verified);
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // check the used SSLSocketFactory
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        assertNotSame("Default SSLSocketFactory should not be used",
27776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                HttpsURLConnection.getDefaultSSLSocketFactory(),
27876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                connection.getSSLSocketFactory());
27976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        assertSame("Result differs from expected", socketFactory, connection.getSSLSocketFactory());
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
28176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        webServer.shutdown();
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Tests the behaviour of HttpsURLConnection in case of retrieving
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * of the connection state parameters before connection has been made.
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void testUnconnectedStateParameters() throws Throwable {
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // create HttpsURLConnection to be tested
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        URL url = new URL("https://localhost:55555");
291f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            connection.getCipherSuite();
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fail("Expected IllegalStateException was not thrown");
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (IllegalStateException e) {}
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            connection.getPeerPrincipal();
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fail("Expected IllegalStateException was not thrown");
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (IllegalStateException e) {}
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            connection.getLocalPrincipal();
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fail("Expected IllegalStateException was not thrown");
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (IllegalStateException e) {}
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            connection.getServerCertificates();
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fail("Expected IllegalStateException was not thrown");
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (IllegalStateException e) {}
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            connection.getLocalCertificates();
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fail("Expected IllegalStateException was not thrown");
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (IllegalStateException e) {}
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Tests if setHostnameVerifier() method replaces default verifier.
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void testSetHostnameVerifier() throws Throwable {
32076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set up the properties pointing to the key/trust stores
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setUpStoreProperties();
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
32376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SSLContext ctx = getContext();
32476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
32576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        TestHostnameVerifier defaultHostnameVerifier = new TestHostnameVerifier();
32676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        HttpsURLConnection.setDefaultHostnameVerifier(defaultHostnameVerifier);
327d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
32876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // create a webserver to check and respond to requests
32976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SingleRequestDispatcher dispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
33076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        MockWebServer webServer = createWebServer(ctx, dispatcher);
331d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
332d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // create HttpsURLConnection to be tested
33376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        URL url = webServer.getUrl("/");
334f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
335f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        connection.setSSLSocketFactory(getContext().getSocketFactory());
336d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
33776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // replace the default verifier
33876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        TestHostnameVerifier connectionHostnameVerifier = new TestHostnameVerifier();
33976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        connection.setHostnameVerifier(connectionHostnameVerifier);
340d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
341d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // perform the interaction between the peers and check the results
34276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        executeClientRequest(connection, false /* doOutput */);
34376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        assertTrue("Hostname verification was not done", connectionHostnameVerifier.verified);
344f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        assertFalse("Hostname verification should not be done by this verifier",
34576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                defaultHostnameVerifier.verified);
346d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
34776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        checkConnectionStateParameters(connection, dispatcher.getLastRequest());
34876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
34976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        webServer.shutdown();
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Tests the behaviour in case of sending the data to the server.
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void test_doOutput() throws Throwable {
35676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set up the properties pointing to the key/trust stores
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setUpStoreProperties();
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
35976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SSLContext ctx = getContext();
360d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
36176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // create a webserver to check and respond to requests
36276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SingleRequestDispatcher dispatcher = new SingleRequestDispatcher(POST_METHOD, OK_CODE);
36376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        MockWebServer webServer = createWebServer(ctx, dispatcher);
36476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
36576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
36676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
367d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
368d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // create HttpsURLConnection to be tested
36976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        URL url = webServer.getUrl("/");
370f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
371f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        connection.setSSLSocketFactory(getContext().getSocketFactory());
372d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
373d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // perform the interaction between the peers and check the results
37476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        executeClientRequest(connection, true /* doOutput */);
37576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        checkConnectionStateParameters(connection, dispatcher.getLastRequest());
376d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
377d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // should silently exit
378d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        connection.connect();
37976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
38076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        webServer.shutdown();
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Tests HTTPS connection process made through the proxy server.
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void testProxyConnection() throws Throwable {
38776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set up the properties pointing to the key/trust stores
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setUpStoreProperties();
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
39076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SSLContext ctx = getContext();
391d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
39276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
39376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
39476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
39576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // create a server that pretends to be both a proxy and then the webserver
39676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // request 1: proxy CONNECT, respond with OK
39776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        ProxyConnectDispatcher proxyConnectDispatcher =
39876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                new ProxyConnectDispatcher(false /* authenticationRequired */);
39976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // request 2: tunnelled GET, respond with OK
40076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SingleRequestDispatcher getDispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
40176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        DelegatingDispatcher delegatingDispatcher =
40276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                new DelegatingDispatcher(proxyConnectDispatcher, getDispatcher);
40376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        MockWebServer proxyAndWebServer = createProxyAndWebServer(ctx, delegatingDispatcher);
404d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
405d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // create HttpsURLConnection to be tested
40676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        URL proxyUrl = proxyAndWebServer.getUrl("/");
40776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl.getPort());
408d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        URL url = new URL("https://requested.host:55556/requested.data");
409f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        HttpsURLConnection connection = (HttpsURLConnection)
41076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                url.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
411f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        connection.setSSLSocketFactory(getContext().getSocketFactory());
412d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
413d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // perform the interaction between the peers and check the results
41476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        executeClientRequest(connection, false /* doOutput */);
41576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        checkConnectionStateParameters(connection, getDispatcher.getLastRequest());
416d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
417d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // should silently exit
418d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        connection.connect();
41976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
42076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        proxyAndWebServer.shutdown();
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Tests HTTPS connection process made through the proxy server.
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Proxy server needs authentication.
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void testProxyAuthConnection() throws Throwable {
42876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set up the properties pointing to the key/trust stores
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setUpStoreProperties();
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
43176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SSLContext ctx = getContext();
432d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
43376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
43476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
435d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
436d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        Authenticator.setDefault(new Authenticator() {
437d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson            protected PasswordAuthentication getPasswordAuthentication() {
43876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                return new PasswordAuthentication("user", "password".toCharArray());
439d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson            }
440d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        });
441d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
44276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // create a server that pretends to be both a proxy and then the webserver
44376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // request 1: proxy CONNECT, respond with auth challenge
44476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        ProxyConnectAuthFailDispatcher authFailDispatcher = new ProxyConnectAuthFailDispatcher();
44576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // request 2: proxy CONNECT, respond with OK
44676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        ProxyConnectDispatcher proxyConnectDispatcher =
44776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                new ProxyConnectDispatcher(true /* authenticationRequired */);
44876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // request 3: tunnelled GET, respond with OK
44976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SingleRequestDispatcher getDispatcher = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
45076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        DelegatingDispatcher delegatingDispatcher = new DelegatingDispatcher(
45176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                authFailDispatcher, proxyConnectDispatcher, getDispatcher);
45276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        MockWebServer proxyAndWebServer = createProxyAndWebServer(ctx, delegatingDispatcher);
45376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
454d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // create HttpsURLConnection to be tested
45576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        URL proxyUrl = proxyAndWebServer.getUrl("/");
45676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl.getPort());
457d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        URL url = new URL("https://requested.host:55555/requested.data");
458f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        HttpsURLConnection connection = (HttpsURLConnection)
45976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                url.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
460f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        connection.setSSLSocketFactory(getContext().getSocketFactory());
461d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
462d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // perform the interaction between the peers and check the results
46376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        executeClientRequest(connection, false /* doOutput */);
46476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        checkConnectionStateParameters(connection, getDispatcher.getLastRequest());
465d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
466d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // should silently exit
467d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        connection.connect();
46876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
46976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        proxyAndWebServer.shutdown();
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Tests HTTPS connection process made through the proxy server.
47476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * Two HTTPS connections are opened for one URL: the first time the connection is opened
47576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * through one proxy, the second time it is opened through another.
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void testConsequentProxyConnection() throws Throwable {
47876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set up the properties pointing to the key/trust stores
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setUpStoreProperties();
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
48176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
48276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
483d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
48476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // create a server that pretends to be both a proxy and then the webserver
48576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SingleRequestDispatcher getDispatcher1 = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
48676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        MockWebServer proxyAndWebServer1 = createProxiedServer(getDispatcher1);
487d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
488d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // create HttpsURLConnection to be tested
48976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        URL proxyUrl1 = proxyAndWebServer1.getUrl("/");
490d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        URL url = new URL("https://requested.host:55555/requested.data");
49176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl1.getPort());
492f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        HttpsURLConnection connection = (HttpsURLConnection)
49376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                url.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
494f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        connection.setSSLSocketFactory(getContext().getSocketFactory());
49576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller         executeClientRequest(connection, false /* doOutput */);
49676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        checkConnectionStateParameters(connection, getDispatcher1.getLastRequest());
497d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
49876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        proxyAndWebServer1.shutdown();
499d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
50076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // create another server
50176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SingleRequestDispatcher getDispatcher2 = new SingleRequestDispatcher(GET_METHOD, OK_CODE);
50276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        MockWebServer proxyAndWebServer2 = createProxiedServer(getDispatcher2);
503d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
50476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // create another HttpsURLConnection to be tested
50576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        URL proxyUrl2 = proxyAndWebServer2.getUrl("/");
50676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        InetSocketAddress proxyAddress2 = new InetSocketAddress("localhost", proxyUrl2.getPort());
50776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        HttpsURLConnection connection2 = (HttpsURLConnection) url.openConnection(
50876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                new Proxy(Proxy.Type.HTTP, proxyAddress2));
50976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        connection2.setSSLSocketFactory(getContext().getSocketFactory());
510d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
511d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // perform the interaction between the peers and check the results
51276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        executeClientRequest(connection2, false /* doOutput */);
51376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        checkConnectionStateParameters(connection2, getDispatcher2.getLastRequest());
51476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
51576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        proxyAndWebServer2.shutdown();
51676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    }
51776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
51876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    private static MockWebServer createProxiedServer(Dispatcher getDispatcher)
51976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            throws Exception {
52076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // request 1: proxy CONNECT, respond with OK
52176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        ProxyConnectDispatcher proxyConnectDispatcher =
52276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                new ProxyConnectDispatcher(false /* authenticationRequired */);
52376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // request 2: The get dispatcher.
52476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        DelegatingDispatcher delegatingDispatcher1 =
52576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                new DelegatingDispatcher(proxyConnectDispatcher, getDispatcher);
52676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        return createProxyAndWebServer(getContext(), delegatingDispatcher1);
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Tests HTTPS connection process made through the proxy server.
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Proxy server needs authentication.
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Client sends data to the server.
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void testProxyAuthConnection_doOutput() throws Throwable {
53576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set up the properties pointing to the key/trust stores
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setUpStoreProperties();
537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
53876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SSLContext ctx = getContext();
539d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
54076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
54176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
542d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
543d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        Authenticator.setDefault(new Authenticator() {
544d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson            protected PasswordAuthentication getPasswordAuthentication() {
54576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                return new PasswordAuthentication("user", "password".toCharArray());
546d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson            }
547d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        });
548d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
54976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // create a server that pretends to be both a proxy and then the webserver
55076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // request 1: proxy CONNECT, respond with auth challenge
55176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        ProxyConnectAuthFailDispatcher authFailDispatcher = new ProxyConnectAuthFailDispatcher();
55276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // request 2: proxy CONNECT, respond with OK
55376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        ProxyConnectDispatcher proxyConnectDispatcher =
55476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                new ProxyConnectDispatcher(true /* authenticationRequired */);
55576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // request 3: tunnelled POST, respond with OK
55676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SingleRequestDispatcher postDispatcher = new SingleRequestDispatcher(POST_METHOD, OK_CODE);
55776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        DelegatingDispatcher delegatingDispatcher = new DelegatingDispatcher(
55876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                authFailDispatcher, proxyConnectDispatcher, postDispatcher);
55976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        MockWebServer proxyAndWebServer = createProxyAndWebServer(ctx, delegatingDispatcher);
56076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        URL proxyUrl = proxyAndWebServer.getUrl("/");
56176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
562d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // create HttpsURLConnection to be tested
56376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl.getPort());
564f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        HttpsURLConnection connection = (HttpsURLConnection)
56576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                proxyUrl.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
566f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        connection.setSSLSocketFactory(getContext().getSocketFactory());
567d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
568d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // perform the interaction between the peers and check the results
56976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        executeClientRequest(connection, true /* doOutput */);
57076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        checkConnectionStateParameters(connection, postDispatcher.getLastRequest());
57176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
57276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // should silently exit
57376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        connection.connect();
57476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
57576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        proxyAndWebServer.shutdown();
576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Tests HTTPS connection process made through the proxy server.
580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Proxy server needs authentication but client fails to authenticate
581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * (Authenticator was not set up in the system).
582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void testProxyAuthConnectionFailed() throws Throwable {
58476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set up the properties pointing to the key/trust stores
585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setUpStoreProperties();
586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
58776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
58876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
589d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
59076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // create a server that pretends to be both a proxy that requests authentication.
59176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        MockWebServer proxyAndWebServer = new MockWebServer();
59276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        ProxyConnectAuthFailDispatcher authFailDispatcher = new ProxyConnectAuthFailDispatcher();
59376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        proxyAndWebServer.setDispatcher(authFailDispatcher);
59476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        proxyAndWebServer.play();
595d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
596d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // create HttpsURLConnection to be tested
59776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        URL proxyUrl = proxyAndWebServer.getUrl("/");
59876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl.getPort());
599d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        URL url = new URL("https://requested.host:55555/requested.data");
600f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        HttpsURLConnection connection = (HttpsURLConnection)
60176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                url.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
602f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        connection.setSSLSocketFactory(getContext().getSocketFactory());
603d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
604d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // perform the interaction between the peers and check the results
605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
60676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            executeClientRequest(connection, false);
607d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        } catch (IOException e) {
608d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson            // SSL Tunnelling failed
609d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson            if (DO_LOG) {
61076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                System.out.println("Got expected IOException: " + e.getMessage());
611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
61676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * Tests the behaviour of HTTPS connection in case of unavailability of requested resource (as
61776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * reported by the target web server).
618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void testProxyConnection_Not_Found_Response() throws Throwable {
62076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set up the properties pointing to the key/trust stores
621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        setUpStoreProperties();
622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
62376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SSLContext ctx = getContext();
624d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
62576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set the HostnameVerifier required to satisfy SSL - always returns "verified".
62676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        HttpsURLConnection.setDefaultHostnameVerifier(new TestHostnameVerifier());
62776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
62876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // create a server that pretends to be a proxy
62976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        ProxyConnectDispatcher proxyConnectDispatcher =
63076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                new ProxyConnectDispatcher(false /* authenticationRequired */);
63176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        SingleRequestDispatcher notFoundDispatcher =
63276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                new SingleRequestDispatcher(GET_METHOD, NOT_FOUND_CODE);
63376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        DelegatingDispatcher delegatingDispatcher =
63476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                new DelegatingDispatcher(proxyConnectDispatcher, notFoundDispatcher);
63576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        MockWebServer proxyAndWebServer = createProxyAndWebServer(ctx, delegatingDispatcher);
636d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
637d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        // create HttpsURLConnection to be tested
63876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        URL proxyUrl = proxyAndWebServer.getUrl("/");
63976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        InetSocketAddress proxyAddress = new InetSocketAddress("localhost", proxyUrl.getPort());
64076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        URL url = new URL("https://requested.host:55555/requested.data");
641f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        HttpsURLConnection connection = (HttpsURLConnection)
64276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                url.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddress));
643f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        connection.setSSLSocketFactory(getContext().getSocketFactory());
644d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
64676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            executeClientRequest(connection, false /* doOutput */);
647d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson            fail("Expected exception was not thrown.");
648d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        } catch (FileNotFoundException e) {
649d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson            if (DO_LOG) {
65076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                System.out.println("Expected exception was thrown: " + e.getMessage());
651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setUp() throws Exception {
656d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson        super.setUp();
657d37c804ccd11e38ee9221194866a152a4de6c8e9Jesse Wilson
658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (DO_LOG) {
65976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            // Log the name of the test case to be executed.
660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.out.println();
661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.out.println("------------------------");
662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.out.println("------ " + getName());
663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.out.println("------------------------");
664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
665f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (store != null) {
66776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            String ksFileName = "org/apache/harmony/luni/tests/key_store." +
66876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                    KeyStore.getDefaultType().toLowerCase();
669507154fd78b95c46be07a52aedd92a45e3783a62Jesse Wilson            InputStream in = getClass().getClassLoader().getResourceAsStream(ksFileName);
670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            FileOutputStream out = new FileOutputStream(store);
671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            BufferedInputStream bufIn = new BufferedInputStream(in, 8192);
672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            while (bufIn.available() > 0) {
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                byte[] buf = new byte[128];
674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int read = bufIn.read(buf);
675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                out.write(buf, 0, read);
676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            bufIn.close();
678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            out.close();
679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fail("couldn't set up key store");
681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void tearDown() {
685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (store != null) {
686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            store.delete();
687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
689f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
69076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    private static void checkConnectionStateParameters(
69176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            HttpsURLConnection connection, RecordedRequest request) throws Exception {
69276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        assertEquals(request.getSslCipherSuite(), connection.getCipherSuite());
69376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        assertEquals(request.getSslLocalPrincipal(), connection.getPeerPrincipal());
69476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        assertEquals(request.getSslPeerPrincipal(), connection.getLocalPrincipal());
695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
69676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        Certificate[] serverCertificates = connection.getServerCertificates();
69776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        Certificate[] localCertificates = request.getSslLocalCertificates();
698f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        assertTrue("Server certificates differ from expected",
69976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                Arrays.equals(serverCertificates, localCertificates));
700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
70176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        localCertificates = connection.getLocalCertificates();
70276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        serverCertificates = request.getSslPeerCertificates();
703f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        assertTrue("Local certificates differ from expected",
70476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                Arrays.equals(serverCertificates, localCertificates));
705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
708f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * Returns the file name of the key/trust store. The key store file
709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * (named as "key_store." + extension equals to the default KeyStore
710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * type installed in the system in lower case) is searched in classpath.
711210834b065f80d2bb9adc194f9e3fc662a12a95dJesse Wilson     * @throws junit.framework.AssertionFailedError if property was not set
712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * or file does not exist.
713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static String getKeyStoreFileName() {
715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return store.getAbsolutePath();
716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Builds and returns the context used for secure socket creation.
720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static SSLContext getContext() throws Exception {
722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String type = KeyStore.getDefaultType();
723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String keyStore = getKeyStoreFileName();
724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        File keyStoreFile = new File(keyStore);
725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        FileInputStream fis = new FileInputStream(keyStoreFile);
726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        KeyStore ks = KeyStore.getInstance(type);
728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ks.load(fis, KS_PASSWORD.toCharArray());
729f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        fis.close();
730f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        if (DO_LOG && false) {
731f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom            TestKeyStore.dump("HttpsURLConnection.getContext", ks, KS_PASSWORD.toCharArray());
732f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        }
733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
734f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        String kmfAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
735f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfAlgorithm);
736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        kmf.init(ks, KS_PASSWORD.toCharArray());
737f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        KeyManager[] keyManagers = kmf.getKeyManagers();
738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
739f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        String tmfAlgorthm = TrustManagerFactory.getDefaultAlgorithm();
740f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorthm);
741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        tmf.init(ks);
742f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        TrustManager[] trustManagers = tmf.getTrustManagers();
743f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        if (DO_LOG) {
744f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom            trustManagers = TestTrustManager.wrap(trustManagers);
745f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        }
746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
7473d74b4bec8543e6e3f89eafe3afe0925f3a69f01Brian Carlstrom        SSLContext ctx = SSLContext.getInstance("TLSv1");
748f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        ctx.init(keyManagers, trustManagers, null);
749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return ctx;
750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets up the properties pointing to the key store and trust store
754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * and used as default values by JSSE staff. This is needed to test
755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * HTTPS behaviour in the case of default SSL Socket Factories.
756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static void setUpStoreProperties() throws Exception {
758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String type = KeyStore.getDefaultType();
759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        System.setProperty("javax.net.ssl.keyStoreType", type);
761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        System.setProperty("javax.net.ssl.keyStore", getKeyStoreFileName());
762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        System.setProperty("javax.net.ssl.keyStorePassword", KS_PASSWORD);
763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        System.setProperty("javax.net.ssl.trustStoreType", type);
765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        System.setProperty("javax.net.ssl.trustStore", getKeyStoreFileName());
766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        System.setProperty("javax.net.ssl.trustStorePassword", KS_PASSWORD);
767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
77076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * The host name verifier used in test.
771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
77276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    static class TestHostnameVerifier implements HostnameVerifier {
77376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
77476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        boolean verified = false;
77576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
77676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        public boolean verify(String hostname, SSLSession session) {
77776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            if (DO_LOG) {
77876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                System.out.println("***> verification " + hostname + " "
77976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                                   + session.getPeerHost());
78076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            }
78176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            verified = true;
78276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            return true;
78376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        }
784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
785adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
78776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * Creates a {@link MockWebServer} that acts as both a proxy and then a web server with the
78876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * supplied {@link SSLContext} and {@link Dispatcher}. The dispatcher provided must handle the
78976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * CONNECT request/responses and {@link SocketPolicy} needed to simulate the hand-off from proxy
79076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * to web server. See {@link HttpsURLConnectionTest.ProxyConnectDispatcher}.
791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
79276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    private static MockWebServer createProxyAndWebServer(SSLContext ctx, Dispatcher dispatcher)
79376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            throws IOException {
79476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        return createServer(ctx, dispatcher, true /* handleProxying */);
795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
79876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * Creates a {@link MockWebServer} that acts as (only) a web server with the supplied
79976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * {@link SSLContext} and {@link Dispatcher}.
800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
80176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    private static MockWebServer createWebServer(SSLContext ctx, Dispatcher dispatcher)
80276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            throws IOException {
80376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        return createServer(ctx, dispatcher, false /* handleProxying */);
80476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    }
805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
80676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    private static MockWebServer createServer(
80776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            SSLContext ctx, Dispatcher dispatcher, boolean handleProxying)
80876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            throws IOException {
80976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        MockWebServer webServer = new MockWebServer();
81076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        webServer.useHttps(ctx.getSocketFactory(), handleProxying /* tunnelProxy */);
81176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        webServer.setDispatcher(dispatcher);
81276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        webServer.play();
81376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        return webServer;
81476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    }
815adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
81676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    /**
81776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * A {@link Dispatcher} that has a list of dispatchers to delegate to, each of which will be
81876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * used for one request and then discarded.
81976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     */
82076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    private static class DelegatingDispatcher extends Dispatcher {
82176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        private LinkedList<Dispatcher> delegates = new LinkedList<Dispatcher>();
822adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
82376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        public DelegatingDispatcher(Dispatcher... dispatchers) {
82476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            addAll(dispatchers);
82576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        }
82676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
82776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        private void addAll(Dispatcher... dispatchers) {
82876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            Collections.addAll(delegates, dispatchers);
82976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        }
83076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
83176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        @Override
83276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
83376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            return delegates.removeFirst().dispatch(request);
834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
835210834b065f80d2bb9adc194f9e3fc662a12a95dJesse Wilson
83676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        @Override
83725f20231a8e43b92d7128aa57e52a1d4d8e90feaNeil Fuller        public MockResponse peek() {
83825f20231a8e43b92d7128aa57e52a1d4d8e90feaNeil Fuller            return delegates.getFirst().peek();
83976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        }
840adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
84276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    /** Handles a request for SSL tunnel: Answers with a request to authenticate. */
84376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    private static class ProxyConnectAuthFailDispatcher extends Dispatcher {
844adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
84576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        @Override
84676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
84776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            assertEquals("CONNECT", request.getMethod());
848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
84976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            MockResponse response = new MockResponse();
85076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            response.setResponseCode(AUTHENTICATION_REQUIRED_CODE);
85176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            response.addHeader("Proxy-authenticate: Basic realm=\"localhost\"");
85276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            log("Authentication required. Sending response: " + response);
85376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            return response;
85476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        }
85576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
85676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        private void log(String msg) {
85776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            HttpsURLConnectionTest.log("ProxyConnectAuthFailDispatcher", msg);
858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
859adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
860adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
86276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * Handles a request for SSL tunnel: Answers with a success and the socket is upgraded to SSL.
863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
86476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    private static class ProxyConnectDispatcher extends Dispatcher {
86576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
86676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        private final boolean authenticationRequired;
86776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
86876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        private ProxyConnectDispatcher(boolean authenticationRequired) {
86976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            this.authenticationRequired = authenticationRequired;
87076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        }
87176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
87276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        @Override
87376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
87476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            if (authenticationRequired) {
87576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                // check provided authorization credentials
87676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                assertNotNull("no proxy-authorization credentials: " + request,
87776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                        request.getHeader("proxy-authorization"));
87876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                log("Got authenticated request:\n" + request);
87976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                log("------------------");
880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
88176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
88276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            assertEquals("CONNECT", request.getMethod());
88376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            log("Send proxy response");
88476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            MockResponse response = new MockResponse();
88576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            response.setResponseCode(200);
88676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            response.setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END);
88776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            return response;
88876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        }
88976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
89076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        @Override
89125f20231a8e43b92d7128aa57e52a1d4d8e90feaNeil Fuller        public MockResponse peek() {
89225f20231a8e43b92d7128aa57e52a1d4d8e90feaNeil Fuller            return new MockResponse().setSocketPolicy(SocketPolicy.UPGRADE_TO_SSL_AT_END);
89376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        }
89476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
89576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        private void log(String msg) {
89676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            HttpsURLConnectionTest.log("ProxyConnectDispatcher", msg);
897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
90176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * Handles a request: Answers with a response with a specified status code.
90276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * If the {@code expectedMethod} is {@code POST} a hardcoded response body {@link #POST_DATA}
90376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * will be included in the response.
904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
90576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    private static class SingleRequestDispatcher extends Dispatcher {
906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
90776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        private final String expectedMethod;
908f02c695ed03e708623d9365dec26d533356ef2d0Brian Carlstrom        private final int responseCode;
909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
91076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        private RecordedRequest lastRequest;
91176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
91276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        private SingleRequestDispatcher(String expectedMethod, int responseCode) {
913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            this.responseCode = responseCode;
91476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            this.expectedMethod = expectedMethod;
915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
91776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        @Override
91876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
91976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            if (lastRequest != null) {
92076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                fail("More than one request received");
921df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom            }
92276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            log("Request received: " + request);
92376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            lastRequest = request;
92476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            assertEquals(expectedMethod, request.getMethod());
92576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            if (POST_METHOD.equals(expectedMethod)) {
92676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller                assertEquals(POST_DATA, request.getUtf8Body());
92776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            }
92876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
92976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            MockResponse response = new MockResponse();
93076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            response.setResponseCode(responseCode);
93176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            response.setBody(RESPONSE_CONTENT);
93276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
93376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            log("Responding with: " + response);
93476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            return response;
935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
93776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        public RecordedRequest getLastRequest() {
93876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            return lastRequest;
93976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        }
940adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
94176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        @Override
94225f20231a8e43b92d7128aa57e52a1d4d8e90feaNeil Fuller        public MockResponse peek() {
94325f20231a8e43b92d7128aa57e52a1d4d8e90feaNeil Fuller            return new MockResponse().setSocketPolicy(SocketPolicy.DISCONNECT_AT_END);
944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
945210834b065f80d2bb9adc194f9e3fc662a12a95dJesse Wilson
94676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        private void log(String msg) {
94776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            HttpsURLConnectionTest.log("SingleRequestDispatcher", msg);
948210834b065f80d2bb9adc194f9e3fc662a12a95dJesse Wilson        }
949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
950adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
951adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
95276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * Executes an HTTP request using the supplied connection. If {@code doOutput} is {@code true}
95376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * the request made is a POST and the request body sent is {@link #POST_DATA}.
95476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * If {@code doOutput} is {@code false} the request made is a GET. The response must be a
95576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * success with a body {@link #RESPONSE_CONTENT}.
956adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
95776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    private static void executeClientRequest(
95876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            HttpsURLConnection connection, boolean doOutput) throws IOException {
959adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
96076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // set up the connection
96176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        connection.setDoInput(true);
96276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        connection.setConnectTimeout(TIMEOUT);
96376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        connection.setReadTimeout(TIMEOUT);
96476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        connection.setDoOutput(doOutput);
96576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller
96676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        log("Client", "Opening the connection to " + connection.getURL());
96776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        connection.connect();
96876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        log("Client", "Connection has been ESTABLISHED, using proxy: " + connection.usingProxy());
96976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        if (doOutput) {
97076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            log("Client", "Posting data");
97176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            // connection configured to post data, do so
97276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            OutputStream os = connection.getOutputStream();
97376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            os.write(POST_DATA.getBytes());
97476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        }
97576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        // read the content of HTTP(s) response
97676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        InputStream is = connection.getInputStream();
97776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        log("Client", "Input Stream obtained");
97876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        byte[] buff = new byte[2048];
97976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        int num = 0;
98076fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        int byt;
98176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        while ((num < buff.length) && ((byt = is.read()) != -1)) {
98276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            buff[num++] = (byte) byt;
983210834b065f80d2bb9adc194f9e3fc662a12a95dJesse Wilson        }
98476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        String message = new String(buff, 0, num);
98576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        log("Client", "Got content:\n" + message);
98676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        log("Client", "------------------");
98776fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        log("Client", "Response code: " + connection.getResponseCode());
98876fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        assertEquals(RESPONSE_CONTENT, message);
98976fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    }
990210834b065f80d2bb9adc194f9e3fc662a12a95dJesse Wilson
99176fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    /**
99276fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     * Prints log message.
99376fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller     */
99476fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller    public static synchronized void log(String origin, String message) {
99576fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller        if (DO_LOG) {
99676fafa7b18ae7e977fabb64742fd3c1449ee0f57Neil Fuller            System.out.println("[" + origin + "]: " + message);
997adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
998adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
999adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
1000