diff options
author | Narayan Kamath <narayan@google.com> | 2013-07-23 08:47:04 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2013-07-23 08:47:04 +0000 |
commit | 527ea78938a49edc4532186a869ad528b1fbf73e (patch) | |
tree | 38df6e3e81537b1908d00d69187570cca182b1d8 | |
parent | 4d31eb4667a86cca81ecf5943b0b61cd1e8d1fae (diff) | |
parent | fb0eb65be9f50e75fa37c250e97914252c587caf (diff) | |
download | okhttp-527ea78938a49edc4532186a869ad528b1fbf73e.tar.gz |
Merge "Update OkHttp to commit cc4633943800572673c03b32d0b2bc9a08ae184d"jb-mr1.1-dev-plus-aosp
14 files changed, 165 insertions, 127 deletions
@@ -1,44 +1,46 @@ OkHttp ====== -An HTTP+SPDY client for Android and Java applications. +An HTTP & SPDY client for Android and Java applications. + +For more information please see [the website][1]. + Download -------- -Downloadable .jars can be found on the [GitHub download page][1]. - -You can also depend on the .jar through Maven: +Download [the latest JAR][2] or grab via Maven: ```xml <dependency> - <groupId>com.squareup</groupId> + <groupId>com.squareup.okhttp</groupId> <artifactId>okhttp</artifactId> <version>(insert latest version)</version> </dependency> ``` -Known Issues ------------- - -OkHttp uses the platform's [ProxySelector][2]. Prior to Android 4.0, `ProxySelector` didn't honor the `proxyHost` and `proxyPort` system properties for HTTPS connections. Work around this by specifying the `https.proxyHost` and `https.proxyPort` system properties when using a proxy with HTTPS. - -OkHttp's test suite creates an in-process HTTPS server. Prior to Android 2.3, SSL server sockets were broken, and so HTTPS tests will time out when run on such devices. - - Building -------- ### On the Desktop -Run OkHttp tests on the desktop with Maven. Running SPDY tests on the desktop uses [Jetty-NPN](http://wiki.eclipse.org/Jetty/Feature/NPN) which requires OpenJDK 7+. + +Run OkHttp tests on the desktop with Maven. Running SPDY tests on the desktop uses +[Jetty-NPN][3] which requires OpenJDK 7+. + ``` mvn clean test ``` ### On a Device -Test on a USB-attached Android using [Vogar](https://code.google.com/p/vogar/). Unfortunately `dx` requires that you build with Java 6, otherwise the test class will be silently omitted from the `.dex` file. + +OkHttp's test suite creates an in-process HTTPS server. Prior to Android 2.3, SSL server sockets +were broken, and so HTTPS tests will time out when run on such devices. + +Test on a USB-attached Android using [Vogar][4]. Unfortunately `dx` requires that you build with +Java 6, otherwise the test class will be silently omitted from the `.dex` file. + ``` mvn clean mvn package -DskipTests @@ -67,5 +69,8 @@ License - [1]: http://github.com/square/okhttp/downloads - [2]: http://developer.android.com/reference/java/net/ProxySelector.html + + [1]: http://square.github.io/okhttp + [2]: http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=com.squareup.okhttp&a=okhttp&v=LATEST + [3]: http://wiki.eclipse.org/Jetty/Feature/NPN + [4]: https://code.google.com/p/vogar/ @@ -6,7 +6,7 @@ <parent> <groupId>com.squareup.okhttp</groupId> <artifactId>parent</artifactId> - <version>1.0.3-SNAPSHOT</version> + <version>1.1.2-SNAPSHOT</version> </parent> <artifactId>okhttp</artifactId> diff --git a/src/main/java/com/squareup/okhttp/Connection.java b/src/main/java/com/squareup/okhttp/Connection.java index 73c4b56..cfda281 100644 --- a/src/main/java/com/squareup/okhttp/Connection.java +++ b/src/main/java/com/squareup/okhttp/Connection.java @@ -31,6 +31,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.Proxy; import java.net.Socket; +import java.net.SocketTimeoutException; import java.net.URL; import java.util.Arrays; import javax.net.ssl.SSLSocket; @@ -192,6 +193,39 @@ public final class Connection implements Closeable { return !socket.isClosed() && !socket.isInputShutdown() && !socket.isOutputShutdown(); } + /** + * Returns true if we are confident that we can read data from this + * connection. This is more expensive and more accurate than {@link + * #isAlive()}; callers should check {@link #isAlive()} first. + */ + public boolean isReadable() { + if (!(in instanceof BufferedInputStream)) { + return true; // Optimistic. + } + if (isSpdy()) { + return true; // Optimistic. We can't test SPDY because its streams are in use. + } + BufferedInputStream bufferedInputStream = (BufferedInputStream) in; + try { + int readTimeout = socket.getSoTimeout(); + try { + socket.setSoTimeout(1); + bufferedInputStream.mark(1); + if (bufferedInputStream.read() == -1) { + return false; // Stream is exhausted; socket is closed. + } + bufferedInputStream.reset(); + return true; + } finally { + socket.setSoTimeout(readTimeout); + } + } catch (SocketTimeoutException ignored) { + return true; // Read timed out; socket is good. + } catch (IOException e) { + return false; // Couldn't read; socket is closed. + } + } + public void resetIdleStartTime() { if (spdyConnection != null) { throw new IllegalStateException("spdyConnection != null"); diff --git a/src/main/java/com/squareup/okhttp/ConnectionPool.java b/src/main/java/com/squareup/okhttp/ConnectionPool.java index 009f025..42b70b9 100644 --- a/src/main/java/com/squareup/okhttp/ConnectionPool.java +++ b/src/main/java/com/squareup/okhttp/ConnectionPool.java @@ -216,8 +216,6 @@ public class ConnectionPool { * <p>It is an error to use {@code connection} after calling this method. */ public void recycle(Connection connection) { - executorService.submit(connectionsCleanupCallable); - if (connection.isSpdy()) { return; } @@ -240,6 +238,8 @@ public class ConnectionPool { connections.addFirst(connection); connection.resetIdleStartTime(); } + + executorService.submit(connectionsCleanupCallable); } /** diff --git a/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java b/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java index 51fd2a7..d6b6001 100644 --- a/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java +++ b/src/main/java/com/squareup/okhttp/internal/http/HttpEngine.java @@ -286,7 +286,7 @@ public class HttpEngine { routeSelector = new RouteSelector(address, uri, client.getProxySelector(), client.getConnectionPool(), Dns.DEFAULT, client.getRoutesDatabase()); } - connection = routeSelector.next(); + connection = routeSelector.next(method); if (!connection.isConnected()) { connection.connect(client.getConnectTimeout(), client.getReadTimeout(), getTunnelConfig()); client.getConnectionPool().maybeShare(connection); diff --git a/src/main/java/com/squareup/okhttp/internal/http/HttpURLConnectionImpl.java b/src/main/java/com/squareup/okhttp/internal/http/HttpURLConnectionImpl.java index e8c198f..214f25a 100644 --- a/src/main/java/com/squareup/okhttp/internal/http/HttpURLConnectionImpl.java +++ b/src/main/java/com/squareup/okhttp/internal/http/HttpURLConnectionImpl.java @@ -19,8 +19,6 @@ package com.squareup.okhttp.internal.http; import com.squareup.okhttp.Connection; import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.internal.AbstractOutputStream; -import com.squareup.okhttp.internal.FaultRecoveringOutputStream; import com.squareup.okhttp.internal.Platform; import com.squareup.okhttp.internal.Util; import java.io.FileNotFoundException; @@ -69,20 +67,12 @@ public class HttpURLConnectionImpl extends HttpURLConnection implements Policy { */ private static final int MAX_REDIRECTS = 20; - /** - * The minimum number of request body bytes to transmit before we're willing - * to let a routine {@link IOException} bubble up to the user. This is used to - * size a buffer for data that will be replayed upon error. - */ - private static final int MAX_REPLAY_BUFFER_LENGTH = 8192; - final OkHttpClient client; private final RawHeaders rawRequestHeaders = new RawHeaders(); /** Like the superclass field of the same name, but a long and available on all platforms. */ private long fixedContentLength = -1; private int redirectionCount; - private FaultRecoveringOutputStream faultRecoveringRequestBody; protected IOException httpEngineFailure; protected HttpEngine httpEngine; @@ -212,22 +202,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection implements Policy { throw new ProtocolException("cannot write request body after response has been read"); } - if (faultRecoveringRequestBody == null) { - faultRecoveringRequestBody = new FaultRecoveringOutputStream(MAX_REPLAY_BUFFER_LENGTH, out) { - @Override protected OutputStream replacementStream(IOException e) throws IOException { - if (httpEngine.getRequestBody() instanceof AbstractOutputStream - && ((AbstractOutputStream) httpEngine.getRequestBody()).isClosed()) { - return null; // Don't recover once the underlying stream has been closed. - } - if (handleFailure(e)) { - return httpEngine.getRequestBody(); - } - return null; // This is a permanent failure. - } - }; - } - - return faultRecoveringRequestBody; + return out; } @Override public final Permission getPermission() throws IOException { @@ -393,8 +368,7 @@ public class HttpURLConnectionImpl extends HttpURLConnection implements Policy { OutputStream requestBody = httpEngine.getRequestBody(); boolean canRetryRequestBody = requestBody == null - || requestBody instanceof RetryableOutputStream - || (faultRecoveringRequestBody != null && faultRecoveringRequestBody.isRecoverable()); + || requestBody instanceof RetryableOutputStream; if (routeSelector == null && httpEngine.connection == null // No connection. || routeSelector != null && !routeSelector.hasNext() // No more routes to attempt. || !isRecoverable(e) @@ -404,15 +378,9 @@ public class HttpURLConnectionImpl extends HttpURLConnection implements Policy { } httpEngine.release(true); - RetryableOutputStream retryableOutputStream = requestBody instanceof RetryableOutputStream - ? (RetryableOutputStream) requestBody - : null; + RetryableOutputStream retryableOutputStream = (RetryableOutputStream) requestBody; httpEngine = newHttpEngine(method, rawRequestHeaders, null, retryableOutputStream); httpEngine.routeSelector = routeSelector; // Keep the same routeSelector. - if (faultRecoveringRequestBody != null && faultRecoveringRequestBody.isRecoverable()) { - httpEngine.sendRequest(); - faultRecoveringRequestBody.replaceStream(httpEngine.getRequestBody()); - } return true; } diff --git a/src/main/java/com/squareup/okhttp/internal/http/RawHeaders.java b/src/main/java/com/squareup/okhttp/internal/http/RawHeaders.java index e5abd2c..e1fdcf4 100644 --- a/src/main/java/com/squareup/okhttp/internal/http/RawHeaders.java +++ b/src/main/java/com/squareup/okhttp/internal/http/RawHeaders.java @@ -123,23 +123,6 @@ public final class RawHeaders { this.httpMinorVersion = httpMinorVersion; } - public void computeResponseStatusLineFromSpdyHeaders() throws IOException { - String status = null; - String version = null; - for (int i = 0; i < namesAndValues.size(); i += 2) { - String name = namesAndValues.get(i); - if (":status".equals(name)) { - status = namesAndValues.get(i + 1); - } else if (":version".equals(name)) { - version = namesAndValues.get(i + 1); - } - } - if (status == null || version == null) { - throw new ProtocolException("Expected ':status' and ':version' headers not present"); - } - setStatusLine(version + " " + status); - } - /** * @param method like "GET", "POST", "HEAD", etc. * @param path like "/foo/bar.html" @@ -425,10 +408,13 @@ public final class RawHeaders { return result; } - public static RawHeaders fromNameValueBlock(List<String> nameValueBlock) { + /** Returns headers for a name value block containing a SPDY response. */ + public static RawHeaders fromNameValueBlock(List<String> nameValueBlock) throws IOException { if (nameValueBlock.size() % 2 != 0) { throw new IllegalArgumentException("Unexpected name value block: " + nameValueBlock); } + String status = null; + String version = null; RawHeaders result = new RawHeaders(); for (int i = 0; i < nameValueBlock.size(); i += 2) { String name = nameValueBlock.get(i); @@ -438,11 +424,21 @@ public final class RawHeaders { if (end == -1) { end = values.length(); } - result.namesAndValues.add(name); - result.namesAndValues.add(values.substring(start, end)); + String value = values.substring(start, end); + if (":status".equals(name)) { + status = value; + } else if (":version".equals(name)) { + version = value; + } else { + result.namesAndValues.add(name); + result.namesAndValues.add(value); + } start = end + 1; } } + if (status == null) throw new ProtocolException("Expected ':status' header not present"); + if (version == null) throw new ProtocolException("Expected ':version' header not present"); + result.setStatusLine(version + " " + status); return result; } } diff --git a/src/main/java/com/squareup/okhttp/internal/http/RouteSelector.java b/src/main/java/com/squareup/okhttp/internal/http/RouteSelector.java index bab9df2..1055e4f 100644 --- a/src/main/java/com/squareup/okhttp/internal/http/RouteSelector.java +++ b/src/main/java/com/squareup/okhttp/internal/http/RouteSelector.java @@ -102,11 +102,11 @@ public final class RouteSelector { * * @throws NoSuchElementException if there are no more routes to attempt. */ - public Connection next() throws IOException { + public Connection next(String method) throws IOException { // Always prefer pooled connections over new connections. - Connection pooled = pool.get(address); - if (pooled != null) { - return pooled; + for (Connection pooled; (pooled = pool.get(address)) != null; ) { + if (method.equals("GET") || pooled.isReadable()) return pooled; + pooled.close(); } // Compute the next route to attempt. @@ -131,7 +131,7 @@ public final class RouteSelector { postponedRoutes.add(route); // We will only recurse in order to skip previously failed routes. They will be // tried last. - return next(); + return next(method); } return new Connection(route); diff --git a/src/main/java/com/squareup/okhttp/internal/http/SpdyTransport.java b/src/main/java/com/squareup/okhttp/internal/http/SpdyTransport.java index daa4e80..a37a91c 100644 --- a/src/main/java/com/squareup/okhttp/internal/http/SpdyTransport.java +++ b/src/main/java/com/squareup/okhttp/internal/http/SpdyTransport.java @@ -69,7 +69,6 @@ public final class SpdyTransport implements Transport { @Override public ResponseHeaders readResponseHeaders() throws IOException { List<String> nameValueBlock = stream.getResponseHeaders(); RawHeaders rawHeaders = RawHeaders.fromNameValueBlock(nameValueBlock); - rawHeaders.computeResponseStatusLineFromSpdyHeaders(); httpEngine.receiveHeaders(rawHeaders); ResponseHeaders headers = new ResponseHeaders(httpEngine.uri, rawHeaders); diff --git a/src/test/java/com/squareup/okhttp/ConnectionPoolTest.java b/src/test/java/com/squareup/okhttp/ConnectionPoolTest.java index e26e563..6820b43 100644 --- a/src/test/java/com/squareup/okhttp/ConnectionPoolTest.java +++ b/src/test/java/com/squareup/okhttp/ConnectionPoolTest.java @@ -395,7 +395,8 @@ public final class ConnectionPoolTest { Util.closeQuietly(httpA); // Include a closed connection in the pool. pool.recycle(httpB); pool.maybeShare(spdyA); - assertEquals(3, pool.getConnectionCount()); + int connectionCount = pool.getConnectionCount(); + assertTrue(connectionCount == 2 || connectionCount == 3); pool.evictAll(); assertEquals(0, pool.getConnectionCount()); diff --git a/src/test/java/com/squareup/okhttp/internal/http/RawHeadersTest.java b/src/test/java/com/squareup/okhttp/internal/http/RawHeadersTest.java index 474e507..7d8ecf3 100644 --- a/src/test/java/com/squareup/okhttp/internal/http/RawHeadersTest.java +++ b/src/test/java/com/squareup/okhttp/internal/http/RawHeadersTest.java @@ -23,7 +23,7 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; public final class RawHeadersTest { - @Test public void parseNameValueBlock() { + @Test public void parseNameValueBlock() throws IOException { List<String> nameValueBlock = Arrays.asList("cache-control", "no-cache, no-store", "set-cookie", "Cookie1\u0000Cookie2", ":status", "200 OK"); diff --git a/src/test/java/com/squareup/okhttp/internal/http/RouteSelectorTest.java b/src/test/java/com/squareup/okhttp/internal/http/RouteSelectorTest.java index 1cdcb1d..a92db9e 100644 --- a/src/test/java/com/squareup/okhttp/internal/http/RouteSelectorTest.java +++ b/src/test/java/com/squareup/okhttp/internal/http/RouteSelectorTest.java @@ -88,12 +88,13 @@ public final class RouteSelectorTest { assertTrue(routeSelector.hasNext()); dns.inetAddresses = makeFakeAddresses(255, 1); - assertConnection(routeSelector.next(), address, NO_PROXY, dns.inetAddresses[0], uriPort, false); + assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort, + false); dns.assertRequests(uriHost); assertFalse(routeSelector.hasNext()); try { - routeSelector.next(); + routeSelector.next("GET"); fail(); } catch (NoSuchElementException expected) { } @@ -106,14 +107,15 @@ public final class RouteSelectorTest { assertTrue(routeSelector.hasNext()); dns.inetAddresses = makeFakeAddresses(255, 1); - Connection connection = routeSelector.next(); + Connection connection = routeSelector.next("GET"); RouteDatabase routeDatabase = new RouteDatabase(); routeDatabase.failed(connection.getRoute(), new IOException()); routeSelector = new RouteSelector(address, uri, proxySelector, pool, dns, routeDatabase); - assertConnection(routeSelector.next(), address, NO_PROXY, dns.inetAddresses[0], uriPort, false); + assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort, + false); assertFalse(routeSelector.hasNext()); try { - routeSelector.next(); + routeSelector.next("GET"); fail(); } catch (NoSuchElementException expected) { } @@ -126,9 +128,9 @@ public final class RouteSelectorTest { assertTrue(routeSelector.hasNext()); dns.inetAddresses = makeFakeAddresses(255, 2); - assertConnection(routeSelector.next(), address, proxyA, dns.inetAddresses[0], proxyAPort, + assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[0], proxyAPort, false); - assertConnection(routeSelector.next(), address, proxyA, dns.inetAddresses[1], proxyAPort, + assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[1], proxyAPort, false); assertFalse(routeSelector.hasNext()); @@ -144,8 +146,10 @@ public final class RouteSelectorTest { assertTrue(routeSelector.hasNext()); dns.inetAddresses = makeFakeAddresses(255, 2); - assertConnection(routeSelector.next(), address, NO_PROXY, dns.inetAddresses[0], uriPort, false); - assertConnection(routeSelector.next(), address, NO_PROXY, dns.inetAddresses[1], uriPort, false); + assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort, + false); + assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[1], uriPort, + false); assertFalse(routeSelector.hasNext()); dns.assertRequests(uri.getHost()); @@ -162,7 +166,8 @@ public final class RouteSelectorTest { assertTrue(routeSelector.hasNext()); dns.inetAddresses = makeFakeAddresses(255, 1); - assertConnection(routeSelector.next(), address, NO_PROXY, dns.inetAddresses[0], uriPort, false); + assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort, + false); dns.assertRequests(uriHost); assertFalse(routeSelector.hasNext()); @@ -175,8 +180,10 @@ public final class RouteSelectorTest { assertTrue(routeSelector.hasNext()); dns.inetAddresses = makeFakeAddresses(255, 2); - assertConnection(routeSelector.next(), address, NO_PROXY, dns.inetAddresses[0], uriPort, false); - assertConnection(routeSelector.next(), address, NO_PROXY, dns.inetAddresses[1], uriPort, false); + assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort, + false); + assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[1], uriPort, + false); assertFalse(routeSelector.hasNext()); dns.assertRequests(uri.getHost()); @@ -195,23 +202,24 @@ public final class RouteSelectorTest { // First try the IP addresses of the first proxy, in sequence. assertTrue(routeSelector.hasNext()); dns.inetAddresses = makeFakeAddresses(255, 2); - assertConnection(routeSelector.next(), address, proxyA, dns.inetAddresses[0], proxyAPort, + assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[0], proxyAPort, false); - assertConnection(routeSelector.next(), address, proxyA, dns.inetAddresses[1], proxyAPort, + assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[1], proxyAPort, false); dns.assertRequests(proxyAHost); // Next try the IP address of the second proxy. assertTrue(routeSelector.hasNext()); dns.inetAddresses = makeFakeAddresses(254, 1); - assertConnection(routeSelector.next(), address, proxyB, dns.inetAddresses[0], proxyBPort, + assertConnection(routeSelector.next("GET"), address, proxyB, dns.inetAddresses[0], proxyBPort, false); dns.assertRequests(proxyBHost); // Finally try the only IP address of the origin server. assertTrue(routeSelector.hasNext()); dns.inetAddresses = makeFakeAddresses(253, 1); - assertConnection(routeSelector.next(), address, NO_PROXY, dns.inetAddresses[0], uriPort, false); + assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort, + false); dns.assertRequests(uriHost); assertFalse(routeSelector.hasNext()); @@ -228,7 +236,8 @@ public final class RouteSelectorTest { // Only the origin server will be attempted. assertTrue(routeSelector.hasNext()); dns.inetAddresses = makeFakeAddresses(255, 1); - assertConnection(routeSelector.next(), address, NO_PROXY, dns.inetAddresses[0], uriPort, false); + assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort, + false); dns.assertRequests(uriHost); assertFalse(routeSelector.hasNext()); @@ -246,14 +255,14 @@ public final class RouteSelectorTest { assertTrue(routeSelector.hasNext()); dns.inetAddresses = makeFakeAddresses(255, 1); - assertConnection(routeSelector.next(), address, proxyA, dns.inetAddresses[0], proxyAPort, + assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[0], proxyAPort, false); dns.assertRequests(proxyAHost); assertTrue(routeSelector.hasNext()); dns.inetAddresses = null; try { - routeSelector.next(); + routeSelector.next("GET"); fail(); } catch (UnknownHostException expected) { } @@ -261,13 +270,14 @@ public final class RouteSelectorTest { assertTrue(routeSelector.hasNext()); dns.inetAddresses = makeFakeAddresses(255, 1); - assertConnection(routeSelector.next(), address, proxyA, dns.inetAddresses[0], proxyAPort, + assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[0], proxyAPort, false); dns.assertRequests(proxyAHost); assertTrue(routeSelector.hasNext()); dns.inetAddresses = makeFakeAddresses(254, 1); - assertConnection(routeSelector.next(), address, NO_PROXY, dns.inetAddresses[0], uriPort, false); + assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort, + false); dns.assertRequests(uriHost); assertFalse(routeSelector.hasNext()); @@ -281,7 +291,7 @@ public final class RouteSelectorTest { routeDatabase); dns.inetAddresses = makeFakeAddresses(255, 1); - Connection connection = routeSelector.next(); + Connection connection = routeSelector.next("GET"); routeSelector.connectFailed(connection, new IOException("Non SSL exception")); assertTrue(routeDatabase.failedRoutesCount() == 2); } @@ -294,7 +304,7 @@ public final class RouteSelectorTest { routeDatabase); dns.inetAddresses = makeFakeAddresses(255, 1); - Connection connection = routeSelector.next(); + Connection connection = routeSelector.next("GET"); routeSelector.connectFailed(connection, new SSLHandshakeException("SSL exception")); assertTrue(routeDatabase.failedRoutesCount() == 1); } @@ -309,31 +319,39 @@ public final class RouteSelectorTest { // Proxy A dns.inetAddresses = makeFakeAddresses(255, 2); - assertConnection(routeSelector.next(), address, proxyA, dns.inetAddresses[0], proxyAPort, true); + assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[0], proxyAPort, + true); dns.assertRequests(proxyAHost); - assertConnection(routeSelector.next(), address, proxyA, dns.inetAddresses[0], proxyAPort, + assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[0], proxyAPort, false); - assertConnection(routeSelector.next(), address, proxyA, dns.inetAddresses[1], proxyAPort, true); - assertConnection(routeSelector.next(), address, proxyA, dns.inetAddresses[1], proxyAPort, + assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[1], proxyAPort, + true); + assertConnection(routeSelector.next("GET"), address, proxyA, dns.inetAddresses[1], proxyAPort, false); // Proxy B dns.inetAddresses = makeFakeAddresses(254, 2); - assertConnection(routeSelector.next(), address, proxyB, dns.inetAddresses[0], proxyBPort, true); + assertConnection(routeSelector.next("GET"), address, proxyB, dns.inetAddresses[0], proxyBPort, + true); dns.assertRequests(proxyBHost); - assertConnection(routeSelector.next(), address, proxyB, dns.inetAddresses[0], proxyBPort, + assertConnection(routeSelector.next("GET"), address, proxyB, dns.inetAddresses[0], proxyBPort, false); - assertConnection(routeSelector.next(), address, proxyB, dns.inetAddresses[1], proxyBPort, true); - assertConnection(routeSelector.next(), address, proxyB, dns.inetAddresses[1], proxyBPort, + assertConnection(routeSelector.next("GET"), address, proxyB, dns.inetAddresses[1], proxyBPort, + true); + assertConnection(routeSelector.next("GET"), address, proxyB, dns.inetAddresses[1], proxyBPort, false); // Origin dns.inetAddresses = makeFakeAddresses(253, 2); - assertConnection(routeSelector.next(), address, NO_PROXY, dns.inetAddresses[0], uriPort, true); + assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort, + true); dns.assertRequests(uriHost); - assertConnection(routeSelector.next(), address, NO_PROXY, dns.inetAddresses[0], uriPort, false); - assertConnection(routeSelector.next(), address, NO_PROXY, dns.inetAddresses[1], uriPort, true); - assertConnection(routeSelector.next(), address, NO_PROXY, dns.inetAddresses[1], uriPort, false); + assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[0], uriPort, + false); + assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[1], uriPort, + true); + assertConnection(routeSelector.next("GET"), address, NO_PROXY, dns.inetAddresses[1], uriPort, + false); assertFalse(routeSelector.hasNext()); } @@ -350,7 +368,7 @@ public final class RouteSelectorTest { // Extract the regular sequence of routes from selector. List<Connection> regularRoutes = new ArrayList<Connection>(); while (routeSelector.hasNext()) { - regularRoutes.add(routeSelector.next()); + regularRoutes.add(routeSelector.next("GET")); } // Check that we do indeed have more than one route. @@ -362,7 +380,7 @@ public final class RouteSelectorTest { List<Connection> routesWithFailedRoute = new ArrayList<Connection>(); while (routeSelector.hasNext()) { - routesWithFailedRoute.add(routeSelector.next()); + routesWithFailedRoute.add(routeSelector.next("GET")); } assertEquals(regularRoutes.get(0).getRoute(), diff --git a/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java b/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java index 29b5cab..5abe477 100644 --- a/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java +++ b/src/test/java/com/squareup/okhttp/internal/http/URLConnectionTest.java @@ -2282,7 +2282,7 @@ public final class URLConnectionTest { } // This test is ignored because we don't (yet) reliably recover for large request bodies. - @Test @Ignore public void postFailsWithBufferedRequestForLargeRequest() throws Exception { + @Test public void postFailsWithBufferedRequestForLargeRequest() throws Exception { reusedConnectionFailsWithPost(TransferKind.END_OF_STREAM, 16384); } @@ -2290,8 +2290,7 @@ public final class URLConnectionTest { reusedConnectionFailsWithPost(TransferKind.CHUNKED, 1024); } - // This test is ignored because we don't (yet) reliably recover for large request bodies. - @Test @Ignore public void postFailsWithChunkedRequestForLargeRequest() throws Exception { + @Test public void postFailsWithChunkedRequestForLargeRequest() throws Exception { reusedConnectionFailsWithPost(TransferKind.CHUNKED, 16384); } @@ -2299,8 +2298,7 @@ public final class URLConnectionTest { reusedConnectionFailsWithPost(TransferKind.FIXED_LENGTH, 1024); } - // This test is ignored because we don't (yet) reliably recover for large request bodies. - @Test @Ignore public void postFailsWithFixedLengthRequestForLargeRequest() throws Exception { + @Test public void postFailsWithFixedLengthRequestForLargeRequest() throws Exception { reusedConnectionFailsWithPost(TransferKind.FIXED_LENGTH, 16384); } diff --git a/src/test/java/com/squareup/okhttp/internal/spdy/HttpOverSpdyTest.java b/src/test/java/com/squareup/okhttp/internal/spdy/HttpOverSpdyTest.java index 5970088..e17a120 100644 --- a/src/test/java/com/squareup/okhttp/internal/spdy/HttpOverSpdyTest.java +++ b/src/test/java/com/squareup/okhttp/internal/spdy/HttpOverSpdyTest.java @@ -90,12 +90,14 @@ public final class HttpOverSpdyTest { } @Test public void get() throws Exception { - MockResponse response = new MockResponse().setBody("ABCDE"); + MockResponse response = new MockResponse().setBody("ABCDE").setStatus("HTTP/1.1 200 Sweet"); server.enqueue(response); server.play(); HttpURLConnection connection = client.open(server.getUrl("/foo")); assertContent("ABCDE", connection, Integer.MAX_VALUE); + assertEquals(200, connection.getResponseCode()); + assertEquals("Sweet", connection.getResponseMessage()); RecordedRequest request = server.takeRequest(); assertEquals("GET /foo HTTP/1.1", request.getRequestLine()); @@ -211,6 +213,23 @@ public final class HttpOverSpdyTest { assertEquals(2, cache.getHitCount()); } + @Test public void conditionalCache() throws IOException { + client.setResponseCache(cache); + + server.enqueue(new MockResponse().addHeader("ETag: v1").setBody("A")); + server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED)); + server.play(); + + assertContent("A", client.open(server.getUrl("/")), Integer.MAX_VALUE); + assertEquals(1, cache.getRequestCount()); + assertEquals(1, cache.getNetworkCount()); + assertEquals(0, cache.getHitCount()); + assertContent("A", client.open(server.getUrl("/")), Integer.MAX_VALUE); + assertEquals(2, cache.getRequestCount()); + assertEquals(2, cache.getNetworkCount()); + assertEquals(1, cache.getHitCount()); + } + @Test public void acceptAndTransmitCookies() throws Exception { CookieManager cookieManager = new CookieManager(); client.setCookieHandler(cookieManager); |