# HG changeset patch # User prappo # Date 1517345012 0 # Node ID f9b6016727b5223c9fe3adf0d2b3cc3533753100 # Parent 2e86bda80f79e491812be46061ada327e935eb32 http-client-branch: (WebSocket) A test for onClose & IllegalStateException diff -r 2e86bda80f79 -r f9b6016727b5 src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/websocket/FrameConsumer.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(); } diff -r 2e86bda80f79 -r f9b6016727b5 test/jdk/java/net/httpclient/websocket/Exceptionally.java --- 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 onCloseCalled = new CompletableFuture<>(); + CompletableFuture 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))); + } + } }