--- old/test/jdk/java/net/httpclient/http2/RedirectTest.java 2017-11-30 04:05:11.628402807 -0800 +++ new/test/jdk/java/net/httpclient/http2/RedirectTest.java 2017-11-30 04:05:11.414384101 -0800 @@ -24,36 +24,34 @@ /* * @test * @bug 8156514 - * @key intermittent * @library /lib/testlibrary server * @build jdk.testlibrary.SimpleSSLContext - * @modules jdk.incubator.httpclient/jdk.incubator.http.internal.common - * @modules jdk.incubator.httpclient/jdk.incubator.http.internal.frame - * @modules jdk.incubator.httpclient/jdk.incubator.http.internal.hpack + * @modules java.base/sun.net.www.http + * jdk.incubator.httpclient/jdk.incubator.http.internal.common + * jdk.incubator.httpclient/jdk.incubator.http.internal.frame + * jdk.incubator.httpclient/jdk.incubator.http.internal.hpack * @run testng/othervm -Djdk.httpclient.HttpClient.log=frames,ssl,requests,responses,errors RedirectTest */ import java.net.*; import jdk.incubator.http.*; -import static jdk.incubator.http.HttpClient.Version.HTTP_2; -import java.nio.file.*; +import java.util.Optional; import java.util.concurrent.*; import java.util.function.*; import java.util.Arrays; import java.util.Iterator; -import static jdk.incubator.http.HttpRequest.BodyProcessor.fromString; -import static jdk.incubator.http.HttpResponse.BodyHandler.asString; - import org.testng.annotations.Test; +import static jdk.incubator.http.HttpClient.Version.HTTP_2; +import static jdk.incubator.http.HttpRequest.BodyPublisher.fromString; +import static jdk.incubator.http.HttpResponse.BodyHandler.asString; -@Test public class RedirectTest { - static int httpPort, altPort; - static Http2TestServer httpServer, altServer; + static int httpPort; + static Http2TestServer httpServer; static HttpClient client; - static ExecutorService exec; static String httpURIString, altURIString1, altURIString2; + static URI httpURI, altURI1, altURI2; static Supplier sup(String... args) { Iterator i = Arrays.asList(args).iterator(); @@ -61,28 +59,56 @@ return () -> i.next(); } + static class Redirector extends Http2RedirectHandler { + private InetSocketAddress remoteAddr; + private boolean error = false; + + Redirector(Supplier supplier) { + super(supplier); + } + + protected synchronized void examineExchange(Http2TestExchange ex) { + InetSocketAddress addr = ex.getRemoteAddress(); + if (remoteAddr == null) { + remoteAddr = addr; + return; + } + // check that the client addr/port stays the same, proving + // that the connection didn't get dropped. + if (!remoteAddr.equals(addr)) { + System.err.printf("Error %s/%s\n", remoteAddr.toString(), + addr.toString()); + error = true; + } + } + + public synchronized boolean error() { + return error; + } + } + static void initialize() throws Exception { try { client = getClient(); - httpServer = new Http2TestServer(false, 0, exec, null); - + httpServer = new Http2TestServer(false, 0, null, null); httpPort = httpServer.getAddress().getPort(); - altServer = new Http2TestServer(false, 0, exec, null); - altPort = altServer.getAddress().getPort(); - // urls are accessed in sequence below - // first two on different servers. Third on same server - // as second. So, the client should use the same http connection + // urls are accessed in sequence below. The first two are on + // different servers. Third on same server as second. So, the + // client should use the same http connection. httpURIString = "http://127.0.0.1:" + httpPort + "/foo/"; - altURIString1 = "http://127.0.0.1:" + altPort + "/redir"; - altURIString2 = "http://127.0.0.1:" + altPort + "/redir/again"; - - httpServer.addHandler(new RedirectHandler(sup(altURIString1)), "/foo"); - altServer.addHandler(new RedirectHandler(sup(altURIString2)), "/redir"); - altServer.addHandler(new Http2EchoHandler(), "/redir/again"); + httpURI = URI.create(httpURIString); + altURIString1 = "http://127.0.0.1:" + httpPort + "/redir"; + altURI1 = URI.create(altURIString1); + altURIString2 = "http://127.0.0.1:" + httpPort + "/redir_again"; + altURI2 = URI.create(altURIString2); + + Redirector r = new Redirector(sup(altURIString1, altURIString2)); + httpServer.addHandler(r, "/foo"); + httpServer.addHandler(r, "/redir"); + httpServer.addHandler(new Http2EchoHandler(), "/redir_again"); httpServer.start(); - altServer.start(); } catch (Throwable e) { System.err.println("Throwing now"); e.printStackTrace(); @@ -90,26 +116,19 @@ } } - @Test(timeOut=3000000) + @Test public static void test() throws Exception { try { initialize(); simpleTest(); - } catch (Throwable tt) { - System.err.println("tt caught"); - tt.printStackTrace(); } finally { httpServer.stop(); - altServer.stop(); - exec.shutdownNow(); } } static HttpClient getClient() { if (client == null) { - exec = Executors.newCachedThreadPool(); client = HttpClient.newBuilder() - .executor(exec) .followRedirects(HttpClient.Redirect.ALWAYS) .version(HTTP_2) .build(); @@ -129,6 +148,15 @@ } } + static void checkURIs(URI expected, URI found) throws Exception { + System.out.printf ("Expected: %s, Found: %s\n", expected.toString(), found.toString()); + if (!expected.equals(found)) { + System.err.printf ("Test failed: wrong URI %s/%s\n", + expected.toString(), found.toString()); + throw new RuntimeException("Test failed"); + } + } + static void checkStrings(String expected, String found) throws Exception { if (!expected.equals(found)) { System.err.printf ("Test failed: wrong string %s/%s\n", @@ -137,18 +165,17 @@ } } - static Void compareFiles(Path path1, Path path2) { - return TestUtil.compareFiles(path1, path2); - } - - static Path tempFile() { - return TestUtil.tempFile(); + static void check(boolean cond, Object... msg) { + if (cond) + return; + StringBuilder sb = new StringBuilder(); + for (Object o : msg) + sb.append(o); + throw new RuntimeException(sb.toString()); } static final String SIMPLE_STRING = "Hello world Goodbye world"; - static final int FILESIZE = 64 * 1024 + 200; - static void simpleTest() throws Exception { URI uri = getURI(); System.err.println("Request to " + uri); @@ -163,8 +190,44 @@ checkStatus(200, response.statusCode()); String responseBody = response.body(); checkStrings(SIMPLE_STRING, responseBody); + checkURIs(response.uri(), altURI2); + + // check two previous responses + HttpResponse prev = response.previousResponse() + .orElseThrow(() -> new RuntimeException("no previous response")); + checkURIs(prev.uri(), altURI1); + + prev = prev.previousResponse() + .orElseThrow(() -> new RuntimeException("no previous response")); + checkURIs(prev.uri(), httpURI); + + checkPreviousRedirectResponses(req, response); System.err.println("DONE"); - Thread.sleep (6000); + } + + static void checkPreviousRedirectResponses(HttpRequest initialRequest, + HttpResponse finalResponse) { + // there must be at least one previous response + finalResponse.previousResponse() + .orElseThrow(() -> new RuntimeException("no previous response")); + + HttpResponse response = finalResponse; + do { + URI uri = response.uri(); + response = response.previousResponse().get(); + check(300 <= response.statusCode() && response.statusCode() <= 309, + "Expected 300 <= code <= 309, got:" + response.statusCode()); + check(response.body() == null, "Unexpected body: " + response.body()); + String locationHeader = response.headers().firstValue("Location") + .orElseThrow(() -> new RuntimeException("no previous Location")); + check(uri.toString().endsWith(locationHeader), + "URI: " + uri + ", Location: " + locationHeader); + } while (response.previousResponse().isPresent()); + + // initial + check(initialRequest.equals(response.request()), + "Expected initial request [%s] to equal last prev req [%s]", + initialRequest, response.request()); } }