http-client-branch: (WebSocket) A test for onClose & IllegalStateException http-client-branch
authorprappo
Tue, 30 Jan 2018 20:43:32 +0000
branchhttp-client-branch
changeset 56048 f9b6016727b5
parent 56047 2e86bda80f79
child 56049 cf81ddfb20a8
http-client-branch: (WebSocket) A test for onClose & IllegalStateException
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/websocket/FrameConsumer.java
test/jdk/java/net/httpclient/websocket/Exceptionally.java
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/websocket/FrameConsumer.java	Tue Jan 30 17:39:58 2018 +0000
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/websocket/FrameConsumer.java	Tue Jan 30 20:43:32 2018 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -26,7 +26,6 @@
 package jdk.incubator.http.internal.websocket;
 
 import jdk.incubator.http.WebSocket.MessagePart;
-import jdk.incubator.http.internal.common.Log;
 import jdk.incubator.http.internal.websocket.Frame.Opcode;
 
 import java.nio.ByteBuffer;
@@ -50,6 +49,7 @@
 /* Non-final for testing purposes only */
 class FrameConsumer implements Frame.Consumer {
 
+    private final static boolean DEBUG = true;
     private final MessageStreamConsumer output;
     private final UTF8AccumulatingDecoder decoder = new UTF8AccumulatingDecoder();
     private boolean fin;
@@ -70,13 +70,17 @@
 
     @Override
     public void fin(boolean value) {
-        Log.logTrace("Reading fin: {0}", value);
+        if (DEBUG) {
+            System.out.printf("Reading fin: %s%n", value);
+        }
         fin = value;
     }
 
     @Override
     public void rsv1(boolean value) {
-        Log.logTrace("Reading rsv1: {0}", value);
+        if (DEBUG) {
+            System.out.printf("Reading rsv1: %s%n", value);
+        }
         if (value) {
             throw new FailWebSocketException("Unexpected rsv1 bit");
         }
@@ -84,7 +88,9 @@
 
     @Override
     public void rsv2(boolean value) {
-        Log.logTrace("Reading rsv2: {0}", value);
+        if (DEBUG) {
+            System.out.printf("Reading rsv2: %s%n", value);
+        }
         if (value) {
             throw new FailWebSocketException("Unexpected rsv2 bit");
         }
@@ -92,7 +98,9 @@
 
     @Override
     public void rsv3(boolean value) {
-        Log.logTrace("Reading rsv3: {0}", value);
+        if (DEBUG) {
+            System.out.printf("Reading rsv3: %s%n", value);
+        }
         if (value) {
             throw new FailWebSocketException("Unexpected rsv3 bit");
         }
@@ -100,7 +108,9 @@
 
     @Override
     public void opcode(Opcode v) {
-        Log.logTrace("Reading opcode: {0}", v);
+        if (DEBUG) {
+            System.out.printf("Reading opcode: %s%n", v);
+        }
         if (v == Opcode.PING || v == Opcode.PONG || v == Opcode.CLOSE) {
             if (!fin) {
                 throw new FailWebSocketException("Fragmented control frame  " + v);
@@ -122,13 +132,15 @@
             }
             opcode = v;
         } else {
-            throw new FailWebSocketException("Unknown opcode " + v);
+            throw new FailWebSocketException("Unexpected opcode " + v);
         }
     }
 
     @Override
     public void mask(boolean value) {
-        Log.logTrace("Reading mask: {0}", value);
+        if (DEBUG) {
+            System.out.printf("Reading mask: %s%n", value);
+        }
         if (value) {
             throw new FailWebSocketException("Masked frame received");
         }
@@ -136,7 +148,9 @@
 
     @Override
     public void payloadLen(long value) {
-        Log.logTrace("Reading payloadLen: {0}", value);
+        if (DEBUG) {
+            System.out.printf("Reading payloadLen: %s%n", value);
+        }
         if (opcode.isControl()) {
             if (value > 125) {
                 throw new FailWebSocketException(
@@ -164,7 +178,9 @@
 
     @Override
     public void payloadData(ByteBuffer data) {
-        Log.logTrace("Reading payloadData: data={0}", data);
+        if (DEBUG) {
+            System.out.printf("Reading payloadData: %s%n", data);
+        }
         unconsumedPayloadLen -= data.remaining();
         boolean isLast = unconsumedPayloadLen == 0;
         if (opcode.isControl()) {
@@ -207,6 +223,9 @@
 
     @Override
     public void endFrame() {
+        if (DEBUG) {
+            System.out.println("End frame");
+        }
         if (opcode.isControl()) {
             binaryData.flip();
         }
--- a/test/jdk/java/net/httpclient/websocket/Exceptionally.java	Tue Jan 30 17:39:58 2018 +0000
+++ b/test/jdk/java/net/httpclient/websocket/Exceptionally.java	Tue Jan 30 20:43:32 2018 +0000
@@ -37,6 +37,7 @@
 import java.nio.charset.StandardCharsets;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CompletionException;
+import java.util.concurrent.CompletionStage;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
@@ -317,4 +318,65 @@
             assertCompletesExceptionally(ISE, ws.sendPong(ByteBuffer.allocate(0)));
         }
     }
+
+    @Test
+    public void testIllegalStateOnClose() throws Exception {
+        DummyWebSocketServer server = new DummyWebSocketServer() {
+            @Override
+            protected void serve(SocketChannel channel) throws IOException {
+                ByteBuffer closeMessage = ByteBuffer.wrap(new byte[]{(byte) 0x88, 0x00});
+                int wrote = channel.write(closeMessage);
+                System.out.println("Wrote bytes: " + wrote);
+                super.serve(channel);
+            }
+        };
+        try (server) {
+            server.open();
+            CompletableFuture<Void> onCloseCalled = new CompletableFuture<>();
+            CompletableFuture<Void> canClose = new CompletableFuture<>();
+
+            WebSocket ws = newHttpClient()
+                    .newWebSocketBuilder()
+                    .buildAsync(server.getURI(), new WebSocket.Listener() {
+                        @Override
+                        public CompletionStage<?> onClose(WebSocket webSocket,
+                                                          int statusCode,
+                                                          String reason) {
+                            System.out.println("onClose(" + statusCode + ")");
+                            onCloseCalled.complete(null);
+                            return canClose;
+                        }
+
+                        @Override
+                        public void onError(WebSocket webSocket, Throwable error) {
+                            System.out.println("onError(" + error + ")");
+                            error.printStackTrace();
+                        }
+                    })
+                    .join();
+
+            onCloseCalled.join();      // Wait for onClose to be called
+            TimeUnit.SECONDS.sleep(5); // Give canClose some time to reach the WebSocket
+            canClose.complete(null);   // Signal to the WebSocket it can close the output
+
+            assertCompletesExceptionally(ISE, ws.sendText("", true));
+            assertCompletesExceptionally(ISE, ws.sendText("", false));
+            assertCompletesExceptionally(ISE, ws.sendText("abc", true));
+            assertCompletesExceptionally(ISE, ws.sendText("abc", false));
+            assertCompletesExceptionally(ISE, ws.sendBinary(ByteBuffer.allocate(0), true));
+            assertCompletesExceptionally(ISE, ws.sendBinary(ByteBuffer.allocate(0), false));
+            assertCompletesExceptionally(ISE, ws.sendBinary(ByteBuffer.allocate(1), true));
+            assertCompletesExceptionally(ISE, ws.sendBinary(ByteBuffer.allocate(1), false));
+
+            assertCompletesExceptionally(ISE, ws.sendPing(ByteBuffer.allocate(125)));
+            assertCompletesExceptionally(ISE, ws.sendPing(ByteBuffer.allocate(124)));
+            assertCompletesExceptionally(ISE, ws.sendPing(ByteBuffer.allocate(1)));
+            assertCompletesExceptionally(ISE, ws.sendPing(ByteBuffer.allocate(0)));
+
+            assertCompletesExceptionally(ISE, ws.sendPong(ByteBuffer.allocate(125)));
+            assertCompletesExceptionally(ISE, ws.sendPong(ByteBuffer.allocate(124)));
+            assertCompletesExceptionally(ISE, ws.sendPong(ByteBuffer.allocate(1)));
+            assertCompletesExceptionally(ISE, ws.sendPong(ByteBuffer.allocate(0)));
+        }
+    }
 }