diff --git a/okhttp-testing-support/src/main/java/okhttp3/FakeDns.java b/okhttp-testing-support/src/main/java/okhttp3/FakeDns.java index f2edc75d6..e12ea9c62 100644 --- a/okhttp-testing-support/src/main/java/okhttp3/FakeDns.java +++ b/okhttp-testing-support/src/main/java/okhttp3/FakeDns.java @@ -19,39 +19,61 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import static org.junit.Assert.assertEquals; public final class FakeDns implements Dns { - private List requestedHosts = new ArrayList<>(); - private List addresses = Collections.emptyList(); + private final Map> hostAddresses = new LinkedHashMap<>(); + private final List requestedHosts = new ArrayList<>(); + private int nextAddress = 100; - /** Sets the addresses to be returned by this fake DNS service. */ - public FakeDns addresses(List addresses) { - this.addresses = new ArrayList<>(addresses); + /** Sets the results for {@code hostname}. */ + public FakeDns set(String hostname, List addresses) { + hostAddresses.put(hostname, addresses); return this; } - /** Sets the service to throw when a hostname is requested. */ - public FakeDns unknownHost() { - this.addresses = Collections.emptyList(); + /** Clears the results for {@code hostname}. */ + public FakeDns clear(String hostname) { + hostAddresses.remove(hostname); return this; } - public InetAddress address(int index) { - return addresses.get(index); + public InetAddress lookup(String hostname, int index) throws UnknownHostException { + return hostAddresses.get(hostname).get(index); } @Override public List lookup(String hostname) throws UnknownHostException { requestedHosts.add(hostname); - if (addresses.isEmpty()) throw new UnknownHostException(); - return addresses; + + List result = hostAddresses.get(hostname); + if (result != null) return result; + + throw new UnknownHostException(); } public void assertRequests(String... expectedHosts) { assertEquals(Arrays.asList(expectedHosts), requestedHosts); requestedHosts.clear(); } + + /** Allocates and returns {@code count} fake addresses like [255.0.0.100, 255.0.0.101]. */ + public List allocate(int count) { + try { + List result = new ArrayList<>(); + for (int i = 0; i < count; i++) { + if (nextAddress > 255) { + throw new AssertionError("too many addresses allocated"); + } + result.add(InetAddress.getByAddress( + new byte[] {(byte) 255, (byte) 0, (byte) 0, (byte) nextAddress++})); + } + return result; + } catch (UnknownHostException e) { + throw new AssertionError(); + } + } } diff --git a/okhttp-tests/src/test/java/okhttp3/CallTest.java b/okhttp-tests/src/test/java/okhttp3/CallTest.java index ded388039..7dc4cc756 100644 --- a/okhttp-tests/src/test/java/okhttp3/CallTest.java +++ b/okhttp-tests/src/test/java/okhttp3/CallTest.java @@ -1518,7 +1518,7 @@ public final class CallTest { // Attempt conditional cache validation and a DNS miss. client.connectionPool().evictAll(); client = client.newBuilder() - .dns(new FakeDns().unknownHost()) + .dns(new FakeDns()) .build(); executeSynchronously("/").assertFailure(UnknownHostException.class); } @@ -2347,9 +2347,9 @@ public final class CallTest { } @Test public void customDns() throws Exception { - // Configure a DNS that returns our MockWebServer for every hostname. + // Configure a DNS that returns our local MockWebServer for android.com. FakeDns dns = new FakeDns(); - dns.addresses(Dns.SYSTEM.lookup(server.url("/").host())); + dns.set("android.com", Dns.SYSTEM.lookup(server.url("/").host())); client = client.newBuilder() .dns(dns) .build(); diff --git a/okhttp-tests/src/test/java/okhttp3/internal/connection/RouteSelectorTest.java b/okhttp-tests/src/test/java/okhttp3/internal/connection/RouteSelectorTest.java index cecd9daa8..347ea7ef3 100644 --- a/okhttp-tests/src/test/java/okhttp3/internal/connection/RouteSelectorTest.java +++ b/okhttp-tests/src/test/java/okhttp3/internal/connection/RouteSelectorTest.java @@ -87,8 +87,8 @@ public final class RouteSelectorTest { RouteSelector routeSelector = new RouteSelector(address, routeDatabase); assertTrue(routeSelector.hasNext()); - dns.addresses(makeFakeAddresses(255, 1)); - assertRoute(routeSelector.next(), address, NO_PROXY, dns.address(0), uriPort); + dns.set(uriHost, dns.allocate(1)); + assertRoute(routeSelector.next(), address, NO_PROXY, dns.lookup(uriHost, 0), uriPort); dns.assertRequests(uriHost); assertFalse(routeSelector.hasNext()); @@ -104,11 +104,11 @@ public final class RouteSelectorTest { RouteSelector routeSelector = new RouteSelector(address, routeDatabase); assertTrue(routeSelector.hasNext()); - dns.addresses(makeFakeAddresses(255, 1)); + dns.set(uriHost, dns.allocate(1)); Route route = routeSelector.next(); routeDatabase.failed(route); routeSelector = new RouteSelector(address, routeDatabase); - assertRoute(routeSelector.next(), address, NO_PROXY, dns.address(0), uriPort); + assertRoute(routeSelector.next(), address, NO_PROXY, dns.lookup(uriHost, 0), uriPort); assertFalse(routeSelector.hasNext()); try { routeSelector.next(); @@ -123,9 +123,9 @@ public final class RouteSelectorTest { RouteSelector routeSelector = new RouteSelector(address, routeDatabase); assertTrue(routeSelector.hasNext()); - dns.addresses(makeFakeAddresses(255, 2)); - assertRoute(routeSelector.next(), address, proxyA, dns.address(0), proxyAPort); - assertRoute(routeSelector.next(), address, proxyA, dns.address(1), proxyAPort); + dns.set(proxyAHost, dns.allocate(2)); + assertRoute(routeSelector.next(), address, proxyA, dns.lookup(proxyAHost, 0), proxyAPort); + assertRoute(routeSelector.next(), address, proxyA, dns.lookup(proxyAHost, 1), proxyAPort); assertFalse(routeSelector.hasNext()); dns.assertRequests(proxyAHost); @@ -138,9 +138,9 @@ public final class RouteSelectorTest { RouteSelector routeSelector = new RouteSelector(address, routeDatabase); assertTrue(routeSelector.hasNext()); - dns.addresses(makeFakeAddresses(255, 2)); - assertRoute(routeSelector.next(), address, NO_PROXY, dns.address(0), uriPort); - assertRoute(routeSelector.next(), address, NO_PROXY, dns.address(1), uriPort); + dns.set(uriHost, dns.allocate(2)); + assertRoute(routeSelector.next(), address, NO_PROXY, dns.lookup(uriHost, 0), uriPort); + assertRoute(routeSelector.next(), address, NO_PROXY, dns.lookup(uriHost, 1), uriPort); assertFalse(routeSelector.hasNext()); dns.assertRequests(uriHost); @@ -164,8 +164,8 @@ public final class RouteSelectorTest { authenticator, null, protocols, connectionSpecs, nullProxySelector); RouteSelector routeSelector = new RouteSelector(address, routeDatabase); assertTrue(routeSelector.hasNext()); - dns.addresses(makeFakeAddresses(255, 1)); - assertRoute(routeSelector.next(), address, NO_PROXY, dns.address(0), uriPort); + dns.set(uriHost, dns.allocate(1)); + assertRoute(routeSelector.next(), address, NO_PROXY, dns.lookup(uriHost, 0), uriPort); dns.assertRequests(uriHost); assertFalse(routeSelector.hasNext()); @@ -176,9 +176,9 @@ public final class RouteSelectorTest { RouteSelector routeSelector = new RouteSelector(address, routeDatabase); assertTrue(routeSelector.hasNext()); - dns.addresses(makeFakeAddresses(255, 2)); - assertRoute(routeSelector.next(), address, NO_PROXY, dns.address(0), uriPort); - assertRoute(routeSelector.next(), address, NO_PROXY, dns.address(1), uriPort); + dns.set(uriHost, dns.allocate(2)); + assertRoute(routeSelector.next(), address, NO_PROXY, dns.lookup(uriHost, 0), uriPort); + assertRoute(routeSelector.next(), address, NO_PROXY, dns.lookup(uriHost, 1), uriPort); assertFalse(routeSelector.hasNext()); dns.assertRequests(uriHost); @@ -195,15 +195,15 @@ public final class RouteSelectorTest { // First try the IP addresses of the first proxy, in sequence. assertTrue(routeSelector.hasNext()); - dns.addresses(makeFakeAddresses(255, 2)); - assertRoute(routeSelector.next(), address, proxyA, dns.address(0), proxyAPort); - assertRoute(routeSelector.next(), address, proxyA, dns.address(1), proxyAPort); + dns.set(proxyAHost, dns.allocate(2)); + assertRoute(routeSelector.next(), address, proxyA, dns.lookup(proxyAHost, 0), proxyAPort); + assertRoute(routeSelector.next(), address, proxyA, dns.lookup(proxyAHost, 1), proxyAPort); dns.assertRequests(proxyAHost); // Next try the IP address of the second proxy. assertTrue(routeSelector.hasNext()); - dns.addresses(makeFakeAddresses(254, 1)); - assertRoute(routeSelector.next(), address, proxyB, dns.address(0), proxyBPort); + dns.set(proxyBHost, dns.allocate(1)); + assertRoute(routeSelector.next(), address, proxyB, dns.lookup(proxyBHost, 0), proxyBPort); dns.assertRequests(proxyBHost); // No more proxies to try. @@ -219,8 +219,8 @@ public final class RouteSelectorTest { // Only the origin server will be attempted. assertTrue(routeSelector.hasNext()); - dns.addresses(makeFakeAddresses(255, 1)); - assertRoute(routeSelector.next(), address, NO_PROXY, dns.address(0), uriPort); + dns.set(uriHost, dns.allocate(1)); + assertRoute(routeSelector.next(), address, NO_PROXY, dns.lookup(uriHost, 0), uriPort); dns.assertRequests(uriHost); assertFalse(routeSelector.hasNext()); @@ -236,12 +236,12 @@ public final class RouteSelectorTest { proxySelector.assertRequests(address.url().uri()); assertTrue(routeSelector.hasNext()); - dns.addresses(makeFakeAddresses(255, 1)); - assertRoute(routeSelector.next(), address, proxyA, dns.address(0), proxyAPort); + dns.set(proxyAHost, dns.allocate(1)); + assertRoute(routeSelector.next(), address, proxyA, dns.lookup(proxyAHost, 0), proxyAPort); dns.assertRequests(proxyAHost); assertTrue(routeSelector.hasNext()); - dns.unknownHost(); + dns.clear(proxyBHost); try { routeSelector.next(); fail(); @@ -250,8 +250,8 @@ public final class RouteSelectorTest { dns.assertRequests(proxyBHost); assertTrue(routeSelector.hasNext()); - dns.addresses(makeFakeAddresses(255, 1)); - assertRoute(routeSelector.next(), address, proxyA, dns.address(0), proxyAPort); + dns.set(proxyAHost, dns.allocate(1)); + assertRoute(routeSelector.next(), address, proxyA, dns.lookup(proxyAHost, 0), proxyAPort); dns.assertRequests(proxyAHost); assertFalse(routeSelector.hasNext()); @@ -264,16 +264,16 @@ public final class RouteSelectorTest { RouteSelector routeSelector = new RouteSelector(address, routeDatabase); // Proxy A - dns.addresses(makeFakeAddresses(255, 2)); - assertRoute(routeSelector.next(), address, proxyA, dns.address(0), proxyAPort); + dns.set(proxyAHost, dns.allocate(2)); + assertRoute(routeSelector.next(), address, proxyA, dns.lookup(proxyAHost, 0), proxyAPort); dns.assertRequests(proxyAHost); - assertRoute(routeSelector.next(), address, proxyA, dns.address(1), proxyAPort); + assertRoute(routeSelector.next(), address, proxyA, dns.lookup(proxyAHost, 1), proxyAPort); // Proxy B - dns.addresses(makeFakeAddresses(254, 2)); - assertRoute(routeSelector.next(), address, proxyB, dns.address(0), proxyBPort); + dns.set(proxyBHost, dns.allocate(2)); + assertRoute(routeSelector.next(), address, proxyB, dns.lookup(proxyBHost, 0), proxyBPort); dns.assertRequests(proxyBHost); - assertRoute(routeSelector.next(), address, proxyB, dns.address(1), proxyBPort); + assertRoute(routeSelector.next(), address, proxyB, dns.lookup(proxyBHost, 1), proxyBPort); // No more proxies to attempt. assertFalse(routeSelector.hasNext()); @@ -284,7 +284,7 @@ public final class RouteSelectorTest { RouteSelector routeSelector = new RouteSelector(address, routeDatabase); final int numberOfAddresses = 2; - dns.addresses(makeFakeAddresses(255, numberOfAddresses)); + dns.set(uriHost, dns.allocate(numberOfAddresses)); // Extract the regular sequence of routes from selector. List regularRoutes = new ArrayList<>(); @@ -351,17 +351,4 @@ public final class RouteSelectorTest { return new Address(uriHost, uriPort, dns, socketFactory, sslSocketFactory, hostnameVerifier, null, authenticator, null, protocols, connectionSpecs, proxySelector); } - - private static List makeFakeAddresses(int prefix, int count) { - try { - List result = new ArrayList<>(); - for (int i = 0; i < count; i++) { - result.add(InetAddress.getByAddress( - new byte[] {(byte) prefix, (byte) 0, (byte) 0, (byte) i})); - } - return result; - } catch (UnknownHostException e) { - throw new AssertionError(); - } - } }