URLConnectionTest.java revision 096aac7b8a607d3da237900f52cab1c5066bf992
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; 36096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilsonimport javax.net.ssl.SSLHandshakeException; 3760476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilsonimport javax.net.ssl.SSLSession; 3860476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilsonimport javax.net.ssl.TestSSLContext; 3951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilsonimport tests.http.DefaultResponseCache; 4060476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilsonimport tests.http.MockResponse; 4160476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilsonimport tests.http.MockWebServer; 4260476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilsonimport tests.http.RecordedRequest; 43e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes 44e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughespublic class URLConnectionTest extends junit.framework.TestCase { 45b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 4651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private MockWebServer server = new MockWebServer(); 4751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 4851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson @Override protected void tearDown() throws Exception { 4951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson ResponseCache.setDefault(null); 5051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.shutdown(); 5151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 5251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 53e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes // Check that if we don't read to the end of a response, the next request on the 54e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes // recycled connection doesn't get the unread tail of the first request's response. 55e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes // http://code.google.com/p/android/issues/detail?id=2939 56e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes public void test_2939() throws Exception { 57b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson MockResponse response = new MockResponse().setChunkedBody("ABCDE\nFGHIJ\nKLMNO\nPQR", 8); 58b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 59b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.enqueue(response); 60b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.enqueue(response); 61b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.play(); 62b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 63c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDE", server.getUrl("/").openConnection(), 5); 64c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDE", server.getUrl("/").openConnection(), 5); 658baf143a7c8921d07b54adbc66ac1e5b42de5fe6Jesse Wilson } 668baf143a7c8921d07b54adbc66ac1e5b42de5fe6Jesse Wilson 678baf143a7c8921d07b54adbc66ac1e5b42de5fe6Jesse Wilson public void testConnectionsArePooled() throws Exception { 68b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson MockResponse response = new MockResponse().setBody("ABCDEFGHIJKLMNOPQR"); 69b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 70b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.enqueue(response); 71b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.enqueue(response); 72b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.enqueue(response); 73b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.play(); 74b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 75c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDEFGHIJKLMNOPQR", server.getUrl("/").openConnection()); 76c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertEquals(0, server.takeRequest().getSequenceNumber()); 77c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDEFGHIJKLMNOPQR", server.getUrl("/").openConnection()); 78c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertEquals(1, server.takeRequest().getSequenceNumber()); 79c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDEFGHIJKLMNOPQR", server.getUrl("/").openConnection()); 80c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertEquals(2, server.takeRequest().getSequenceNumber()); 81c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson } 82c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 83c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson public void testChunkedConnectionsArePooled() throws Exception { 84c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson MockResponse response = new MockResponse().setChunkedBody("ABCDEFGHIJKLMNOPQR", 5); 85c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 86c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.enqueue(response); 87c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.enqueue(response); 88c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.enqueue(response); 89c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.play(); 90c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 91c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDEFGHIJKLMNOPQR", server.getUrl("/").openConnection()); 92b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson assertEquals(0, server.takeRequest().getSequenceNumber()); 93c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDEFGHIJKLMNOPQR", server.getUrl("/").openConnection()); 94b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson assertEquals(1, server.takeRequest().getSequenceNumber()); 95c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("ABCDEFGHIJKLMNOPQR", server.getUrl("/").openConnection()); 96b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson assertEquals(2, server.takeRequest().getSequenceNumber()); 97e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes } 9802f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 99b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson enum WriteKind { BYTE_BY_BYTE, SMALL_BUFFERS, LARGE_BUFFERS } 10002f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 10102f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes public void test_chunkedUpload_byteByByte() throws Exception { 10251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson doUpload(TransferKind.CHUNKED, WriteKind.BYTE_BY_BYTE); 10302f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 10402f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 10502f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes public void test_chunkedUpload_smallBuffers() throws Exception { 10651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson doUpload(TransferKind.CHUNKED, WriteKind.SMALL_BUFFERS); 10702f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 10802f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 10902f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes public void test_chunkedUpload_largeBuffers() throws Exception { 11051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson doUpload(TransferKind.CHUNKED, WriteKind.LARGE_BUFFERS); 11102f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 11202f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 11302f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes public void test_fixedLengthUpload_byteByByte() throws Exception { 11451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson doUpload(TransferKind.FIXED_LENGTH, WriteKind.BYTE_BY_BYTE); 11502f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 11602f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 11702f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes public void test_fixedLengthUpload_smallBuffers() throws Exception { 11851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson doUpload(TransferKind.FIXED_LENGTH, WriteKind.SMALL_BUFFERS); 11902f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 12002f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 12102f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes public void test_fixedLengthUpload_largeBuffers() throws Exception { 12251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson doUpload(TransferKind.FIXED_LENGTH, WriteKind.LARGE_BUFFERS); 12302f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 12402f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes 12551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private void doUpload(TransferKind uploadKind, WriteKind writeKind) throws Exception { 12602f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes int n = 512*1024; 127b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.setBodyLimit(0); 128b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.enqueue(new MockResponse()); 129b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.play(); 130b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 131b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson HttpURLConnection conn = (HttpURLConnection) server.getUrl("/").openConnection(); 13202f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes conn.setDoOutput(true); 13302f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes conn.setRequestMethod("POST"); 13451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson if (uploadKind == TransferKind.CHUNKED) { 13502f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes conn.setChunkedStreamingMode(-1); 13602f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } else { 13702f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes conn.setFixedLengthStreamingMode(n); 13802f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 13902f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes OutputStream out = conn.getOutputStream(); 14002f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes if (writeKind == WriteKind.BYTE_BY_BYTE) { 14102f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes for (int i = 0; i < n; ++i) { 14202f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes out.write('x'); 14302f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 14402f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } else { 14502f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes byte[] buf = new byte[writeKind == WriteKind.SMALL_BUFFERS ? 256 : 64*1024]; 14602f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes Arrays.fill(buf, (byte) 'x'); 14702f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes for (int i = 0; i < n; i += buf.length) { 14802f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes out.write(buf, 0, Math.min(buf.length, n - i)); 14902f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 15002f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 15102f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes out.close(); 1524cb7f05dc68abb23ae54a5891c369062185f2210Elliott Hughes assertEquals(200, conn.getResponseCode()); 153b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson RecordedRequest request = server.takeRequest(); 154b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson assertEquals(n, request.getBodySize()); 15551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson if (uploadKind == TransferKind.CHUNKED) { 156b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson assertTrue(request.getChunkSizes().size() > 0); 157b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } else { 158b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson assertTrue(request.getChunkSizes().isEmpty()); 159b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson } 16002f0cb2eb84a112fcf644d7d1fd0b5f94ea2f03bElliott Hughes } 1616247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes 16251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson /** 16351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * Test that response caching is consistent with the RI and the spec. 16451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4 16551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson */ 1666247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes public void test_responseCaching() throws Exception { 1676247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes // Test each documented HTTP/1.1 code, plus the first unused value in each range. 1686247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 1696247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes 1706247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes // We can't test 100 because it's not really a response. 1716247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes // assertCached(false, 100); 1726247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 101); 1736247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 102); 1746247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(true, 200); 1756247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 201); 1766247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 202); 1776247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(true, 203); 1786247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 204); 1796247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 205); 1806247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(true, 206); 1816247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 207); 18251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson // (See test_responseCaching_300.) 1836247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(true, 301); 1846247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes for (int i = 302; i <= 308; ++i) { 1856247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, i); 1866247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes } 1876247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes for (int i = 400; i <= 406; ++i) { 1886247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, i); 1896247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes } 1906247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes // (See test_responseCaching_407.) 1916247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 408); 1926247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 409); 19351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson // (See test_responseCaching_410.) 1946247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes for (int i = 411; i <= 418; ++i) { 1956247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, i); 1966247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes } 1976247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes for (int i = 500; i <= 506; ++i) { 1986247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, i); 1996247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes } 2006247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes } 2016247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes 20251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void test_responseCaching_300() throws Exception { 20351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson // TODO: fix this for android 20451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertCached(false, 300); 20551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 20651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 2076247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes public void test_responseCaching_407() throws Exception { 2086247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes // This test will fail on Android because we throw if we're not using a proxy. 2096247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes // This isn't true of the RI, but it seems like useful debugging behavior. 2106247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertCached(false, 407); 2116247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes } 2126247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes 21351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void test_responseCaching_410() throws Exception { 21451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson // the HTTP spec permits caching 410s, but the RI doesn't. 21551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertCached(false, 410); 21651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 21751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 2186247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes private void assertCached(boolean shouldPut, int responseCode) throws Exception { 21951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server = new MockWebServer(); 220b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.enqueue(new MockResponse() 221b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson .setResponseCode(responseCode) 22251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson .setBody("ABCDE") 223b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson .addHeader("WWW-Authenticate: challenge")); 224b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson server.play(); 225b1b5baac449d2725002338735f4db34bec8fd001Jesse Wilson 22651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson DefaultResponseCache responseCache = new DefaultResponseCache(); 22751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson ResponseCache.setDefault(responseCache); 22851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson URL url = server.getUrl("/"); 22951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 2306247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes assertEquals(responseCode, conn.getResponseCode()); 2316247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes 23251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson // exhaust the content stream 23351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson try { 23451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson // TODO: remove special case once testUnauthorizedResponseHandling() is fixed 23551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson if (responseCode != 401) { 23651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson readAscii(conn.getInputStream(), Integer.MAX_VALUE); 23751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 23851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } catch (IOException ignored) { 23951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 24051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 24151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson Set<URI> expectedCachedUris = shouldPut 24251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson ? Collections.singleton(url.toURI()) 24351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson : Collections.<URI>emptySet(); 24451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(Integer.toString(responseCode), 24551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson expectedCachedUris, responseCache.getContents().keySet()); 24651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.shutdown(); // tearDown() isn't sufficient; this test starts multiple servers 2476247987eb505a482a67f5f19678260d9e7240a5fElliott Hughes } 24860476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 24960476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson public void testConnectViaHttps() throws IOException, InterruptedException { 25060476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson TestSSLContext testSSLContext = TestSSLContext.create(); 25160476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 25260476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson server.useHttps(testSSLContext.sslContext.getSocketFactory(), false); 25360476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson server.enqueue(new MockResponse() 25460476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson .setResponseCode(200) 25560476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson .setBody("this response comes via HTTPS")); 25660476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson server.play(); 25760476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 258096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/foo").openConnection(); 25960476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson connection.setSSLSocketFactory(testSSLContext.sslContext.getSocketFactory()); 26060476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 261c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("this response comes via HTTPS", connection); 26260476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 26360476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson RecordedRequest request = server.takeRequest(); 26460476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertEquals("GET /foo HTTP/1.1", request.getRequestLine()); 26560476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson } 26660476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 267096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson public void testConnectViaHttpsReusingConnections() throws IOException, InterruptedException { 268096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson TestSSLContext testSSLContext = TestSSLContext.create(); 269096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson 270096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson server.useHttps(testSSLContext.sslContext.getSocketFactory(), false); 271096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson server.enqueue(new MockResponse().setBody("this response comes via HTTPS")); 272096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson server.enqueue(new MockResponse().setBody("another response via HTTPS")); 273096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson server.play(); 274096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson 275096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson // install a custom SSL socket factory so the server can be authorized 276096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection(); 277096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson connection.setSSLSocketFactory(testSSLContext.sslContext.getSocketFactory()); 278096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson assertContent("this response comes via HTTPS", connection); 279096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson 280096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson // without an SSL socket factory, the connection should fail 281096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson connection = (HttpsURLConnection) server.getUrl("/").openConnection(); 282096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson try { 283096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson readAscii(connection.getInputStream(), Integer.MAX_VALUE); 284096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson fail(); 285096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson } catch (SSLException expected) { 286096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson } 287096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson } 288096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson 28960476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson public void testConnectViaProxy() throws IOException, InterruptedException { 29060476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson MockResponse mockResponse = new MockResponse() 29160476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson .setResponseCode(200) 29260476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson .setBody("this response comes via a proxy"); 29351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(mockResponse); 29451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.play(); 29560476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 29660476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson URLConnection connection = new URL("http://android.com/foo").openConnection( 29751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.toProxyAddress()); 298c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("this response comes via a proxy", connection); 29960476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 30051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson RecordedRequest request = server.takeRequest(); 30160476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertEquals("GET http://android.com/foo HTTP/1.1", request.getRequestLine()); 30260476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertContains(request.getHeaders(), "Host: android.com"); 30360476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson } 30460476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 305c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson public void testContentDisagreesWithContentLengthHeader() throws IOException { 306c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.enqueue(new MockResponse() 307c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson .setResponseCode(200) 308c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson .setBody("abc\r\nYOU SHOULD NOT SEE THIS") 309c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson .clearHeaders() 310c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson .addHeader("Content-Length: 3")); 311c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.play(); 312c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 313c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("abc", server.getUrl("/").openConnection()); 314c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson } 315c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 316c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson public void testContentDisagreesWithChunkedHeader() throws IOException { 317c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson MockResponse mockResponse = new MockResponse(); 318c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson mockResponse.setResponseCode(200); 319c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson mockResponse.setChunkedBody("abc", 3); 320c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); 321c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson bytesOut.write(mockResponse.getBody()); 322c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson bytesOut.write("\r\nYOU SHOULD NOT SEE THIS".getBytes()); 323c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson mockResponse.setBody(bytesOut.toByteArray()); 324c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson mockResponse.clearHeaders(); 325c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson mockResponse.addHeader("Transfer-encoding: chunked"); 326c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 327c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.enqueue(mockResponse); 328c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson server.play(); 329c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 330c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("abc", server.getUrl("/").openConnection()); 331c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson } 332c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 33360476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson public void testConnectViaHttpProxyToHttps() throws IOException, InterruptedException { 33460476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson TestSSLContext testSSLContext = TestSSLContext.create(); 33560476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 33651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.useHttps(testSSLContext.sslContext.getSocketFactory(), true); 33751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(new MockResponse().setResponseCode(200).clearHeaders()); // for CONNECT 33851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(new MockResponse() 33960476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson .setResponseCode(200) 34060476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson .setBody("this response comes via a secure proxy")); 34151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.play(); 34260476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 34360476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson URL url = new URL("https://android.com/foo"); 34460476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson HttpsURLConnection connection = (HttpsURLConnection) url.openConnection( 34551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.toProxyAddress()); 34660476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson connection.setSSLSocketFactory(testSSLContext.sslContext.getSocketFactory()); 34760476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson connection.setHostnameVerifier(new HostnameVerifier() { 34860476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson public boolean verify(String hostname, SSLSession session) { 34960476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson return true; 35060476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson } 35160476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson }); 35260476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 353c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent("this response comes via a secure proxy", connection); 35460476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 35551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson RecordedRequest connect = server.takeRequest(); 35660476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertEquals("Connect line failure on proxy", 35760476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson "CONNECT android.com:443 HTTP/1.1", connect.getRequestLine()); 35860476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertContains(connect.getHeaders(), "Host: android.com"); 35960476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 36051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson RecordedRequest get = server.takeRequest(); 36160476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertEquals("GET /foo HTTP/1.1", get.getRequestLine()); 36260476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertContains(get.getHeaders(), "Host: android.com"); 36360476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson } 36460476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson 36551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testResponseCachingAndInputStreamSkipWithFixedLength() throws IOException { 36651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testResponseCaching(TransferKind.FIXED_LENGTH); 36751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 36851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 36951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testResponseCachingAndInputStreamSkipWithChunkedEncoding() throws IOException { 37051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testResponseCaching(TransferKind.CHUNKED); 37151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 37251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 37351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testResponseCachingAndInputStreamSkipWithNoLengthHeaders() throws IOException { 37451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testResponseCaching(TransferKind.END_OF_STREAM); 37551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 37651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 37751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson /** 37851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * HttpURLConnection.getInputStream().skip(long) causes ResponseCache corruption 37951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * http://code.google.com/p/android/issues/detail?id=8175 38051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson */ 38151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private void testResponseCaching(TransferKind transferKind) throws IOException { 38251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson MockResponse response = new MockResponse(); 38351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson transferKind.setBody(response, "I love puppies but hate spiders", 1); 38451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(response); 38551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.play(); 38651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 38751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson DefaultResponseCache cache = new DefaultResponseCache(); 38851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson ResponseCache.setDefault(cache); 38951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 39051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson // Make sure that calling skip() doesn't omit bytes from the cache. 39151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson URLConnection urlConnection = server.getUrl("/").openConnection(); 39251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson InputStream in = urlConnection.getInputStream(); 39351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals("I love ", readAscii(in, "I love ".length())); 39451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson reliableSkip(in, "puppies but hate ".length()); 39551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals("spiders", readAscii(in, "spiders".length())); 39651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(-1, in.read()); 39751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson in.close(); 39851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getSuccessCount()); 399096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson assertEquals(0, cache.getAbortCount()); 40051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 40151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson urlConnection = server.getUrl("/").openConnection(); // this response is cached! 40251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson in = urlConnection.getInputStream(); 40351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals("I love puppies but hate spiders", 40451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson readAscii(in, "I love puppies but hate spiders".length())); 40551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(-1, in.read()); 40651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getMissCount()); 40751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getHitCount()); 408096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson assertEquals(1, cache.getSuccessCount()); 409096aac7b8a607d3da237900f52cab1c5066bf992Jesse Wilson assertEquals(0, cache.getAbortCount()); 41051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 41151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 41251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private void reliableSkip(InputStream in, int length) throws IOException { 41351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson while (length > 0) { 41451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson length -= in.skip(length); 41551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 41651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 41751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 41851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson /** 41951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * Reads {@code count} characters from the stream. If the stream is 42051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * exhausted before {@code count} characters can be read, the remaining 42151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * characters are returned and the stream is closed. 42251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson */ 42351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private String readAscii(InputStream in, int count) throws IOException { 42451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson StringBuilder result = new StringBuilder(); 42551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson for (int i = 0; i < count; i++) { 42651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson int value = in.read(); 42751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson if (value == -1) { 42851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson in.close(); 42951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson break; 43051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 43151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson result.append((char) value); 43251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 43351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson return result.toString(); 43451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 43551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 43651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testServerDisconnectsPrematurelyWithContentLengthHeader() throws IOException { 43751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testServerPrematureDisconnect(TransferKind.FIXED_LENGTH); 43851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 43951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 44051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testServerDisconnectsPrematurelyWithChunkedEncoding() throws IOException { 44151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testServerPrematureDisconnect(TransferKind.CHUNKED); 44251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 44351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 44451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testServerDisconnectsPrematurelyWithNoLengthHeaders() throws IOException { 44551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson /* 44651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * Intentionally empty. This case doesn't make sense because there's no 44751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * such thing as a premature disconnect when the disconnect itself 44851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * indicates the end of the data stream. 44951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson */ 45051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 45151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 45251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private void testServerPrematureDisconnect(TransferKind transferKind) throws IOException { 45351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson MockResponse response = new MockResponse(); 45451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 16); 45551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(truncateViolently(response, 16)); 45651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(new MockResponse().setBody("Request #2")); 45751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.play(); 45851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 45951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson DefaultResponseCache cache = new DefaultResponseCache(); 46051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson ResponseCache.setDefault(cache); 46151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 46251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson BufferedReader reader = new BufferedReader(new InputStreamReader( 46351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.getUrl("/").openConnection().getInputStream())); 46451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals("ABCDE", reader.readLine()); 46551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson try { 46651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson reader.readLine(); 46751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson fail("This implementation silently ignored a truncated HTTP body."); 46851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } catch (IOException expected) { 46951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 47051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 47151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getAbortCount()); 47251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(0, cache.getSuccessCount()); 47351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertContent("Request #2", server.getUrl("/").openConnection()); 47451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getAbortCount()); 47551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getSuccessCount()); 47651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 47751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 47851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testClientPrematureDisconnectWithContentLengthHeader() throws IOException { 47951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testClientPrematureDisconnect(TransferKind.FIXED_LENGTH); 48051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 48151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 48251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testClientPrematureDisconnectWithChunkedEncoding() throws IOException { 48351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testClientPrematureDisconnect(TransferKind.CHUNKED); 48451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 48551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 48651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testClientPrematureDisconnectWithNoLengthHeaders() throws IOException { 48751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testClientPrematureDisconnect(TransferKind.END_OF_STREAM); 48851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 48951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 49051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private void testClientPrematureDisconnect(TransferKind transferKind) throws IOException { 49151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson MockResponse response = new MockResponse(); 49251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 1024); 49351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(response); 49451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(new MockResponse().setBody("Request #2")); 49551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.play(); 49651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 49751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson DefaultResponseCache cache = new DefaultResponseCache(); 49851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson ResponseCache.setDefault(cache); 49951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 50051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson InputStream in = server.getUrl("/").openConnection().getInputStream(); 50151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals("ABCDE", readAscii(in, 5)); 50251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson in.close(); 50351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson try { 50451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson in.read(); 50551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson fail("Expected an IOException because the stream is closed."); 50651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } catch (IOException expected) { 50751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 50851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 50951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getAbortCount()); 51051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(0, cache.getSuccessCount()); 51151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertContent("Request #2", server.getUrl("/").openConnection()); 51251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getAbortCount()); 51351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getSuccessCount()); 51451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 51551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 51651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson /** 51751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * Shortens the body of {@code response} but not the corresponding headers. 51851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * Only useful to test how clients respond to the premature conclusion of 51951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * the HTTP body. 52051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson */ 52151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson private MockResponse truncateViolently(MockResponse response, int numBytesToKeep) { 52251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.setDisconnectAtEnd(true); 52351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson List<String> headers = new ArrayList<String>(response.getHeaders()); 52451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.setBody(Arrays.copyOfRange(response.getBody(), 0, numBytesToKeep)); 52551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.getHeaders().clear(); 52651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.getHeaders().addAll(headers); 52751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson return response; 52851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 52951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 53051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testMarkAndResetWithContentLengthHeader() throws IOException { 53151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testMarkAndReset(TransferKind.FIXED_LENGTH); 53251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 53351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 53451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testMarkAndResetWithChunkedEncoding() throws IOException { 53551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testMarkAndReset(TransferKind.CHUNKED); 53651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 53751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 53851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testMarkAndResetWithNoLengthHeaders() throws IOException { 53951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson testMarkAndReset(TransferKind.END_OF_STREAM); 54051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 54151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 54251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testMarkAndReset(TransferKind transferKind) throws IOException { 54351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson MockResponse response = new MockResponse(); 54451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson transferKind.setBody(response, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 1024); 54551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(response); 54651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.play(); 54751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 54851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson DefaultResponseCache cache = new DefaultResponseCache(); 54951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson ResponseCache.setDefault(cache); 55051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 55151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson InputStream in = server.getUrl("/").openConnection().getInputStream(); 55251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertFalse("This implementation claims to support mark().", in.markSupported()); 55351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson in.mark(5); 55451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals("ABCDE", readAscii(in, 5)); 55551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson try { 55651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson in.reset(); 55751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson fail(); 55851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } catch (IOException expected) { 55951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 56051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals("FGHIJKLMNOPQRSTUVWXYZ", readAscii(in, Integer.MAX_VALUE)); 56151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 56251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertContent("ABCDEFGHIJKLMNOPQRSTUVWXYZ", server.getUrl("/").openConnection()); 56351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getSuccessCount()); 56451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, cache.getHitCount()); 56551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 56651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 56751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson /** 56851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * We've had a bug where we forget the HTTP response when we see response 56951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * code 401. This causes a new HTTP request to be issued for every call into 57051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson * the URLConnection. 57151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson */ 57251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson public void testUnauthorizedResponseHandling() throws IOException { 57351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson MockResponse response = new MockResponse() 57451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson .addHeader("WWW-Authenticate: challenge") 57551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson .setResponseCode(401) // UNAUTHORIZED 57651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson .setBody("Unauthorized"); 57751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(response); 57851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(response); 57951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.enqueue(response); 58051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson server.play(); 58151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 58251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson URL url = server.getUrl("/"); 58351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 58451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 58551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(401, conn.getResponseCode()); 58651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(401, conn.getResponseCode()); 58751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(401, conn.getResponseCode()); 58851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(1, server.getRequestCount()); 58951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 59051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 5916906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson public void testNonHexChunkSize() throws IOException { 5926906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson server.enqueue(new MockResponse() 5936906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson .setBody("5\r\nABCDE\r\nG\r\nFGHIJKLMNOPQRSTU\r\n0\r\n\r\n") 5946906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson .clearHeaders() 5956906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson .addHeader("Transfer-encoding: chunked")); 5966906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson server.play(); 5976906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 5986906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 5996906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson try { 6006906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson readAscii(connection.getInputStream(), Integer.MAX_VALUE); 6016906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson fail(); 6026906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } catch (IOException e) { 6036906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 6046906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 6056906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 6066906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson public void testMissingChunkBody() throws IOException { 6076906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson server.enqueue(new MockResponse() 6086906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson .setBody("5") 6096906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson .clearHeaders() 6106906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson .addHeader("Transfer-encoding: chunked") 6116906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson .setDisconnectAtEnd(true)); 6126906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson server.play(); 6136906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 6146906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 6156906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson try { 6166906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson readAscii(connection.getInputStream(), Integer.MAX_VALUE); 6176906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson fail(); 6186906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } catch (IOException e) { 6196906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 6206906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson } 6216906b0c12dcf3216883d0373973a252812a20d32Jesse Wilson 622deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson public void testClientConfiguredGzipContentEncoding() throws Exception { 623deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson server.enqueue(new MockResponse() 624deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson .setBody(gzip("ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes("UTF-8"))) 625deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson .addHeader("Content-Encoding: gzip")); 626deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson server.play(); 627deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 628deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 629deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson connection.addRequestProperty("Accept-Encoding", "gzip"); 630deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson InputStream gunzippedIn = new GZIPInputStream(connection.getInputStream()); 631deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ", readAscii(gunzippedIn, Integer.MAX_VALUE)); 632deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 633deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson RecordedRequest request = server.takeRequest(); 634deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson assertContains(request.getHeaders(), "Accept-Encoding: gzip"); 635deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson } 636deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 637deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson public void testGzipAndConnectionReuseWithFixedLength() throws Exception { 638deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind.FIXED_LENGTH); 639deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson } 640deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 641deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson public void testGzipAndConnectionReuseWithChunkedEncoding() throws Exception { 642deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson testClientConfiguredGzipContentEncodingAndConnectionReuse(TransferKind.CHUNKED); 643deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson } 644deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 645deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson /** 646deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson * Test a bug where gzip input streams weren't exhausting the input stream, 647deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson * which corrupted the request that followed. 648deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson * http://code.google.com/p/android/issues/detail?id=7059 649deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson */ 650deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson private void testClientConfiguredGzipContentEncodingAndConnectionReuse( 651deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson TransferKind transferKind) throws Exception { 652deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson MockResponse responseOne = new MockResponse(); 653deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson responseOne.addHeader("Content-Encoding: gzip"); 654deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson transferKind.setBody(responseOne, gzip("one (gzipped)".getBytes("UTF-8")), 5); 655deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson server.enqueue(responseOne); 656deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson MockResponse responseTwo = new MockResponse(); 657deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson transferKind.setBody(responseTwo, "two (identity)", 5); 658deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson server.enqueue(responseTwo); 659deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson server.play(); 660deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 661deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson URLConnection connection = server.getUrl("/").openConnection(); 662deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson connection.addRequestProperty("Accept-Encoding", "gzip"); 663deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson InputStream gunzippedIn = new GZIPInputStream(connection.getInputStream()); 664deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson assertEquals("one (gzipped)", readAscii(gunzippedIn, Integer.MAX_VALUE)); 665deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson assertEquals(0, server.takeRequest().getSequenceNumber()); 666deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 667deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson connection = server.getUrl("/").openConnection(); 668deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson assertEquals("two (identity)", readAscii(connection.getInputStream(), Integer.MAX_VALUE)); 669deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson assertEquals(1, server.takeRequest().getSequenceNumber()); 670deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson } 671deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 672deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson /** 673deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson * Encodes the response body using GZIP and adds the corresponding header. 674deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson */ 675deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson public byte[] gzip(byte[] bytes) throws IOException { 676deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); 677deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson OutputStream gzippedOut = new GZIPOutputStream(bytesOut); 678deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson gzippedOut.write(bytes); 679deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson gzippedOut.close(); 680deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson return bytesOut.toByteArray(); 681deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson } 682deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 683c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson /** 684c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson * Reads at most {@code limit} characters from {@code in} and asserts that 685c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson * content equals {@code expected}. 686c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson */ 687c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson private void assertContent(String expected, URLConnection connection, int limit) 688c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson throws IOException { 68951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson assertEquals(expected, readAscii(connection.getInputStream(), limit)); 690c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson ((HttpURLConnection) connection).disconnect(); 691c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson } 692c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 693c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson private void assertContent(String expected, URLConnection connection) throws IOException { 694c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson assertContent(expected, connection, Integer.MAX_VALUE); 695c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson } 696c8977f474b30c5f3807398859a6b16687af6fc7bJesse Wilson 69760476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson private void assertContains(List<String> headers, String header) { 69860476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson assertTrue(headers.toString(), headers.contains(header)); 69960476787f0e0f052366d8031c74e507ffd3d16a3Jesse Wilson } 70051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 70151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson enum TransferKind { 70251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson CHUNKED() { 703deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson @Override void setBody(MockResponse response, byte[] content, int chunkSize) 70451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson throws IOException { 70551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.setChunkedBody(content, chunkSize); 70651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 70751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson }, 70851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson FIXED_LENGTH() { 709deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson @Override void setBody(MockResponse response, byte[] content, int chunkSize) { 71051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.setBody(content); 71151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 71251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson }, 71351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson END_OF_STREAM() { 714deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson @Override void setBody(MockResponse response, byte[] content, int chunkSize) { 71551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.setBody(content); 71651e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson response.setDisconnectAtEnd(true); 71751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson for (Iterator<String> h = response.getHeaders().iterator(); h.hasNext(); ) { 71851e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson if (h.next().startsWith("Content-Length:")) { 71951e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson h.remove(); 72051e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson break; 72151e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 72251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 72351e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 72451e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson }; 72551e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson 726deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson abstract void setBody(MockResponse response, byte[] content, int chunkSize) 72751e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson throws IOException; 728deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson 729deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson void setBody(MockResponse response, String content, int chunkSize) throws IOException { 730deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson setBody(response, content.getBytes("UTF-8"), chunkSize); 731deb236fb06f2a14861e7d40dea959f181cd5cf28Jesse Wilson } 73251e468abf2628ce964d3657042f3ac8f2c947504Jesse Wilson } 733e40c9e3935a5024c0f3ebfb3f1441fcd5c48ed86Elliott Hughes} 734