--- a/test/jdk/java/net/httpclient/http2/BasicTest.java Wed Nov 15 11:39:54 2017 +0000
+++ b/test/jdk/java/net/httpclient/http2/BasicTest.java Thu Nov 16 10:01:34 2017 +0000
@@ -83,7 +83,7 @@
}
}
- @Test(timeOut=3000000)
+ @Test
public static void test() throws Exception {
try {
initialize();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/http2/ContinuationFrameTest.java Thu Nov 16 10:01:34 2017 +0000
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test for CONTINUATION frame handling
+ * @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
+ * @library /lib/testlibrary server
+ * @build Http2TestServer
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @run testng/othervm ContinuationFrameTest
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.BiFunction;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import jdk.incubator.http.HttpClient;
+import jdk.incubator.http.HttpRequest;
+import jdk.incubator.http.HttpResponse;
+import jdk.incubator.http.internal.common.HttpHeadersImpl;
+import jdk.incubator.http.internal.frame.ContinuationFrame;
+import jdk.incubator.http.internal.frame.HeaderFrame;
+import jdk.incubator.http.internal.frame.HeadersFrame;
+import jdk.incubator.http.internal.frame.Http2Frame;
+import jdk.testlibrary.SimpleSSLContext;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static java.lang.System.out;
+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;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public class ContinuationFrameTest {
+
+ SSLContext sslContext;
+ Http2TestServer http2TestServer; // HTTP/2 ( h2c )
+ Http2TestServer https2TestServer; // HTTP/2 ( h2 )
+ String http2URI;
+ String https2URI;
+
+ /**
+ * A function that returns a list of 1) a HEADERS frame ( with an empty
+ * payload ), and 2) a CONTINUATION frame with the actual headers.
+ */
+ static BiFunction<Integer,List<ByteBuffer>,List<Http2Frame>> oneContinuation =
+ (Integer streamid, List<ByteBuffer> encodedHeaders) -> {
+ List<ByteBuffer> empty = List.of(ByteBuffer.wrap(new byte[0]));
+ HeadersFrame hf = new HeadersFrame(streamid, 0, empty);
+ ContinuationFrame cf = new ContinuationFrame(streamid,
+ HeaderFrame.END_HEADERS,
+ encodedHeaders);
+ return List.of(hf, cf);
+ };
+
+ /**
+ * A function that returns a list of a HEADERS frame followed by a number of
+ * CONTINUATION frames. Each frame contains just a single byte of payload.
+ */
+ static BiFunction<Integer,List<ByteBuffer>,List<Http2Frame>> byteAtATime =
+ (Integer streamid, List<ByteBuffer> encodedHeaders) -> {
+ assert encodedHeaders.get(0).hasRemaining();
+ List<Http2Frame> frames = new ArrayList<>();
+ ByteBuffer hb = ByteBuffer.wrap(new byte[] {encodedHeaders.get(0).get()});
+ HeadersFrame hf = new HeadersFrame(streamid, 0, hb);
+ frames.add(hf);
+ for (ByteBuffer bb : encodedHeaders) {
+ while (bb.hasRemaining()) {
+ List<ByteBuffer> data = List.of(ByteBuffer.wrap(new byte[] {bb.get()}));
+ ContinuationFrame cf = new ContinuationFrame(streamid, 0, data);
+ frames.add(cf);
+ }
+ }
+ frames.get(frames.size() - 1).setFlag(HeaderFrame.END_HEADERS);
+ return frames;
+ };
+
+ @DataProvider(name = "variants")
+ public Object[][] variants() {
+ return new Object[][] {
+ { http2URI, false, oneContinuation },
+ { https2URI, false, oneContinuation },
+ { http2URI, true, oneContinuation },
+ { https2URI, true, oneContinuation },
+
+ { http2URI, false, byteAtATime },
+ { https2URI, false, byteAtATime },
+ { http2URI, true, byteAtATime },
+ { https2URI, true, byteAtATime },
+ };
+ }
+
+ static final int ITERATION_COUNT = 20;
+
+ @Test(dataProvider = "variants")
+ void test(String uri,
+ boolean sameClient,
+ BiFunction<Integer,List<ByteBuffer>,List<Http2Frame>> headerFramesSupplier)
+ throws Exception
+ {
+ CFTHttp2TestExchange.setHeaderFrameSupplier(headerFramesSupplier);
+
+ HttpClient client = null;
+ for (int i=0; i< ITERATION_COUNT; i++) {
+ if (!sameClient || client == null)
+ client = HttpClient.newBuilder().sslContext(sslContext).build();
+
+ HttpRequest request = HttpRequest.newBuilder(URI.create(uri))
+ .POST(fromString("Hello there!"))
+ .build();
+ HttpResponse<String> resp;
+ if (i % 2 == 0) {
+ resp = client.send(request, asString());
+ } else {
+ resp = client.sendAsync(request, asString()).join();
+ }
+
+ out.println("Got response: " + resp);
+ out.println("Got body: " + resp.body());
+ assertTrue(resp.statusCode() == 200,
+ "Expected 200, got:" + resp.statusCode());
+ assertEquals(resp.body(), "Hello there!");
+ assertEquals(resp.version(), HTTP_2);
+ }
+ }
+
+ @BeforeTest
+ public void setup() throws Exception {
+ sslContext = new SimpleSSLContext().get();
+ if (sslContext == null)
+ throw new AssertionError("Unexpected null sslContext");
+
+ http2TestServer = new Http2TestServer("127.0.0.1", false, 0);
+ http2TestServer.addHandler(new Http2EchoHandler(), "/http2/echo");
+ int port = http2TestServer.getAddress().getPort();
+ http2URI = "http://127.0.0.1:" + port + "/http2/echo";
+
+ https2TestServer = new Http2TestServer("127.0.0.1", true, 0);
+ https2TestServer.addHandler(new Http2EchoHandler(), "/https2/echo");
+ port = https2TestServer.getAddress().getPort();
+ https2URI = "https://127.0.0.1:" + port + "/https2/echo";
+
+ // Override the default exchange supplier with a custom one to enable
+ // particular test scenarios
+ http2TestServer.setExchangeSupplier(CFTHttp2TestExchange::new);
+ https2TestServer.setExchangeSupplier(CFTHttp2TestExchange::new);
+
+ http2TestServer.start();
+ https2TestServer.start();
+ }
+
+ @AfterTest
+ public void teardown() throws Exception {
+ http2TestServer.stop();
+ https2TestServer.stop();
+ }
+
+ static class Http2EchoHandler implements Http2Handler {
+ @Override
+ public void handle(Http2TestExchange t) throws IOException {
+ try (InputStream is = t.getRequestBody();
+ OutputStream os = t.getResponseBody()) {
+ byte[] bytes = is.readAllBytes();
+ t.getResponseHeaders().addHeader("just some", "noise");
+ t.getResponseHeaders().addHeader("to add ", "payload in ");
+ t.getResponseHeaders().addHeader("the header", "frames");
+ t.sendResponseHeaders(200, bytes.length);
+ os.write(bytes);
+ }
+ }
+ }
+
+ // A custom Http2TestExchangeImpl that overrides sendResponseHeaders to
+ // allow headers to be sent with a number of CONTINUATION frames.
+ static class CFTHttp2TestExchange extends Http2TestExchangeImpl {
+ static volatile BiFunction<Integer,List<ByteBuffer>,List<Http2Frame>> headerFrameSupplier;
+
+ static void setHeaderFrameSupplier(BiFunction<Integer,List<ByteBuffer>,List<Http2Frame>> hfs) {
+ headerFrameSupplier = hfs;
+ }
+
+ CFTHttp2TestExchange(int streamid, String method, HttpHeadersImpl reqheaders,
+ HttpHeadersImpl rspheaders, URI uri, InputStream is,
+ SSLSession sslSession, BodyOutputStream os,
+ Http2TestServerConnection conn, boolean pushAllowed) {
+ super(streamid, method, reqheaders, rspheaders, uri, is, sslSession,
+ os, conn, pushAllowed);
+
+ }
+
+ @Override
+ public void sendResponseHeaders(int rCode, long responseLength) throws IOException {
+ this.responseLength = responseLength;
+ if (responseLength > 0 || responseLength < 0) {
+ long clen = responseLength > 0 ? responseLength : 0;
+ rspheaders.setHeader("Content-length", Long.toString(clen));
+ }
+ rspheaders.setHeader(":status", Integer.toString(rCode));
+
+ List<ByteBuffer> encodeHeaders = conn.encodeHeaders(rspheaders);
+ List<Http2Frame> headerFrames = headerFrameSupplier.apply(streamid, encodeHeaders);
+ assert headerFrames.size() > 0; // there must always be at least 1
+
+ if (responseLength < 0) {
+ headerFrames.get(headerFrames.size() -1).setFlag(HeadersFrame.END_STREAM);
+ os.closeInternal();
+ }
+
+ for (Http2Frame f : headerFrames)
+ conn.outputQ.put(f);
+
+ os.goodToGo();
+ System.err.println("Sent response headers " + rCode);
+ }
+ }
+}
--- a/test/jdk/java/net/httpclient/http2/server/EchoHandler.java Wed Nov 15 11:39:54 2017 +0000
+++ b/test/jdk/java/net/httpclient/http2/server/EchoHandler.java Thu Nov 16 10:01:34 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
--- a/test/jdk/java/net/httpclient/http2/server/Http2TestExchange.java Wed Nov 15 11:39:54 2017 +0000
+++ b/test/jdk/java/net/httpclient/http2/server/Http2TestExchange.java Thu Nov 16 10:01:34 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,148 +21,43 @@
* questions.
*/
+import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.IOException;
import java.net.URI;
import java.net.InetSocketAddress;
import javax.net.ssl.SSLSession;
import jdk.incubator.http.internal.common.HttpHeadersImpl;
-import jdk.incubator.http.internal.frame.HeaderFrame;
-import jdk.incubator.http.internal.frame.HeadersFrame;
-public class Http2TestExchange {
+public interface Http2TestExchange {
- final HttpHeadersImpl reqheaders;
- final HttpHeadersImpl rspheaders;
- final URI uri;
- final String method;
- final InputStream is;
- final BodyOutputStream os;
- final SSLSession sslSession;
- final int streamid;
- final boolean pushAllowed;
- final Http2TestServerConnection conn;
- final Http2TestServer server;
+ HttpHeadersImpl getRequestHeaders();
- int responseCode = -1;
- long responseLength;
+ HttpHeadersImpl getResponseHeaders();
- Http2TestExchange(int streamid,
- String method,
- HttpHeadersImpl reqheaders,
- HttpHeadersImpl rspheaders,
- URI uri,
- InputStream is,
- SSLSession sslSession,
- BodyOutputStream os,
- Http2TestServerConnection conn,
- boolean pushAllowed) {
- this.reqheaders = reqheaders;
- this.rspheaders = rspheaders;
- this.uri = uri;
- this.method = method;
- this.is = is;
- this.streamid = streamid;
- this.os = os;
- this.sslSession = sslSession;
- this.pushAllowed = pushAllowed;
- this.conn = conn;
- this.server = conn.server;
- }
+ URI getRequestURI();
+
+ String getRequestMethod();
- public HttpHeadersImpl getRequestHeaders() {
- return reqheaders;
- }
-
- public HttpHeadersImpl getResponseHeaders() {
- return rspheaders;
- }
+ SSLSession getSSLSession();
- public URI getRequestURI() {
- return uri;
- }
+ void close();
- public String getRequestMethod() {
- return method;
- }
-
- public SSLSession getSSLSession() {
- return sslSession;
- }
+ InputStream getRequestBody();
- public void close() {
- try {
- is.close();
- os.close();
- } catch (IOException e) {
- System.err.println("TestServer: HttpExchange.close exception: " + e);
- e.printStackTrace();
- }
- }
+ OutputStream getResponseBody();
+
+ void sendResponseHeaders(int rCode, long responseLength) throws IOException;
- public InputStream getRequestBody() {
- return is;
- }
-
- public OutputStream getResponseBody() {
- return os;
- }
+ InetSocketAddress getRemoteAddress();
- public void sendResponseHeaders(int rCode, long responseLength) throws IOException {
- this.responseLength = responseLength;
- if (responseLength > 0 || responseLength < 0) {
- long clen = responseLength > 0 ? responseLength : 0;
- rspheaders.setHeader("Content-length", Long.toString(clen));
- }
-
- rspheaders.setHeader(":status", Integer.toString(rCode));
+ int getResponseCode();
- Http2TestServerConnection.ResponseHeaders response
- = new Http2TestServerConnection.ResponseHeaders(rspheaders);
- response.streamid(streamid);
- response.setFlag(HeaderFrame.END_HEADERS);
- if (responseLength < 0) {
- response.setFlag(HeadersFrame.END_STREAM);
- os.closeInternal();
- }
- conn.outputQ.put(response);
- os.goodToGo();
- System.err.println("Sent response headers " + rCode);
- }
+ InetSocketAddress getLocalAddress();
- public InetSocketAddress getRemoteAddress() {
- return (InetSocketAddress) conn.socket.getRemoteSocketAddress();
- }
-
- public int getResponseCode() {
- return responseCode;
- }
+ String getProtocol();
- public InetSocketAddress getLocalAddress() {
- return server.getAddress();
- }
-
- public String getProtocol() {
- return "HTTP/2";
- }
-
- public boolean serverPushAllowed() {
- return pushAllowed;
- }
+ boolean serverPushAllowed();
- public void serverPush(URI uri, HttpHeadersImpl headers, InputStream content) {
- OutgoingPushPromise pp = new OutgoingPushPromise(
- streamid, uri, headers, content);
- headers.setHeader(":method", "GET");
- headers.setHeader(":scheme", uri.getScheme());
- headers.setHeader(":authority", uri.getAuthority());
- headers.setHeader(":path", uri.getPath());
- try {
- conn.outputQ.put(pp);
- // writeLoop will spin up thread to read the InputStream
- } catch (IOException ex) {
- System.err.println("TestServer: pushPromise exception: " + ex);
- }
- }
+ void serverPush(URI uri, HttpHeadersImpl headers, InputStream content);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/http2/server/Http2TestExchangeImpl.java Thu Nov 16 10:01:34 2017 +0000
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.InetSocketAddress;
+import javax.net.ssl.SSLSession;
+import jdk.incubator.http.internal.common.HttpHeadersImpl;
+import jdk.incubator.http.internal.frame.HeaderFrame;
+import jdk.incubator.http.internal.frame.HeadersFrame;
+
+public class Http2TestExchangeImpl implements Http2TestExchange {
+
+ final HttpHeadersImpl reqheaders;
+ final HttpHeadersImpl rspheaders;
+ final URI uri;
+ final String method;
+ final InputStream is;
+ final BodyOutputStream os;
+ final SSLSession sslSession;
+ final int streamid;
+ final boolean pushAllowed;
+ final Http2TestServerConnection conn;
+ final Http2TestServer server;
+
+ int responseCode = -1;
+ long responseLength;
+
+ Http2TestExchangeImpl(int streamid,
+ String method,
+ HttpHeadersImpl reqheaders,
+ HttpHeadersImpl rspheaders,
+ URI uri,
+ InputStream is,
+ SSLSession sslSession,
+ BodyOutputStream os,
+ Http2TestServerConnection conn,
+ boolean pushAllowed) {
+ this.reqheaders = reqheaders;
+ this.rspheaders = rspheaders;
+ this.uri = uri;
+ this.method = method;
+ this.is = is;
+ this.streamid = streamid;
+ this.os = os;
+ this.sslSession = sslSession;
+ this.pushAllowed = pushAllowed;
+ this.conn = conn;
+ this.server = conn.server;
+ }
+
+ @Override
+ public HttpHeadersImpl getRequestHeaders() {
+ return reqheaders;
+ }
+
+ @Override
+ public HttpHeadersImpl getResponseHeaders() {
+ return rspheaders;
+ }
+
+ @Override
+ public URI getRequestURI() {
+ return uri;
+ }
+
+ @Override
+ public String getRequestMethod() {
+ return method;
+ }
+
+ @Override
+ public SSLSession getSSLSession() {
+ return sslSession;
+ }
+
+ @Override
+ public void close() {
+ try {
+ is.close();
+ os.close();
+ } catch (IOException e) {
+ System.err.println("TestServer: HttpExchange.close exception: " + e);
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public InputStream getRequestBody() {
+ return is;
+ }
+
+ @Override
+ public OutputStream getResponseBody() {
+ return os;
+ }
+
+ @Override
+ public void sendResponseHeaders(int rCode, long responseLength) throws IOException {
+ this.responseLength = responseLength;
+ if (responseLength > 0 || responseLength < 0) {
+ long clen = responseLength > 0 ? responseLength : 0;
+ rspheaders.setHeader("Content-length", Long.toString(clen));
+ }
+
+ rspheaders.setHeader(":status", Integer.toString(rCode));
+
+ Http2TestServerConnection.ResponseHeaders response
+ = new Http2TestServerConnection.ResponseHeaders(rspheaders);
+ response.streamid(streamid);
+ response.setFlag(HeaderFrame.END_HEADERS);
+
+
+ if (responseLength < 0) {
+ response.setFlag(HeadersFrame.END_STREAM);
+ os.closeInternal();
+ }
+ conn.outputQ.put(response);
+ os.goodToGo();
+ System.err.println("Sent response headers " + rCode);
+ }
+
+ @Override
+ public InetSocketAddress getRemoteAddress() {
+ return (InetSocketAddress) conn.socket.getRemoteSocketAddress();
+ }
+
+ @Override
+ public int getResponseCode() {
+ return responseCode;
+ }
+
+ @Override
+ public InetSocketAddress getLocalAddress() {
+ return server.getAddress();
+ }
+
+ @Override
+ public String getProtocol() {
+ return "HTTP/2";
+ }
+
+ @Override
+ public boolean serverPushAllowed() {
+ return pushAllowed;
+ }
+
+ @Override
+ public void serverPush(URI uri, HttpHeadersImpl headers, InputStream content) {
+ OutgoingPushPromise pp = new OutgoingPushPromise(
+ streamid, uri, headers, content);
+ headers.setHeader(":method", "GET");
+ headers.setHeader(":scheme", uri.getScheme());
+ headers.setHeader(":authority", uri.getAuthority());
+ headers.setHeader(":path", uri.getPath());
+ try {
+ conn.outputQ.put(pp);
+ // writeLoop will spin up thread to read the InputStream
+ } catch (IOException ex) {
+ System.err.println("TestServer: pushPromise exception: " + ex);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/http2/server/Http2TestExchangeSupplier.java Thu Nov 16 10:01:34 2017 +0000
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.net.ssl.SSLSession;
+import java.io.InputStream;
+import java.net.URI;
+import jdk.incubator.http.internal.common.HttpHeadersImpl;
+
+/**
+ * A supplier of Http2TestExchanges. If the default Http2TestExchange impl is
+ * not sufficient, then a supplier may be set on an Http2TestServer through its
+ * {@link Http2TestServer#setExchangeSupplier(Http2TestExchangeSupplier)}.
+ *
+ * Useful for testing scenarios where non-standard or specific server behaviour
+ * is required, either direct control over the frames sent, "bad" behaviour, or
+ * something else.
+ */
+public interface Http2TestExchangeSupplier {
+
+ Http2TestExchange get(int streamid,
+ String method,
+ HttpHeadersImpl reqheaders,
+ HttpHeadersImpl rspheaders,
+ URI uri,
+ InputStream is,
+ SSLSession sslSession,
+ BodyOutputStream os,
+ Http2TestServerConnection conn,
+ boolean pushAllowed);
+
+ static Http2TestExchangeSupplier ofDefault() {
+ return Http2TestExchangeImpl::new;
+ }
+}
--- a/test/jdk/java/net/httpclient/http2/server/Http2TestServer.java Wed Nov 15 11:39:54 2017 +0000
+++ b/test/jdk/java/net/httpclient/http2/server/Http2TestServer.java Thu Nov 16 10:01:34 2017 +0000
@@ -131,6 +131,18 @@
handlers.put(path, handler);
}
+ volatile Http2TestExchangeSupplier exchangeSupplier = Http2TestExchangeSupplier.ofDefault();
+
+ /**
+ * Sets an explicit exchange handler to be used for all future connections.
+ * Useful for testing scenarios where non-standard or specific server
+ * behaviour is required, either direct control over the frames sent, "bad"
+ * behaviour, or something else.
+ */
+ public void setExchangeSupplier(Http2TestExchangeSupplier exchangeSupplier) {
+ this.exchangeSupplier = exchangeSupplier;
+ }
+
Http2Handler getHandlerFor(String path) {
if (path == null || path.equals(""))
path = "/";
@@ -199,7 +211,8 @@
while (!stopping) {
Socket socket = server.accept();
InetSocketAddress addr = (InetSocketAddress) socket.getRemoteSocketAddress();
- Http2TestServerConnection c = new Http2TestServerConnection(this, socket);
+ Http2TestServerConnection c =
+ new Http2TestServerConnection(this, socket, exchangeSupplier);
connections.put(addr, c);
try {
c.run();
--- a/test/jdk/java/net/httpclient/http2/server/Http2TestServerConnection.java Wed Nov 15 11:39:54 2017 +0000
+++ b/test/jdk/java/net/httpclient/http2/server/Http2TestServerConnection.java Thu Nov 16 10:01:34 2017 +0000
@@ -69,6 +69,7 @@
final Queue<Http2Frame> outputQ;
volatile int nextstream;
final Socket socket;
+ final Http2TestExchangeSupplier exchangeSupplier;
final InputStream is;
final OutputStream os;
volatile Encoder hpackOut;
@@ -85,12 +86,17 @@
final static byte[] clientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".getBytes();
- Http2TestServerConnection(Http2TestServer server, Socket socket) throws IOException {
+ Http2TestServerConnection(Http2TestServer server,
+ Socket socket,
+ Http2TestExchangeSupplier exchangeSupplier)
+ throws IOException
+ {
if (socket instanceof SSLSocket) {
handshake(server.serverName(), (SSLSocket)socket);
}
System.err.println("TestServer: New connection from " + socket);
this.server = server;
+ this.exchangeSupplier = exchangeSupplier;
this.streams = Collections.synchronizedMap(new HashMap<>());
this.outputQ = new Queue<>();
this.socket = socket;
@@ -451,7 +457,7 @@
String us = scheme + "://" + authority + path;
URI uri = new URI(us);
boolean pushAllowed = clientSettings.getParameter(SettingsFrame.ENABLE_PUSH) == 1;
- Http2TestExchange exchange = new Http2TestExchange(streamid, method,
+ Http2TestExchange exchange = exchangeSupplier.get(streamid, method,
headers, rspheaders, uri, bis, getSSLSession(),
bos, this, pushAllowed);