URLConnectionTest.java revision da289bcd0a9e207cc03c752f7c21c9004056e179
1e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes/* 2e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes * Copyright (C) 2009 The Android Open Source Project 3f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 4e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 5e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes * you may not use this file except in compliance with the License. 6e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes * You may obtain a copy of the License at 7f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 8e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 9f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 10e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes * Unless required by applicable law or agreed to in writing, software 11e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 12e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes * See the License for the specific language governing permissions and 14e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes * limitations under the License. 15e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes */ 16e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes 17e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughespackage java.net; 18e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes 1951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilsonimport java.io.BufferedReader; 20c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilsonimport java.io.ByteArrayOutputStream; 216247987eb505a482a67f5f19678260d9e7240a5fElliott Hughesimport java.io.IOException; 2251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilsonimport java.io.InputStream; 23e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughesimport java.io.InputStreamReader; 2402f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughesimport java.io.OutputStream; 2551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilsonimport java.util.ArrayList; 2602f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughesimport java.util.Arrays; 2751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilsonimport java.util.Collections; 2851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilsonimport java.util.Iterator; 296247987eb505a482a67f5f19678260d9e7240a5fElliott Hughesimport java.util.List; 3051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilsonimport java.util.Set; 31deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilsonimport java.util.zip.GZIPInputStream; 32deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilsonimport java.util.zip.GZIPOutputStream; 3360476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilsonimport javax.net.ssl.HostnameVerifier; 3460476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilsonimport javax.net.ssl.HttpsURLConnection; 35096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilsonimport javax.net.ssl.SSLException; 3660476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilsonimport javax.net.ssl.SSLSession; 3760476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilsonimport javax.net.ssl.TestSSLContext; 3851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilsonimport tests.http.DefaultResponseCache; 3960476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilsonimport tests.http.MockResponse; 4060476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilsonimport tests.http.MockWebServer; 4160476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilsonimport tests.http.RecordedRequest; 42e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes 43e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughespublic class URLConnectionTest extends junit.framework.TestCase { 44b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 45ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson private static final Authenticator SIMPLE_AUTHENTICATOR = new Authenticator() { 46ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson protected PasswordAuthentication getPasswordAuthentication() { 47ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson return new PasswordAuthentication("username", "password".toCharArray()); 48ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } 49ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson }; 50ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 5151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private MockWebServer server = new MockWebServer(); 5251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 5351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson @Override protected void tearDown() throws Exception { 5451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson ResponseCache.setDefault(null); 55ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson Authenticator.setDefault(null); 5651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.shutdown(); 5751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 5851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 59e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes // Check that if we don't read to the end of a response, the next request on the 60e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes // recycled connection doesn't get the unread tail of the first request's response. 61e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes // http://code.google.com/p/android/issues/detail?id=2939 62e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes public void test_2939() throws Exception { 63b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson MockResponse response = new MockResponse().setChunkedBody("ABCDE\nFGHIJ\nKLMNO\nPQR", 8); 64b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 65b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.enqueue(response); 66b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.enqueue(response); 67b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.play(); 68b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 69c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDE", server.getUrl("/").openConnection(), 5); 70c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDE", server.getUrl("/").openConnection(), 5); 718baf143a7c8921d07b54adbc66ac1e5b42de5fe6Jesse Wilson } 728baf143a7c8921d07b54adbc66ac1e5b42de5fe6Jesse Wilson 738baf143a7c8921d07b54adbc66ac1e5b42de5fe6Jesse Wilson public void testConnectionsArePooled() throws Exception { 74b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson MockResponse response = new MockResponse().setBody("ABCDEFGHIJKLMNOPQR"); 75b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 76b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.enqueue(response); 77b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.enqueue(response); 78b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.enqueue(response); 79b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.play(); 80b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 81c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDEFGHIJKLMNOPQR", server.getUrl("/").openConnection()); 82c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertEquals(0, server.takeRequest().getSequenceNumber()); 83c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDEFGHIJKLMNOPQR", server.getUrl("/").openConnection()); 84c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertEquals(1, server.takeRequest().getSequenceNumber()); 85c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDEFGHIJKLMNOPQR", server.getUrl("/").openConnection()); 86c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertEquals(2, server.takeRequest().getSequenceNumber()); 87c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson } 88c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 89c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson public void testChunkedConnectionsArePooled() throws Exception { 90c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson MockResponse response = new MockResponse().setChunkedBody("ABCDEFGHIJKLMNOPQR", 5); 91c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 92c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.enqueue(response); 93c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.enqueue(response); 94c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.enqueue(response); 95c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.play(); 96c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 97c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDEFGHIJKLMNOPQR", server.getUrl("/").openConnection()); 98b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson assertEquals(0, server.takeRequest().getSequenceNumber()); 99c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDEFGHIJKLMNOPQR", server.getUrl("/").openConnection()); 100b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson assertEquals(1, server.takeRequest().getSequenceNumber()); 101c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDEFGHIJKLMNOPQR", server.getUrl("/").openConnection()); 102b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson assertEquals(2, server.takeRequest().getSequenceNumber()); 103e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes } 10402f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 105b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson enum WriteKind { BYTE_BY_BYTE, SMALL_BUFFERS, LARGE_BUFFERS } 10602f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 10702f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes public void test_chunkedUpload_byteByByte() throws Exception { 10851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson doUpload(TransferKind.CHUNKED, WriteKind.BYTE_BY_BYTE); 10902f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 11002f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 11102f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes public void test_chunkedUpload_smallBuffers() throws Exception { 11251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson doUpload(TransferKind.CHUNKED, WriteKind.SMALL_BUFFERS); 11302f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 11402f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 11502f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes public void test_chunkedUpload_largeBuffers() throws Exception { 11651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson doUpload(TransferKind.CHUNKED, WriteKind.LARGE_BUFFERS); 11702f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 11802f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 11902f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes public void test_fixedLengthUpload_byteByByte() throws Exception { 12051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson doUpload(TransferKind.FIXED_LENGTH, WriteKind.BYTE_BY_BYTE); 12102f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 12202f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 12302f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes public void test_fixedLengthUpload_smallBuffers() throws Exception { 12451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson doUpload(TransferKind.FIXED_LENGTH, WriteKind.SMALL_BUFFERS); 12502f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 12602f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 12702f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes public void test_fixedLengthUpload_largeBuffers() throws Exception { 12851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson doUpload(TransferKind.FIXED_LENGTH, WriteKind.LARGE_BUFFERS); 12902f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 13002f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 13151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private void doUpload(TransferKind uploadKind, WriteKind writeKind) throws Exception { 13202f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes int n = 512*1024; 133b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.setBodyLimit(0); 134b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.enqueue(new MockResponse()); 135b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.play(); 136b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 137b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson HttpURLConnection conn = (HttpURLConnection) server.getUrl("/").openConnection(); 13802f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes conn.setDoOutput(true); 13902f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes conn.setRequestMethod("POST"); 14051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson if (uploadKind == TransferKind.CHUNKED) { 14102f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes conn.setChunkedStreamingMode(-1); 14202f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } else { 14302f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes conn.setFixedLengthStreamingMode(n); 14402f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 14502f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes OutputStream out = conn.getOutputStream(); 14602f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes if (writeKind == WriteKind.BYTE_BY_BYTE) { 14702f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes for (int i = 0; i < n; ++i) { 14802f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes out.write('x'); 14902f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 15002f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } else { 15102f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes byte[] buf = new byte[writeKind == WriteKind.SMALL_BUFFERS ? 256 : 64*1024]; 15202f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes Arrays.fill(buf, (byte) 'x'); 15302f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes for (int i = 0; i < n; i += buf.length) { 15402f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes out.write(buf, 0, Math.min(buf.length, n - i)); 15502f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 15602f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 15702f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes out.close(); 1584cb7f05dc68abb23ae54a5891c369062185f2210Elliott Hughes assertEquals(200, conn.getResponseCode()); 159b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson RecordedRequest request = server.takeRequest(); 160b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson assertEquals(n, request.getBodySize()); 16151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson if (uploadKind == TransferKind.CHUNKED) { 162b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson assertTrue(request.getChunkSizes().size() > 0); 163b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } else { 164b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson assertTrue(request.getChunkSizes().isEmpty()); 165b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 16602f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 1676247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes 16851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson /** 16951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * Test that response caching is consistent with the RI and the spec. 17051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4 17151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson */ 1726247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes public void test_responseCaching() throws Exception { 1736247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes // Test each documented HTTP/1.1 code, plus the first unused value in each range. 1746247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 1756247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes 1766247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes // We can't test 100 because it's not really a response. 1776247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes // assertCached(false, 100); 1786247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 101); 1796247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 102); 1806247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(true, 200); 1816247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 201); 1826247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 202); 1836247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(true, 203); 1846247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 204); 1856247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 205); 1866247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(true, 206); 1876247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 207); 18851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson // (See test_responseCaching_300.) 1896247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(true, 301); 1906247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes for (int i = 302; i <= 308; ++i) { 1916247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, i); 1926247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes } 1936247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes for (int i = 400; i <= 406; ++i) { 1946247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, i); 1956247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes } 1966247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes // (See test_responseCaching_407.) 1976247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 408); 1986247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 409); 19951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson // (See test_responseCaching_410.) 2006247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes for (int i = 411; i <= 418; ++i) { 2016247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, i); 2026247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes } 2036247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes for (int i = 500; i <= 506; ++i) { 2046247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, i); 2056247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes } 2066247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes } 2076247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes 20851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void test_responseCaching_300() throws Exception { 20951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson // TODO: fix this for android 21051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertCached(false, 300); 21151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 21251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 2136247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes public void test_responseCaching_407() throws Exception { 2146247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes // This test will fail on Android because we throw if we're not using a proxy. 2156247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes // This isn't true of the RI, but it seems like useful debugging behavior. 2166247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 407); 2176247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes } 2186247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes 21951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void test_responseCaching_410() throws Exception { 22051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson // the HTTP spec permits caching 410s, but the RI doesn't. 22151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertCached(false, 410); 22251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 22351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 2246247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes private void assertCached(boolean shouldPut, int responseCode) throws Exception { 22551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server = new MockWebServer(); 226b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.enqueue(new MockResponse() 227b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson .setResponseCode(responseCode) 22851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson .setBody("ABCDE") 229b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson .addHeader("WWW-Authenticate: challenge")); 230b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.play(); 231b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 23251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson DefaultResponseCache responseCache = new DefaultResponseCache(); 23351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson ResponseCache.setDefault(responseCache); 23451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson URL url = server.getUrl("/"); 23551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 2366247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertEquals(responseCode, conn.getResponseCode()); 2376247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes 23851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson // exhaust the content stream 23951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson try { 24051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson // TODO: remove special case once testUnauthorizedResponseHandling() is fixed 24151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson if (responseCode != 401) { 24251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson readAscii(conn.getInputStream(), Integer.MAX_VALUE); 24351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 24451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } catch (IOException ignored) { 24551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 24651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 24751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson Set<URI> expectedCachedUris = shouldPut 24851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson ? Collections.singleton(url.toURI()) 24951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson : Collections.<URI>emptySet(); 25051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(Integer.toString(responseCode), 25151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson expectedCachedUris, responseCache.getContents().keySet()); 25251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.shutdown(); // tearDown() isn't sufficient; this test starts multiple servers 2536247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes } 25460476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 25560476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson public void testConnectViaHttps() throws IOException, InterruptedException { 25660476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson TestSSLContext testSSLContext = TestSSLContext.create(); 25760476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 25860476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson server.useHttps(testSSLContext.sslContext.getSocketFactory(), false); 25960476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson server.enqueue(new MockResponse() 26060476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson .setResponseCode(200) 26160476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson .setBody("this response comes via HTTPS")); 26260476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson server.play(); 26360476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 264096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/foo").openConnection(); 26560476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson connection.setSSLSocketFactory(testSSLContext.sslContext.getSocketFactory()); 26660476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 267c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("this response comes via HTTPS", connection); 26860476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 26960476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson RecordedRequest request = server.takeRequest(); 27060476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertEquals("GET /foo HTTP/1.1", request.getRequestLine()); 27160476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson } 27260476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 273096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson public void testConnectViaHttpsReusingConnections() throws IOException, InterruptedException { 274096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson TestSSLContext testSSLContext = TestSSLContext.create(); 275096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson 276096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson server.useHttps(testSSLContext.sslContext.getSocketFactory(), false); 277096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson server.enqueue(new MockResponse().setBody("this response comes via HTTPS")); 278096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson server.enqueue(new MockResponse().setBody("another response via HTTPS")); 279096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson server.play(); 280096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson 281096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson // install a custom SSL socket factory so the server can be authorized 282096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection(); 283096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson connection.setSSLSocketFactory(testSSLContext.sslContext.getSocketFactory()); 284096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson assertContent("this response comes via HTTPS", connection); 285096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson 286096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson // without an SSL socket factory, the connection should fail 287096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson connection = (HttpsURLConnection) server.getUrl("/").openConnection(); 288096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson try { 289096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson readAscii(connection.getInputStream(), Integer.MAX_VALUE); 290096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson fail(); 291096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson } catch (SSLException expected) { 292096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson } 293096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson } 294096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson 29560476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson public void testConnectViaProxy() throws IOException, InterruptedException { 29660476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson MockResponse mockResponse = new MockResponse() 29760476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson .setResponseCode(200) 29860476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson .setBody("this response comes via a proxy"); 29951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(mockResponse); 30051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.play(); 30160476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 30260476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson URLConnection connection = new URL("http://android.com/foo").openConnection( 30351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.toProxyAddress()); 304c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("this response comes via a proxy", connection); 30560476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 30651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson RecordedRequest request = server.takeRequest(); 30760476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertEquals("GET http://android.com/foo HTTP/1.1", request.getRequestLine()); 30860476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertContains(request.getHeaders(), "Host: android.com"); 30960476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson } 31060476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 311c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson public void testContentDisagreesWithContentLengthHeader() throws IOException { 312c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.enqueue(new MockResponse() 313c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson .setResponseCode(200) 314c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson .setBody("abc\r\nYOU SHOULD NOT SEE THIS") 315c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson .clearHeaders() 316c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson .addHeader("Content-Length: 3")); 317c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.play(); 318c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 319c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("abc", server.getUrl("/").openConnection()); 320c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson } 321c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 322c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson public void testContentDisagreesWithChunkedHeader() throws IOException { 323c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson MockResponse mockResponse = new MockResponse(); 324c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson mockResponse.setResponseCode(200); 325c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson mockResponse.setChunkedBody("abc", 3); 326c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); 327c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson bytesOut.write(mockResponse.getBody()); 328c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson bytesOut.write("\r\nYOU SHOULD NOT SEE THIS".getBytes()); 329c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson mockResponse.setBody(bytesOut.toByteArray()); 330c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson mockResponse.clearHeaders(); 331c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson mockResponse.addHeader("Transfer-encoding: chunked"); 332c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 333c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.enqueue(mockResponse); 334c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.play(); 335c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 336c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("abc", server.getUrl("/").openConnection()); 337c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson } 338c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 33960476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson public void testConnectViaHttpProxyToHttps() throws IOException, InterruptedException { 34060476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson TestSSLContext testSSLContext = TestSSLContext.create(); 34160476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 34251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.useHttps(testSSLContext.sslContext.getSocketFactory(), true); 34351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(new MockResponse().setResponseCode(200).clearHeaders()); // for CONNECT 34451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(new MockResponse() 34560476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson .setResponseCode(200) 34660476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson .setBody("this response comes via a secure proxy")); 34751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.play(); 34860476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 34960476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson URL url = new URL("https://android.com/foo"); 35060476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson HttpsURLConnection connection = (HttpsURLConnection) url.openConnection( 35151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.toProxyAddress()); 35260476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson connection.setSSLSocketFactory(testSSLContext.sslContext.getSocketFactory()); 35360476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson connection.setHostnameVerifier(new HostnameVerifier() { 35460476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson public boolean verify(String hostname, SSLSession session) { 35560476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson return true; 35660476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson } 35760476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson }); 35860476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 359c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("this response comes via a secure proxy", connection); 36060476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 36151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson RecordedRequest connect = server.takeRequest(); 36260476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertEquals("Connect line failure on proxy", 36360476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson "CONNECT android.com:443 HTTP/1.1", connect.getRequestLine()); 36460476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertContains(connect.getHeaders(), "Host: android.com"); 36560476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 36651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson RecordedRequest get = server.takeRequest(); 36760476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertEquals("GET /foo HTTP/1.1", get.getRequestLine()); 36860476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertContains(get.getHeaders(), "Host: android.com"); 36960476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson } 37060476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 37151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testResponseCachingAndInputStreamSkipWithFixedLength() throws IOException { 37251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testResponseCaching(TransferKind.FIXED_LENGTH); 37351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 37451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 37551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testResponseCachingAndInputStreamSkipWithChunkedEncoding() throws IOException { 37651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testResponseCaching(TransferKind.CHUNKED); 37751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 37851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 37951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testResponseCachingAndInputStreamSkipWithNoLengthHeaders() throws IOException { 38051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testResponseCaching(TransferKind.END_OF_STREAM); 38151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 38251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 38351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson /** 38451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * HttpURLConnection.getInputStream().skip(long) causes ResponseCache corruption 38551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * http://code.google.com/p/android/issues/detail?id=8175 38651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson */ 38751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private void testResponseCaching(TransferKind transferKind) throws IOException { 38851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson MockResponse response = new MockResponse(); 38951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson transferKind.setBody(response, "I love puppies but hate spiders", 1); 39051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(response); 39151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.play(); 39251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 39351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson DefaultResponseCache cache = new DefaultResponseCache(); 39451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson ResponseCache.setDefault(cache); 39551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 39651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson // Make sure that calling skip() doesn't omit bytes from the cache. 39751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson URLConnection urlConnection = server.getUrl("/").openConnection(); 39851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson InputStream in = urlConnection.getInputStream(); 39951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals("I love ", readAscii(in, "I love ".length())); 40051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson reliableSkip(in, "puppies but hate ".length()); 40151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals("spiders", readAscii(in, "spiders".length())); 40251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(-1, in.read()); 40351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson in.close(); 40451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getSuccessCount()); 405096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson assertEquals(0, cache.getAbortCount()); 40651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 40751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson urlConnection = server.getUrl("/").openConnection(); // this response is cached! 40851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson in = urlConnection.getInputStream(); 40951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals("I love puppies but hate spiders", 41051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson readAscii(in, "I love puppies but hate spiders".length())); 41151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(-1, in.read()); 41251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getMissCount()); 41351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getHitCount()); 414096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson assertEquals(1, cache.getSuccessCount()); 415096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson assertEquals(0, cache.getAbortCount()); 41651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 41751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 41851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private void reliableSkip(InputStream in, int length) throws IOException { 41951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson while (length > 0) { 42051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson length -= in.skip(length); 42151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 42251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 42351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 42451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson /** 42551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * Reads {@code count} characters from the stream. If the stream is 42651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * exhausted before {@code count} characters can be read, the remaining 42751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * characters are returned and the stream is closed. 42851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson */ 42951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private String readAscii(InputStream in, int count) throws IOException { 43051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson StringBuilder result = new StringBuilder(); 43151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson for (int i = 0; i < count; i++) { 43251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson int value = in.read(); 43351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson if (value == -1) { 43451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson in.close(); 43551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson break; 43651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 43751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson result.append((char) value); 43851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 43951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson return result.toString(); 44051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 44151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 44251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testServerDisconnectsPrematurelyWithContentLengthHeader() throws IOException { 44351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testServerPrematureDisconnect(TransferKind.FIXED_LENGTH); 44451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 44551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 44651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testServerDisconnectsPrematurelyWithChunkedEncoding() throws IOException { 44751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testServerPrematureDisconnect(TransferKind.CHUNKED); 44851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 44951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 45051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testServerDisconnectsPrematurelyWithNoLengthHeaders() throws IOException { 45151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson /* 45251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * Intentionally empty. This case doesn't make sense because there's no 45351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * such thing as a premature disconnect when the disconnect itself 45451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * indicates the end of the data stream. 45551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson */ 45651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 45751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 45851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private void testServerPrematureDisconnect(TransferKind transferKind) throws IOException { 45951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson MockResponse response = new MockResponse(); 46051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 16); 46151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(truncateViolently(response, 16)); 46251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(new MockResponse().setBody("Request #2")); 46351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.play(); 46451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 46551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson DefaultResponseCache cache = new DefaultResponseCache(); 46651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson ResponseCache.setDefault(cache); 46751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 46851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson BufferedReader reader = new BufferedReader(new InputStreamReader( 46951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.getUrl("/").openConnection().getInputStream())); 47051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals("ABCDE", reader.readLine()); 47151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson try { 47251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson reader.readLine(); 47351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson fail("This implementation silently ignored a truncated HTTP body."); 47451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } catch (IOException expected) { 47551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 47651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 47751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getAbortCount()); 47851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(0, cache.getSuccessCount()); 47951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertContent("Request #2", server.getUrl("/").openConnection()); 48051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getAbortCount()); 48151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getSuccessCount()); 48251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 48351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 48451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testClientPrematureDisconnectWithContentLengthHeader() throws IOException { 48551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testClientPrematureDisconnect(TransferKind.FIXED_LENGTH); 48651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 48751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 48851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testClientPrematureDisconnectWithChunkedEncoding() throws IOException { 48951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testClientPrematureDisconnect(TransferKind.CHUNKED); 49051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 49151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 49251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testClientPrematureDisconnectWithNoLengthHeaders() throws IOException { 49351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testClientPrematureDisconnect(TransferKind.END_OF_STREAM); 49451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 49551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 49651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private void testClientPrematureDisconnect(TransferKind transferKind) throws IOException { 49751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson MockResponse response = new MockResponse(); 49851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 1024); 49951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(response); 50051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(new MockResponse().setBody("Request #2")); 50151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.play(); 50251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 50351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson DefaultResponseCache cache = new DefaultResponseCache(); 50451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson ResponseCache.setDefault(cache); 50551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 50651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson InputStream in = server.getUrl("/").openConnection().getInputStream(); 50751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals("ABCDE", readAscii(in, 5)); 50851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson in.close(); 50951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson try { 51051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson in.read(); 51151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson fail("Expected an IOException because the stream is closed."); 51251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } catch (IOException expected) { 51351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 51451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 51551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getAbortCount()); 51651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(0, cache.getSuccessCount()); 51751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertContent("Request #2", server.getUrl("/").openConnection()); 51851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getAbortCount()); 51951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getSuccessCount()); 52051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 52151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 52251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson /** 52351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * Shortens the body of {@code response} but not the corresponding headers. 52451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * Only useful to test how clients respond to the premature conclusion of 52551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * the HTTP body. 52651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson */ 52751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private MockResponse truncateViolently(MockResponse response, int numBytesToKeep) { 52851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.setDisconnectAtEnd(true); 52951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson List<String> headers = new ArrayList<String>(response.getHeaders()); 53051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.setBody(Arrays.copyOfRange(response.getBody(), 0, numBytesToKeep)); 53151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.getHeaders().clear(); 53251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.getHeaders().addAll(headers); 53351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson return response; 53451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 53551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 53651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testMarkAndResetWithContentLengthHeader() throws IOException { 53751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testMarkAndReset(TransferKind.FIXED_LENGTH); 53851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 53951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 54051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testMarkAndResetWithChunkedEncoding() throws IOException { 54151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testMarkAndReset(TransferKind.CHUNKED); 54251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 54351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 54451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testMarkAndResetWithNoLengthHeaders() throws IOException { 54551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testMarkAndReset(TransferKind.END_OF_STREAM); 54651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 54751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 54851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testMarkAndReset(TransferKind transferKind) throws IOException { 54951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson MockResponse response = new MockResponse(); 55051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson transferKind.setBody(response, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 1024); 55151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(response); 55251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.play(); 55351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 55451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson DefaultResponseCache cache = new DefaultResponseCache(); 55551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson ResponseCache.setDefault(cache); 55651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 55751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson InputStream in = server.getUrl("/").openConnection().getInputStream(); 55851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertFalse("This implementation claims to support mark().", in.markSupported()); 55951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson in.mark(5); 56051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals("ABCDE", readAscii(in, 5)); 56151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson try { 56251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson in.reset(); 56351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson fail(); 56451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } catch (IOException expected) { 56551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 56651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals("FGHIJKLMNOPQRSTUVWXYZ", readAscii(in, Integer.MAX_VALUE)); 56751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 56851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertContent("ABCDEFGHIJKLMNOPQRSTUVWXYZ", server.getUrl("/").openConnection()); 56951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getSuccessCount()); 57051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getHitCount()); 57151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 57251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 57351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson /** 57451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * We've had a bug where we forget the HTTP response when we see response 57551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * code 401. This causes a new HTTP request to be issued for every call into 57651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * the URLConnection. 57751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson */ 57851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testUnauthorizedResponseHandling() throws IOException { 57951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson MockResponse response = new MockResponse() 58051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson .addHeader("WWW-Authenticate: challenge") 58151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson .setResponseCode(401) // UNAUTHORIZED 58251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson .setBody("Unauthorized"); 58351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(response); 58451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(response); 58551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(response); 58651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.play(); 58751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 58851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson URL url = server.getUrl("/"); 58951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 59051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 59151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(401, conn.getResponseCode()); 59251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(401, conn.getResponseCode()); 59351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(401, conn.getResponseCode()); 59451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, server.getRequestCount()); 59551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 59651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 5976906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson public void testNonHexChunkSize() throws IOException { 5986906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson server.enqueue(new MockResponse() 5996906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson .setBody("5\r\nABCDE\r\nG\r\nFGHIJKLMNOPQRSTU\r\n0\r\n\r\n") 6006906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson .clearHeaders() 6016906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson .addHeader("Transfer-encoding: chunked")); 6026906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson server.play(); 6036906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 6046906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 6056906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson try { 6066906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson readAscii(connection.getInputStream(), Integer.MAX_VALUE); 6076906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson fail(); 6086906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } catch (IOException e) { 6096906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 6106906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 6116906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 6126906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson public void testMissingChunkBody() throws IOException { 6136906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson server.enqueue(new MockResponse() 6146906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson .setBody("5") 6156906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson .clearHeaders() 6166906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson .addHeader("Transfer-encoding: chunked") 6176906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson .setDisconnectAtEnd(true)); 6186906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson server.play(); 6196906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 6206906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 6216906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson try { 6226906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson readAscii(connection.getInputStream(), Integer.MAX_VALUE); 6236906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson fail(); 6246906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } catch (IOException e) { 6256906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 6266906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 6276906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 628deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson public void testClientConfiguredGzipContentEncoding() throws Exception { 629deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson server.enqueue(new MockResponse() 630deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson .setBody(gzip("ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes("UTF-8"))) 631deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson .addHeader("Content-Encoding: gzip")); 632deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson server.play(); 633deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 634deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 635deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson connection.addRequestProperty("Accept-Encoding", "gzip"); 636deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson InputStream gunzippedIn = new GZIPInputStream(connection.getInputStream()); 637deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ", readAscii(gunzippedIn, Integer.MAX_VALUE)); 638deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 639deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson RecordedRequest request = server.takeRequest(); 640deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson assertContains(request.getHeaders(), "Accept-Encoding: gzip"); 641deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson } 642deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 643deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson public void testGzipAndConnectionReuseWithFixedLength() throws Exception { 644deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind.FIXED_LENGTH); 645deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson } 646deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 647deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson public void testGzipAndConnectionReuseWithChunkedEncoding() throws Exception { 648deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind.CHUNKED); 649deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson } 650deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 651deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson /** 652deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson * Test a bug where gzip input streams weren't exhausting the input stream, 653deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson * which corrupted the request that followed. 654deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson * http://code.google.com/p/android/issues/detail?id=7059 655deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson */ 656deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson private void testClientConfiguredGzipContentEncodingAndConnectionReuse( 657deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson TransferKind transferKind) throws Exception { 658deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson MockResponse responseOne = new MockResponse(); 659deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson responseOne.addHeader("Content-Encoding: gzip"); 660deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson transferKind.setBody(responseOne, gzip("one (gzipped)".getBytes("UTF-8")), 5); 661deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson server.enqueue(responseOne); 662deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson MockResponse responseTwo = new MockResponse(); 663deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson transferKind.setBody(responseTwo, "two (identity)", 5); 664deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson server.enqueue(responseTwo); 665deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson server.play(); 666deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 667deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 668deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson connection.addRequestProperty("Accept-Encoding", "gzip"); 669deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson InputStream gunzippedIn = new GZIPInputStream(connection.getInputStream()); 670deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson assertEquals("one (gzipped)", readAscii(gunzippedIn, Integer.MAX_VALUE)); 671deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson assertEquals(0, server.takeRequest().getSequenceNumber()); 672deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 673deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson connection = server.getUrl("/").openConnection(); 674deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson assertEquals("two (identity)", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 675deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson assertEquals(1, server.takeRequest().getSequenceNumber()); 676deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson } 677deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 678deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson /** 679ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson * Obnoxiously test that the chunk sizes transmitted exactly equal the 680ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson * requested data+chunk header size. Although setChunkedStreamingMode() 681ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson * isn't specific about whether the size applies to the data or the 682ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson * complete chunk, the RI interprets it as a complete chunk. 683ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson */ 684ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson public void testSetChunkedStreamingMode() throws IOException, InterruptedException { 685ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson server.enqueue(new MockResponse()); 686ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson server.play(); 687ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 688ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson HttpURLConnection urlConnection = (HttpURLConnection) server.getUrl("/").openConnection(); 689ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson urlConnection.setChunkedStreamingMode(8); 690ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson urlConnection.setDoOutput(true); 691ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson OutputStream outputStream = urlConnection.getOutputStream(); 692ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson outputStream.write("ABCDEFGHIJKLMNOPQ".getBytes("US-ASCII")); 693ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson assertEquals(200, urlConnection.getResponseCode()); 694ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 695ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson RecordedRequest request = server.takeRequest(); 696ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson assertEquals("ABCDEFGHIJKLMNOPQ", new String(request.getBody(), "US-ASCII")); 697ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson assertEquals(Arrays.asList(3, 3, 3, 3, 3, 2), request.getChunkSizes()); 698ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } 699ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 700ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson public void testAuthenticateWithFixedLengthStreaming() throws Exception { 701ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson testAuthenticateWithStreamingPost(StreamingMode.FIXED_LENGTH); 702ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } 703ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 704ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson public void testAuthenticateWithChunkedStreaming() throws Exception { 705ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson testAuthenticateWithStreamingPost(StreamingMode.CHUNKED); 706ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } 707ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 708ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson private void testAuthenticateWithStreamingPost(StreamingMode streamingMode) throws Exception { 709ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson MockResponse pleaseAuthenticate = new MockResponse() 710ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson .setResponseCode(401) 711ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson .addHeader("WWW-Authenticate: Basic realm=\"protected area\"") 712ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson .setBody("Please authenticate."); 713ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson server.enqueue(pleaseAuthenticate); 714ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson server.play(); 715ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 716ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson Authenticator.setDefault(SIMPLE_AUTHENTICATOR); 717ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); 718ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson connection.setDoOutput(true); 719ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson byte[] requestBody = { 'A', 'B', 'C', 'D' }; 720ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson if (streamingMode == StreamingMode.FIXED_LENGTH) { 721ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson connection.setFixedLengthStreamingMode(requestBody.length); 722ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } else if (streamingMode == StreamingMode.CHUNKED) { 723ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson connection.setChunkedStreamingMode(0); 724ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } 725ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson OutputStream outputStream = connection.getOutputStream(); 726ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson outputStream.write(requestBody); 727ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson outputStream.close(); 728ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson try { 729ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson connection.getInputStream(); 730ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson fail(); 731ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } catch (HttpRetryException expected) { 732ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } 733ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 734ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson // no authorization header for the request... 735ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson RecordedRequest request = server.takeRequest(); 736ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson assertContainsNoneMatching(request.getHeaders(), "Authorization: Basic .*"); 737ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson assertEquals(Arrays.toString(requestBody), Arrays.toString(request.getBody())); 738ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } 739ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 740ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson enum StreamingMode { 741ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson FIXED_LENGTH, CHUNKED 742ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } 743ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 744ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson public void testAuthenticateWithPost() throws Exception { 745ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson MockResponse pleaseAuthenticate = new MockResponse() 746ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson .setResponseCode(401) 747ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson .addHeader("WWW-Authenticate: Basic realm=\"protected area\"") 748ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson .setBody("Please authenticate."); 749ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson // fail auth three times... 750ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson server.enqueue(pleaseAuthenticate); 751ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson server.enqueue(pleaseAuthenticate); 752ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson server.enqueue(pleaseAuthenticate); 753ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson // ...then succeed the fourth time 754ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson server.enqueue(new MockResponse().setBody("Successful auth!")); 755ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson server.play(); 756ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 757ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson Authenticator.setDefault(SIMPLE_AUTHENTICATOR); 758ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); 759ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson connection.setDoOutput(true); 760ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson byte[] requestBody = { 'A', 'B', 'C', 'D' }; 761ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson OutputStream outputStream = connection.getOutputStream(); 762ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson outputStream.write(requestBody); 763ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson outputStream.close(); 764ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 765ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 766ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson // no authorization header for the first request... 767ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson RecordedRequest request = server.takeRequest(); 768ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson assertContainsNoneMatching(request.getHeaders(), "Authorization: Basic .*"); 769ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 770da289bcd0a9e207cc03c752f7c21c9004056e179Jesse Wilson // ...but the three requests that follow include an authorization header 771ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson for (int i = 0; i < 3; i++) { 772ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson request = server.takeRequest(); 773ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson assertEquals("POST / HTTP/1.1", request.getRequestLine()); 774ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson assertContains(request.getHeaders(), "Authorization: Basic " 775ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson + "dXNlcm5hbWU6cGFzc3dvcmQ="); // "dXNl..." == base64("username:password") 776ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson assertEquals(Arrays.toString(requestBody), Arrays.toString(request.getBody())); 777ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } 778ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } 779ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 780ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson public void testAuthenticateWithGet() throws Exception { 781ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson MockResponse pleaseAuthenticate = new MockResponse() 782ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson .setResponseCode(401) 783ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson .addHeader("WWW-Authenticate: Basic realm=\"protected area\"") 784ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson .setBody("Please authenticate."); 785ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson // fail auth three times... 786ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson server.enqueue(pleaseAuthenticate); 787ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson server.enqueue(pleaseAuthenticate); 788ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson server.enqueue(pleaseAuthenticate); 789ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson // ...then succeed the fourth time 790ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson server.enqueue(new MockResponse().setBody("Successful auth!")); 791ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson server.play(); 792ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 793ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson Authenticator.setDefault(SIMPLE_AUTHENTICATOR); 794ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection(); 795ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson assertEquals("Successful auth!", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 796ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 797ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson // no authorization header for the first request... 798ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson RecordedRequest request = server.takeRequest(); 799ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson assertContainsNoneMatching(request.getHeaders(), "Authorization: Basic .*"); 800ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 801ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson // ...but the three requests that follow requests include an authorization header 802ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson for (int i = 0; i < 3; i++) { 803ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson request = server.takeRequest(); 804ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson assertEquals("GET / HTTP/1.1", request.getRequestLine()); 805ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson assertContains(request.getHeaders(), "Authorization: Basic " 806ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson + "dXNlcm5hbWU6cGFzc3dvcmQ="); // "dXNl..." == base64("username:password") 807ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } 808ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } 809ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 810ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson /** 811deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson * Encodes the response body using GZIP and adds the corresponding header. 812deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson */ 813deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson public byte[] gzip(byte[] bytes) throws IOException { 814deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); 815deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson OutputStream gzippedOut = new GZIPOutputStream(bytesOut); 816deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson gzippedOut.write(bytes); 817deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson gzippedOut.close(); 818deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson return bytesOut.toByteArray(); 819deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson } 820deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 821c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson /** 822c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson * Reads at most {@code limit} characters from {@code in} and asserts that 823c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson * content equals {@code expected}. 824c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson */ 825c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson private void assertContent(String expected, URLConnection connection, int limit) 826c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson throws IOException { 82751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(expected, readAscii(connection.getInputStream(), limit)); 828c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson ((HttpURLConnection) connection).disconnect(); 829c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson } 830c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 831c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson private void assertContent(String expected, URLConnection connection) throws IOException { 832c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent(expected, connection, Integer.MAX_VALUE); 833c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson } 834c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 83560476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson private void assertContains(List<String> headers, String header) { 83660476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertTrue(headers.toString(), headers.contains(header)); 83760476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson } 83851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 839ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson private void assertContainsNoneMatching(List<String> headers, String pattern) { 840ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson for (String header : headers) { 841ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson if (header.matches(pattern)) { 842ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson fail("Header " + header + " matches " + pattern); 843ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } 844ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } 845ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson } 846ffd579b668428272b78f5c6c64f9c89766f37c1aJesse Wilson 84751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson enum TransferKind { 84851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson CHUNKED() { 849deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson @Override void setBody(MockResponse response, byte[] content, int chunkSize) 85051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson throws IOException { 85151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.setChunkedBody(content, chunkSize); 85251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 85351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson }, 85451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson FIXED_LENGTH() { 855deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson @Override void setBody(MockResponse response, byte[] content, int chunkSize) { 85651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.setBody(content); 85751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 85851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson }, 85951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson END_OF_STREAM() { 860deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson @Override void setBody(MockResponse response, byte[] content, int chunkSize) { 86151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.setBody(content); 86251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.setDisconnectAtEnd(true); 86351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson for (Iterator<String> h = response.getHeaders().iterator(); h.hasNext(); ) { 86451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson if (h.next().startsWith("Content-Length:")) { 86551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson h.remove(); 86651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson break; 86751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 86851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 86951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 87051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson }; 87151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 872deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson abstract void setBody(MockResponse response, byte[] content, int chunkSize) 87351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson throws IOException; 874deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 875deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson void setBody(MockResponse response, String content, int chunkSize) throws IOException { 876deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson setBody(response, content.getBytes("UTF-8"), chunkSize); 877deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson } 87851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 879e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes} 880