test/jdk/java/net/httpclient/websocket/WebSocketTest.java
changeset 58289 3a79d4cccbcb
parent 53521 41fa3e6f2785
equal deleted inserted replaced
58288:48e480e56aad 58289:3a79d4cccbcb
    27  * @build DummyWebSocketServer
    27  * @build DummyWebSocketServer
    28  * @run testng/othervm
    28  * @run testng/othervm
    29  *       WebSocketTest
    29  *       WebSocketTest
    30  */
    30  */
    31 
    31 
    32 import org.testng.annotations.AfterTest;
       
    33 import org.testng.annotations.DataProvider;
    32 import org.testng.annotations.DataProvider;
    34 import org.testng.annotations.Test;
    33 import org.testng.annotations.Test;
    35 
    34 
    36 import java.io.IOException;
    35 import java.io.IOException;
    37 import java.net.Authenticator;
    36 import java.net.Authenticator;
    71     private static void assertFails(Class<? extends Throwable> clazz,
    70     private static void assertFails(Class<? extends Throwable> clazz,
    72                                     CompletionStage<?> stage) {
    71                                     CompletionStage<?> stage) {
    73         Support.assertCompletesExceptionally(clazz, stage);
    72         Support.assertCompletesExceptionally(clazz, stage);
    74     }
    73     }
    75 
    74 
    76     private DummyWebSocketServer server;
       
    77     private WebSocket webSocket;
       
    78 
       
    79     @AfterTest
       
    80     public void cleanup() {
       
    81         System.out.println("AFTER TEST");
       
    82         if (server != null)
       
    83             server.close();
       
    84         if (webSocket != null)
       
    85             webSocket.abort();
       
    86     }
       
    87 
       
    88     @Test
    75     @Test
    89     public void illegalArgument() throws IOException {
    76     public void illegalArgument() throws IOException {
    90         server = new DummyWebSocketServer();
    77         try (var server = new DummyWebSocketServer()) {
    91         server.open();
    78             server.open();
    92         webSocket = newBuilder().proxy(NO_PROXY).build()
    79             var webSocket = newBuilder().proxy(NO_PROXY).build()
    93                 .newWebSocketBuilder()
    80                     .newWebSocketBuilder()
    94                 .buildAsync(server.getURI(), new WebSocket.Listener() { })
    81                     .buildAsync(server.getURI(), new WebSocket.Listener() { })
    95                 .join();
    82                     .join();
    96 
    83             try {
    97         assertFails(IAE, webSocket.sendPing(ByteBuffer.allocate(126)));
    84                 assertFails(IAE, webSocket.sendPing(ByteBuffer.allocate(126)));
    98         assertFails(IAE, webSocket.sendPing(ByteBuffer.allocate(127)));
    85                 assertFails(IAE, webSocket.sendPing(ByteBuffer.allocate(127)));
    99         assertFails(IAE, webSocket.sendPing(ByteBuffer.allocate(128)));
    86                 assertFails(IAE, webSocket.sendPing(ByteBuffer.allocate(128)));
   100         assertFails(IAE, webSocket.sendPing(ByteBuffer.allocate(129)));
    87                 assertFails(IAE, webSocket.sendPing(ByteBuffer.allocate(129)));
   101         assertFails(IAE, webSocket.sendPing(ByteBuffer.allocate(256)));
    88                 assertFails(IAE, webSocket.sendPing(ByteBuffer.allocate(256)));
   102 
    89 
   103         assertFails(IAE, webSocket.sendPong(ByteBuffer.allocate(126)));
    90                 assertFails(IAE, webSocket.sendPong(ByteBuffer.allocate(126)));
   104         assertFails(IAE, webSocket.sendPong(ByteBuffer.allocate(127)));
    91                 assertFails(IAE, webSocket.sendPong(ByteBuffer.allocate(127)));
   105         assertFails(IAE, webSocket.sendPong(ByteBuffer.allocate(128)));
    92                 assertFails(IAE, webSocket.sendPong(ByteBuffer.allocate(128)));
   106         assertFails(IAE, webSocket.sendPong(ByteBuffer.allocate(129)));
    93                 assertFails(IAE, webSocket.sendPong(ByteBuffer.allocate(129)));
   107         assertFails(IAE, webSocket.sendPong(ByteBuffer.allocate(256)));
    94                 assertFails(IAE, webSocket.sendPong(ByteBuffer.allocate(256)));
   108 
    95 
   109         assertFails(IOE, webSocket.sendText(Support.incompleteString(), true));
    96                 assertFails(IOE, webSocket.sendText(Support.incompleteString(), true));
   110         assertFails(IOE, webSocket.sendText(Support.incompleteString(), false));
    97                 assertFails(IOE, webSocket.sendText(Support.incompleteString(), false));
   111         assertFails(IOE, webSocket.sendText(Support.malformedString(), true));
    98                 assertFails(IOE, webSocket.sendText(Support.malformedString(), true));
   112         assertFails(IOE, webSocket.sendText(Support.malformedString(), false));
    99                 assertFails(IOE, webSocket.sendText(Support.malformedString(), false));
   113 
   100 
   114         assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.stringWithNBytes(124)));
   101                 assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.stringWithNBytes(124)));
   115         assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.stringWithNBytes(125)));
   102                 assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.stringWithNBytes(125)));
   116         assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.stringWithNBytes(128)));
   103                 assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.stringWithNBytes(128)));
   117         assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.stringWithNBytes(256)));
   104                 assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.stringWithNBytes(256)));
   118         assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.stringWithNBytes(257)));
   105                 assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.stringWithNBytes(257)));
   119         assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.stringWith2NBytes((123 / 2) + 1)));
   106                 assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.stringWith2NBytes((123 / 2) + 1)));
   120         assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.malformedString()));
   107                 assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.malformedString()));
   121         assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.incompleteString()));
   108                 assertFails(IAE, webSocket.sendClose(NORMAL_CLOSURE, Support.incompleteString()));
   122 
   109 
   123         assertFails(IAE, webSocket.sendClose(-2, "a reason"));
   110                 assertFails(IAE, webSocket.sendClose(-2, "a reason"));
   124         assertFails(IAE, webSocket.sendClose(-1, "a reason"));
   111                 assertFails(IAE, webSocket.sendClose(-1, "a reason"));
   125         assertFails(IAE, webSocket.sendClose(0, "a reason"));
   112                 assertFails(IAE, webSocket.sendClose(0, "a reason"));
   126         assertFails(IAE, webSocket.sendClose(1, "a reason"));
   113                 assertFails(IAE, webSocket.sendClose(1, "a reason"));
   127         assertFails(IAE, webSocket.sendClose(500, "a reason"));
   114                 assertFails(IAE, webSocket.sendClose(500, "a reason"));
   128         assertFails(IAE, webSocket.sendClose(998, "a reason"));
   115                 assertFails(IAE, webSocket.sendClose(998, "a reason"));
   129         assertFails(IAE, webSocket.sendClose(999, "a reason"));
   116                 assertFails(IAE, webSocket.sendClose(999, "a reason"));
   130         assertFails(IAE, webSocket.sendClose(1002, "a reason"));
   117                 assertFails(IAE, webSocket.sendClose(1002, "a reason"));
   131         assertFails(IAE, webSocket.sendClose(1003, "a reason"));
   118                 assertFails(IAE, webSocket.sendClose(1003, "a reason"));
   132         assertFails(IAE, webSocket.sendClose(1006, "a reason"));
   119                 assertFails(IAE, webSocket.sendClose(1006, "a reason"));
   133         assertFails(IAE, webSocket.sendClose(1007, "a reason"));
   120                 assertFails(IAE, webSocket.sendClose(1007, "a reason"));
   134         assertFails(IAE, webSocket.sendClose(1009, "a reason"));
   121                 assertFails(IAE, webSocket.sendClose(1009, "a reason"));
   135         assertFails(IAE, webSocket.sendClose(1010, "a reason"));
   122                 assertFails(IAE, webSocket.sendClose(1010, "a reason"));
   136         assertFails(IAE, webSocket.sendClose(1012, "a reason"));
   123                 assertFails(IAE, webSocket.sendClose(1012, "a reason"));
   137         assertFails(IAE, webSocket.sendClose(1013, "a reason"));
   124                 assertFails(IAE, webSocket.sendClose(1013, "a reason"));
   138         assertFails(IAE, webSocket.sendClose(1015, "a reason"));
   125                 assertFails(IAE, webSocket.sendClose(1015, "a reason"));
   139         assertFails(IAE, webSocket.sendClose(5000, "a reason"));
   126                 assertFails(IAE, webSocket.sendClose(5000, "a reason"));
   140         assertFails(IAE, webSocket.sendClose(32768, "a reason"));
   127                 assertFails(IAE, webSocket.sendClose(32768, "a reason"));
   141         assertFails(IAE, webSocket.sendClose(65535, "a reason"));
   128                 assertFails(IAE, webSocket.sendClose(65535, "a reason"));
   142         assertFails(IAE, webSocket.sendClose(65536, "a reason"));
   129                 assertFails(IAE, webSocket.sendClose(65536, "a reason"));
   143         assertFails(IAE, webSocket.sendClose(Integer.MAX_VALUE, "a reason"));
   130                 assertFails(IAE, webSocket.sendClose(Integer.MAX_VALUE, "a reason"));
   144         assertFails(IAE, webSocket.sendClose(Integer.MIN_VALUE, "a reason"));
   131                 assertFails(IAE, webSocket.sendClose(Integer.MIN_VALUE, "a reason"));
   145 
   132 
   146         assertThrows(IAE, () -> webSocket.request(Integer.MIN_VALUE));
   133                 assertThrows(IAE, () -> webSocket.request(Integer.MIN_VALUE));
   147         assertThrows(IAE, () -> webSocket.request(Long.MIN_VALUE));
   134                 assertThrows(IAE, () -> webSocket.request(Long.MIN_VALUE));
   148         assertThrows(IAE, () -> webSocket.request(-1));
   135                 assertThrows(IAE, () -> webSocket.request(-1));
   149         assertThrows(IAE, () -> webSocket.request(0));
   136                 assertThrows(IAE, () -> webSocket.request(0));
   150 
   137 
   151         server.close();
   138             } finally {
       
   139                 webSocket.abort();
       
   140             }
       
   141         }
   152     }
   142     }
   153 
   143 
   154     @Test
   144     @Test
   155     public void partialBinaryThenText() throws IOException {
   145     public void partialBinaryThenText() throws IOException {
   156         server = new DummyWebSocketServer();
   146         try (var server = new DummyWebSocketServer()) {
   157         server.open();
   147             server.open();
   158         webSocket = newBuilder().proxy(NO_PROXY).build().newWebSocketBuilder()
   148             var webSocket = newBuilder().proxy(NO_PROXY).build().newWebSocketBuilder()
   159                 .buildAsync(server.getURI(), new WebSocket.Listener() { })
   149                     .buildAsync(server.getURI(), new WebSocket.Listener() { })
   160                 .join();
   150                     .join();
   161         webSocket.sendBinary(ByteBuffer.allocate(16), false).join();
   151             try {
   162         assertFails(ISE, webSocket.sendText("text", false));
   152                 webSocket.sendBinary(ByteBuffer.allocate(16), false).join();
   163         assertFails(ISE, webSocket.sendText("text", true));
   153                 assertFails(ISE, webSocket.sendText("text", false));
   164         // Pings & Pongs are fine
   154                 assertFails(ISE, webSocket.sendText("text", true));
   165         webSocket.sendPing(ByteBuffer.allocate(125)).join();
   155                 // Pings & Pongs are fine
   166         webSocket.sendPong(ByteBuffer.allocate(125)).join();
   156                 webSocket.sendPing(ByteBuffer.allocate(125)).join();
   167         server.close();
   157                 webSocket.sendPong(ByteBuffer.allocate(125)).join();
       
   158             } finally {
       
   159                 webSocket.abort();
       
   160             }
       
   161         }
   168     }
   162     }
   169 
   163 
   170     @Test
   164     @Test
   171     public void partialTextThenBinary() throws IOException {
   165     public void partialTextThenBinary() throws IOException {
   172         server = new DummyWebSocketServer();
   166         try (var server = new DummyWebSocketServer()) {
   173         server.open();
   167             server.open();
   174         webSocket = newBuilder().proxy(NO_PROXY).build().newWebSocketBuilder()
   168             var webSocket = newBuilder().proxy(NO_PROXY).build().newWebSocketBuilder()
   175                 .buildAsync(server.getURI(), new WebSocket.Listener() { })
   169                     .buildAsync(server.getURI(), new WebSocket.Listener() { })
   176                 .join();
   170                     .join();
   177 
   171             try {
   178         webSocket.sendText("text", false).join();
   172                 webSocket.sendText("text", false).join();
   179         assertFails(ISE, webSocket.sendBinary(ByteBuffer.allocate(16), false));
   173                 assertFails(ISE, webSocket.sendBinary(ByteBuffer.allocate(16), false));
   180         assertFails(ISE, webSocket.sendBinary(ByteBuffer.allocate(16), true));
   174                 assertFails(ISE, webSocket.sendBinary(ByteBuffer.allocate(16), true));
   181         // Pings & Pongs are fine
   175                 // Pings & Pongs are fine
   182         webSocket.sendPing(ByteBuffer.allocate(125)).join();
   176                 webSocket.sendPing(ByteBuffer.allocate(125)).join();
   183         webSocket.sendPong(ByteBuffer.allocate(125)).join();
   177                 webSocket.sendPong(ByteBuffer.allocate(125)).join();
   184         server.close();
   178             } finally {
       
   179                 webSocket.abort();
       
   180             }
       
   181         }
   185     }
   182     }
   186 
   183 
   187     @Test
   184     @Test
   188     public void sendMethodsThrowIOE1() throws IOException {
   185     public void sendMethodsThrowIOE1() throws IOException {
   189         server = new DummyWebSocketServer();
   186         try (var server = new DummyWebSocketServer()) {
   190         server.open();
   187             server.open();
   191         webSocket = newBuilder().proxy(NO_PROXY).build()
   188             var webSocket = newBuilder().proxy(NO_PROXY).build()
   192                 .newWebSocketBuilder()
   189                     .newWebSocketBuilder()
   193                 .buildAsync(server.getURI(), new WebSocket.Listener() { })
   190                     .buildAsync(server.getURI(), new WebSocket.Listener() { })
   194                 .join();
   191                     .join();
   195 
   192             try {
   196         webSocket.sendClose(NORMAL_CLOSURE, "ok").join();
   193                 webSocket.sendClose(NORMAL_CLOSURE, "ok").join();
   197 
   194 
   198         assertFails(IOE, webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok"));
   195                 assertFails(IOE, webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok"));
   199 
   196 
   200         assertFails(IOE, webSocket.sendText("", true));
   197                 assertFails(IOE, webSocket.sendText("", true));
   201         assertFails(IOE, webSocket.sendText("", false));
   198                 assertFails(IOE, webSocket.sendText("", false));
   202         assertFails(IOE, webSocket.sendText("abc", true));
   199                 assertFails(IOE, webSocket.sendText("abc", true));
   203         assertFails(IOE, webSocket.sendText("abc", false));
   200                 assertFails(IOE, webSocket.sendText("abc", false));
   204         assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(0), true));
   201                 assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(0), true));
   205         assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(0), false));
   202                 assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(0), false));
   206         assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(1), true));
   203                 assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(1), true));
   207         assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(1), false));
   204                 assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(1), false));
   208 
   205 
   209         assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(125)));
   206                 assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(125)));
   210         assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(124)));
   207                 assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(124)));
   211         assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(1)));
   208                 assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(1)));
   212         assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(0)));
   209                 assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(0)));
   213 
   210 
   214         assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(125)));
   211                 assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(125)));
   215         assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(124)));
   212                 assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(124)));
   216         assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(1)));
   213                 assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(1)));
   217         assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(0)));
   214                 assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(0)));
   218 
   215             } finally {
   219         server.close();
   216                 webSocket.abort();
       
   217             }
       
   218         }
   220     }
   219     }
   221 
   220 
   222     @DataProvider(name = "sequence")
   221     @DataProvider(name = "sequence")
   223     public Object[][] data1() {
   222     public Object[][] data1() {
   224         int[] CLOSE = {
   223         int[] CLOSE = {
   249 
   248 
   250     @Test(dataProvider = "sequence")
   249     @Test(dataProvider = "sequence")
   251     public void listenerSequentialOrder(int[] binary, long requestSize)
   250     public void listenerSequentialOrder(int[] binary, long requestSize)
   252             throws IOException
   251             throws IOException
   253     {
   252     {
   254 
   253         try (var server = Support.serverWithCannedData(binary)) {
   255         server = Support.serverWithCannedData(binary);
   254             server.open();
   256         server.open();
   255 
   257 
   256             CompletableFuture<Void> violation = new CompletableFuture<>();
   258         CompletableFuture<Void> violation = new CompletableFuture<>();
   257 
   259 
   258             MockListener listener = new MockListener(requestSize) {
   260         MockListener listener = new MockListener(requestSize) {
   259 
   261 
   260                 final AtomicBoolean guard = new AtomicBoolean();
   262             final AtomicBoolean guard = new AtomicBoolean();
   261 
   263 
   262                 private <T> T checkRunExclusively(Supplier<T> action) {
   264             private <T> T checkRunExclusively(Supplier<T> action) {
   263                     if (guard.getAndSet(true)) {
   265                 if (guard.getAndSet(true)) {
       
   266                     violation.completeExceptionally(new RuntimeException());
       
   267                 }
       
   268                 try {
       
   269                     return action.get();
       
   270                 } finally {
       
   271                     if (!guard.getAndSet(false)) {
       
   272                         violation.completeExceptionally(new RuntimeException());
   264                         violation.completeExceptionally(new RuntimeException());
   273                     }
   265                     }
   274                 }
   266                     try {
   275             }
   267                         return action.get();
   276 
   268                     } finally {
   277             @Override
   269                         if (!guard.getAndSet(false)) {
   278             public void onOpen(WebSocket webSocket) {
   270                             violation.completeExceptionally(new RuntimeException());
   279                 checkRunExclusively(() -> {
   271                         }
   280                     super.onOpen(webSocket);
   272                     }
   281                     return null;
   273                 }
   282                 });
   274 
   283             }
   275                 @Override
   284 
   276                 public void onOpen(WebSocket webSocket) {
   285             @Override
   277                     checkRunExclusively(() -> {
   286             public CompletionStage<?> onText(WebSocket webSocket,
   278                         super.onOpen(webSocket);
   287                                              CharSequence data,
   279                         return null;
   288                                              boolean last) {
   280                     });
   289                 return checkRunExclusively(
   281                 }
   290                         () -> super.onText(webSocket, data, last));
   282 
   291             }
   283                 @Override
   292 
   284                 public CompletionStage<?> onText(WebSocket webSocket,
   293             @Override
   285                                                  CharSequence data,
   294             public CompletionStage<?> onBinary(WebSocket webSocket,
   286                                                  boolean last) {
   295                                                ByteBuffer data,
   287                     return checkRunExclusively(
   296                                                boolean last) {
   288                             () -> super.onText(webSocket, data, last));
   297                 return checkRunExclusively(
   289                 }
   298                         () -> super.onBinary(webSocket, data, last));
   290 
   299             }
   291                 @Override
   300 
   292                 public CompletionStage<?> onBinary(WebSocket webSocket,
   301             @Override
   293                                                    ByteBuffer data,
   302             public CompletionStage<?> onPing(WebSocket webSocket,
   294                                                    boolean last) {
   303                                              ByteBuffer message) {
   295                     return checkRunExclusively(
   304                 return checkRunExclusively(
   296                             () -> super.onBinary(webSocket, data, last));
   305                         () -> super.onPing(webSocket, message));
   297                 }
   306             }
   298 
   307 
   299                 @Override
   308             @Override
   300                 public CompletionStage<?> onPing(WebSocket webSocket,
   309             public CompletionStage<?> onPong(WebSocket webSocket,
   301                                                  ByteBuffer message) {
   310                                              ByteBuffer message) {
   302                     return checkRunExclusively(
   311                 return checkRunExclusively(
   303                             () -> super.onPing(webSocket, message));
   312                         () -> super.onPong(webSocket, message));
   304                 }
   313             }
   305 
   314 
   306                 @Override
   315             @Override
   307                 public CompletionStage<?> onPong(WebSocket webSocket,
   316             public CompletionStage<?> onClose(WebSocket webSocket,
   308                                                  ByteBuffer message) {
   317                                               int statusCode,
   309                     return checkRunExclusively(
   318                                               String reason) {
   310                             () -> super.onPong(webSocket, message));
   319                 return checkRunExclusively(
   311                 }
   320                         () -> super.onClose(webSocket, statusCode, reason));
   312 
   321             }
   313                 @Override
   322 
   314                 public CompletionStage<?> onClose(WebSocket webSocket,
   323             @Override
   315                                                   int statusCode,
   324             public void onError(WebSocket webSocket, Throwable error) {
   316                                                   String reason) {
   325                 checkRunExclusively(() -> {
   317                     return checkRunExclusively(
   326                     super.onError(webSocket, error);
   318                             () -> super.onClose(webSocket, statusCode, reason));
   327                     return null;
   319                 }
   328                 });
   320 
   329             }
   321                 @Override
   330         };
   322                 public void onError(WebSocket webSocket, Throwable error) {
   331 
   323                     checkRunExclusively(() -> {
   332         webSocket = newBuilder().proxy(NO_PROXY).build().newWebSocketBuilder()
   324                         super.onError(webSocket, error);
   333                 .buildAsync(server.getURI(), listener)
   325                         return null;
   334                 .join();
   326                     });
   335 
   327                 }
   336 
   328             };
   337         listener.invocations();
   329 
   338         violation.complete(null); // won't affect if completed exceptionally
   330             var webSocket = newBuilder().proxy(NO_PROXY).build().newWebSocketBuilder()
   339         violation.join();
   331                     .buildAsync(server.getURI(), listener)
   340 
   332                     .join();
   341         server.close();
   333             try {
       
   334                 listener.invocations();
       
   335                 violation.complete(null); // won't affect if completed exceptionally
       
   336                 violation.join();
       
   337             } finally {
       
   338                 webSocket.abort();
       
   339             }
       
   340         }
   342     }
   341     }
   343 
   342 
   344     @Test
   343     @Test
   345     public void sendMethodsThrowIOE2() throws Exception {
   344     public void sendMethodsThrowIOE2() throws Exception {
   346         server = Support.serverWithCannedData(0x88, 0x00);
   345         try (var server = Support.serverWithCannedData(0x88, 0x00)) {
   347         server.open();
   346             server.open();
   348         CompletableFuture<Void> onCloseCalled = new CompletableFuture<>();
   347 
   349         CompletableFuture<Void> canClose = new CompletableFuture<>();
   348             CompletableFuture<Void> onCloseCalled = new CompletableFuture<>();
   350 
   349             CompletableFuture<Void> canClose = new CompletableFuture<>();
   351         WebSocket.Listener listener = new WebSocket.Listener() {
   350 
   352             @Override
   351             WebSocket.Listener listener = new WebSocket.Listener() {
   353             public CompletionStage<?> onClose(WebSocket webSocket,
   352                 @Override
   354                                               int statusCode,
   353                 public CompletionStage<?> onClose(WebSocket webSocket,
   355                                               String reason) {
   354                                                   int statusCode,
   356                 System.out.printf("onClose(%s, '%s')%n", statusCode, reason);
   355                                                   String reason) {
   357                 onCloseCalled.complete(null);
   356                     System.out.printf("onClose(%s, '%s')%n", statusCode, reason);
   358                 return canClose;
   357                     onCloseCalled.complete(null);
   359             }
   358                     return canClose;
   360 
   359                 }
   361             @Override
   360 
   362             public void onError(WebSocket webSocket, Throwable error) {
   361                 @Override
   363                 System.out.println("onError(" + error + ")");
   362                 public void onError(WebSocket webSocket, Throwable error) {
   364                 onCloseCalled.completeExceptionally(error);
   363                     System.out.println("onError(" + error + ")");
   365             }
   364                     onCloseCalled.completeExceptionally(error);
   366         };
   365                 }
   367 
   366             };
   368         webSocket = newBuilder().proxy(NO_PROXY).build().newWebSocketBuilder()
   367 
   369                 .buildAsync(server.getURI(), listener)
   368             var webSocket = newBuilder().proxy(NO_PROXY).build().newWebSocketBuilder()
   370                 .join();
   369                     .buildAsync(server.getURI(), listener)
   371 
   370                     .join();
   372         onCloseCalled.join();      // Wait for onClose to be called
   371             try {
   373         canClose.complete(null);   // Signal to the WebSocket it can close the output
   372                 onCloseCalled.join();      // Wait for onClose to be called
   374         TimeUnit.SECONDS.sleep(5); // Give canClose some time to reach the WebSocket
   373                 canClose.complete(null);   // Signal to the WebSocket it can close the output
   375 
   374                 TimeUnit.SECONDS.sleep(5); // Give canClose some time to reach the WebSocket
   376         assertFails(IOE, webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok"));
   375 
   377 
   376                 assertFails(IOE, webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok"));
   378         assertFails(IOE, webSocket.sendText("", true));
   377 
   379         assertFails(IOE, webSocket.sendText("", false));
   378                 assertFails(IOE, webSocket.sendText("", true));
   380         assertFails(IOE, webSocket.sendText("abc", true));
   379                 assertFails(IOE, webSocket.sendText("", false));
   381         assertFails(IOE, webSocket.sendText("abc", false));
   380                 assertFails(IOE, webSocket.sendText("abc", true));
   382         assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(0), true));
   381                 assertFails(IOE, webSocket.sendText("abc", false));
   383         assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(0), false));
   382                 assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(0), true));
   384         assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(1), true));
   383                 assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(0), false));
   385         assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(1), false));
   384                 assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(1), true));
   386 
   385                 assertFails(IOE, webSocket.sendBinary(ByteBuffer.allocate(1), false));
   387         assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(125)));
   386 
   388         assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(124)));
   387                 assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(125)));
   389         assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(1)));
   388                 assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(124)));
   390         assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(0)));
   389                 assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(1)));
   391 
   390                 assertFails(IOE, webSocket.sendPing(ByteBuffer.allocate(0)));
   392         assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(125)));
   391 
   393         assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(124)));
   392                 assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(125)));
   394         assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(1)));
   393                 assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(124)));
   395         assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(0)));
   394                 assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(1)));
   396 
   395                 assertFails(IOE, webSocket.sendPong(ByteBuffer.allocate(0)));
   397         server.close();
   396             } finally {
       
   397                 webSocket.abort();
       
   398             }
       
   399         }
   398     }
   400     }
   399 
   401 
   400     // Used to verify a server requiring Authentication
   402     // Used to verify a server requiring Authentication
   401     private static final String USERNAME = "chegar";
   403     private static final String USERNAME = "chegar";
   402     private static final String PASSWORD = "a1b2c3";
   404     private static final String PASSWORD = "a1b2c3";
   456                 0x80, 0x00,                               // ]
   458                 0x80, 0x00,                               // ]
   457                 0x88, 0x00                                // <CLOSE>
   459                 0x88, 0x00                                // <CLOSE>
   458         };
   460         };
   459         CompletableFuture<List<byte[]>> actual = new CompletableFuture<>();
   461         CompletableFuture<List<byte[]>> actual = new CompletableFuture<>();
   460 
   462 
   461         server = serverSupplier.apply(binary);
   463         try (var server = serverSupplier.apply(binary)) {
   462         server.open();
   464             server.open();
   463 
   465 
   464         WebSocket.Listener listener = new WebSocket.Listener() {
   466             WebSocket.Listener listener = new WebSocket.Listener() {
   465 
   467 
   466             List<byte[]> collectedBytes = new ArrayList<>();
   468                 List<byte[]> collectedBytes = new ArrayList<>();
   467             ByteBuffer buffer = ByteBuffer.allocate(1024);
   469                 ByteBuffer buffer = ByteBuffer.allocate(1024);
   468 
   470 
   469             @Override
   471                 @Override
   470             public CompletionStage<?> onBinary(WebSocket webSocket,
   472                 public CompletionStage<?> onBinary(WebSocket webSocket,
   471                                                ByteBuffer message,
   473                                                    ByteBuffer message,
   472                                                boolean last) {
   474                                                    boolean last) {
   473                 System.out.printf("onBinary(%s, %s)%n", message, last);
   475                     System.out.printf("onBinary(%s, %s)%n", message, last);
   474                 webSocket.request(1);
   476                     webSocket.request(1);
   475 
   477 
   476                 append(message);
   478                     append(message);
   477                 if (last) {
   479                     if (last) {
   478                     buffer.flip();
   480                         buffer.flip();
   479                     byte[] bytes = new byte[buffer.remaining()];
   481                         byte[] bytes = new byte[buffer.remaining()];
   480                     buffer.get(bytes);
   482                         buffer.get(bytes);
   481                     buffer.clear();
   483                         buffer.clear();
   482                     processWholeBinary(bytes);
   484                         processWholeBinary(bytes);
   483                 }
   485                     }
   484                 return null;
   486                     return null;
   485             }
   487                 }
   486 
   488 
   487             private void append(ByteBuffer message) {
   489                 private void append(ByteBuffer message) {
   488                 if (buffer.remaining() < message.remaining()) {
   490                     if (buffer.remaining() < message.remaining()) {
   489                     assert message.remaining() > 0;
   491                         assert message.remaining() > 0;
   490                     int cap = (buffer.capacity() + message.remaining()) * 2;
   492                         int cap = (buffer.capacity() + message.remaining()) * 2;
   491                     ByteBuffer b = ByteBuffer.allocate(cap);
   493                         ByteBuffer b = ByteBuffer.allocate(cap);
   492                     b.put(buffer.flip());
   494                         b.put(buffer.flip());
   493                     buffer = b;
   495                         buffer = b;
   494                 }
   496                     }
   495                 buffer.put(message);
   497                     buffer.put(message);
   496             }
   498                 }
   497 
   499 
   498             private void processWholeBinary(byte[] bytes) {
   500                 private void processWholeBinary(byte[] bytes) {
   499                 String stringBytes = new String(bytes, UTF_8);
   501                     String stringBytes = new String(bytes, UTF_8);
   500                 System.out.println("processWholeBinary: " + stringBytes);
   502                     System.out.println("processWholeBinary: " + stringBytes);
   501                 collectedBytes.add(bytes);
   503                     collectedBytes.add(bytes);
   502             }
   504                 }
   503 
   505 
   504             @Override
   506                 @Override
   505             public CompletionStage<?> onClose(WebSocket webSocket,
   507                 public CompletionStage<?> onClose(WebSocket webSocket,
   506                                               int statusCode,
   508                                                   int statusCode,
   507                                               String reason) {
   509                                                   String reason) {
   508                 actual.complete(collectedBytes);
   510                     actual.complete(collectedBytes);
   509                 return null;
   511                     return null;
   510             }
   512                 }
   511 
   513 
   512             @Override
   514                 @Override
   513             public void onError(WebSocket webSocket, Throwable error) {
   515                 public void onError(WebSocket webSocket, Throwable error) {
   514                 actual.completeExceptionally(error);
   516                     actual.completeExceptionally(error);
   515             }
   517                 }
   516         };
   518             };
   517 
   519 
   518         webSocket = newBuilder()
   520             var webSocket = newBuilder()
   519                 .proxy(NO_PROXY)
   521                     .proxy(NO_PROXY)
   520                 .authenticator(new WSAuthenticator())
   522                     .authenticator(new WSAuthenticator())
   521                 .build().newWebSocketBuilder()
   523                     .build().newWebSocketBuilder()
   522                 .buildAsync(server.getURI(), listener)
   524                     .buildAsync(server.getURI(), listener)
   523                 .join();
   525                     .join();
   524 
   526             try {
   525         List<byte[]> a = actual.join();
   527                 List<byte[]> a = actual.join();
   526         assertEquals(a, expected);
   528                 assertEquals(a, expected);
   527 
   529             } finally {
   528         server.close();
   530                 webSocket.abort();
       
   531             }
       
   532         }
   529     }
   533     }
   530 
   534 
   531     @Test(dataProvider = "servers")
   535     @Test(dataProvider = "servers")
   532     public void simpleAggregatingTextMessages
   536     public void simpleAggregatingTextMessages
   533             (Function<int[],DummyWebSocketServer> serverSupplier)
   537             (Function<int[],DummyWebSocketServer> serverSupplier)
   552                 0x80, 0x00,                               // "
   556                 0x80, 0x00,                               // "
   553                 0x88, 0x00                                // <CLOSE>
   557                 0x88, 0x00                                // <CLOSE>
   554         };
   558         };
   555         CompletableFuture<List<String>> actual = new CompletableFuture<>();
   559         CompletableFuture<List<String>> actual = new CompletableFuture<>();
   556 
   560 
   557         server = serverSupplier.apply(binary);
   561         try (var server = serverSupplier.apply(binary)) {
   558         server.open();
   562             server.open();
   559 
   563 
   560         WebSocket.Listener listener = new WebSocket.Listener() {
   564             WebSocket.Listener listener = new WebSocket.Listener() {
   561 
   565 
   562             List<String> collectedStrings = new ArrayList<>();
   566                 List<String> collectedStrings = new ArrayList<>();
   563             StringBuilder text = new StringBuilder();
   567                 StringBuilder text = new StringBuilder();
   564 
   568 
   565             @Override
   569                 @Override
   566             public CompletionStage<?> onText(WebSocket webSocket,
   570                 public CompletionStage<?> onText(WebSocket webSocket,
   567                                              CharSequence message,
   571                                                  CharSequence message,
   568                                              boolean last) {
   572                                                  boolean last) {
   569                 System.out.printf("onText(%s, %s)%n", message, last);
   573                     System.out.printf("onText(%s, %s)%n", message, last);
   570                 webSocket.request(1);
   574                     webSocket.request(1);
   571                 text.append(message);
   575                     text.append(message);
   572                 if (last) {
   576                     if (last) {
   573                     String str = text.toString();
   577                         String str = text.toString();
   574                     text.setLength(0);
   578                         text.setLength(0);
   575                     processWholeText(str);
   579                         processWholeText(str);
   576                 }
   580                     }
   577                 return null;
   581                     return null;
   578             }
   582                 }
   579 
   583 
   580             private void processWholeText(String string) {
   584                 private void processWholeText(String string) {
   581                 System.out.println(string);
   585                     System.out.println(string);
   582                 collectedStrings.add(string);
   586                     collectedStrings.add(string);
   583             }
   587                 }
   584 
   588 
   585             @Override
   589                 @Override
   586             public CompletionStage<?> onClose(WebSocket webSocket,
   590                 public CompletionStage<?> onClose(WebSocket webSocket,
   587                                               int statusCode,
   591                                                   int statusCode,
   588                                               String reason) {
   592                                                   String reason) {
   589                 actual.complete(collectedStrings);
   593                     actual.complete(collectedStrings);
   590                 return null;
   594                     return null;
   591             }
   595                 }
   592 
   596 
   593             @Override
   597                 @Override
   594             public void onError(WebSocket webSocket, Throwable error) {
   598                 public void onError(WebSocket webSocket, Throwable error) {
   595                 actual.completeExceptionally(error);
   599                     actual.completeExceptionally(error);
   596             }
   600                 }
   597         };
   601             };
   598 
   602 
   599         webSocket = newBuilder()
   603             var webSocket = newBuilder()
   600                 .proxy(NO_PROXY)
   604                     .proxy(NO_PROXY)
   601                 .authenticator(new WSAuthenticator())
   605                     .authenticator(new WSAuthenticator())
   602                 .build().newWebSocketBuilder()
   606                     .build().newWebSocketBuilder()
   603                 .buildAsync(server.getURI(), listener)
   607                     .buildAsync(server.getURI(), listener)
   604                 .join();
   608                     .join();
   605 
   609             try {
   606         List<String> a = actual.join();
   610                 List<String> a = actual.join();
   607         assertEquals(a, expected);
   611                 assertEquals(a, expected);
   608 
   612             } finally {
   609         server.close();
   613                 webSocket.abort();
       
   614             }
       
   615         }
   610     }
   616     }
   611 
   617 
   612     /*
   618     /*
   613      * Exercises the scenario where requests for more messages are made prior to
   619      * Exercises the scenario where requests for more messages are made prior to
   614      * completing the returned CompletionStage instances.
   620      * completing the returned CompletionStage instances.
   637                 0x80, 0x00,                               // "
   643                 0x80, 0x00,                               // "
   638                 0x88, 0x00                                // <CLOSE>
   644                 0x88, 0x00                                // <CLOSE>
   639         };
   645         };
   640         CompletableFuture<List<String>> actual = new CompletableFuture<>();
   646         CompletableFuture<List<String>> actual = new CompletableFuture<>();
   641 
   647 
   642         server = serverSupplier.apply(binary);
   648         try (var server = serverSupplier.apply(binary)) {
   643         server.open();
   649             server.open();
   644 
   650 
   645         WebSocket.Listener listener = new WebSocket.Listener() {
   651             WebSocket.Listener listener = new WebSocket.Listener() {
   646 
   652 
   647             List<CharSequence> parts = new ArrayList<>();
   653                 List<CharSequence> parts = new ArrayList<>();
   648             /*
   654                 /*
   649              * A CompletableFuture which will complete once the current
   655                  * A CompletableFuture which will complete once the current
   650              * message has been fully assembled. Until then the listener
   656                  * message has been fully assembled. Until then the listener
   651              * returns this instance for every call.
   657                  * returns this instance for every call.
   652              */
   658                  */
   653             CompletableFuture<?> currentCf = new CompletableFuture<>();
   659                 CompletableFuture<?> currentCf = new CompletableFuture<>();
   654             List<String> collected = new ArrayList<>();
   660                 List<String> collected = new ArrayList<>();
   655 
   661 
   656             @Override
   662                 @Override
   657             public CompletionStage<?> onText(WebSocket webSocket,
   663                 public CompletionStage<?> onText(WebSocket webSocket,
   658                                              CharSequence message,
   664                                                  CharSequence message,
   659                                              boolean last) {
   665                                                  boolean last) {
   660                 parts.add(message);
   666                     parts.add(message);
   661                 if (!last) {
   667                     if (!last) {
   662                     webSocket.request(1);
   668                         webSocket.request(1);
   663                 } else {
   669                     } else {
   664                     this.currentCf.thenRun(() -> webSocket.request(1));
   670                         this.currentCf.thenRun(() -> webSocket.request(1));
   665                     CompletableFuture<?> refCf = this.currentCf;
   671                         CompletableFuture<?> refCf = this.currentCf;
   666                     processWholeMessage(new ArrayList<>(parts), refCf);
   672                         processWholeMessage(new ArrayList<>(parts), refCf);
   667                     currentCf = new CompletableFuture<>();
   673                         currentCf = new CompletableFuture<>();
   668                     parts.clear();
   674                         parts.clear();
   669                     return refCf;
   675                         return refCf;
   670                 }
   676                     }
   671                 return currentCf;
   677                     return currentCf;
   672             }
   678                 }
   673 
   679 
   674             @Override
   680                 @Override
   675             public CompletionStage<?> onClose(WebSocket webSocket,
   681                 public CompletionStage<?> onClose(WebSocket webSocket,
   676                                               int statusCode,
   682                                                   int statusCode,
   677                                               String reason) {
   683                                                   String reason) {
   678                 actual.complete(collected);
   684                     actual.complete(collected);
   679                 return null;
   685                     return null;
   680             }
   686                 }
   681 
   687 
   682             @Override
   688                 @Override
   683             public void onError(WebSocket webSocket, Throwable error) {
   689                 public void onError(WebSocket webSocket, Throwable error) {
   684                 actual.completeExceptionally(error);
   690                     actual.completeExceptionally(error);
   685             }
   691                 }
   686 
   692 
   687             public void processWholeMessage(List<CharSequence> data,
   693                 public void processWholeMessage(List<CharSequence> data,
   688                                             CompletableFuture<?> cf) {
   694                                                 CompletableFuture<?> cf) {
   689                 StringBuilder b = new StringBuilder();
   695                     StringBuilder b = new StringBuilder();
   690                 data.forEach(b::append);
   696                     data.forEach(b::append);
   691                 String s = b.toString();
   697                     String s = b.toString();
   692                 System.out.println(s);
   698                     System.out.println(s);
   693                 cf.complete(null);
   699                     cf.complete(null);
   694                 collected.add(s);
   700                     collected.add(s);
   695             }
   701                 }
   696         };
   702             };
   697 
   703 
   698         webSocket = newBuilder()
   704             var webSocket = newBuilder()
   699                 .proxy(NO_PROXY)
   705                     .proxy(NO_PROXY)
   700                 .authenticator(new WSAuthenticator())
   706                     .authenticator(new WSAuthenticator())
   701                 .build().newWebSocketBuilder()
   707                     .build().newWebSocketBuilder()
   702                 .buildAsync(server.getURI(), listener)
   708                     .buildAsync(server.getURI(), listener)
   703                 .join();
   709                     .join();
   704 
   710             try {
   705         List<String> a = actual.join();
   711                 List<String> a = actual.join();
   706         assertEquals(a, expected);
   712                 assertEquals(a, expected);
   707 
   713             } finally {
   708         server.close();
   714                 webSocket.abort();
       
   715             }
       
   716         }
   709     }
   717     }
   710 
   718 
   711     // -- authentication specific tests
   719     // -- authentication specific tests
   712 
   720 
   713     /*
   721     /*
   723                     .authenticator(new WSAuthenticator())
   731                     .authenticator(new WSAuthenticator())
   724                     .build()
   732                     .build()
   725                     .newWebSocketBuilder()
   733                     .newWebSocketBuilder()
   726                     .buildAsync(server.getURI(), new WebSocket.Listener() { })
   734                     .buildAsync(server.getURI(), new WebSocket.Listener() { })
   727                     .join();
   735                     .join();
       
   736             webSocket.abort();
   728         }
   737         }
   729     }
   738     }
   730 
   739 
   731     /*
   740     /*
   732      * Ensures authentication succeeds when an `Authorization` header is explicitly set.
   741      * Ensures authentication succeeds when an `Authorization` header is explicitly set.
   743                     .proxy(NO_PROXY).build()
   752                     .proxy(NO_PROXY).build()
   744                     .newWebSocketBuilder()
   753                     .newWebSocketBuilder()
   745                     .header("Authorization", hv)
   754                     .header("Authorization", hv)
   746                     .buildAsync(server.getURI(), new WebSocket.Listener() { })
   755                     .buildAsync(server.getURI(), new WebSocket.Listener() { })
   747                     .join();
   756                     .join();
       
   757             webSocket.abort();
   748         }
   758         }
   749     }
   759     }
   750 
   760 
   751     /*
   761     /*
   752      * Ensures authentication does not succeed when no authenticator is present.
   762      * Ensures authentication does not succeed when no authenticator is present.
   761                     .newWebSocketBuilder()
   771                     .newWebSocketBuilder()
   762                     .buildAsync(server.getURI(), new WebSocket.Listener() { });
   772                     .buildAsync(server.getURI(), new WebSocket.Listener() { });
   763 
   773 
   764             try {
   774             try {
   765                 var webSocket = cf.join();
   775                 var webSocket = cf.join();
       
   776                 silentAbort(webSocket);
   766                 fail("Expected exception not thrown");
   777                 fail("Expected exception not thrown");
   767             } catch (CompletionException expected) {
   778             } catch (CompletionException expected) {
   768                 WebSocketHandshakeException e = (WebSocketHandshakeException)expected.getCause();
   779                 WebSocketHandshakeException e = (WebSocketHandshakeException)expected.getCause();
   769                 HttpResponse<?> response = e.getResponse();
   780                 HttpResponse<?> response = e.getResponse();
   770                 assertEquals(response.statusCode(), 401);
   781                 assertEquals(response.statusCode(), 401);
   781         try (var server = new DummyWebSocketServer(USERNAME, PASSWORD)) {
   792         try (var server = new DummyWebSocketServer(USERNAME, PASSWORD)) {
   782             server.open();
   793             server.open();
   783 
   794 
   784             Authenticator authenticator = new Authenticator() {
   795             Authenticator authenticator = new Authenticator() {
   785                 @Override protected PasswordAuthentication getPasswordAuthentication() {
   796                 @Override protected PasswordAuthentication getPasswordAuthentication() {
   786                     return new PasswordAuthentication("BAD"+USERNAME, "".toCharArray());
   797                     return new PasswordAuthentication("BAD" + USERNAME, "".toCharArray());
   787                 }
   798                 }
   788             };
   799             };
   789 
   800 
   790             CompletableFuture<WebSocket> cf = newBuilder()
   801             CompletableFuture<WebSocket> cf = newBuilder()
   791                     .proxy(NO_PROXY)
   802                     .proxy(NO_PROXY)
   794                     .newWebSocketBuilder()
   805                     .newWebSocketBuilder()
   795                     .buildAsync(server.getURI(), new WebSocket.Listener() { });
   806                     .buildAsync(server.getURI(), new WebSocket.Listener() { });
   796 
   807 
   797             try {
   808             try {
   798                 var webSocket = cf.join();
   809                 var webSocket = cf.join();
       
   810                 silentAbort(webSocket);
   799                 fail("Expected exception not thrown");
   811                 fail("Expected exception not thrown");
   800             } catch (CompletionException expected) {
   812             } catch (CompletionException expected) {
   801                 System.out.println("caught expected exception:" + expected);
   813                 System.out.println("caught expected exception:" + expected);
   802             }
   814             }
   803         }
   815         }
   804     }
   816     }
       
   817     private static void silentAbort(WebSocket ws) {
       
   818         try {
       
   819             ws.abort();
       
   820         } catch (Throwable t) { }
       
   821     }
   805 }
   822 }