http-client-branch: review comment - WebSocket tests http-client-branch
authorprappo
Thu, 07 Jun 2018 10:45:30 +0100
branchhttp-client-branch
changeset 56688 0b633bdb7010
parent 56682 9822bbe48b9b
child 56695 d219df0c7d24
http-client-branch: review comment - WebSocket tests
test/jdk/java/net/httpclient/websocket/BlowupOutputQueue.java
test/jdk/java/net/httpclient/websocket/MockListener.java
test/jdk/java/net/httpclient/websocket/WebSocketTest.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 */
                 }
--- 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);