# HG changeset patch # User prappo # Date 1528364730 -3600 # Node ID 0b633bdb70109441ec5eeb8086e435b4453bd29e # Parent 9822bbe48b9bb06f2cabbe9317fb281b5fd868ba http-client-branch: review comment - WebSocket tests diff -r 9822bbe48b9b -r 0b633bdb7010 test/jdk/java/net/httpclient/websocket/BlowupOutputQueue.java --- 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 */ } diff -r 9822bbe48b9b -r 0b633bdb7010 test/jdk/java/net/httpclient/websocket/MockListener.java --- 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 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 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 { diff -r 9822bbe48b9b -r 0b633bdb7010 test/jdk/java/net/httpclient/websocket/WebSocketTest.java --- 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, // + 0x8a, 0x00, // + 0x88, 0x00, // + }; + int[] ERROR = { + 0x81, 0x00, // "" + 0x82, 0x00, // [] + 0x89, 0x00, // + 0x8a, 0x00, // + 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 violation = new CompletableFuture<>(); + + MockListener listener = new MockListener(requestSize) { + + final AtomicBoolean guard = new AtomicBoolean(); + + private T checkRunExclusively(Supplier 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);