--- old/test/jdk/java/net/httpclient/websocket/jdk.incubator.httpclient/jdk/incubator/http/internal/websocket/CloseTest.java 2017-11-30 04:06:36.733841109 -0800 +++ /dev/null 2017-10-28 22:49:55.551349757 -0700 @@ -1,246 +0,0 @@ -/* - * Copyright (c) 2016, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.incubator.http.internal.websocket; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import jdk.incubator.http.WebSocket; - -import java.net.URI; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.CharacterCodingException; -import java.nio.charset.StandardCharsets; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; - -import static jdk.incubator.http.internal.websocket.TestSupport.Expectation.ifExpect; -import static jdk.incubator.http.internal.websocket.TestSupport.cartesianIterator; -import static java.util.Arrays.asList; -import static java.util.List.of; - -/* - * Tests for Close message handling: examines sendClose/onClose contracts. - */ -public final class CloseTest { - - /* - * Verifies the domain of the arguments of sendClose(code, reason). - */ - @Test(dataProvider = "sendClose") - public void testSendCloseArguments(int code, String reason) { - WebSocket ws = newWebSocket(); - ifExpect( - reason == null, - NullPointerException.class::isInstance) - .orExpect( - !isOutgoingCodeLegal(code), - IllegalArgumentException.class::isInstance) - .orExpect( - !isReasonLegal(reason), - IllegalArgumentException.class::isInstance) - .assertThrows(() -> ws.sendClose(code, reason)); - } - - /* - * After sendClose(code, reason) has returned normally or exceptionally, no - * more messages can be sent. However, if the invocation has thrown IAE/NPE - * (i.e. programming error) messages can still be sent (failure atomicity). - */ - public void testSendClose(int code, String reason) { - newWebSocket().sendClose(10, ""); - } - - /* - * After sendClose() has been invoked, no more messages can be sent. - */ - public void testSendClose() { - WebSocket ws = newWebSocket(); - CompletableFuture cf = ws.sendClose(); - } - - // TODO: sendClose can be invoked whenever is suitable without ISE - // + idempotency - - /* - * An invocation of sendClose(code, reason) will cause a Close message with - * the same code and the reason to appear on the wire. - */ - public void testSendCloseWysiwyg(int code, String reason) { - - } - - /* - * An invocation of sendClose() will cause an empty Close message to appear - * on the wire. - */ - public void testSendCloseWysiwyg() { - - } - - /* - * Automatic Closing handshake. Listener receives onClose() and returns from - * it. WebSocket closes in accordance to the returned value. - */ - public void testClosingHandshake1() { - // TODO: closed if observed shortly after the returned CS completes - } - - /* - * sendClose is invoked from within onClose. After sendClose has returned, - * isClosed() reports true. - */ - public void testClosingHandshake2() { - // 1. newWebSocket().sendClose(); - // 2. onClose return null - // 3. isClosed() == true - } - - /* - * sendClose has been invoked, then onClose. Shortly after onClose has - * returned, isClosed reports true. - */ - public void testClosingHandshake3() { - } - - /* - * Return from onClose with nevercompleting CS then sendClose(). - */ - public void testClosingHandshake4() { - - } - - /* - * Exceptions thrown from onClose and exceptions a CS returned from onClose - * "completes exceptionally" with are ignored. In other words, they are - * never reported to onError(). - */ - public void testOnCloseExceptions() { - - } - - /* - * An incoming Close message on the wire will cause an invocation of onClose - * with appropriate values. However, if this message violates the WebSocket - * Protocol, onError is invoked instead. - * - * // TODO: automatic close (if error) AND isClose returns true from onError - */ - public void testOnCloseWysiwyg() { - - } - - /* - * Data is read off the wire. An end-of-stream has been reached while - * reading a frame. - * - * onError is invoked with java.net.ProtocolException and the WebSocket this - * listener has been attached to - */ - public void testUnexpectedEOS() { - - } - - /* - * Data is read off the wire. An end-of-stream has been reached in between - * frames, and no Close frame has been received yet. - * - * onClose is invoked with the status code 1006 and the WebSocket this - * listener has been attached to - */ - public void testEOS() { - - } - - // TODO: check buffers for change - - @DataProvider(name = "sendClose") - public Iterator createData() { - List codes = asList( - Integer.MIN_VALUE, -1, 0, 1, 500, 998, 999, 1000, 1001, 1002, - 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, - 1013, 1014, 1015, 1016, 2998, 2999, 3000, 3001, 3998, 3999, - 4000, 4001, 4998, 4999, 5000, 5001, 32768, 65535, 65536, - Integer.MAX_VALUE); - String longReason1 = "This is a reason string. Nothing special except " + - "its UTF-8 representation is a bit " + - "longer than one hundred and twenty three bytes."; - assert longReason1.getBytes(StandardCharsets.UTF_8).length > 123; - - // Russian alphabet repeated cyclically until it's enough to pass "123" - // bytes length - StringBuilder b = new StringBuilder(); - char c = '\u0410'; - for (int i = 0; i < 62; i++) { - b.append(c); - if (++c > '\u042F') { - c = '\u0410'; - } - } - String longReason2 = b.toString(); - assert longReason2.length() <= 123 - && longReason2.getBytes(StandardCharsets.UTF_8).length > 123; - - String malformedReason = new String(new char[]{0xDC00, 0xD800}); - - List reasons = asList - (null, "", "abc", longReason1, longReason2, malformedReason); - - return cartesianIterator(of(codes, reasons), args -> args); - } - - private boolean isReasonLegal(String reason) { - if (reason == null) { - return false; - } - ByteBuffer result; - try { - result = StandardCharsets.UTF_8.newEncoder().encode(CharBuffer.wrap(reason)); - } catch (CharacterCodingException e) { - return false; - } - return result.remaining() <= 123; - } - - private static boolean isOutgoingCodeLegal(int code) { - if (code < 1000 || code > 4999) { - return false; - } - if (code < 1016) { - return code == 1000 || code == 1001 || code == 1008 || code == 1011; - } - return code >= 3000; - } - - private WebSocket newWebSocket() { - WebSocket.Listener l = new WebSocket.Listener() { }; - return new WebSocketImpl(URI.create("ws://example.com"), - "", - new MockChannel.Builder().build(), - l); - } -}