--- a/test/jdk/java/net/httpclient/websocket/BlowupOutputQueue.java Wed Jun 06 15:01:02 2018 +0100
+++ b/test/jdk/java/net/httpclient/websocket/BlowupOutputQueue.java Thu Jun 07 10:45:30 2018 +0100
@@ -87,6 +87,11 @@
listener = new MockListener() {
@Override
+ protected void onOpen0(WebSocket webSocket) {
+ /* do nothing */
+ }
+
+ @Override
protected void replenish(WebSocket webSocket) {
/* do nothing */
}
--- a/test/jdk/java/net/httpclient/websocket/MockListener.java Wed Jun 06 15:01:02 2018 +0100
+++ b/test/jdk/java/net/httpclient/websocket/MockListener.java Thu Jun 07 10:45:30 2018 +0100
@@ -39,11 +39,15 @@
private final Predicate<? super Invocation> collectUntil;
public MockListener() {
- this(i -> i instanceof OnClose || i instanceof OnError);
+ this(1, MockListener::closeOrError);
+ }
+
+ public MockListener(long bufferSize) {
+ this(bufferSize, MockListener::closeOrError);
}
public MockListener(Predicate<? super Invocation> collectUntil) {
- this(2, collectUntil);
+ this(1, collectUntil);
}
/*
@@ -59,6 +63,10 @@
this.collectUntil = collectUntil;
}
+ private static boolean closeOrError(Invocation i) {
+ return i instanceof OnClose || i instanceof OnError;
+ }
+
@Override
public void onOpen(WebSocket webSocket) {
System.out.printf("onOpen(%s)%n", webSocket);
@@ -73,7 +81,9 @@
}
protected void onOpen0(WebSocket webSocket) {
- replenish(webSocket);
+ count = bufferSize - bufferSize / 2;
+ System.out.printf("request(%d)%n", bufferSize);
+ webSocket.request(bufferSize);
}
@Override
@@ -209,8 +219,9 @@
protected void replenish(WebSocket webSocket) {
if (--count <= 0) {
count = bufferSize - bufferSize / 2;
+ webSocket.request(count);
+ System.out.printf("request(%d)%n", count);
}
- webSocket.request(count);
}
public abstract static class Invocation {
--- a/test/jdk/java/net/httpclient/websocket/WebSocketTest.java Wed Jun 06 15:01:02 2018 +0100
+++ b/test/jdk/java/net/httpclient/websocket/WebSocketTest.java Thu Jun 07 10:45:30 2018 +0100
@@ -25,11 +25,11 @@
* @test
* @build DummyWebSocketServer
* @run testng/othervm
- * -Djdk.internal.httpclient.websocket.debug=true
* WebSocketTest
*/
import org.testng.annotations.AfterTest;
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.io.IOException;
@@ -41,7 +41,10 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
import java.util.stream.Collectors;
+
import static java.net.http.HttpClient.Builder.NO_PROXY;
import static java.net.http.HttpClient.newBuilder;
import static java.net.http.WebSocket.NORMAL_CLOSURE;
@@ -197,6 +200,126 @@
assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(0)));
}
+ @DataProvider(name = "sequence")
+ public Object[][] data1() {
+ int[] CLOSE = {
+ 0x81, 0x00, // ""
+ 0x82, 0x00, // []
+ 0x89, 0x00, // <PING>
+ 0x8a, 0x00, // <PONG>
+ 0x88, 0x00, // <CLOSE>
+ };
+ int[] ERROR = {
+ 0x81, 0x00, // ""
+ 0x82, 0x00, // []
+ 0x89, 0x00, // <PING>
+ 0x8a, 0x00, // <PONG>
+ 0x8b, 0x00, // 0xB control frame (causes an error)
+ };
+ return new Object[][]{
+ {CLOSE, 1},
+ {CLOSE, 3},
+ {CLOSE, 4},
+ {CLOSE, Long.MAX_VALUE},
+ {ERROR, 1},
+ {ERROR, 3},
+ {ERROR, 4},
+ {ERROR, Long.MAX_VALUE},
+ };
+ }
+
+ @Test(dataProvider = "sequence")
+ public void listenerSequentialOrder(int[] binary, long requestSize)
+ throws IOException
+ {
+
+ server = Support.serverWithCannedData(binary);
+ server.open();
+
+ CompletableFuture<Void> violation = new CompletableFuture<>();
+
+ MockListener listener = new MockListener(requestSize) {
+
+ final AtomicBoolean guard = new AtomicBoolean();
+
+ private <T> T checkRunExclusively(Supplier<T> action) {
+ if (guard.getAndSet(true)) {
+ violation.completeExceptionally(new RuntimeException());
+ }
+ try {
+ return action.get();
+ } finally {
+ if (!guard.getAndSet(false)) {
+ violation.completeExceptionally(new RuntimeException());
+ }
+ }
+ }
+
+ @Override
+ public void onOpen(WebSocket webSocket) {
+ checkRunExclusively(() -> {
+ super.onOpen(webSocket);
+ return null;
+ });
+ }
+
+ @Override
+ public CompletionStage<?> onText(WebSocket webSocket,
+ CharSequence data,
+ boolean last) {
+ return checkRunExclusively(
+ () -> super.onText(webSocket, data, last));
+ }
+
+ @Override
+ public CompletionStage<?> onBinary(WebSocket webSocket,
+ ByteBuffer data,
+ boolean last) {
+ return checkRunExclusively(
+ () -> super.onBinary(webSocket, data, last));
+ }
+
+ @Override
+ public CompletionStage<?> onPing(WebSocket webSocket,
+ ByteBuffer message) {
+ return checkRunExclusively(
+ () -> super.onPing(webSocket, message));
+ }
+
+ @Override
+ public CompletionStage<?> onPong(WebSocket webSocket,
+ ByteBuffer message) {
+ return checkRunExclusively(
+ () -> super.onPong(webSocket, message));
+ }
+
+ @Override
+ public CompletionStage<?> onClose(WebSocket webSocket,
+ int statusCode,
+ String reason) {
+ return checkRunExclusively(
+ () -> super.onClose(webSocket, statusCode, reason));
+ }
+
+ @Override
+ public void onError(WebSocket webSocket, Throwable error) {
+ checkRunExclusively(() -> {
+ super.onError(webSocket, error);
+ return null;
+ });
+ }
+ };
+
+ webSocket = newBuilder().proxy(NO_PROXY).build().newWebSocketBuilder()
+ .buildAsync(server.getURI(), listener)
+ .join();
+
+
+ listener.invocations();
+ violation.complete(null); // won't affect if completed exceptionally
+ violation.join();
+ }
+
@Test
public void sendMethodsThrowIOE2() throws Exception {
server = Support.serverWithCannedData(0x88, 0x00);