ResponseCacheAdapterTest.java revision 4944713f5c5b141966ac82973d6a31a634e8e01e
1/*
2 * Copyright (C) 2014 Square, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.squareup.okhttp.internal.http;
17
18import com.squareup.okhttp.OkHttpClient;
19import com.squareup.okhttp.internal.SslContextBuilder;
20import com.squareup.okhttp.mockwebserver.MockResponse;
21import com.squareup.okhttp.mockwebserver.MockWebServer;
22
23import org.junit.After;
24import org.junit.Before;
25import org.junit.Test;
26
27import java.io.IOException;
28import java.net.CacheRequest;
29import java.net.CacheResponse;
30import java.net.HttpURLConnection;
31import java.net.ResponseCache;
32import java.net.URI;
33import java.net.URISyntaxException;
34import java.net.URL;
35import java.net.URLConnection;
36import java.util.Collections;
37import java.util.List;
38import java.util.Map;
39
40import javax.net.ssl.HostnameVerifier;
41import javax.net.ssl.HttpsURLConnection;
42import javax.net.ssl.SSLContext;
43import javax.net.ssl.SSLSession;
44
45import static org.junit.Assert.assertArrayEquals;
46import static org.junit.Assert.assertEquals;
47import static org.junit.Assert.assertFalse;
48import static org.junit.Assert.assertNotNull;
49import static org.junit.Assert.assertNull;
50import static org.junit.Assert.assertTrue;
51import static org.junit.Assert.fail;
52
53/**
54 * A white-box test for {@link ResponseCacheAdapter}. See also:
55 * <ul>
56 *   <li>{@link ResponseCacheTest} for black-box tests that check that {@link ResponseCache}
57 *   classes are called correctly by OkHttp.</li>
58 *   <li>{@link JavaApiConverterTest} for tests that check Java API classes / OkHttp conversion
59 *   logic. </li>
60 * </ul>
61 */
62public class ResponseCacheAdapterTest {
63
64  private static final SSLContext sslContext = SslContextBuilder.localhost();
65  private static final HostnameVerifier NULL_HOSTNAME_VERIFIER = new HostnameVerifier() {
66    public boolean verify(String hostname, SSLSession session) {
67      return true;
68    }
69  };
70
71  private MockWebServer server;
72
73  private OkHttpClient client;
74
75  private HttpURLConnection connection;
76
77  @Before public void setUp() throws Exception {
78    server = new MockWebServer();
79    client = new OkHttpClient();
80  }
81
82  @After public void tearDown() throws Exception {
83    if (connection != null) {
84      connection.disconnect();
85    }
86    server.shutdown();
87  }
88
89  @Test public void get_httpGet() throws Exception {
90    final URL serverUrl = configureServer(new MockResponse());
91    assertEquals("http", serverUrl.getProtocol());
92
93    ResponseCache responseCache = new NoOpResponseCache() {
94      @Override
95      public CacheResponse get(URI uri, String method, Map<String, List<String>> headers) throws IOException {
96        assertEquals(toUri(serverUrl), uri);
97        assertEquals("GET", method);
98        assertTrue("Arbitrary standard header not present", headers.containsKey("User-Agent"));
99        assertEquals(Collections.singletonList("value1"), headers.get("key1"));
100        return null;
101      }
102    };
103    client.setResponseCache(responseCache);
104
105    connection = client.open(serverUrl);
106    connection.setRequestProperty("key1", "value1");
107
108    executeGet(connection);
109  }
110
111  @Test public void get_httpsGet() throws Exception {
112    final URL serverUrl = configureHttpsServer(new MockResponse());
113    assertEquals("https", serverUrl.getProtocol());
114
115    ResponseCache responseCache = new NoOpResponseCache() {
116      @Override
117      public CacheResponse get(URI uri, String method, Map<String, List<String>> headers)
118          throws IOException {
119        assertEquals("https", uri.getScheme());
120        assertEquals(toUri(serverUrl), uri);
121        assertEquals("GET", method);
122        assertTrue("Arbitrary standard header not present", headers.containsKey("User-Agent"));
123        assertEquals(Collections.singletonList("value1"), headers.get("key1"));
124        return null;
125      }
126    };
127    client.setResponseCache(responseCache);
128    client.setSslSocketFactory(sslContext.getSocketFactory());
129    client.setHostnameVerifier(NULL_HOSTNAME_VERIFIER);
130
131    connection = client.open(serverUrl);
132    connection.setRequestProperty("key1", "value1");
133
134    executeGet(connection);
135  }
136
137  @Test public void put_httpGet() throws Exception {
138    final String statusLine = "HTTP/1.1 200 Fantastic";
139    final URL serverUrl = configureServer(
140        new MockResponse()
141            .setStatus(statusLine)
142            .addHeader("A", "c"));
143
144    ResponseCache responseCache = new NoOpResponseCache() {
145      @Override
146      public CacheRequest put(URI uri, URLConnection urlConnection) throws IOException {
147        assertTrue(urlConnection instanceof HttpURLConnection);
148        assertFalse(urlConnection instanceof HttpsURLConnection);
149
150        assertEquals(0, urlConnection.getContentLength());
151
152        HttpURLConnection httpUrlConnection = (HttpURLConnection) urlConnection;
153        assertEquals("GET", httpUrlConnection.getRequestMethod());
154        assertTrue(httpUrlConnection.getDoInput());
155        assertFalse(httpUrlConnection.getDoOutput());
156
157        assertEquals("Fantastic", httpUrlConnection.getResponseMessage());
158        assertEquals(toUri(serverUrl), uri);
159        assertEquals(serverUrl, urlConnection.getURL());
160        assertEquals("value", urlConnection.getRequestProperty("key"));
161
162        // Check retrieval by string key.
163        assertEquals(statusLine, httpUrlConnection.getHeaderField(null));
164        assertEquals("c", httpUrlConnection.getHeaderField("A"));
165        // The RI and OkHttp supports case-insensitive matching for this method.
166        assertEquals("c", httpUrlConnection.getHeaderField("a"));
167        return null;
168      }
169    };
170    client.setResponseCache(responseCache);
171
172    connection = client.open(serverUrl);
173    connection.setRequestProperty("key", "value");
174    executeGet(connection);
175  }
176
177  @Test public void put_httpPost() throws Exception {
178    final String statusLine = "HTTP/1.1 200 Fantastic";
179    final URL serverUrl = configureServer(
180        new MockResponse()
181            .setStatus(statusLine)
182            .addHeader("A", "c"));
183
184    ResponseCache responseCache = new NoOpResponseCache() {
185      @Override
186      public CacheRequest put(URI uri, URLConnection urlConnection) throws IOException {
187        assertTrue(urlConnection instanceof HttpURLConnection);
188        assertFalse(urlConnection instanceof HttpsURLConnection);
189
190        assertEquals(0, urlConnection.getContentLength());
191
192        HttpURLConnection httpUrlConnection = (HttpURLConnection) urlConnection;
193        assertEquals("POST", httpUrlConnection.getRequestMethod());
194        assertTrue(httpUrlConnection.getDoInput());
195        assertTrue(httpUrlConnection.getDoOutput());
196
197        assertEquals("Fantastic", httpUrlConnection.getResponseMessage());
198        assertEquals(toUri(serverUrl), uri);
199        assertEquals(serverUrl, urlConnection.getURL());
200        assertEquals("value", urlConnection.getRequestProperty("key"));
201
202        // Check retrieval by string key.
203        assertEquals(statusLine, httpUrlConnection.getHeaderField(null));
204        assertEquals("c", httpUrlConnection.getHeaderField("A"));
205        // The RI and OkHttp supports case-insensitive matching for this method.
206        assertEquals("c", httpUrlConnection.getHeaderField("a"));
207        return null;
208      }
209    };
210    client.setResponseCache(responseCache);
211
212    connection = client.open(serverUrl);
213
214    executePost(connection);
215  }
216
217  @Test public void put_httpsGet() throws Exception {
218    final URL serverUrl = configureHttpsServer(new MockResponse());
219    assertEquals("https", serverUrl.getProtocol());
220
221    ResponseCache responseCache = new NoOpResponseCache() {
222      @Override
223      public CacheRequest put(URI uri, URLConnection urlConnection) throws IOException {
224        assertTrue(urlConnection instanceof HttpsURLConnection);
225        assertEquals(toUri(serverUrl), uri);
226        assertEquals(serverUrl, urlConnection.getURL());
227
228        HttpsURLConnection cacheHttpsUrlConnection = (HttpsURLConnection) urlConnection;
229        HttpsURLConnection realHttpsUrlConnection = (HttpsURLConnection) connection;
230        assertEquals(realHttpsUrlConnection.getCipherSuite(),
231            cacheHttpsUrlConnection.getCipherSuite());
232        assertEquals(realHttpsUrlConnection.getPeerPrincipal(),
233            cacheHttpsUrlConnection.getPeerPrincipal());
234        assertArrayEquals(realHttpsUrlConnection.getLocalCertificates(),
235            cacheHttpsUrlConnection.getLocalCertificates());
236        assertArrayEquals(realHttpsUrlConnection.getServerCertificates(),
237            cacheHttpsUrlConnection.getServerCertificates());
238        assertEquals(realHttpsUrlConnection.getLocalPrincipal(),
239            cacheHttpsUrlConnection.getLocalPrincipal());
240        return null;
241      }
242    };
243    client.setResponseCache(responseCache);
244    client.setSslSocketFactory(sslContext.getSocketFactory());
245    client.setHostnameVerifier(NULL_HOSTNAME_VERIFIER);
246
247    connection = client.open(serverUrl);
248    executeGet(connection);
249  }
250
251  private void executeGet(HttpURLConnection connection) throws IOException {
252    connection.connect();
253    connection.getHeaderFields();
254    connection.disconnect();
255  }
256
257  private void executePost(HttpURLConnection connection) throws IOException {
258    connection.setDoOutput(true);
259    connection.connect();
260    connection.getOutputStream().write("Hello World".getBytes());
261    connection.disconnect();
262  }
263
264  private URL configureServer(MockResponse mockResponse) throws Exception {
265    server.enqueue(mockResponse);
266    server.play();
267    return server.getUrl("/");
268  }
269
270  private URL configureHttpsServer(MockResponse mockResponse) throws Exception {
271    server.useHttps(sslContext.getSocketFactory(), false /* tunnelProxy */);
272    server.enqueue(mockResponse);
273    server.play();
274    return server.getUrl("/");
275  }
276
277  private static class NoOpResponseCache extends ResponseCache {
278
279    @Override
280    public CacheResponse get(URI uri, String s, Map<String, List<String>> stringListMap)
281        throws IOException {
282      return null;
283    }
284
285    @Override
286    public CacheRequest put(URI uri, URLConnection urlConnection) throws IOException {
287      return null;
288    }
289  }
290
291  private static URI toUri(URL serverUrl) {
292    try {
293      return serverUrl.toURI();
294    } catch (URISyntaxException e) {
295      fail(e.getMessage());
296      return null;
297    }
298  }
299}
300