ResponseCacheTest.java revision 7899c5ab935cf542069835ec7d3e457db596dbf7
17899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath/* 27899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Copyright (C) 2011 The Android Open Source Project 37899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * 47899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Licensed under the Apache License, Version 2.0 (the "License"); 57899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * you may not use this file except in compliance with the License. 67899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * You may obtain a copy of the License at 77899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * 87899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * http://www.apache.org/licenses/LICENSE-2.0 97899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * 107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Unless required by applicable law or agreed to in writing, software 117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * distributed under the License is distributed on an "AS IS" BASIS, 127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * See the License for the specific language governing permissions and 147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * limitations under the License. 157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathpackage libcore.net.http; 187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport com.google.mockwebserver.MockResponse; 207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport com.google.mockwebserver.MockWebServer; 217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport com.google.mockwebserver.RecordedRequest; 227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport com.squareup.okhttp.OkHttpConnection; 237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.io.BufferedReader; 247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.io.ByteArrayOutputStream; 257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.io.File; 267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.io.FileNotFoundException; 277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.io.IOException; 287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.io.InputStream; 297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.io.InputStreamReader; 307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.io.OutputStream; 317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.net.CacheRequest; 327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.net.CacheResponse; 337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.net.CookieHandler; 347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.net.CookieManager; 357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.net.HttpCookie; 367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.net.HttpURLConnection; 377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.net.ResponseCache; 387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.net.SecureCacheResponse; 397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.net.URI; 407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.net.URISyntaxException; 417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.net.URL; 427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.net.URLConnection; 437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.text.DateFormat; 447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.text.SimpleDateFormat; 457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.util.ArrayList; 467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.util.Arrays; 477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.util.Collections; 487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.util.Date; 497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.util.Iterator; 507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.util.List; 517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.util.Locale; 527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.util.Map; 537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.util.TimeZone; 547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.util.UUID; 557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.util.concurrent.TimeUnit; 567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.util.concurrent.atomic.AtomicInteger; 577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.util.concurrent.atomic.AtomicReference; 587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport java.util.zip.GZIPOutputStream; 597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport junit.framework.TestCase; 607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathimport static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END; 627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath/** 647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Android's HttpResponseCacheTest. 657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamathpublic final class HttpResponseCacheTest extends TestCase { 677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private MockWebServer server = new MockWebServer(); 687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private HttpResponseCache cache; 697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// private final MockOs mockOs = new MockOs(); 707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private final CookieManager cookieManager = new CookieManager(); 717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath @Override protected void setUp() throws Exception { 737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath super.setUp(); 747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath String tmp = System.getProperty("java.io.tmpdir"); 767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath File cacheDir = new File(tmp, "HttpCache-" + UUID.randomUUID()); 777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath cache = new HttpResponseCache(cacheDir, Integer.MAX_VALUE); 787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath ResponseCache.setDefault(cache); 797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// mockOs.install(); 807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath CookieHandler.setDefault(cookieManager); 817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath @Override protected void tearDown() throws Exception { 847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// mockOs.uninstall(); 857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.shutdown(); 867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath ResponseCache.setDefault(null); 877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath cache.getCache().delete(); 887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath CookieHandler.setDefault(null); 897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath super.tearDown(); 907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private static OkHttpConnection openConnection(URL url) { 937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return OkHttpConnection.open(url); 947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath /** 977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Test that response caching is consistent with the RI and the spec. 987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4 997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 1007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testResponseCachingByResponseCode() throws Exception { 1017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // Test each documented HTTP/1.1 code, plus the first unused value in each range. 1027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 1037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 1047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // We can't test 100 because it's not really a response. 1057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // assertCached(false, 100); 1067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(false, 101); 1077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(false, 102); 1087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(true, 200); 1097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(false, 201); 1107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(false, 202); 1117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(true, 203); 1127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(false, 204); 1137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(false, 205); 1147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(false, 206); // we don't cache partial responses 1157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(false, 207); 1167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(true, 300); 1177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(true, 301); 1187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath for (int i = 302; i <= 308; ++i) { 1197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(false, i); 1207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 1217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath for (int i = 400; i <= 406; ++i) { 1227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(false, i); 1237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 1247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // (See test_responseCaching_407.) 1257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(false, 408); 1267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(false, 409); 1277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // (See test_responseCaching_410.) 1287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath for (int i = 411; i <= 418; ++i) { 1297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(false, i); 1307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 1317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath for (int i = 500; i <= 506; ++i) { 1327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(false, i); 1337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 1347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 1357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 1367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath /** 1377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Response code 407 should only come from proxy servers. Android's client 1387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * throws if it is sent by an origin server. 1397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 1407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testOriginServerSends407() throws Exception { 1417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setResponseCode(407)); 1427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 1437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 1447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 1457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection conn = openConnection(url); 1467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath try { 1477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath conn.getResponseCode(); 1487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath fail(); 1497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } catch (IOException expected) { 1507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 1517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 1527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 1537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void test_responseCaching_410() throws Exception { 1547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // the HTTP spec permits caching 410s, but the RI doesn't. 1557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCached(true, 410); 1567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 1577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 1587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private void assertCached(boolean shouldPut, int responseCode) throws Exception { 1597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server = new MockWebServer(); 1607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath MockResponse response = new MockResponse() 1617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 1627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 1637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setResponseCode(responseCode) 1647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("ABCDE") 1657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("WWW-Authenticate: challenge"); 1667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath if (responseCode == HttpURLConnection.HTTP_PROXY_AUTH) { 1677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath response.addHeader("Proxy-Authenticate: Basic realm=\"protected area\""); 1687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } else if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) { 1697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath response.addHeader("WWW-Authenticate: Basic realm=\"protected area\""); 1707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 1717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(response); 1727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 1737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 1747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 1757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection conn = openConnection(url); 1767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(responseCode, conn.getResponseCode()); 1777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 1787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // exhaust the content stream 1797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath readAscii(conn); 1807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 1817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath CacheResponse cached = cache.get(url.toURI(), "GET", 1827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath Collections.<String, List<String>>emptyMap()); 1837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath if (shouldPut) { 1847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertNotNull(Integer.toString(responseCode), cached); 1857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath cached.getBody().close(); 1867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } else { 1877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertNull(Integer.toString(responseCode), cached); 1887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 1897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.shutdown(); // tearDown() isn't sufficient; this test starts multiple servers 1907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 1917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 1927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath /** 1937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Test that we can interrogate the response when the cache is being 1947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * populated. http://code.google.com/p/android/issues/detail?id=7787 1957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 1967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testResponseCacheCallbackApis() throws Exception { 1977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath final String body = "ABCDE"; 1987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath final AtomicInteger cacheCount = new AtomicInteger(); 1997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 2007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 2017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setStatus("HTTP/1.1 200 Fantastic") 2027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("fgh: ijk") 2037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody(body)); 2047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 2057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 2067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath ResponseCache.setDefault(new ResponseCache() { 2077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath @Override public CacheResponse get(URI uri, String requestMethod, 2087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath Map<String, List<String>> requestHeaders) throws IOException { 2097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return null; 2107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 2117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath @Override public CacheRequest put(URI uri, URLConnection conn) throws IOException { 2127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection httpConnection = (OkHttpConnection) conn; 2137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath try { 2147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath httpConnection.getRequestProperties(); 2157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath fail(); 2167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } catch (IllegalStateException expected) { 2177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 2187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath try { 2197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath httpConnection.addRequestProperty("K", "V"); 2207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath fail(); 2217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } catch (IllegalStateException expected) { 2227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 2237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("HTTP/1.1 200 Fantastic", httpConnection.getHeaderField(null)); 2247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(Arrays.asList("HTTP/1.1 200 Fantastic"), 2257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath httpConnection.getHeaderFields().get(null)); 2267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(200, httpConnection.getResponseCode()); 2277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("Fantastic", httpConnection.getResponseMessage()); 2287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(body.length(), httpConnection.getContentLength()); 2297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("ijk", httpConnection.getHeaderField("fgh")); 2307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath try { 2317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath httpConnection.getInputStream(); // the RI doesn't forbid this, but it should 2327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath fail(); 2337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } catch (IOException expected) { 2347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 2357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath cacheCount.incrementAndGet(); 2367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return null; 2377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 2387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath }); 2397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 2407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 2417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection connection = openConnection(url); 2427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(body, readAscii(connection)); 2437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cacheCount.get()); 2447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 2457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 2467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 2477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testResponseCachingAndInputStreamSkipWithFixedLength() throws IOException { 2487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testResponseCaching(TransferKind.FIXED_LENGTH); 2497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 2507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 2517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testResponseCachingAndInputStreamSkipWithChunkedEncoding() throws IOException { 2527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testResponseCaching(TransferKind.CHUNKED); 2537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 2547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 2557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testResponseCachingAndInputStreamSkipWithNoLengthHeaders() throws IOException { 2567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testResponseCaching(TransferKind.END_OF_STREAM); 2577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 2587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 2597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath /** 2607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * HttpURLConnection.getInputStream().skip(long) causes ResponseCache corruption 2617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * http://code.google.com/p/android/issues/detail?id=8175 2627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 2637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private void testResponseCaching(TransferKind transferKind) throws IOException { 2647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath MockResponse response = new MockResponse() 2657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 2667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 2677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setStatus("HTTP/1.1 200 Fantastic"); 2687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath transferKind.setBody(response, "I love puppies but hate spiders", 1); 2697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(response); 2707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 2717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 2727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // Make sure that calling skip() doesn't omit bytes from the cache. 2737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection urlConnection = openConnection(server.getUrl("/")); 2747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath InputStream in = urlConnection.getInputStream(); 2757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("I love ", readAscii(urlConnection, "I love ".length())); 2767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath reliableSkip(in, "puppies but hate ".length()); 2777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("spiders", readAscii(urlConnection, "spiders".length())); 2787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(-1, in.read()); 2797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath in.close(); 2807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getWriteSuccessCount()); 2817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(0, cache.getWriteAbortCount()); 2827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 2837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath urlConnection = openConnection(server.getUrl("/")); // cached! 2847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath in = urlConnection.getInputStream(); 2857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("I love puppies but hate spiders", 2867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath readAscii(urlConnection, "I love puppies but hate spiders".length())); 2877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(200, urlConnection.getResponseCode()); 2887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("Fantastic", urlConnection.getResponseMessage()); 2897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 2907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(-1, in.read()); 2917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath in.close(); 2927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getWriteSuccessCount()); 2937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(0, cache.getWriteAbortCount()); 2947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(2, cache.getRequestCount()); 2957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getHitCount()); 2967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 2977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 2987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// public void testSecureResponseCaching() throws IOException { 2997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// TestSSLContext testSSLContext = TestSSLContext.create(); 3007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); 3017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.enqueue(new MockResponse() 3027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 3037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 3047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// .setBody("ABC")); 3057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.play(); 3067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 3077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection(); 3087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 3097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals("ABC", readAscii(connection)); 3107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 3117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// // OpenJDK 6 fails on this line, complaining that the connection isn't open yet 3127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// String suite = connection.getCipherSuite(); 3137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// List<Certificate> localCerts = toListOrNull(connection.getLocalCertificates()); 3147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// List<Certificate> serverCerts = toListOrNull(connection.getServerCertificates()); 3157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// Principal peerPrincipal = connection.getPeerPrincipal(); 3167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// Principal localPrincipal = connection.getLocalPrincipal(); 3177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 3187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // cached! 3197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 3207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals("ABC", readAscii(connection)); 3217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 3227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals(2, cache.getRequestCount()); 3237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals(1, cache.getNetworkCount()); 3247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals(1, cache.getHitCount()); 3257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 3267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals(suite, connection.getCipherSuite()); 3277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals(localCerts, toListOrNull(connection.getLocalCertificates())); 3287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals(serverCerts, toListOrNull(connection.getServerCertificates())); 3297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals(peerPrincipal, connection.getPeerPrincipal()); 3307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals(localPrincipal, connection.getLocalPrincipal()); 3317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// } 3327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 3337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// public void testCacheReturnsInsecureResponseForSecureRequest() throws IOException { 3347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// TestSSLContext testSSLContext = TestSSLContext.create(); 3357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); 3367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.enqueue(new MockResponse().setBody("ABC")); 3377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.enqueue(new MockResponse().setBody("DEF")); 3387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.play(); 3397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 3407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// ResponseCache.setDefault(new InsecureResponseCache()); 3417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 3427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection(); 3437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 3447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals("ABC", readAscii(connection)); 3457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 3467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // not cached! 3477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 3487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals("DEF", readAscii(connection)); 3497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// } 3507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 3517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testResponseCachingAndRedirects() throws Exception { 3527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 3537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 3547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 3557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM) 3567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Location: /foo")); 3577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 3587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 3597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 3607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("ABC")); 3617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("DEF")); 3627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 3637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 3647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection connection = openConnection(server.getUrl("/")); 3657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("ABC", readAscii(connection)); 3667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 3677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection = openConnection(server.getUrl("/")); // cached! 3687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("ABC", readAscii(connection)); 3697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 3707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(4, cache.getRequestCount()); // 2 requests + 2 redirects 3717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(2, cache.getNetworkCount()); 3727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(2, cache.getHitCount()); 3737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 3747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 3757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRedirectToCachedResult() throws Exception { 3767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 3777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 3787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("ABC")); 3797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 3807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM) 3817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Location: /foo")); 3827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("DEF")); 3837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 3847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 3857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("ABC", readAscii(openConnection(server.getUrl("/foo")))); 3867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath RecordedRequest request1 = server.takeRequest(); 3877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("GET /foo HTTP/1.1", request1.getRequestLine()); 3887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(0, request1.getSequenceNumber()); 3897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 3907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("ABC", readAscii(openConnection(server.getUrl("/bar")))); 3917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath RecordedRequest request2 = server.takeRequest(); 3927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("GET /bar HTTP/1.1", request2.getRequestLine()); 3937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, request2.getSequenceNumber()); 3947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 3957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // an unrelated request should reuse the pooled connection 3967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("DEF", readAscii(openConnection(server.getUrl("/baz")))); 3977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath RecordedRequest request3 = server.takeRequest(); 3987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("GET /baz HTTP/1.1", request3.getRequestLine()); 3997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(2, request3.getSequenceNumber()); 4007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 4017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 4027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// public void testSecureResponseCachingAndRedirects() throws IOException { 4037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// TestSSLContext testSSLContext = TestSSLContext.create(); 4047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); 4057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.enqueue(new MockResponse() 4067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 4077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 4087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM) 4097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// .addHeader("Location: /foo")); 4107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.enqueue(new MockResponse() 4117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 4127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 4137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// .setBody("ABC")); 4147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.enqueue(new MockResponse().setBody("DEF")); 4157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.play(); 4167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 4177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection(); 4187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 4197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals("ABC", readAscii(connection)); 4207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 4217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // cached! 4227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 4237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals("ABC", readAscii(connection)); 4247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 4257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals(4, cache.getRequestCount()); // 2 direct + 2 redirect = 4 4267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals(2, cache.getHitCount()); 4277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// } 4287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 4297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testResponseCacheRequestHeaders() throws IOException, URISyntaxException { 4307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("ABC")); 4317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 4327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 4337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath final AtomicReference<Map<String, List<String>>> requestHeadersRef 4347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath = new AtomicReference<Map<String, List<String>>>(); 4357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath ResponseCache.setDefault(new ResponseCache() { 4367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath @Override public CacheResponse get(URI uri, String requestMethod, 4377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath Map<String, List<String>> requestHeaders) throws IOException { 4387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath requestHeadersRef.set(requestHeaders); 4397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return null; 4407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 4417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath @Override public CacheRequest put(URI uri, URLConnection conn) throws IOException { 4427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return null; 4437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 4447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath }); 4457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 4467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 4477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection urlConnection = openConnection(url); 4487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath urlConnection.addRequestProperty("A", "android"); 4497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath readAscii(urlConnection); 4507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(Arrays.asList("android"), requestHeadersRef.get().get("A")); 4517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 4527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 4537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 4547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testServerDisconnectsPrematurelyWithContentLengthHeader() throws IOException { 4557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testServerPrematureDisconnect(TransferKind.FIXED_LENGTH); 4567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 4577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 4587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testServerDisconnectsPrematurelyWithChunkedEncoding() throws IOException { 4597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testServerPrematureDisconnect(TransferKind.CHUNKED); 4607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 4617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 4627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testServerDisconnectsPrematurelyWithNoLengthHeaders() throws IOException { 4637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath /* 4647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Intentionally empty. This case doesn't make sense because there's no 4657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * such thing as a premature disconnect when the disconnect itself 4667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * indicates the end of the data stream. 4677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 4687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 4697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 4707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private void testServerPrematureDisconnect(TransferKind transferKind) throws IOException { 4717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath MockResponse response = new MockResponse(); 4727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 16); 4737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(truncateViolently(response, 16)); 4747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("Request #2")); 4757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 4767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 4777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath BufferedReader reader = new BufferedReader(new InputStreamReader( 4787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath openConnection(server.getUrl("/")).getInputStream())); 4797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("ABCDE", reader.readLine()); 4807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath try { 4817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath reader.readLine(); 4827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath fail("This implementation silently ignored a truncated HTTP body."); 4837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } catch (IOException expected) { 4847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } finally { 4857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath reader.close(); 4867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 4877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 4887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getWriteAbortCount()); 4897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(0, cache.getWriteSuccessCount()); 4907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(server.getUrl("/")); 4917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("Request #2", readAscii(connection)); 4927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getWriteAbortCount()); 4937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getWriteSuccessCount()); 4947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 4957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 4967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testClientPrematureDisconnectWithContentLengthHeader() throws IOException { 4977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testClientPrematureDisconnect(TransferKind.FIXED_LENGTH); 4987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 4997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 5007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testClientPrematureDisconnectWithChunkedEncoding() throws IOException { 5017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testClientPrematureDisconnect(TransferKind.CHUNKED); 5027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 5037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 5047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testClientPrematureDisconnectWithNoLengthHeaders() throws IOException { 5057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testClientPrematureDisconnect(TransferKind.END_OF_STREAM); 5067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 5077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 5087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private void testClientPrematureDisconnect(TransferKind transferKind) throws IOException { 5097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath MockResponse response = new MockResponse(); 5107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 1024); 5117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(response); 5127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("Request #2")); 5137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 5147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 5157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(server.getUrl("/")); 5167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath InputStream in = connection.getInputStream(); 5177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("ABCDE", readAscii(connection, 5)); 5187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath in.close(); 5197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath try { 5207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath in.read(); 5217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath fail("Expected an IOException because the stream is closed."); 5227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } catch (IOException expected) { 5237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 5247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 5257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getWriteAbortCount()); 5267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(0, cache.getWriteSuccessCount()); 5277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection = openConnection(server.getUrl("/")); 5287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("Request #2", readAscii(connection)); 5297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getWriteAbortCount()); 5307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getWriteSuccessCount()); 5317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 5327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 5337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testDefaultExpirationDateFullyCachedForLessThan24Hours() throws Exception { 5347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // last modified: 105 seconds ago 5357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // served: 5 seconds ago 5367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // default lifetime: (105 - 5) / 10 = 10 seconds 5377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // expires: 10 seconds from served date = 5 seconds from now 5387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 5397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.SECONDS)) 5407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(-5, TimeUnit.SECONDS)) 5417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 5427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 5437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 5447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 5457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(url))); 5467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(url); 5477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection)); 5487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertNull(connection.getHeaderField("Warning")); 5497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 5507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 5517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testDefaultExpirationDateConditionallyCached() throws Exception { 5527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // last modified: 115 seconds ago 5537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // served: 15 seconds ago 5547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // default lifetime: (115 - 15) / 10 = 10 seconds 5557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // expires: 10 seconds from served date = 5 seconds ago 5567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath String lastModifiedDate = formatDate(-115, TimeUnit.SECONDS); 5577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 5587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + lastModifiedDate) 5597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(-15, TimeUnit.SECONDS))); 5607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath List<String> headers = conditionalRequest.getHeaders(); 5617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 5627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 5637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 5647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testDefaultExpirationDateFullyCachedForMoreThan24Hours() throws Exception { 5657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // last modified: 105 days ago 5667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // served: 5 days ago 5677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // default lifetime: (105 - 5) / 10 = 10 days 5687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // expires: 10 days from served date = 5 days from now 5697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 5707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.DAYS)) 5717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(-5, TimeUnit.DAYS)) 5727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 5737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 5747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 5757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 5767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(server.getUrl("/")); 5777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection)); 5787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("113 HttpURLConnection \"Heuristic expiration\"", 5797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.getHeaderField("Warning")); 5807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 5817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 5827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testNoDefaultExpirationForUrlsWithQueryString() throws Exception { 5837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 5847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.SECONDS)) 5857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(-5, TimeUnit.SECONDS)) 5867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 5877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 5887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 5897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 5907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/?foo=bar"); 5917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(url))); 5927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(openConnection(url))); 5937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 5947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 5957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testExpirationDateInThePastWithLastModifiedHeader() throws Exception { 5967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 5977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 5987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + lastModifiedDate) 5997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 6007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath List<String> headers = conditionalRequest.getHeaders(); 6017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 6027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testExpirationDateInThePastWithNoLastModifiedHeader() throws Exception { 6057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertNotCached(new MockResponse() 6067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 6077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testExpirationDateInTheFuture() throws Exception { 6107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertFullyCached(new MockResponse() 6117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 6127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testMaxAgePreferredWithMaxAgeAndExpires() throws Exception { 6157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertFullyCached(new MockResponse() 6167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(0, TimeUnit.HOURS)) 6177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)) 6187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60")); 6197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testMaxAgeInThePastWithDateAndLastModifiedHeaders() throws Exception { 6227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 6237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 6247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(-120, TimeUnit.SECONDS)) 6257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + lastModifiedDate) 6267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60")); 6277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath List<String> headers = conditionalRequest.getHeaders(); 6287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 6297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testMaxAgeInThePastWithDateHeaderButNoLastModifiedHeader() throws Exception { 6327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath /* 6337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Chrome interprets max-age relative to the local clock. Both our cache 6347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * and Firefox both use the earlier of the local and server's clock. 6357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 6367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertNotCached(new MockResponse() 6377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(-120, TimeUnit.SECONDS)) 6387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60")); 6397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testMaxAgeInTheFutureWithDateHeader() throws Exception { 6427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertFullyCached(new MockResponse() 6437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(0, TimeUnit.HOURS)) 6447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60")); 6457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testMaxAgeInTheFutureWithNoDateHeader() throws Exception { 6487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertFullyCached(new MockResponse() 6497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60")); 6507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testMaxAgeWithLastModifiedButNoServedDate() throws Exception { 6537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertFullyCached(new MockResponse() 6547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 6557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60")); 6567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testMaxAgeInTheFutureWithDateAndLastModifiedHeaders() throws Exception { 6597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertFullyCached(new MockResponse() 6607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 6617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS)) 6627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60")); 6637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testMaxAgePreferredOverLowerSharedMaxAge() throws Exception { 6667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertFullyCached(new MockResponse() 6677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES)) 6687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: s-maxage=60") 6697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=180")); 6707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testMaxAgePreferredOverHigherMaxAge() throws Exception { 6737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertNotCached(new MockResponse() 6747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES)) 6757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: s-maxage=180") 6767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60")); 6777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestMethodOptionsIsNotCached() throws Exception { 6807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testRequestMethod("OPTIONS", false); 6817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestMethodGetIsCached() throws Exception { 6847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testRequestMethod("GET", true); 6857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestMethodHeadIsNotCached() throws Exception { 6887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // We could support this but choose not to for implementation simplicity 6897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testRequestMethod("HEAD", false); 6907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestMethodPostIsNotCached() throws Exception { 6937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // We could support this but choose not to for implementation simplicity 6947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testRequestMethod("POST", false); 6957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 6967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 6977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestMethodPutIsNotCached() throws Exception { 6987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testRequestMethod("PUT", false); 6997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 7007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestMethodDeleteIsNotCached() throws Exception { 7027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testRequestMethod("DELETE", false); 7037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 7047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestMethodTraceIsNotCached() throws Exception { 7067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testRequestMethod("TRACE", false); 7077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 7087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private void testRequestMethod(String requestMethod, boolean expectCached) throws Exception { 7107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath /* 7117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * 1. seed the cache (potentially) 7127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * 2. expect a cache hit or miss 7137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 7147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 7157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 7167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("X-Response-ID: 1")); 7177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 7187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("X-Response-ID: 2")); 7197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 7207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 7227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection request1 = (OkHttpConnection) openConnection(url); 7247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath request1.setRequestMethod(requestMethod); 7257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath addRequestBodyIfNecessary(requestMethod, request1); 7267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("1", request1.getHeaderField("X-Response-ID")); 7277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection request2 = openConnection(url); 7297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath if (expectCached) { 7307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("1", request1.getHeaderField("X-Response-ID")); 7317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } else { 7327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("2", request2.getHeaderField("X-Response-ID")); 7337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 7347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 7357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testPostInvalidatesCache() throws Exception { 7377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testMethodInvalidates("POST"); 7387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 7397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testPutInvalidatesCache() throws Exception { 7417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testMethodInvalidates("PUT"); 7427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 7437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testDeleteMethodInvalidatesCache() throws Exception { 7457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath testMethodInvalidates("DELETE"); 7467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 7477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private void testMethodInvalidates(String requestMethod) throws Exception { 7497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath /* 7507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * 1. seed the cache 7517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * 2. invalidate it 7527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * 3. expect a cache miss 7537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 7547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("A") 7557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 7567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 7577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("C")); 7587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 7597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 7617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(url))); 7637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection invalidate = openConnection(url); 7657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath invalidate.setRequestMethod(requestMethod); 7667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath addRequestBodyIfNecessary(requestMethod, invalidate); 7677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(invalidate)); 7687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("C", readAscii(openConnection(url))); 7707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 7717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testEtag() throws Exception { 7737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 7747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("ETag: v1")); 7757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertTrue(conditionalRequest.getHeaders().contains("If-None-Match: v1")); 7767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 7777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testEtagAndExpirationDateInThePast() throws Exception { 7797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 7807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 7817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("ETag: v1") 7827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + lastModifiedDate) 7837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 7847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath List<String> headers = conditionalRequest.getHeaders(); 7857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertTrue(headers.contains("If-None-Match: v1")); 7867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 7877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 7887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testEtagAndExpirationDateInTheFuture() throws Exception { 7907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertFullyCached(new MockResponse() 7917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("ETag: v1") 7927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 7937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 7947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 7957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 7967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testCacheControlNoCache() throws Exception { 7977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertNotCached(new MockResponse().addHeader("Cache-Control: no-cache")); 7987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 7997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testCacheControlNoCacheAndExpirationDateInTheFuture() throws Exception { 8017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 8027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 8037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + lastModifiedDate) 8047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 8057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: no-cache")); 8067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath List<String> headers = conditionalRequest.getHeaders(); 8077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 8087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 8097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testPragmaNoCache() throws Exception { 8117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertNotCached(new MockResponse().addHeader("Pragma: no-cache")); 8127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 8137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testPragmaNoCacheAndExpirationDateInTheFuture() throws Exception { 8157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath String lastModifiedDate = formatDate(-2, TimeUnit.HOURS); 8167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse() 8177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + lastModifiedDate) 8187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 8197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Pragma: no-cache")); 8207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath List<String> headers = conditionalRequest.getHeaders(); 8217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate)); 8227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 8237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testCacheControlNoStore() throws Exception { 8257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertNotCached(new MockResponse().addHeader("Cache-Control: no-store")); 8267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 8277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testCacheControlNoStoreAndExpirationDateInTheFuture() throws Exception { 8297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertNotCached(new MockResponse() 8307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 8317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 8327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: no-store")); 8337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 8347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testPartialRangeResponsesDoNotCorruptCache() throws Exception { 8367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath /* 8377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * 1. request a range 8387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * 2. request a full document, expecting a cache miss 8397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 8407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("AA") 8417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setResponseCode(HttpURLConnection.HTTP_PARTIAL) 8427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)) 8437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Content-Range: bytes 1000-1001/2000")); 8447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("BB")); 8457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 8467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 8487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection range = openConnection(url); 8507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath range.addRequestProperty("Range", "bytes=1000-1001"); 8517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("AA", readAscii(range)); 8527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("BB", readAscii(openConnection(url))); 8547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 8557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testServerReturnsDocumentOlderThanCache() throws Exception { 8577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("A") 8587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 8597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 8607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B") 8617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-4, TimeUnit.HOURS))); 8627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 8637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 8657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(url))); 8677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(url))); 8687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 8697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testNonIdentityEncodingAndConditionalCache() throws Exception { 8717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertNonIdentityEncodingCached(new MockResponse() 8727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 8737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))); 8747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 8757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testNonIdentityEncodingAndFullCache() throws Exception { 8777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertNonIdentityEncodingCached(new MockResponse() 8787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 8797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 8807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 8817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private void assertNonIdentityEncodingCached(MockResponse response) throws Exception { 8837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(response 8847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody(gzip("ABCABCABC".getBytes("UTF-8"))) 8857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Content-Encoding: gzip")); 8867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 8877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 8897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("ABCABCABC", readAscii(openConnection(server.getUrl("/")))); 8907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("ABCABCABC", readAscii(openConnection(server.getUrl("/")))); 8917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 8927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testExpiresDateBeforeModifiedDate() throws Exception { 8947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertConditionallyCached(new MockResponse() 8957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 8967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(-2, TimeUnit.HOURS))); 8977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 8987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 8997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestMaxAge() throws IOException { 9007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("A") 9017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS)) 9027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(-1, TimeUnit.MINUTES)) 9037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))); 9047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 9057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 9077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 9087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(server.getUrl("/")); 9107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.addRequestProperty("Cache-Control", "max-age=30"); 9117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(connection)); 9127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 9137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestMinFresh() throws IOException { 9157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("A") 9167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 9177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES))); 9187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 9197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 9217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 9227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(server.getUrl("/")); 9247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.addRequestProperty("Cache-Control", "min-fresh=120"); 9257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(connection)); 9267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 9277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestMaxStale() throws IOException { 9297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("A") 9307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=120") 9317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(-4, TimeUnit.MINUTES))); 9327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 9337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 9357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 9367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(server.getUrl("/")); 9387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.addRequestProperty("Cache-Control", "max-stale=180"); 9397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection)); 9407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("110 HttpURLConnection \"Response is stale\"", 9417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.getHeaderField("Warning")); 9427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 9437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestMaxStaleNotHonoredWithMustRevalidate() throws IOException { 9457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("A") 9467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=120, must-revalidate") 9477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(-4, TimeUnit.MINUTES))); 9487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 9497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 9517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 9527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(server.getUrl("/")); 9547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.addRequestProperty("Cache-Control", "max-stale=180"); 9557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(connection)); 9567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 9577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestOnlyIfCachedWithNoResponseCached() throws IOException { 9597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // (no responses enqueued) 9607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 9617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection connection = openConnection(server.getUrl("/")); 9637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.addRequestProperty("Cache-Control", "only-if-cached"); 9647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertGatewayTimeout(connection); 9657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 9667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestOnlyIfCachedWithFullResponseCached() throws IOException { 9687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("A") 9697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=30") 9707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES))); 9717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 9727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 9747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(server.getUrl("/")); 9757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.addRequestProperty("Cache-Control", "only-if-cached"); 9767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 9777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 9787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestOnlyIfCachedWithConditionalResponseCached() throws IOException { 9807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("A") 9817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=30") 9827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(-1, TimeUnit.MINUTES))); 9837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 9847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 9867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection connection = openConnection(server.getUrl("/")); 9877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.addRequestProperty("Cache-Control", "only-if-cached"); 9887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertGatewayTimeout(connection); 9897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 9907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestOnlyIfCachedWithUnhelpfulResponseCached() throws IOException { 9927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("A")); 9937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 9947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 9957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 9967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection connection = openConnection(server.getUrl("/")); 9977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.addRequestProperty("Cache-Control", "only-if-cached"); 9987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertGatewayTimeout(connection); 9997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 10007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 10017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestCacheControlNoCache() throws Exception { 10027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 10037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 10047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS)) 10057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 10067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 10077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 10087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 10097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 10107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 10117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(url))); 10127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(url); 10137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.setRequestProperty("Cache-Control", "no-cache"); 10147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(connection)); 10157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 10167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 10177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testRequestPragmaNoCache() throws Exception { 10187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 10197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS)) 10207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS)) 10217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 10227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 10237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 10247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 10257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 10267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 10277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(url))); 10287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(url); 10297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.setRequestProperty("Pragma", "no-cache"); 10307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(connection)); 10317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 10327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 10337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testClientSuppliedIfModifiedSinceWithCachedResult() throws Exception { 10347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath MockResponse response = new MockResponse() 10357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("ETag: v3") 10367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=0"); 10377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath String ifModifiedSinceDate = formatDate(-24, TimeUnit.HOURS); 10387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath RecordedRequest request = assertClientSuppliedCondition( 10397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath response, "If-Modified-Since", ifModifiedSinceDate); 10407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath List<String> headers = request.getHeaders(); 10417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertTrue(headers.contains("If-Modified-Since: " + ifModifiedSinceDate)); 10427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertFalse(headers.contains("If-None-Match: v3")); 10437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 10447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 10457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testClientSuppliedIfNoneMatchSinceWithCachedResult() throws Exception { 10467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath String lastModifiedDate = formatDate(-3, TimeUnit.MINUTES); 10477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath MockResponse response = new MockResponse() 10487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + lastModifiedDate) 10497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES)) 10507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=0"); 10517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath RecordedRequest request = assertClientSuppliedCondition( 10527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath response, "If-None-Match", "v1"); 10537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath List<String> headers = request.getHeaders(); 10547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertTrue(headers.contains("If-None-Match: v1")); 10557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertFalse(headers.contains("If-Modified-Since: " + lastModifiedDate)); 10567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 10577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 10587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private RecordedRequest assertClientSuppliedCondition(MockResponse seed, String conditionName, 10597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath String conditionValue) throws Exception { 10607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(seed.setBody("A")); 10617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 10627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 10637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 10647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 10657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(url))); 10667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 10677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection connection = openConnection(url); 10687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.addRequestProperty(conditionName, conditionValue); 10697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection.getResponseCode()); 10707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("", readAscii(connection)); 10717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 10727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.takeRequest(); // seed 10737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return server.takeRequest(); 10747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 10757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 10767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testSetIfModifiedSince() throws Exception { 10777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath Date since = new Date(); 10787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("A")); 10797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 10807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 10817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 10827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(url); 10837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.setIfModifiedSince(since.getTime()); 10847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection)); 10857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath RecordedRequest request = server.takeRequest(); 10867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertTrue(request.getHeaders().contains("If-Modified-Since: " + formatDate(since))); 10877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 10887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 10897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testClientSuppliedConditionWithoutCachedResult() throws Exception { 10907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 10917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 10927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 10937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 10947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection connection = openConnection(server.getUrl("/")); 10957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath String clientIfModifiedSince = formatDate(-24, TimeUnit.HOURS); 10967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.addRequestProperty("If-Modified-Since", clientIfModifiedSince); 10977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection.getResponseCode()); 10987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("", readAscii(connection)); 10997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 11007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 11017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testAuthorizationRequestHeaderPreventsCaching() throws Exception { 11027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 11037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.MINUTES)) 11047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 11057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 11067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 11077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 11087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 11097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 11107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(url); 11117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.addRequestProperty("Authorization", "password"); 11127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection)); 11137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(openConnection(url))); 11147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 11157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 11167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testAuthorizationResponseCachedWithSMaxAge() throws Exception { 11177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertAuthorizationRequestFullyCached(new MockResponse() 11187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: s-maxage=60")); 11197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 11207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 11217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testAuthorizationResponseCachedWithPublic() throws Exception { 11227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertAuthorizationRequestFullyCached(new MockResponse() 11237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: public")); 11247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 11257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 11267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testAuthorizationResponseCachedWithMustRevalidate() throws Exception { 11277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertAuthorizationRequestFullyCached(new MockResponse() 11287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: must-revalidate")); 11297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 11307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 11317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void assertAuthorizationRequestFullyCached(MockResponse response) throws Exception { 11327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(response 11337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 11347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 11357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 11367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 11377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 11387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 11397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(url); 11407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.addRequestProperty("Authorization", "password"); 11417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection)); 11427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(url))); 11437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 11447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 11457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testContentLocationDoesNotPopulateCache() throws Exception { 11467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 11477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 11487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Content-Location: /bar") 11497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 11507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 11517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 11527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 11537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/foo")))); 11547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(openConnection(server.getUrl("/bar")))); 11557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 11567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 11577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testUseCachesFalseDoesNotWriteToCache() throws Exception { 11587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 11597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 11607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A").setBody("A")); 11617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 11627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 11637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 11647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(server.getUrl("/")); 11657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.setUseCaches(false); 11667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection)); 11677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(openConnection(server.getUrl("/")))); 11687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 11697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 11707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testUseCachesFalseDoesNotReadFromCache() throws Exception { 11717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 11727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 11737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A").setBody("A")); 11747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 11757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 11767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 11777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 11787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(server.getUrl("/")); 11797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.setUseCaches(false); 11807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(connection)); 11817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 11827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 11837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testDefaultUseCachesSetsInitialValueOnly() throws Exception { 11847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = new URL("http://localhost/"); 11857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection c1 = openConnection(url); 11867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection c2 = openConnection(url); 11877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertTrue(c1.getDefaultUseCaches()); 11887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath c1.setDefaultUseCaches(false); 11897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath try { 11907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertTrue(c1.getUseCaches()); 11917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertTrue(c2.getUseCaches()); 11927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection c3 = openConnection(url); 11937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertFalse(c3.getUseCaches()); 11947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } finally { 11957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath c1.setDefaultUseCaches(true); 11967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 11977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 11987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 11997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testConnectionIsReturnedToPoolAfterConditionalSuccess() throws Exception { 12007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 12017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 12027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=0") 12037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 12047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 12057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 12067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 12077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 12087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/a")))); 12097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/a")))); 12107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(openConnection(server.getUrl("/b")))); 12117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 12127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(0, server.takeRequest().getSequenceNumber()); 12137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, server.takeRequest().getSequenceNumber()); 12147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(2, server.takeRequest().getSequenceNumber()); 12157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 12167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 12177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testStatisticsConditionalCacheMiss() throws Exception { 12187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 12197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 12207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=0") 12217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 12227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 12237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("C")); 12247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 12257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 12267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 12277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getRequestCount()); 12287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getNetworkCount()); 12297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(0, cache.getHitCount()); 12307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(openConnection(server.getUrl("/")))); 12317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("C", readAscii(openConnection(server.getUrl("/")))); 12327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(3, cache.getRequestCount()); 12337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(3, cache.getNetworkCount()); 12347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(0, cache.getHitCount()); 12357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 12367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 12377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testStatisticsConditionalCacheHit() throws Exception { 12387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 12397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 12407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=0") 12417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 12427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 12437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 12447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 12457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 12467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 12477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getRequestCount()); 12487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getNetworkCount()); 12497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(0, cache.getHitCount()); 12507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 12517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 12527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(3, cache.getRequestCount()); 12537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(3, cache.getNetworkCount()); 12547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(2, cache.getHitCount()); 12557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 12567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 12577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testStatisticsFullCacheHit() throws Exception { 12587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 12597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 12607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 12617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 12627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 12637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 12647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getRequestCount()); 12657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getNetworkCount()); 12667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(0, cache.getHitCount()); 12677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 12687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 12697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(3, cache.getRequestCount()); 12707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(1, cache.getNetworkCount()); 12717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(2, cache.getHitCount()); 12727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 12737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 12747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testVaryMatchesChangedRequestHeaderField() throws Exception { 12757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 12767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 12777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Vary: Accept-Language") 12787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 12797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 12807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 12817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 12827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 12837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection frConnection = openConnection(url); 12847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath frConnection.addRequestProperty("Accept-Language", "fr-CA"); 12857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(frConnection)); 12867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 12877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection enConnection = openConnection(url); 12887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath enConnection.addRequestProperty("Accept-Language", "en-US"); 12897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(enConnection)); 12907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 12917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 12927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testVaryMatchesUnchangedRequestHeaderField() throws Exception { 12937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 12947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 12957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Vary: Accept-Language") 12967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 12977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 12987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 12997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 13007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 13017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection1 = openConnection(url); 13027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection1.addRequestProperty("Accept-Language", "fr-CA"); 13037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection1)); 13047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection2 = openConnection(url); 13057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection2.addRequestProperty("Accept-Language", "fr-CA"); 13067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection2)); 13077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 13087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 13097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testVaryMatchesAbsentRequestHeaderField() throws Exception { 13107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 13117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 13127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Vary: Foo") 13137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 13147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 13157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 13167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 13177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 13187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 13197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 13207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 13217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testVaryMatchesAddedRequestHeaderField() throws Exception { 13227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 13237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 13247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Vary: Foo") 13257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 13267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 13277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 13287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 13297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 13307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection fooConnection = openConnection(server.getUrl("/")); 13317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath fooConnection.addRequestProperty("Foo", "bar"); 13327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(fooConnection)); 13337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 13347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 13357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testVaryMatchesRemovedRequestHeaderField() throws Exception { 13367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 13377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 13387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Vary: Foo") 13397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 13407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 13417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 13427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 13437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection fooConnection = openConnection(server.getUrl("/")); 13447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath fooConnection.addRequestProperty("Foo", "bar"); 13457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(fooConnection)); 13467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(openConnection(server.getUrl("/")))); 13477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 13487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 13497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testVaryFieldsAreCaseInsensitive() throws Exception { 13507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 13517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 13527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Vary: ACCEPT-LANGUAGE") 13537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 13547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 13557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 13567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 13577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 13587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection1 = openConnection(url); 13597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection1.addRequestProperty("Accept-Language", "fr-CA"); 13607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection1)); 13617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection2 = openConnection(url); 13627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection2.addRequestProperty("accept-language", "fr-CA"); 13637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection2)); 13647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 13657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 13667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testVaryMultipleFieldsWithMatch() throws Exception { 13677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 13687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 13697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Vary: Accept-Language, Accept-Charset") 13707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Vary: Accept-Encoding") 13717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 13727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 13737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 13747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 13757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 13767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection1 = openConnection(url); 13777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection1.addRequestProperty("Accept-Language", "fr-CA"); 13787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection1.addRequestProperty("Accept-Charset", "UTF-8"); 13797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection1.addRequestProperty("Accept-Encoding", "identity"); 13807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection1)); 13817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection2 = openConnection(url); 13827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection2.addRequestProperty("Accept-Language", "fr-CA"); 13837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection2.addRequestProperty("Accept-Charset", "UTF-8"); 13847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection2.addRequestProperty("Accept-Encoding", "identity"); 13857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection2)); 13867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 13877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 13887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testVaryMultipleFieldsWithNoMatch() throws Exception { 13897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 13907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 13917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Vary: Accept-Language, Accept-Charset") 13927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Vary: Accept-Encoding") 13937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 13947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 13957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 13967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 13977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 13987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection frConnection = openConnection(url); 13997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath frConnection.addRequestProperty("Accept-Language", "fr-CA"); 14007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath frConnection.addRequestProperty("Accept-Charset", "UTF-8"); 14017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath frConnection.addRequestProperty("Accept-Encoding", "identity"); 14027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(frConnection)); 14037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection enConnection = openConnection(url); 14047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath enConnection.addRequestProperty("Accept-Language", "en-CA"); 14057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath enConnection.addRequestProperty("Accept-Charset", "UTF-8"); 14067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath enConnection.addRequestProperty("Accept-Encoding", "identity"); 14077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(enConnection)); 14087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 14097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 14107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testVaryMultipleFieldValuesWithMatch() throws Exception { 14117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 14127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 14137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Vary: Accept-Language") 14147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 14157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 14167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 14177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 14187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 14197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection1 = openConnection(url); 14207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection1.addRequestProperty("Accept-Language", "fr-CA, fr-FR"); 14217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection1.addRequestProperty("Accept-Language", "en-US"); 14227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection1)); 14237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 14247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection2 = openConnection(url); 14257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection2.addRequestProperty("Accept-Language", "fr-CA, fr-FR"); 14267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection2.addRequestProperty("Accept-Language", "en-US"); 14277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection2)); 14287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 14297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 14307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testVaryMultipleFieldValuesWithNoMatch() throws Exception { 14317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 14327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 14337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Vary: Accept-Language") 14347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 14357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 14367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 14377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 14387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 14397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection1 = openConnection(url); 14407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection1.addRequestProperty("Accept-Language", "fr-CA, fr-FR"); 14417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection1.addRequestProperty("Accept-Language", "en-US"); 14427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection1)); 14437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 14447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection2 = openConnection(url); 14457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection2.addRequestProperty("Accept-Language", "fr-CA"); 14467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection2.addRequestProperty("Accept-Language", "en-US"); 14477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(connection2)); 14487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 14497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 14507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testVaryAsterisk() throws Exception { 14517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 14527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 14537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Vary: *") 14547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 14557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 14567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 14577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 14587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(server.getUrl("/")))); 14597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(openConnection(server.getUrl("/")))); 14607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 14617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 14627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// public void testVaryAndHttps() throws Exception { 14637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// TestSSLContext testSSLContext = TestSSLContext.create(); 14647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.useHttps(testSSLContext.serverContext.getSocketFactory(), false); 14657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.enqueue(new MockResponse() 14667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// .addHeader("Cache-Control: max-age=60") 14677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// .addHeader("Vary: Accept-Language") 14687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// .setBody("A")); 14697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.enqueue(new MockResponse().setBody("B")); 14707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// server.play(); 14717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 14727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// URL url = server.getUrl("/"); 14737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// HttpsURLConnection connection1 = (HttpsURLConnection) url.openConnection(); 14747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// connection1.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 14757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// connection1.addRequestProperty("Accept-Language", "en-US"); 14767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals("A", readAscii(connection1)); 14777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 14787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// HttpsURLConnection connection2 = (HttpsURLConnection) url.openConnection(); 14797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// connection2.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory()); 14807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// connection2.addRequestProperty("Accept-Language", "en-US"); 14817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// assertEquals("A", readAscii(connection2)); 14827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// } 14837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 14847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// public void testDiskWriteFailureCacheDegradation() throws Exception { 14857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// Deque<InvocationHandler> writeHandlers = mockOs.getHandlers("write"); 14867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// int i = 0; 14877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// boolean hasMoreScenarios = true; 14887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// while (hasMoreScenarios) { 14897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// mockOs.enqueueNormal("write", i++); 14907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// mockOs.enqueueFault("write"); 14917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// exercisePossiblyFaultyCache(false); 14927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// hasMoreScenarios = writeHandlers.isEmpty(); 14937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// writeHandlers.clear(); 14947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// } 14957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// System.out.println("Exercising the cache performs " + (i - 1) + " writes."); 14967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// } 14977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// 14987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// public void testDiskReadFailureCacheDegradation() throws Exception { 14997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// Deque<InvocationHandler> readHandlers = mockOs.getHandlers("read"); 15007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// int i = 0; 15017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// boolean hasMoreScenarios = true; 15027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// while (hasMoreScenarios) { 15037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// mockOs.enqueueNormal("read", i++); 15047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// mockOs.enqueueFault("read"); 15057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// exercisePossiblyFaultyCache(true); 15067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// hasMoreScenarios = readHandlers.isEmpty(); 15077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// readHandlers.clear(); 15087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// } 15097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// System.out.println("Exercising the cache performs " + (i - 1) + " reads."); 15107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath// } 15117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 15127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testCachePlusCookies() throws Exception { 15137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 15147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Set-Cookie: a=FIRST; domain=" + server.getCookieDomain() + ";") 15157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 15167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=0") 15177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 15187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 15197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Set-Cookie: a=SECOND; domain=" + server.getCookieDomain() + ";") 15207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 15217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 15227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 15237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 15247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(url))); 15257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCookies(url, "a=FIRST"); 15267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(url))); 15277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertCookies(url, "a=SECOND"); 15287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 15297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 15307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testGetHeadersReturnsNetworkEndToEndHeaders() throws Exception { 15317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 15327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Allow: GET, HEAD") 15337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 15347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=0") 15357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 15367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 15377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Allow: GET, HEAD, PUT") 15387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 15397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 15407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 15417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection1 = openConnection(server.getUrl("/")); 15427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection1)); 15437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("GET, HEAD", connection1.getHeaderField("Allow")); 15447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 15457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection2 = openConnection(server.getUrl("/")); 15467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection2)); 15477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("GET, HEAD, PUT", connection2.getHeaderField("Allow")); 15487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 15497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 15507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testGetHeadersReturnsCachedHopByHopHeaders() throws Exception { 15517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 15527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Transfer-Encoding: identity") 15537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 15547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=0") 15557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 15567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 15577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Transfer-Encoding: none") 15587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 15597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 15607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 15617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection1 = openConnection(server.getUrl("/")); 15627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection1)); 15637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("identity", connection1.getHeaderField("Transfer-Encoding")); 15647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 15657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection2 = openConnection(server.getUrl("/")); 15667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection2)); 15677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("identity", connection2.getHeaderField("Transfer-Encoding")); 15687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 15697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 15707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testGetHeadersDeletesCached100LevelWarnings() throws Exception { 15717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 15727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Warning: 199 test danger") 15737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 15747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=0") 15757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 15767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 15777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 15787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 15797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 15807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection1 = openConnection(server.getUrl("/")); 15817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection1)); 15827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("199 test danger", connection1.getHeaderField("Warning")); 15837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 15847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection2 = openConnection(server.getUrl("/")); 15857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection2)); 15867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(null, connection2.getHeaderField("Warning")); 15877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 15887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 15897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testGetHeadersRetainsCached200LevelWarnings() throws Exception { 15907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 15917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Warning: 299 test danger") 15927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS)) 15937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=0") 15947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 15957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 15967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 15977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 15987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 15997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection1 = openConnection(server.getUrl("/")); 16007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection1)); 16017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("299 test danger", connection1.getHeaderField("Warning")); 16027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 16037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection2 = openConnection(server.getUrl("/")); 16047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection2)); 16057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("299 test danger", connection2.getHeaderField("Warning")); 16067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 16077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 16087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void assertCookies(URL url, String... expectedCookies) throws Exception { 16097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath List<String> actualCookies = new ArrayList<String>(); 16107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath for (HttpCookie cookie : cookieManager.getCookieStore().get(url.toURI())) { 16117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath actualCookies.add(cookie.toString()); 16127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 16137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(Arrays.asList(expectedCookies), actualCookies); 16147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 16157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 16167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testCachePlusRange() throws Exception { 16177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertNotCached(new MockResponse() 16187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setResponseCode(HttpURLConnection.HTTP_PARTIAL) 16197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Date: " + formatDate(0, TimeUnit.HOURS)) 16207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Content-Range: bytes 100-100/200") 16217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60")); 16227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 16237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 16247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public void testConditionalHitUpdatesCache() throws Exception { 16257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 16267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Last-Modified: " + formatDate(0, TimeUnit.SECONDS)) 16277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=0") 16287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 16297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 16307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=30") 16317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Allow: GET, HEAD") 16327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 16337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 16347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 16357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 16367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // cache miss; seed the cache 16377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection connection1 = openConnection(server.getUrl("/a")); 16387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection1)); 16397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(null, connection1.getHeaderField("Allow")); 16407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 16417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // conditional cache hit; update the cache 16427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection connection2 = openConnection(server.getUrl("/a")); 16437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(HttpURLConnection.HTTP_OK, connection2.getResponseCode()); 16447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection2)); 16457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("GET, HEAD", connection2.getHeaderField("Allow")); 16467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 16477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // full cache hit 16487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection connection3 = openConnection(server.getUrl("/a")); 16497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection3)); 16507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("GET, HEAD", connection3.getHeaderField("Allow")); 16517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 16527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(2, server.getRequestCount()); 16537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 16547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 16557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath /** 16567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * @param delta the offset from the current date to use. Negative 16577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * values yield dates in the past; positive values yield dates in the 16587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * future. 16597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 16607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private String formatDate(long delta, TimeUnit timeUnit) { 16617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return formatDate(new Date(System.currentTimeMillis() + timeUnit.toMillis(delta))); 16627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 16637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 16647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private String formatDate(Date date) { 16657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath DateFormat rfc1123 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); 16667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath rfc1123.setTimeZone(TimeZone.getTimeZone("UTC")); 16677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return rfc1123.format(date); 16687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 16697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 16707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private void addRequestBodyIfNecessary(String requestMethod, OkHttpConnection invalidate) 16717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath throws IOException { 16727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath if (requestMethod.equals("POST") || requestMethod.equals("PUT")) { 16737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath invalidate.setDoOutput(true); 16747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OutputStream requestBody = invalidate.getOutputStream(); 16757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath requestBody.write('x'); 16767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath requestBody.close(); 16777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 16787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 16797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 16807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private void assertNotCached(MockResponse response) throws Exception { 16817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(response.setBody("A")); 16827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 16837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 16847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 16857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 16867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(url))); 16877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(openConnection(url))); 16887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 16897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 16907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private void exercisePossiblyFaultyCache(boolean permitReadBodyFailures) throws Exception { 16917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.shutdown(); 16927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server = new MockWebServer(); 16937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse() 16947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .addHeader("Cache-Control: max-age=60") 16957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath .setBody("A")); 16967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setBody("B")); 16977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 16987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 16997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/" + UUID.randomUUID()); 17007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(url))); 17017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 17027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URLConnection connection = openConnection(url); 17037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath InputStream in = connection.getInputStream(); 17047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath try { 17057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath int bodyChar = in.read(); 17067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertTrue(bodyChar == 'A' || bodyChar == 'B'); 17077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(-1, in.read()); 17087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } catch (IOException e) { 17097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath if (!permitReadBodyFailures) { 17107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath throw e; 17117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 17127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 17137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 17147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 17157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath /** 17167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * @return the request with the conditional get headers. 17177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 17187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private RecordedRequest assertConditionallyCached(MockResponse response) throws Exception { 17197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // scenario 1: condition succeeds 17207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(response.setBody("A").setStatus("HTTP/1.1 200 A-OK")); 17217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); 17227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 17237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath // scenario 2: condition fails 17247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(response.setBody("B").setStatus("HTTP/1.1 200 B-OK")); 17257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(new MockResponse().setStatus("HTTP/1.1 200 C-OK").setBody("C")); 17267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 17277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 17287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 17297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL valid = server.getUrl("/valid"); 17307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection connection1 = openConnection(valid); 17317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection1)); 17327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(HttpURLConnection.HTTP_OK, connection1.getResponseCode()); 17337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A-OK", connection1.getResponseMessage()); 17347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection connection2 = openConnection(valid); 17357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(connection2)); 17367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(HttpURLConnection.HTTP_OK, connection2.getResponseCode()); 17377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A-OK", connection2.getResponseMessage()); 17387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 17397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL invalid = server.getUrl("/invalid"); 17407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection connection3 = openConnection(invalid); 17417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B", readAscii(connection3)); 17427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(HttpURLConnection.HTTP_OK, connection3.getResponseCode()); 17437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("B-OK", connection3.getResponseMessage()); 17447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection connection4 = openConnection(invalid); 17457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("C", readAscii(connection4)); 17467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(HttpURLConnection.HTTP_OK, connection4.getResponseCode()); 17477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("C-OK", connection4.getResponseMessage()); 17487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 17497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.takeRequest(); // regular get 17507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return server.takeRequest(); // conditional get 17517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 17527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 17537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private void assertFullyCached(MockResponse response) throws Exception { 17547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(response.setBody("A")); 17557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.enqueue(response.setBody("B")); 17567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath server.play(); 17577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 17587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath URL url = server.getUrl("/"); 17597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(url))); 17607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals("A", readAscii(openConnection(url))); 17617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 17627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 17637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath /** 17647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Shortens the body of {@code response} but not the corresponding headers. 17657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Only useful to test how clients respond to the premature conclusion of 17667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * the HTTP body. 17677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 17687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private MockResponse truncateViolently(MockResponse response, int numBytesToKeep) { 17697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath response.setSocketPolicy(DISCONNECT_AT_END); 17707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath List<String> headers = new ArrayList<String>(response.getHeaders()); 17717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath response.setBody(Arrays.copyOfRange(response.getBody(), 0, numBytesToKeep)); 17727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath response.getHeaders().clear(); 17737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath response.getHeaders().addAll(headers); 17747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return response; 17757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 17767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 17777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath /** 17787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Reads {@code count} characters from the stream. If the stream is 17797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * exhausted before {@code count} characters can be read, the remaining 17807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * characters are returned and the stream is closed. 17817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 17827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private String readAscii(URLConnection connection, int count) throws IOException { 17837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OkHttpConnection httpConnection = (OkHttpConnection) connection; 17847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath InputStream in = httpConnection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST 17857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath ? connection.getInputStream() 17867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath : httpConnection.getErrorStream(); 17877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath StringBuilder result = new StringBuilder(); 17887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath for (int i = 0; i < count; i++) { 17897899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath int value = in.read(); 17907899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath if (value == -1) { 17917899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath in.close(); 17927899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath break; 17937899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 17947899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath result.append((char) value); 17957899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 17967899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return result.toString(); 17977899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 17987899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 17997899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private String readAscii(URLConnection connection) throws IOException { 18007899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return readAscii(connection, Integer.MAX_VALUE); 18017899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18027899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 18037899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private void reliableSkip(InputStream in, int length) throws IOException { 18047899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath while (length > 0) { 18057899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath length -= in.skip(length); 18067899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18077899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18087899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 18097899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private void assertGatewayTimeout(OkHttpConnection connection) throws IOException { 18107899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath try { 18117899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath connection.getInputStream(); 18127899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath fail(); 18137899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } catch (FileNotFoundException expected) { 18147899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18157899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(504, connection.getResponseCode()); 18167899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath assertEquals(-1, connection.getErrorStream().read()); 18177899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18187899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 18197899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath enum TransferKind { 18207899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath CHUNKED() { 18217899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath @Override void setBody(MockResponse response, byte[] content, int chunkSize) 18227899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath throws IOException { 18237899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath response.setChunkedBody(content, chunkSize); 18247899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18257899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath }, 18267899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath FIXED_LENGTH() { 18277899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath @Override void setBody(MockResponse response, byte[] content, int chunkSize) { 18287899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath response.setBody(content); 18297899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18307899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath }, 18317899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath END_OF_STREAM() { 18327899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath @Override void setBody(MockResponse response, byte[] content, int chunkSize) { 18337899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath response.setBody(content); 18347899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath response.setSocketPolicy(DISCONNECT_AT_END); 18357899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath for (Iterator<String> h = response.getHeaders().iterator(); h.hasNext(); ) { 18367899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath if (h.next().startsWith("Content-Length:")) { 18377899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath h.remove(); 18387899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath break; 18397899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18407899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18417899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18427899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath }; 18437899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 18447899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath abstract void setBody(MockResponse response, byte[] content, int chunkSize) 18457899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath throws IOException; 18467899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 18477899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath void setBody(MockResponse response, String content, int chunkSize) throws IOException { 18487899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath setBody(response, content.getBytes("UTF-8"), chunkSize); 18497899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18507899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18517899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 18527899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private <T> List<T> toListOrNull(T[] arrayOrNull) { 18537899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return arrayOrNull != null ? Arrays.asList(arrayOrNull) : null; 18547899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18557899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 18567899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath /** 18577899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath * Returns a gzipped copy of {@code bytes}. 18587899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath */ 18597899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath public byte[] gzip(byte[] bytes) throws IOException { 18607899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); 18617899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath OutputStream gzippedOut = new GZIPOutputStream(bytesOut); 18627899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath gzippedOut.write(bytes); 18637899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath gzippedOut.close(); 18647899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return bytesOut.toByteArray(); 18657899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18667899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 18677899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath private class InsecureResponseCache extends ResponseCache { 18687899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath @Override public CacheRequest put(URI uri, URLConnection connection) throws IOException { 18697899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return cache.put(uri, connection); 18707899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18717899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath 18727899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath @Override public CacheResponse get(URI uri, String requestMethod, 18737899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath Map<String, List<String>> requestHeaders) throws IOException { 18747899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath final CacheResponse response = cache.get(uri, requestMethod, requestHeaders); 18757899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath if (response instanceof SecureCacheResponse) { 18767899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return new CacheResponse() { 18777899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath @Override public InputStream getBody() throws IOException { 18787899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return response.getBody(); 18797899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18807899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath @Override public Map<String, List<String>> getHeaders() throws IOException { 18817899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return response.getHeaders(); 18827899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18837899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath }; 18847899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18857899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath return response; 18867899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18877899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath } 18887899c5ab935cf542069835ec7d3e457db596dbf7Narayan Kamath} 1889