http-client-branch: (WebSocket) tiny spec simplification + test http-client-branch
authorprappo
Wed, 31 Jan 2018 16:31:48 +0000
branchhttp-client-branch
changeset 56055 7d387d151a3e
parent 56054 352e845ae744
child 56056 762b9b148767
http-client-branch: (WebSocket) tiny spec simplification + test
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/WebSocket.java
test/jdk/java/net/httpclient/websocket/WebSocketTest.java
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/WebSocket.java	Wed Jan 31 16:18:41 2018 +0000
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/WebSocket.java	Wed Jan 31 16:31:48 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
@@ -506,9 +506,8 @@
      * <li> {@link IllegalArgumentException} -
      *          if {@code message} is a malformed UTF-16 sequence
      * <li> {@link IllegalStateException} -
-     *          if {@code sendClose} has been invoked
-     *          or if the previous message has not been sent yet
-     *          or if a previous Binary message was sent with
+     *          if the previous Text or Binary message has not been sent yet
+     *          or if a previous Binary message has been sent with
      *          {@code isLast == false}
      * <li> {@link IOException} -
      *          if an I/O error occurs
@@ -542,9 +541,8 @@
      * complete exceptionally with:
      * <ul>
      * <li> {@link IllegalStateException} -
-     *          if {@code sendClose} has been invoked
-     *          or if the previous message has not been sent yet
-     *          or if a previous Text message was sent with
+     *          if the previous Binary or Text message has not been sent yet
+     *          or if a previous Text message has been sent with
      *              {@code isLast == false}
      * <li> {@link IOException} -
      *          if an I/O error occurs
@@ -574,8 +572,6 @@
      * <ul>
      * <li> {@link IllegalArgumentException} -
      *          if the message is too long
-     * <li> {@link IllegalStateException} -
-     *          if {@code sendClose} has been invoked
      * <li> {@link IOException} -
      *          if an I/O error occurs
      * </ul>
@@ -601,8 +597,6 @@
      * <ul>
      * <li> {@link IllegalArgumentException} -
      *          if the message is too long
-     * <li> {@link IllegalStateException} -
-     *          if {@code sendClose} has been invoked
      * <li> {@link IOException} -
      *          if an I/O error occurs
      * </ul>
@@ -619,8 +613,6 @@
      * Sends a Close message with the given status code and the reason,
      * initiating an orderly closure.
      *
-     * <p> When this method returns the output will have been closed.
-     *
      * <p> The {@code statusCode} is an integer from the range
      * {@code 1000 <= code <= 4999}. Status codes {@code 1002}, {@code 1003},
      * {@code 1006}, {@code 1007}, {@code 1009}, {@code 1010}, {@code 1012},
@@ -640,6 +632,9 @@
      *          if an I/O error occurs
      * </ul>
      *
+     * <p> By the time the {@code CompletableFuture} returned from this method
+     * completes normally, the output will have been closed.
+     *
      * @implSpec An endpoint sending a Close message might not receive a
      * complementing Close message in a timely manner for a variety of reasons.
      * The {@code WebSocket} implementation is responsible for providing a
@@ -666,8 +661,6 @@
      * {@code onBinary}, {@code onPing}, {@code onPong} or {@code onClose}
      * methods up to {@code n} more times.
      *
-     * <p> This method may be invoked at any time.
-     *
      * @param n
      *         the number of messages requested
      *
@@ -679,8 +672,6 @@
     /**
      * Returns the subprotocol for this {@code WebSocket}.
      *
-     * <p> This method may be invoked at any time.
-     *
      * @return the subprotocol for this {@code WebSocket}, or an empty
      * {@code String} if there's no subprotocol
      */
@@ -691,7 +682,7 @@
      * for sending messages.
      *
      * <p> If this method returns {@code true}, subsequent invocations will also
-     * return {@code true}. This method may be invoked at any time.
+     * return {@code true}.
      *
      * @return {@code true} if closed, {@code false} otherwise
      */
@@ -702,7 +693,7 @@
      * for receiving messages.
      *
      * <p> If this method returns {@code true}, subsequent invocations will also
-     * return {@code true}. This method may be invoked at any time.
+     * return {@code true}.
      *
      * @return {@code true} if closed, {@code false} otherwise
      */
@@ -711,9 +702,8 @@
     /**
      * Closes this {@code WebSocket} abruptly.
      *
-     * <p> When this method returns both the input and output will have been
-     * closed. This method may be invoked at any time. Subsequent invocations
-     * have no effect.
+     * <p> When this method returns both the input and the output will have been
+     * closed. Subsequent invocations will have no effect.
      *
      * @apiNote Depending on its implementation, the state (for example, whether
      * or not a message is being transferred at the moment) and possible errors
--- a/test/jdk/java/net/httpclient/websocket/WebSocketTest.java	Wed Jan 31 16:18:41 2018 +0000
+++ b/test/jdk/java/net/httpclient/websocket/WebSocketTest.java	Wed Jan 31 16:31:48 2018 +0000
@@ -58,6 +58,39 @@
             = IllegalStateException.class;
 
     @Test
+    public void abort() throws IOException {
+        try (DummyWebSocketServer server = new DummyWebSocketServer()) {
+            server.open();
+            WebSocket ws = newHttpClient()
+                    .newWebSocketBuilder()
+                    .buildAsync(server.getURI(), new WebSocket.Listener() {
+                        @Override
+                        public void onOpen(WebSocket webSocket) { /* no initial request */ }
+                    })
+                    .join();
+
+            ws.abort();
+            // Each consecutive abort MUST be a no-op:
+            ws.abort();
+            assertTrue(ws.isInputClosed());
+            assertTrue(ws.isOutputClosed());
+            assertEquals(ws.getSubprotocol(), "");
+            ws.abort();
+            assertTrue(ws.isInputClosed());
+            assertTrue(ws.isOutputClosed());
+            assertEquals(ws.getSubprotocol(), "");
+            // At this point request MUST be a no-op:
+            ws.request(1);
+            ws.request(Long.MAX_VALUE);
+            // Throws IAE regardless of whether WebSocket is closed or not:
+            assertThrows(IAE, () -> ws.request(Integer.MIN_VALUE));
+            assertThrows(IAE, () -> ws.request(Long.MIN_VALUE));
+            assertThrows(IAE, () -> ws.request(-1));
+            assertThrows(IAE, () -> ws.request(0));
+        }
+    }
+
+    @Test
     public void testNull() throws IOException {
         try (DummyWebSocketServer server = new DummyWebSocketServer()) {
             server.open();
@@ -197,6 +230,7 @@
             assertCompletesExceptionally(IAE, ws.sendClose(Integer.MIN_VALUE, "a reason"));
 
             assertThrows(IAE, () -> ws.request(Integer.MIN_VALUE));
+            assertThrows(IAE, () -> ws.request(Long.MIN_VALUE));
             assertThrows(IAE, () -> ws.request(-1));
             assertThrows(IAE, () -> ws.request(0));
         }