diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/IPAccessHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/IPAccessHandlerTest.java deleted file mode 100644 index be13ae5bfb9..00000000000 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/IPAccessHandlerTest.java +++ /dev/null @@ -1,545 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.server.handler; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.io.BufferedReader; -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.Socket; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.Locale; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Stream; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.http.HttpStatus; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.NetworkConnector; -import org.eclipse.jetty.server.Request; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -public class IPAccessHandlerTest -{ - private static Server _server; - private static NetworkConnector _connector; - private static IPAccessHandler _handler; - - @BeforeAll - public static void setUp() - throws Exception - { - _server = new Server(); - _connector = new ServerConnector(_server); - _server.setConnectors(new Connector[] { _connector }); - - _handler = new IPAccessHandler(); - _handler.setHandler(new AbstractHandler() - { - @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException - { - baseRequest.setHandled(true); - response.setStatus(HttpStatus.OK_200); - } - }); - _server.setHandler(_handler); - _server.start(); - } - - /* ------------------------------------------------------------ */ - @AfterAll - public static void tearDown() - throws Exception - { - _server.stop(); - } - - /* ------------------------------------------------------------ */ - @ParameterizedTest - @MethodSource("data") - public void testHandler(String white, String black, String host, String uri, String code, boolean byPath) - throws Exception - { - _handler.setWhite(white.split(";",-1)); - _handler.setBlack(black.split(";",-1)); - _handler.setWhiteListByPath(byPath); - - String request = "GET " + uri + " HTTP/1.1\n" + "Host: "+ host + "\n\n"; - Socket socket = new Socket("127.0.0.1", _connector.getLocalPort()); - socket.setSoTimeout(5000); - try - { - OutputStream output = socket.getOutputStream(); - BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream())); - - output.write(request.getBytes(StandardCharsets.UTF_8)); - output.flush(); - - Response response = readResponse(input); - Object[] params = new Object[]{ - "Request WBHUC", white, black, host, uri, code, - "Response", response.getCode()}; - assertEquals(code, response.getCode(), Arrays.deepToString(params)); - } - finally - { - socket.close(); - } - } - - /* ------------------------------------------------------------ */ - protected Response readResponse(BufferedReader reader) - throws IOException - { - // Simplified parser for HTTP responses - String line = reader.readLine(); - if (line == null) - throw new EOFException(); - Matcher responseLine = Pattern.compile("HTTP/1\\.1\\s+(\\d+)").matcher(line); - assertTrue(responseLine.lookingAt()); - String code = responseLine.group(1); - - Map headers = new LinkedHashMap<>(); - while ((line = reader.readLine()) != null) - { - if (line.trim().length() == 0) - break; - - Matcher header = Pattern.compile("([^:]+):\\s*(.*)").matcher(line); - assertTrue(header.lookingAt()); - String headerName = header.group(1); - String headerValue = header.group(2); - headers.put(headerName.toLowerCase(Locale.ENGLISH), headerValue.toLowerCase(Locale.ENGLISH)); - } - - StringBuilder body = new StringBuilder(); - if (headers.containsKey("content-length")) - { - int length = Integer.parseInt(headers.get("content-length")); - for (int i = 0; i < length; ++i) - { - char c = (char)reader.read(); - body.append(c); - } - } - else if ("chunked".equals(headers.get("transfer-encoding"))) - { - while ((line = reader.readLine()) != null) - { - if ("0".equals(line)) - { - line = reader.readLine(); - assertEquals("", line); - break; - } - - int length = Integer.parseInt(line, 16); - for (int i = 0; i < length; ++i) - { - char c = (char)reader.read(); - body.append(c); - } - line = reader.readLine(); - assertEquals("", line); - } - } - - return new Response(code, headers, body.toString().trim()); - } - - /* ------------------------------------------------------------ */ - protected class Response - { - private final String code; - private final Map headers; - private final String body; - - /* ------------------------------------------------------------ */ - private Response(String code, Map headers, String body) - { - this.code = code; - this.headers = headers; - this.body = body; - } - - /* ------------------------------------------------------------ */ - public String getCode() - { - return code; - } - - /* ------------------------------------------------------------ */ - public Map getHeaders() - { - return headers; - } - - /* ------------------------------------------------------------ */ - public String getBody() - { - return body; - } - - /* ------------------------------------------------------------ */ - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append(code).append("\r\n"); - for (Map.Entry entry : headers.entrySet()) - builder.append(entry.getKey()).append(": ").append(entry.getValue()).append("\r\n"); - builder.append("\r\n"); - builder.append(body); - return builder.toString(); - } - } - - /* ------------------------------------------------------------ */ - public static Stream data() { - Object[][] data = new Object[][] { - // Empty lists - {"", "", "127.0.0.1", "/", "200", false}, - {"", "", "127.0.0.1", "/dump/info", "200", false}, - - // White list - {"127.0.0.1", "", "127.0.0.1", "/", "200", false}, - {"127.0.0.1", "", "127.0.0.1", "/dispatch", "200", false}, - {"127.0.0.1", "", "127.0.0.1", "/dump/info", "200", false}, - - {"127.0.0.1|/", "", "127.0.0.1", "/", "200", false}, - {"127.0.0.1|/", "", "127.0.0.1", "/dispatch", "403", false}, - {"127.0.0.1|/", "", "127.0.0.1", "/dump/info", "403", false}, - - {"127.0.0.1|/*", "", "127.0.0.1", "/", "200", false}, - {"127.0.0.1|/*", "", "127.0.0.1", "/dispatch", "200", false}, - {"127.0.0.1|/*", "", "127.0.0.1", "/dump/info", "200", false}, - - {"127.0.0.1|/dump/*", "", "127.0.0.1", "/", "403", false}, - {"127.0.0.1|/dump/*", "", "127.0.0.1", "/dispatch", "403", false}, - {"127.0.0.1|/dump/*", "", "127.0.0.1", "/dump/info", "200", false}, - {"127.0.0.1|/dump/*", "", "127.0.0.1", "/dump/test", "200", false}, - - {"127.0.0.1|/dump/info", "", "127.0.0.1", "/", "403", false}, - {"127.0.0.1|/dump/info", "", "127.0.0.1", "/dispatch", "403", false}, - {"127.0.0.1|/dump/info", "", "127.0.0.1", "/dump/info", "200", false}, - {"127.0.0.1|/dump/info", "", "127.0.0.1", "/dump/test", "403", false}, - - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "", "127.0.0.1", "/", "403", false}, - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "", "127.0.0.1", "/dispatch", "403", false}, - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "", "127.0.0.1", "/dump/info", "200", false}, - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "", "127.0.0.1", "/dump/test", "200", false}, - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "", "127.0.0.1", "/dump/fail", "403", false}, - - {"127.0.0.0-2|", "", "127.0.0.1", "/", "200", false}, - {"127.0.0.0-2|", "", "127.0.0.1", "/dump/info", "403", false}, - - {"127.0.0.0-2|/", "", "127.0.0.1", "/", "200", false}, - {"127.0.0.0-2|/", "", "127.0.0.1", "/dispatch", "403", false}, - {"127.0.0.0-2|/", "", "127.0.0.1", "/dump/info", "403", false}, - - {"127.0.0.0-2|/dump/*", "", "127.0.0.1", "/", "403", false}, - {"127.0.0.0-2|/dump/*", "", "127.0.0.1", "/dispatch", "403", false}, - {"127.0.0.0-2|/dump/*", "", "127.0.0.1", "/dump/info", "200", false}, - - {"127.0.0.0-2|/dump/info", "", "127.0.0.1", "/", "403", false}, - {"127.0.0.0-2|/dump/info", "", "127.0.0.1", "/dispatch", "403", false}, - {"127.0.0.0-2|/dump/info", "", "127.0.0.1", "/dump/info", "200", false}, - {"127.0.0.0-2|/dump/info", "", "127.0.0.1", "/dump/test", "403", false}, - - {"127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "", "127.0.0.1", "/", "403", false}, - {"127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "", "127.0.0.1", "/dispatch", "403", false}, - {"127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "", "127.0.0.1", "/dump/info", "200", false}, - {"127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "", "127.0.0.1", "/dump/test", "200", false}, - {"127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "", "127.0.0.1", "/dump/fail", "403", false}, - - // Black list - {"", "127.0.0.1", "127.0.0.1", "/", "403", false}, - {"", "127.0.0.1", "127.0.0.1", "/dispatch", "403", false}, - {"", "127.0.0.1", "127.0.0.1", "/dump/info", "403", false}, - - {"", "127.0.0.1|/", "127.0.0.1", "/", "403", false}, - {"", "127.0.0.1|/", "127.0.0.1", "/dispatch", "200", false}, - {"", "127.0.0.1|/", "127.0.0.1", "/dump/info", "200", false}, - - {"", "127.0.0.1|/*", "127.0.0.1", "/", "403", false}, - {"", "127.0.0.1|/*", "127.0.0.1", "/dispatch", "403", false}, - {"", "127.0.0.1|/*", "127.0.0.1", "/dump/info", "403", false}, - - {"", "127.0.0.1|/dump/*", "127.0.0.1", "/", "200", false}, - {"", "127.0.0.1|/dump/*", "127.0.0.1", "/dispatch", "200", false}, - {"", "127.0.0.1|/dump/*", "127.0.0.1", "/dump/info", "403", false}, - {"", "127.0.0.1|/dump/*", "127.0.0.1", "/dump/test", "403", false}, - - {"", "127.0.0.1|/dump/info", "127.0.0.1", "/", "200", false}, - {"", "127.0.0.1|/dump/info", "127.0.0.1", "/dispatch", "200", false}, - {"", "127.0.0.1|/dump/info", "127.0.0.1", "/dump/info", "403", false}, - {"", "127.0.0.1|/dump/info", "127.0.0.1", "/dump/test", "200", false}, - - {"", "127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1", "/", "200", false}, - {"", "127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1", "/dispatch", "200", false}, - {"", "127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1", "/dump/info", "403", false}, - {"", "127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1", "/dump/test", "403", false}, - {"", "127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1", "/dump/fail", "200", false}, - - {"", "127.0.0.0-2|", "127.0.0.1", "/", "403", false}, - {"", "127.0.0.0-2|", "127.0.0.1", "/dump/info", "200", false}, - - {"", "127.0.0.0-2|/", "127.0.0.1", "/", "403", false}, - {"", "127.0.0.0-2|/", "127.0.0.1", "/dispatch", "200", false}, - {"", "127.0.0.0-2|/", "127.0.0.1", "/dump/info", "200", false}, - - {"", "127.0.0.0-2|/dump/*", "127.0.0.1", "/", "200", false}, - {"", "127.0.0.0-2|/dump/*", "127.0.0.1", "/dispatch", "200", false}, - {"", "127.0.0.0-2|/dump/*", "127.0.0.1", "/dump/info", "403", false}, - - {"", "127.0.0.0-2|/dump/info", "127.0.0.1", "/", "200", false}, - {"", "127.0.0.0-2|/dump/info", "127.0.0.1", "/dispatch", "200", false}, - {"", "127.0.0.0-2|/dump/info", "127.0.0.1", "/dump/info", "403", false}, - {"", "127.0.0.0-2|/dump/info", "127.0.0.1", "/dump/test", "200", false}, - - {"", "127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "127.0.0.1", "/", "200", false}, - {"", "127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "127.0.0.1", "/dispatch", "200", false}, - {"", "127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "127.0.0.1", "/dump/info", "403", false}, - {"", "127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "127.0.0.1", "/dump/test", "403", false}, - {"", "127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "127.0.0.1", "/dump/fail", "200", false}, - - // Both lists - {"127.0.0.1|/dump", "127.0.0.1|/dump/fail", "127.0.0.1", "/dump", "200", false}, - {"127.0.0.1|/dump", "127.0.0.1|/dump/fail", "127.0.0.1", "/dump/info", "403", false}, - {"127.0.0.1|/dump", "127.0.0.1|/dump/fail", "127.0.0.1", "/dump/fail", "403", false}, - - {"127.0.0.1|/dump/*", "127.0.0.1|/dump/fail", "127.0.0.1", "/dump", "200", false}, - {"127.0.0.1|/dump/*", "127.0.0.1|/dump/fail", "127.0.0.1", "/dump/info", "200", false}, - {"127.0.0.1|/dump/*", "127.0.0.1|/dump/fail", "127.0.0.1", "/dump/fail", "403", false}, - - {"127.0.0.1|/dump/*", "127.0.0.1|/dump/test;127.0.0.1|/dump/fail", "127.0.0.1", "/dump", "200", false}, - {"127.0.0.1|/dump/*", "127.0.0.1|/dump/test;127.0.0.1|/dump/fail", "127.0.0.1", "/dump/info", "200", false}, - {"127.0.0.1|/dump/*", "127.0.0.1|/dump/test;127.0.0.1|/dump/fail", "127.0.0.1", "/dump/test", "403", false}, - {"127.0.0.1|/dump/*", "127.0.0.1|/dump/test;127.0.0.1|/dump/fail", "127.0.0.1", "/dump/fail", "403", false}, - - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1|/dump/test", "127.0.0.1", "/dump", "403", false}, - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1|/dump/test", "127.0.0.1", "/dump/info", "200", false}, - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1|/dump/test", "127.0.0.1", "/dump/test", "403", false}, - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1|/dump/test", "127.0.0.1", "/dump/fail", "403", false}, - - {"127.0.0.1|/;127.0.0.0-2|/dump/*", "127.0.0.0,1|/dump/fail", "127.0.0.1", "/", "200", false}, - {"127.0.0.1|/;127.0.0.0-2|/dump/*", "127.0.0.0,1|/dump/fail", "127.0.0.1", "/dump/info", "200", false}, - {"127.0.0.1|/;127.0.0.0-2|/dump/*", "127.0.0.0,1|/dump/fail", "127.0.0.1", "/dump/fail", "403", false}, - - // Different address - {"127.0.0.2", "", "127.0.0.1", "/", "403", false}, - {"127.0.0.2", "", "127.0.0.1", "/dump/info", "403", false}, - - {"127.0.0.2|/dump/*", "", "127.0.0.1", "/", "403", false}, - {"127.0.0.2|/dump/*", "", "127.0.0.1", "/dump/info", "403", false}, - - {"127.0.0.2|/dump/info", "", "127.0.0.1", "/", "403", false}, - {"127.0.0.2|/dump/info", "", "127.0.0.1", "/dump/info", "403", false}, - {"127.0.0.2|/dump/info", "", "127.0.0.1", "/dump/test", "403", false}, - - {"127.0.0.1|/dump/info;127.0.0.2|/dump/test", "", "127.0.0.1", "/", "403", false}, - {"127.0.0.1|/dump/info;127.0.0.2|/dump/test", "", "127.0.0.1", "/dispatch", "403", false}, - {"127.0.0.1|/dump/info;127.0.0.2|/dump/test", "", "127.0.0.1", "/dump/info", "200", false}, - {"127.0.0.1|/dump/info;127.0.0.2|/dump/test", "", "127.0.0.1", "/dump/test", "403", false}, - {"127.0.0.1|/dump/info;127.0.0.2|/dump/test", "", "127.0.0.1", "/dump/fail", "403", false}, - - {"172.0.0.0-255", "", "127.0.0.1", "/", "403", false}, - {"172.0.0.0-255", "", "127.0.0.1", "/dump/info", "403", false}, - - {"172.0.0.0-255|/dump/*;127.0.0.0-255|/dump/*", "", "127.0.0.1", "/", "403", false}, - {"172.0.0.0-255|/dump/*;127.0.0.0-255|/dump/*", "", "127.0.0.1", "/dispatch", "403", false}, - {"172.0.0.0-255|/dump/*;127.0.0.0-255|/dump/*", "", "127.0.0.1", "/dump/info", "200", false}, - - /*-----------------------------------------------------------------------------------------*/ - // Match by path starts with [117] - // test cases affected by _whiteListByPath highlighted accordingly - - {"", "", "127.0.0.1", "/", "200", true}, - {"", "", "127.0.0.1", "/dump/info", "200", true}, - - // White list - {"127.0.0.1", "", "127.0.0.1", "/", "200", true}, - {"127.0.0.1", "", "127.0.0.1", "/dispatch", "200", true}, - {"127.0.0.1", "", "127.0.0.1", "/dump/info", "200", true}, - - {"127.0.0.1|/", "", "127.0.0.1", "/", "200", true}, - {"127.0.0.1|/", "", "127.0.0.1", "/dispatch", "200", true}, // _whiteListByPath - {"127.0.0.1|/", "", "127.0.0.1", "/dump/info", "200", true}, // _whiteListByPath - - {"127.0.0.1|/*", "", "127.0.0.1", "/", "200", true}, - {"127.0.0.1|/*", "", "127.0.0.1", "/dispatch", "200", true}, - {"127.0.0.1|/*", "", "127.0.0.1", "/dump/info", "200", true}, - - {"127.0.0.1|/dump/*", "", "127.0.0.1", "/", "200", true}, // _whiteListByPath - {"127.0.0.1|/dump/*", "", "127.0.0.1", "/dispatch", "200", true}, // _whiteListByPath - {"127.0.0.1|/dump/*", "", "127.0.0.1", "/dump/info", "200", true}, - {"127.0.0.1|/dump/*", "", "127.0.0.1", "/dump/test", "200", true}, - - {"127.0.0.1|/dump/info", "", "127.0.0.1", "/", "200", true}, // _whiteListByPath - {"127.0.0.1|/dump/info", "", "127.0.0.1", "/dispatch", "200", true}, // _whiteListByPath - {"127.0.0.1|/dump/info", "", "127.0.0.1", "/dump/info", "200", true}, - {"127.0.0.1|/dump/info", "", "127.0.0.1", "/dump/test", "200", true}, // _whiteListByPath - - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "", "127.0.0.1", "/", "200", true}, // _whiteListByPath - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "", "127.0.0.1", "/dispatch", "200", true}, // _whiteListByPath - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "", "127.0.0.1", "/dump/info", "200", true}, - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "", "127.0.0.1", "/dump/test", "200", true}, - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "", "127.0.0.1", "/dump/fail", "200", true}, // _whiteListByPath - - {"127.0.0.0-2|", "", "127.0.0.1", "/", "200", true}, - {"127.0.0.0-2|", "", "127.0.0.1", "/dump/info", "200", true}, - - {"127.0.0.0-2|/", "", "127.0.0.1", "/", "200", true}, - {"127.0.0.0-2|/", "", "127.0.0.1", "/dispatch", "200", true}, // _whiteListByPath - {"127.0.0.0-2|/", "", "127.0.0.1", "/dump/info", "200", true}, // _whiteListByPath - - {"127.0.0.0-2|/dump/*", "", "127.0.0.1", "/", "200", true}, // _whiteListByPath - {"127.0.0.0-2|/dump/*", "", "127.0.0.1", "/dispatch", "200", true}, // _whiteListByPath - {"127.0.0.0-2|/dump/*", "", "127.0.0.1", "/dump/info", "200", true}, - - {"127.0.0.0-2|/dump/info", "", "127.0.0.1", "/", "200", true}, // _whiteListByPath - {"127.0.0.0-2|/dump/info", "", "127.0.0.1", "/dispatch", "200", true}, // _whiteListByPath - {"127.0.0.0-2|/dump/info", "", "127.0.0.1", "/dump/info", "200", true}, - {"127.0.0.0-2|/dump/info", "", "127.0.0.1", "/dump/test", "200", true}, // _whiteListByPath - - {"127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "", "127.0.0.1", "/", "200", true}, // _whiteListByPath - {"127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "", "127.0.0.1", "/dispatch", "200", true}, // _whiteListByPath - {"127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "", "127.0.0.1", "/dump/info", "200", true}, - {"127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "", "127.0.0.1", "/dump/test", "200", true}, - {"127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "", "127.0.0.1", "/dump/fail", "200", true}, // _whiteListByPath - - // Black list - {"", "127.0.0.1", "127.0.0.1", "/", "403", true}, - {"", "127.0.0.1", "127.0.0.1", "/dispatch", "403", true}, - {"", "127.0.0.1", "127.0.0.1", "/dump/info", "403", true}, - - {"", "127.0.0.1|/", "127.0.0.1", "/", "403", true}, - {"", "127.0.0.1|/", "127.0.0.1", "/dispatch", "200", true}, - {"", "127.0.0.1|/", "127.0.0.1", "/dump/info", "200", true}, - - {"", "127.0.0.1|/*", "127.0.0.1", "/", "403", true}, - {"", "127.0.0.1|/*", "127.0.0.1", "/dispatch", "403", true}, - {"", "127.0.0.1|/*", "127.0.0.1", "/dump/info", "403", true}, - - {"", "127.0.0.1|/dump/*", "127.0.0.1", "/", "200", true}, - {"", "127.0.0.1|/dump/*", "127.0.0.1", "/dispatch", "200", true}, - {"", "127.0.0.1|/dump/*", "127.0.0.1", "/dump/info", "403", true}, - {"", "127.0.0.1|/dump/*", "127.0.0.1", "/dump/test", "403", true}, - - {"", "127.0.0.1|/dump/info", "127.0.0.1", "/", "200", true}, - {"", "127.0.0.1|/dump/info", "127.0.0.1", "/dispatch", "200", true}, - {"", "127.0.0.1|/dump/info", "127.0.0.1", "/dump/info", "403", true}, - {"", "127.0.0.1|/dump/info", "127.0.0.1", "/dump/test", "200", true}, - - {"", "127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1", "/", "200", true}, - {"", "127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1", "/dispatch", "200", true}, - {"", "127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1", "/dump/info", "403", true}, - {"", "127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1", "/dump/test", "403", true}, - {"", "127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1", "/dump/fail", "200", true}, - - {"", "127.0.0.0-2|", "127.0.0.1", "/", "403", true}, - {"", "127.0.0.0-2|", "127.0.0.1", "/dump/info", "200", true}, - - {"", "127.0.0.0-2|/", "127.0.0.1", "/", "403", true}, - {"", "127.0.0.0-2|/", "127.0.0.1", "/dispatch", "200", true}, - {"", "127.0.0.0-2|/", "127.0.0.1", "/dump/info", "200", true}, - - {"", "127.0.0.0-2|/dump/*", "127.0.0.1", "/", "200", true}, - {"", "127.0.0.0-2|/dump/*", "127.0.0.1", "/dispatch", "200", true}, - {"", "127.0.0.0-2|/dump/*", "127.0.0.1", "/dump/info", "403", true}, - - {"", "127.0.0.0-2|/dump/info", "127.0.0.1", "/", "200", true}, - {"", "127.0.0.0-2|/dump/info", "127.0.0.1", "/dispatch", "200", true}, - {"", "127.0.0.0-2|/dump/info", "127.0.0.1", "/dump/info", "403", true}, - {"", "127.0.0.0-2|/dump/info", "127.0.0.1", "/dump/test", "200", true}, - - {"", "127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "127.0.0.1", "/", "200", true}, - {"", "127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "127.0.0.1", "/dispatch", "200", true}, - {"", "127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "127.0.0.1", "/dump/info", "403", true}, - {"", "127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "127.0.0.1", "/dump/test", "403", true}, - {"", "127.0.0.0-2|/dump/info;127.0.0.0-2|/dump/test", "127.0.0.1", "/dump/fail", "200", true}, - - // Both lists - {"127.0.0.1|/dump", "127.0.0.1|/dump/fail", "127.0.0.1", "/dump", "200", true}, - {"127.0.0.1|/dump", "127.0.0.1|/dump/fail", "127.0.0.1", "/dump/info", "200", true}, // _whiteListByPath - {"127.0.0.1|/dump", "127.0.0.1|/dump/fail", "127.0.0.1", "/dump/fail", "403", true}, - - {"127.0.0.1|/dump/*", "127.0.0.1|/dump/fail", "127.0.0.1", "/dump", "200", true}, - {"127.0.0.1|/dump/*", "127.0.0.1|/dump/fail", "127.0.0.1", "/dump/info", "200", true}, - {"127.0.0.1|/dump/*", "127.0.0.1|/dump/fail", "127.0.0.1", "/dump/fail", "403", true}, - - {"127.0.0.1|/dump/*", "127.0.0.1|/dump/test;127.0.0.1|/dump/fail", "127.0.0.1", "/dump", "200", true}, - {"127.0.0.1|/dump/*", "127.0.0.1|/dump/test;127.0.0.1|/dump/fail", "127.0.0.1", "/dump/info", "200", true}, - {"127.0.0.1|/dump/*", "127.0.0.1|/dump/test;127.0.0.1|/dump/fail", "127.0.0.1", "/dump/test", "403", true}, - {"127.0.0.1|/dump/*", "127.0.0.1|/dump/test;127.0.0.1|/dump/fail", "127.0.0.1", "/dump/fail", "403", true}, - - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1|/dump/test", "127.0.0.1", "/dump", "200", true}, // _whiteListByPath - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1|/dump/test", "127.0.0.1", "/dump/info", "200", true}, - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1|/dump/test", "127.0.0.1", "/dump/test", "403", true}, - {"127.0.0.1|/dump/info;127.0.0.1|/dump/test", "127.0.0.1|/dump/test", "127.0.0.1", "/dump/fail", "200", true}, // _whiteListByPath - - {"127.0.0.1|/;127.0.0.0-2|/dump/*", "127.0.0.0,1|/dump/fail", "127.0.0.1", "/", "200", true}, - {"127.0.0.1|/;127.0.0.0-2|/dump/*", "127.0.0.0,1|/dump/fail", "127.0.0.1", "/dump/info", "200", true}, - {"127.0.0.1|/;127.0.0.0-2|/dump/*", "127.0.0.0,1|/dump/fail", "127.0.0.1", "/dump/fail", "403", true}, - - // Different address - {"127.0.0.2", "", "127.0.0.1", "/", "403", true}, - {"127.0.0.2", "", "127.0.0.1", "/dump/info", "403", true}, - - {"127.0.0.2|/dump/*", "", "127.0.0.1", "/", "200", true}, // _whiteListByPath - {"127.0.0.2|/dump/*", "", "127.0.0.1", "/dump/info", "403", true}, - - {"127.0.0.2|/dump/info", "", "127.0.0.1", "/", "200", true}, // _whiteListByPath - {"127.0.0.2|/dump/info", "", "127.0.0.1", "/dump/info", "403", true}, - {"127.0.0.2|/dump/info", "", "127.0.0.1", "/dump/test", "200", true}, // _whiteListByPath - - {"127.0.0.1|/dump/info;127.0.0.2|/dump/test", "", "127.0.0.1", "/", "200", true}, // _whiteListByPath - {"127.0.0.1|/dump/info;127.0.0.2|/dump/test", "", "127.0.0.1", "/dispatch", "200", true}, // _whiteListByPath - {"127.0.0.1|/dump/info;127.0.0.2|/dump/test", "", "127.0.0.1", "/dump/info", "200", true}, - {"127.0.0.1|/dump/info;127.0.0.2|/dump/test", "", "127.0.0.1", "/dump/test", "403", true}, - {"127.0.0.1|/dump/info;127.0.0.2|/dump/test", "", "127.0.0.1", "/dump/fail", "200", true}, // _whiteListByPath - - {"172.0.0.0-255", "", "127.0.0.1", "/", "403", true}, - {"172.0.0.0-255", "", "127.0.0.1", "/dump/info", "403", true}, - - {"172.0.0.0-255|/dump/*;127.0.0.0-255|/dump/*", "", "127.0.0.1", "/", "200", true}, // _whiteListByPath - {"172.0.0.0-255|/dump/*;127.0.0.0-255|/dump/*", "", "127.0.0.1", "/dispatch", "200", true}, // _whiteListByPath - {"172.0.0.0-255|/dump/*;127.0.0.0-255|/dump/*", "", "127.0.0.1", "/dump/info", "200", true}, - }; - return Arrays.asList(data).stream().map(Arguments::of); - } -} diff --git a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebAppContextTest.java b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebAppContextTest.java index 2334041fc7e..a657670370d 100644 --- a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebAppContextTest.java +++ b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebAppContextTest.java @@ -18,14 +18,8 @@ package org.eclipse.jetty.webapp; -<<<<<<< HEAD import static org.hamcrest.Matchers.containsString; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertEquals; -======= +import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -33,7 +27,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; ->>>>>>> a3f1592c50... Issue #2431 - Upgrade to Junit 5 (#2436) + import java.io.File; import java.io.IOException; @@ -119,7 +113,8 @@ public class WebAppContextTest //test if no classnames set, its the defaults WebAppContext wac = new WebAppContext(); - assertThat(wac.getWebAppConfigurations().stream().map(c->{return c.getClass().getName();}).collect(Collectors.toList()),Matchers.containsInAnyOrder(known_and_enabled)); + assertThat(wac.getWebAppConfigurations().stream().map(c->{return c.getClass().getName();}).collect(Collectors.toList()), + containsInAnyOrder(known_and_enabled)); String[] classNames = wac.getConfigurationClasses(); assertNotNull(classNames); @@ -133,8 +128,8 @@ public class WebAppContextTest { WebAppContext wac = new WebAppContext(); wac.setServer(new Server()); - Assert.assertThat(wac.getWebAppConfigurations().stream().map(c->c.getClass().getName()).collect(Collectors.toList()), - Matchers.contains( + assertThat(wac.getWebAppConfigurations().stream().map(c->c.getClass().getName()).collect(Collectors.toList()), + contains( "org.eclipse.jetty.webapp.JmxConfiguration", "org.eclipse.jetty.webapp.WebInfConfiguration", "org.eclipse.jetty.webapp.WebXmlConfiguration", @@ -150,14 +145,14 @@ public class WebAppContextTest Configuration[] configs = {new WebInfConfiguration()}; WebAppContext wac = new WebAppContext(); wac.setConfigurations(configs); - Assert.assertThat(wac.getWebAppConfigurations(),Matchers.contains(configs)); + assertThat(wac.getWebAppConfigurations(),contains(configs)); //test that explicit config instances override any from server String[] classNames = {"x.y.z"}; Server server = new Server(); server.setAttribute(Configuration.ATTR, classNames); wac.setServer(server); - Assert.assertThat(wac.getWebAppConfigurations(),Matchers.contains(configs)); + assertThat(wac.getWebAppConfigurations(),contains(configs)); } @Test @@ -264,11 +259,8 @@ public class WebAppContextTest try { String response = connector.getResponse("GET http://localhost:8080 HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n"); -<<<<<<< HEAD assertThat(response,containsString("200 OK")); -======= - assertTrue(response.indexOf("200 OK")>=0); ->>>>>>> a3f1592c50... Issue #2431 - Upgrade to Junit 5 (#2436) + } finally { diff --git a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebInfConfigurationTest.java b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebInfConfigurationTest.java deleted file mode 100644 index 21634e101a0..00000000000 --- a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebInfConfigurationTest.java +++ /dev/null @@ -1,121 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - - -package org.eclipse.jetty.webapp; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.anyOf; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.endsWith; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.List; - -import org.eclipse.jetty.util.JavaVersion; -import org.eclipse.jetty.util.resource.Resource; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledOnJre; -import org.junit.jupiter.api.condition.EnabledIfSystemProperty; -import org.junit.jupiter.api.condition.EnabledOnJre; -import org.junit.jupiter.api.condition.JRE; - -/** - * WebInfConfigurationTest - * - * - */ -public class WebInfConfigurationTest -{ - - /** - * Assume target < jdk9. In this case, we should be able to extract - * the urls from the application classloader, and we should not look - * at the java.class.path property. - * @throws Exception - */ - @Test - @EnabledOnJre(JRE.JAVA_8) - public void testFindAndFilterContainerPaths() - throws Exception - { - WebInfConfiguration config = new WebInfConfiguration(); - WebAppContext context = new WebAppContext(); - context.setAttribute(WebInfConfiguration.CONTAINER_JAR_PATTERN, ".*/jetty-util-[^/]*\\.jar$|.*/jetty-util/target/classes/"); - - WebAppClassLoader loader = new WebAppClassLoader(context); - context.setClassLoader(loader); - config.findAndFilterContainerPaths(context); - List containerResources = context.getMetaData().getContainerResources(); - assertEquals(1, containerResources.size()); - assertThat(containerResources.get(0).toString(), containsString("jetty-util")); - } - - /** - * Assume target jdk9 or above. In this case we should extract what we need - * from the java.class.path. We should also examine the module path. - * @throws Exception - */ - @Test - @DisabledOnJre(JRE.JAVA_8) - @EnabledIfSystemProperty(named="jdk.module.path", matches=".*") - public void testFindAndFilterContainerPathsJDK9() - throws Exception - { - WebInfConfiguration config = new WebInfConfiguration(); - WebAppContext context = new WebAppContext(); - context.setAttribute(WebInfConfiguration.CONTAINER_JAR_PATTERN, ".*/jetty-util-[^/]*\\.jar$|.*/jetty-util/target/classes/$|.*/foo-bar-janb.jar"); - WebAppClassLoader loader = new WebAppClassLoader(context); - context.setClassLoader(loader); - config.findAndFilterContainerPaths(context); - List containerResources = context.getMetaData().getContainerResources(); - assertEquals(2, containerResources.size()); - for (Resource r:containerResources) - { - String s = r.toString(); - assertThat(s, anyOf(endsWith("foo-bar-janb.jar"), containsString("jetty-util"))); - } - } - - - /** - * Assume runtime is jdk9 or above. Target is jdk 8. In this - * case we must extract from the java.class.path (because jdk 9 - * has no url based application classloader), but we should - * ignore the module path. - * @throws Exception - */ - @Test - @DisabledOnJre(JRE.JAVA_8) - @EnabledIfSystemProperty(named="jdk.module.path", matches=".*") - public void testFindAndFilterContainerPathsTarget8() - throws Exception - { - WebInfConfiguration config = new WebInfConfiguration(); - WebAppContext context = new WebAppContext(); - context.setAttribute(JavaVersion.JAVA_TARGET_PLATFORM, "8"); - context.setAttribute(WebInfConfiguration.CONTAINER_JAR_PATTERN, ".*/jetty-util-[^/]*\\.jar$|.*/jetty-util/target/classes/$|.*/foo-bar-janb.jar"); - WebAppClassLoader loader = new WebAppClassLoader(context); - context.setClassLoader(loader); - config.findAndFilterContainerPaths(context); - List containerResources = context.getMetaData().getContainerResources(); - assertEquals(1, containerResources.size()); - assertThat(containerResources.get(0).toString(), containsString("jetty-util")); - } - -} diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ClientCloseTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ClientCloseTest.java deleted file mode 100644 index e95cbd4f3c7..00000000000 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ClientCloseTest.java +++ /dev/null @@ -1,673 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.client; - - -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.anyOf; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.empty; - -import static java.time.Duration.ofSeconds; -import static org.hamcrest.MatcherAssert.assertThat; - -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; - - -import java.io.IOException; -import java.lang.reflect.Field; -import java.net.SocketTimeoutException; -import java.nio.ByteBuffer; -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; -import java.nio.channels.SocketChannel; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP; -import org.eclipse.jetty.io.EndPoint; -import org.eclipse.jetty.io.EofException; -import org.eclipse.jetty.io.ManagedSelector; -import org.eclipse.jetty.io.SelectorManager; -import org.eclipse.jetty.io.SocketChannelEndPoint; -import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.util.log.StacklessLogging; -import org.eclipse.jetty.util.thread.Scheduler; -import org.eclipse.jetty.websocket.api.ProtocolException; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.StatusCode; -import org.eclipse.jetty.websocket.api.WebSocketAdapter; -import org.eclipse.jetty.websocket.common.CloseInfo; -import org.eclipse.jetty.websocket.common.OpCode; -import org.eclipse.jetty.websocket.common.Parser; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.WebSocketSession; -import org.eclipse.jetty.websocket.common.frames.TextFrame; -import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection; -import org.eclipse.jetty.websocket.common.test.BlockheadConnection; -import org.eclipse.jetty.websocket.common.test.BlockheadServer; -import org.eclipse.jetty.websocket.common.test.RawFrameBuilder; -import org.eclipse.jetty.websocket.common.test.Timeouts; -import org.hamcrest.Matcher; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - - -public class ClientCloseTest -{ - private static final Logger LOG = Log.getLogger(ClientCloseTest.class); - - private static class CloseTrackingSocket extends WebSocketAdapter - { - private static final Logger LOG = ClientCloseTest.LOG.getLogger("CloseTrackingSocket"); - - public int closeCode = -1; - public String closeReason = null; - public CountDownLatch closeLatch = new CountDownLatch(1); - public AtomicInteger closeCount = new AtomicInteger(0); - public CountDownLatch openLatch = new CountDownLatch(1); - public CountDownLatch errorLatch = new CountDownLatch(1); - - public LinkedBlockingQueue messageQueue = new LinkedBlockingQueue<>(); - public AtomicReference error = new AtomicReference<>(); - - public void assertNoCloseEvent() - { - assertThat("Client Close Event",closeLatch.getCount(),is(1L)); - assertThat("Client Close Event Status Code ",closeCode,is(-1)); - } - - public void assertReceivedCloseEvent(int clientTimeoutMs, Matcher statusCodeMatcher, Matcher reasonMatcher) - throws InterruptedException - { - long maxTimeout = clientTimeoutMs * 4; - - assertThat("Client Close Event Occurred",closeLatch.await(maxTimeout,TimeUnit.MILLISECONDS),is(true)); - assertThat("Client Close Event Count",closeCount.get(),is(1)); - assertThat("Client Close Event Status Code",closeCode,statusCodeMatcher); - if (reasonMatcher == null) - { - assertThat("Client Close Event Reason",closeReason,nullValue()); - } - else - { - assertThat("Client Close Event Reason",closeReason,reasonMatcher); - } - } - - public void clearQueues() - { - messageQueue.clear(); - } - - @Override - public void onWebSocketClose(int statusCode, String reason) - { - LOG.debug("onWebSocketClose({},{})",statusCode,reason); - super.onWebSocketClose(statusCode,reason); - closeCount.incrementAndGet(); - closeCode = statusCode; - closeReason = reason; - closeLatch.countDown(); - } - - @Override - public void onWebSocketConnect(Session session) - { - LOG.debug("onWebSocketConnect({})",session); - super.onWebSocketConnect(session); - openLatch.countDown(); - } - - @Override - public void onWebSocketError(Throwable cause) - { - LOG.debug("onWebSocketError",cause); - assertThat("Unique Error Event", error.compareAndSet(null, cause), is(true)); - errorLatch.countDown(); - } - - @Override - public void onWebSocketText(String message) - { - LOG.debug("onWebSocketText({})",message); - messageQueue.offer(message); - } - - public EndPoint getEndPoint() throws Exception - { - Session session = getSession(); - assertThat("Session type",session,instanceOf(WebSocketSession.class)); - - WebSocketSession wssession = (WebSocketSession)session; - Field fld = wssession.getClass().getDeclaredField("connection"); - fld.setAccessible(true); - assertThat("Field: connection",fld,notNullValue()); - - Object val = fld.get(wssession); - assertThat("Connection type",val,instanceOf(AbstractWebSocketConnection.class)); - @SuppressWarnings("resource") - AbstractWebSocketConnection wsconn = (AbstractWebSocketConnection)val; - return wsconn.getEndPoint(); - } - } - - private static BlockheadServer server; - private WebSocketClient client; - - private void confirmConnection(CloseTrackingSocket clientSocket, Future clientFuture, BlockheadConnection serverConns) throws Exception - { - // Wait for client connect on via future - clientFuture.get(30,TimeUnit.SECONDS); - - // Wait for client connect via client websocket - assertThat("Client WebSocket is Open",clientSocket.openLatch.await(30,TimeUnit.SECONDS),is(true)); - - try - { - // Send message from client to server - final String echoMsg = "echo-test"; - Future testFut = clientSocket.getRemote().sendStringByFuture(echoMsg); - - // Wait for send future - testFut.get(Timeouts.SEND, Timeouts.SEND_UNIT); - - // Read Frame on server side - LinkedBlockingQueue serverCapture = serverConns.getFrameQueue(); - WebSocketFrame frame = serverCapture.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - assertThat("Server received frame",frame.getOpCode(),is(OpCode.TEXT)); - assertThat("Server received frame payload",frame.getPayloadAsUTF8(),is(echoMsg)); - - // Server send echo reply - serverConns.write(new TextFrame().setPayload(echoMsg)); - - // Verify received message - String recvMsg = clientSocket.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - assertThat("Received message",recvMsg,is(echoMsg)); - - // Verify that there are no errors - assertThat("Error events",clientSocket.error.get(),nullValue()); - } - finally - { - clientSocket.clearQueues(); - } - } - - private void confirmServerReceivedCloseFrame(BlockheadConnection serverConn, int expectedCloseCode, Matcher closeReasonMatcher) throws InterruptedException - { - LinkedBlockingQueue serverCapture = serverConn.getFrameQueue(); - WebSocketFrame frame = serverCapture.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - assertThat("Server close frame", frame, is(notNullValue())); - assertThat("Server received close frame",frame.getOpCode(),is(OpCode.CLOSE)); - CloseInfo closeInfo = new CloseInfo(frame); - assertThat("Server received close code",closeInfo.getStatusCode(),is(expectedCloseCode)); - if (closeReasonMatcher == null) - { - assertThat("Server received close reason",closeInfo.getReason(),nullValue()); - } - else - { - assertThat("Server received close reason",closeInfo.getReason(),closeReasonMatcher); - } - } - - public static class TestClientTransportOverHTTP extends HttpClientTransportOverHTTP - { - @Override - protected SelectorManager newSelectorManager(HttpClient client) - { - return new ClientSelectorManager(client, 1){ - @Override - protected EndPoint newEndPoint(SelectableChannel channel, ManagedSelector selector, SelectionKey key) - { - TestEndPoint endPoint = new TestEndPoint(channel,selector,key,getScheduler()); - endPoint.setIdleTimeout(client.getIdleTimeout()); - return endPoint; - } - }; - } - } - - public static class TestEndPoint extends SocketChannelEndPoint - { - public AtomicBoolean congestedFlush = new AtomicBoolean(false); - - public TestEndPoint(SelectableChannel channel, ManagedSelector selector, SelectionKey key, Scheduler scheduler) - { - super((SocketChannel)channel,selector,key,scheduler); - } - - @Override - public boolean flush(ByteBuffer... buffers) throws IOException - { - boolean flushed = super.flush(buffers); - congestedFlush.set(!flushed); - return flushed; - } - } - - @BeforeEach - public void startClient() throws Exception - { - HttpClient httpClient = new HttpClient(new TestClientTransportOverHTTP(), null); - client = new WebSocketClient(httpClient); - client.addBean(httpClient); - client.start(); - } - - @BeforeAll - public static void startServer() throws Exception - { - server = new BlockheadServer(); - server.start(); - } - - @AfterEach - public void stopClient() throws Exception - { - client.stop(); - } - - @AfterAll - public static void stopServer() throws Exception - { - server.stop(); - } - - @Test - public void testHalfClose() throws Exception - { - // Set client timeout - final int timeout = 5000; - client.setMaxIdleTimeout(timeout); - - // Hook into server connection creation - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - // Client connects - CloseTrackingSocket clientSocket = new CloseTrackingSocket(); - Future clientConnectFuture = client.connect(clientSocket,server.getWsUri()); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - // client confirms connection via echo - confirmConnection(clientSocket, clientConnectFuture, serverConn); - - // client sends close frame (code 1000, normal) - final String origCloseReason = "Normal Close"; - clientSocket.getSession().close(StatusCode.NORMAL, origCloseReason); - - // server receives close frame - confirmServerReceivedCloseFrame(serverConn, StatusCode.NORMAL, is(origCloseReason)); - - // server sends 2 messages - serverConn.write(new TextFrame().setPayload("Hello")); - serverConn.write(new TextFrame().setPayload("World")); - - // server sends close frame (code 1000, no reason) - CloseInfo sclose = new CloseInfo(StatusCode.NORMAL, "From Server"); - serverConn.write(sclose.asFrame()); - - // Verify received messages - String recvMsg = clientSocket.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - assertThat("Received message 1", recvMsg, is("Hello")); - recvMsg = clientSocket.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - assertThat("Received message 2", recvMsg, is("World")); - - // Verify that there are no errors - assertThat("Error events", clientSocket.error.get(), nullValue()); - - // client close event on ws-endpoint - clientSocket.assertReceivedCloseEvent(timeout, is(StatusCode.NORMAL), containsString("From Server")); - } - - assertThat("Client Open Sessions", client.getOpenSessions(), empty()); - } - - @Disabled("Need sbordet's help here") - @Test - public void testNetworkCongestion() throws Exception - { - // Set client timeout - final int timeout = 1000; - client.setMaxIdleTimeout(timeout); - - // Hook into server connection creation - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - // Client connects - CloseTrackingSocket clientSocket = new CloseTrackingSocket(); - Future clientConnectFuture = client.connect(clientSocket,server.getWsUri()); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - // client confirms connection via echo - confirmConnection(clientSocket, clientConnectFuture, serverConn); - - // client sends BIG frames (until it cannot write anymore) - // server must not read (for test purpose, in order to congest connection) - // when write is congested, client enqueue close frame - // client initiate write, but write never completes - EndPoint endp = clientSocket.getEndPoint(); - assertThat("EndPoint is testable", endp, instanceOf(TestEndPoint.class)); - TestEndPoint testendp = (TestEndPoint) endp; - - char msg[] = new char[10240]; - int writeCount = 0; - long writeSize = 0; - int i = 0; - while (!testendp.congestedFlush.get()) - { - int z = i - ((i / 26) * 26); - char c = (char) ('a' + z); - Arrays.fill(msg, c); - clientSocket.getRemote().sendStringByFuture(String.valueOf(msg)); - writeCount++; - writeSize += msg.length; - } - LOG.info("Wrote {} frames totalling {} bytes of payload before congestion kicked in", writeCount, writeSize); - - // Verify timeout error - assertThat("OnError Latch", clientSocket.errorLatch.await(2, TimeUnit.SECONDS), is(true)); - assertThat("OnError", clientSocket.error.get(), instanceOf(SocketTimeoutException.class)); - } - } - - @Test - public void testProtocolException() throws Exception - { - // Set client timeout - final int timeout = 1000; - client.setMaxIdleTimeout(timeout); - - // Hook into server connection creation - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - // Client connects - CloseTrackingSocket clientSocket = new CloseTrackingSocket(); - Future clientConnectFuture = client.connect(clientSocket,server.getWsUri()); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - // client confirms connection via echo - confirmConnection(clientSocket, clientConnectFuture, serverConn); - - // client should not have received close message (yet) - clientSocket.assertNoCloseEvent(); - - // server sends bad close frame (too big of a reason message) - byte msg[] = new byte[400]; - Arrays.fill(msg, (byte) 'x'); - ByteBuffer bad = ByteBuffer.allocate(500); - RawFrameBuilder.putOpFin(bad, OpCode.CLOSE, true); - RawFrameBuilder.putLength(bad, msg.length + 2, false); - bad.putShort((short) StatusCode.NORMAL); - bad.put(msg); - BufferUtil.flipToFlush(bad, 0); - - try (StacklessLogging ignore = new StacklessLogging(Parser.class)) - { - serverConn.writeRaw(bad); - - // client should have noticed the error - assertThat("OnError Latch", clientSocket.errorLatch.await(2, TimeUnit.SECONDS), is(true)); - assertThat("OnError", clientSocket.error.get(), instanceOf(ProtocolException.class)); - assertThat("OnError", clientSocket.error.get().getMessage(), containsString("Invalid control frame")); - - // client parse invalid frame, notifies server of close (protocol error) - confirmServerReceivedCloseFrame(serverConn, StatusCode.PROTOCOL, allOf(containsString("Invalid control frame"), containsString("length"))); - } - } - - // client triggers close event on client ws-endpoint - clientSocket.assertReceivedCloseEvent(timeout,is(StatusCode.PROTOCOL),allOf(containsString("Invalid control frame"),containsString("length"))); - assertThat("Client Open Sessions", client.getOpenSessions(), empty()); - } - - @Test - public void testReadEOF() throws Exception - { - // Set client timeout - final int timeout = 1000; - client.setMaxIdleTimeout(timeout); - - // Hook into server connection creation - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - // Client connects - CloseTrackingSocket clientSocket = new CloseTrackingSocket(); - Future clientConnectFuture = client.connect(clientSocket,server.getWsUri()); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - // client confirms connection via echo - confirmConnection(clientSocket, clientConnectFuture, serverConn); - - // client sends close frame - final String origCloseReason = "Normal Close"; - clientSocket.getSession().close(StatusCode.NORMAL, origCloseReason); - - // server receives close frame - confirmServerReceivedCloseFrame(serverConn, StatusCode.NORMAL, is(origCloseReason)); - - // client should not have received close message (yet) - clientSocket.assertNoCloseEvent(); - - // server shuts down connection (no frame reply) - serverConn.abort(); - - // client reads -1 (EOF) - // client triggers close event on client ws-endpoint - clientSocket.assertReceivedCloseEvent(timeout, is(StatusCode.ABNORMAL), - anyOf( - containsString("EOF"), - containsString("Disconnected") - )); - } - assertThat("Client Open Sessions", client.getOpenSessions(), empty()); - } - - @Test - public void testServerNoCloseHandshake() throws Exception - { - // Set client timeout - final int timeout = 1000; - client.setMaxIdleTimeout(timeout); - - // Hook into server connection creation - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - // Client connects - CloseTrackingSocket clientSocket = new CloseTrackingSocket(); - Future clientConnectFuture = client.connect(clientSocket,server.getWsUri()); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - // client confirms connection via echo - confirmConnection(clientSocket, clientConnectFuture, serverConn); - - // client sends close frame - final String origCloseReason = "Normal Close"; - clientSocket.getSession().close(StatusCode.NORMAL, origCloseReason); - - // server receives close frame - confirmServerReceivedCloseFrame(serverConn, StatusCode.NORMAL, is(origCloseReason)); - - // client should not have received close message (yet) - clientSocket.assertNoCloseEvent(); - - // server never sends close frame handshake - // server sits idle - - // client idle timeout triggers close event on client ws-endpoint - assertThat("OnError Latch", clientSocket.errorLatch.await(2, TimeUnit.SECONDS), is(true)); - assertThat("OnError", clientSocket.error.get(), instanceOf(TimeoutException.class)); - - // client close should occur - clientSocket.assertReceivedCloseEvent(timeout, is(StatusCode.ABNORMAL), - anyOf( - containsString("Timeout"), - containsString("Disconnected") - )); - } - assertThat("Client Open Sessions", client.getOpenSessions(), empty()); - } - - @Test - public void testStopLifecycle() throws Exception - { - // Set client timeout - final int timeout = 1000; - client.setMaxIdleTimeout(timeout); - - int clientCount = 3; - List clientSockets = new ArrayList<>(); - List> serverConnFuts = new ArrayList<>(); - List serverConns = new ArrayList<>(); - - try - { - assertTimeoutPreemptively(ofSeconds(5), ()-> { - // Open Multiple Clients - for (int i = 0; i < clientCount; i++) - { - // Client Request Upgrade - CloseTrackingSocket clientSocket = new CloseTrackingSocket(); - clientSockets.add(clientSocket); - Future clientConnectFuture = client.connect(clientSocket, server.getWsUri()); - - // Server accepts connection - CompletableFuture serverConnFut = new CompletableFuture<>(); - serverConnFuts.add(serverConnFut); - server.addConnectFuture(serverConnFut); - BlockheadConnection serverConn = serverConnFut.get(); - serverConns.add(serverConn); - - // client confirms connection via echo - confirmConnection(clientSocket, clientConnectFuture, serverConn); - } - - // client lifecycle stop (the meat of this test) - client.stop(); - - // clients send close frames (code 1001, shutdown) - for (int i = 0; i < clientCount; i++) - { - // server receives close frame - confirmServerReceivedCloseFrame(serverConns.get(i), StatusCode.SHUTDOWN, containsString("Shutdown")); - } - - // clients disconnect - for (int i = 0; i < clientCount; i++) - { - clientSockets.get(i).assertReceivedCloseEvent(timeout, is(StatusCode.SHUTDOWN), containsString("Shutdown")); - } - assertThat("Client Open Sessions", client.getOpenSessions(), empty()); - - // clients disconnect - for (int i = 0; i < clientCount; i++) - { - clientSockets.get(i).assertReceivedCloseEvent(timeout, is(StatusCode.SHUTDOWN), containsString("Shutdown")); - } - }); - - } - finally - { - for(BlockheadConnection serverConn: serverConns) - { - try - { - serverConn.close(); - } - catch (Exception ignore) - { - } - } - } - } - - @Test - public void testWriteException() throws Exception - { - // Set client timeout - final int timeout = 1000; - client.setMaxIdleTimeout(timeout); - - // Hook into server connection creation - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - // Client connects - CloseTrackingSocket clientSocket = new CloseTrackingSocket(); - Future clientConnectFuture = client.connect(clientSocket,server.getWsUri()); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - // client confirms connection via echo - confirmConnection(clientSocket, clientConnectFuture, serverConn); - - // setup client endpoint for write failure (test only) - EndPoint endp = clientSocket.getEndPoint(); - endp.shutdownOutput(); - - // client enqueue close frame - // client write failure - final String origCloseReason = "Normal Close"; - clientSocket.getSession().close(StatusCode.NORMAL, origCloseReason); - - assertThat("OnError Latch", clientSocket.errorLatch.await(2, TimeUnit.SECONDS), is(true)); - assertThat("OnError", clientSocket.error.get(), instanceOf(EofException.class)); - - // client triggers close event on client ws-endpoint - // assert - close code==1006 (abnormal) - // assert - close reason message contains (write failure) - clientSocket.assertReceivedCloseEvent(timeout, is(StatusCode.ABNORMAL), containsString("EOF")); - } - assertThat("Client Open Sessions", client.getOpenSessions(), empty()); - } -} diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ClientConnectTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ClientConnectTest.java deleted file mode 100644 index 14f894a40ef..00000000000 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ClientConnectTest.java +++ /dev/null @@ -1,463 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.client; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.anyOf; -import static org.hamcrest.Matchers.greaterThanOrEqualTo; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.fail; - -import java.net.ConnectException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.SocketTimeoutException; -import java.net.URI; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -import javax.servlet.http.HttpServletResponse; - -import org.eclipse.jetty.client.HttpClient; -import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpHeader; -import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.io.MappedByteBufferPool; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.UpgradeException; -import org.eclipse.jetty.websocket.common.AcceptHash; -import org.eclipse.jetty.websocket.common.test.BlockheadConnection; -import org.eclipse.jetty.websocket.common.test.BlockheadServer; -import org.eclipse.jetty.websocket.common.test.Timeouts; -import org.hamcrest.Matcher; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -/** - * Various connect condition testing - */ -@SuppressWarnings("Duplicates") -public class ClientConnectTest -{ - public ByteBufferPool bufferPool = new MappedByteBufferPool(); - - private static BlockheadServer server; - private WebSocketClient client; - - @SuppressWarnings("unchecked") - private E assertExpectedError(ExecutionException e, JettyTrackingSocket wsocket, Matcher errorMatcher) - { - // Validate thrown cause - Throwable cause = e.getCause(); - - assertThat("ExecutionException.cause",cause,errorMatcher); - - // Validate websocket captured cause - assertThat("Error Queue Length",wsocket.errorQueue.size(),greaterThanOrEqualTo(1)); - Throwable capcause = wsocket.errorQueue.poll(); - assertThat("Error Queue[0]",capcause,notNullValue()); - assertThat("Error Queue[0]",capcause,errorMatcher); - - // Validate that websocket didn't see an open event - wsocket.assertNotOpened(); - - // Return the captured cause - return (E)capcause; - } - - @BeforeEach - public void startClient() throws Exception - { - client = new WebSocketClient(); - client.setBufferPool(bufferPool); - client.setConnectTimeout(Timeouts.CONNECT_UNIT.toMillis(Timeouts.CONNECT)); - client.start(); - } - - @BeforeAll - public static void startServer() throws Exception - { - server = new BlockheadServer(); - server.start(); - } - - @BeforeEach - public void resetServerHandler() - { - // for each test, reset the server request handling to default - server.resetRequestHandling(); - } - - @AfterEach - public void stopClient() throws Exception - { - client.stop(); - } - - @AfterAll - public static void stopServer() throws Exception - { - server.stop(); - } - - @Test - public void testUpgradeRequest() throws Exception - { - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - - URI wsUri = server.getWsUri(); - Future future = client.connect(wsocket,wsUri); - - Session sess = future.get(30,TimeUnit.SECONDS); - - wsocket.waitForConnected(); - - assertThat("Connect.UpgradeRequest", wsocket.connectUpgradeRequest, notNullValue()); - assertThat("Connect.UpgradeResponse", wsocket.connectUpgradeResponse, notNullValue()); - - sess.close(); - } - - @Test - public void testAltConnect() throws Exception - { - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - URI wsUri = server.getWsUri(); - - HttpClient httpClient = new HttpClient(); - try - { - httpClient.start(); - - WebSocketUpgradeRequest req = new WebSocketUpgradeRequest(new WebSocketClient(), httpClient, wsUri, wsocket); - req.header("X-Foo", "Req"); - CompletableFuture sess = req.sendAsync(); - - sess.thenAccept((s) -> { - System.out.printf("Session: %s%n", s); - s.close(); - assertThat("Connect.UpgradeRequest", wsocket.connectUpgradeRequest, notNullValue()); - assertThat("Connect.UpgradeResponse", wsocket.connectUpgradeResponse, notNullValue()); - }); - } - finally - { - httpClient.stop(); - } - } - - @Test - public void testUpgradeWithAuthorizationHeader() throws Exception - { - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - - // Hook into server connection creation - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - URI wsUri = server.getWsUri(); - ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest(); - // actual value for this test is irrelevant, its important that this - // header actually be sent with a value (the value specified) - upgradeRequest.setHeader("Authorization", "Basic YWxhZGRpbjpvcGVuc2VzYW1l"); - Future future = client.connect(wsocket,wsUri,upgradeRequest); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - HttpFields upgradeRequestHeaders = serverConn.getUpgradeRequestHeaders(); - - Session sess = future.get(30, TimeUnit.SECONDS); - - HttpField authHeader = upgradeRequestHeaders.getField(HttpHeader.AUTHORIZATION); - assertThat("Server Request Authorization Header", authHeader, is(notNullValue())); - assertThat("Server Request Authorization Value", authHeader.getValue(), is("Basic YWxhZGRpbjpvcGVuc2VzYW1l")); - assertThat("Connect.UpgradeRequest", wsocket.connectUpgradeRequest, notNullValue()); - assertThat("Connect.UpgradeResponse", wsocket.connectUpgradeResponse, notNullValue()); - - sess.close(); - } - } - - @Test - public void testBadHandshake() throws Exception - { - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - - // Force 404 response, no upgrade for this test - server.setRequestHandling((req, resp) -> { - resp.setStatus(HttpServletResponse.SC_NOT_FOUND); - return true; - }); - - URI wsUri = server.getWsUri(); - Future future = client.connect(wsocket,wsUri); - - // The attempt to get upgrade response future should throw error - ExecutionException e = assertThrows(ExecutionException.class, - ()-> future.get(30,TimeUnit.SECONDS)); - - UpgradeException ue = assertExpectedError(e,wsocket,instanceOf(UpgradeException.class)); - assertThat("UpgradeException.requestURI",ue.getRequestURI(),notNullValue()); - assertThat("UpgradeException.requestURI",ue.getRequestURI().toASCIIString(),is(wsUri.toASCIIString())); - assertThat("UpgradeException.responseStatusCode",ue.getResponseStatusCode(),is(404)); - } - - @Test - public void testBadHandshake_GetOK() throws Exception - { - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - - // Force 200 response, no response body content, no upgrade for this test - server.setRequestHandling((req, resp) -> { - resp.setStatus(HttpServletResponse.SC_OK); - return true; - }); - - URI wsUri = server.getWsUri(); - Future future = client.connect(wsocket,wsUri); - - // The attempt to get upgrade response future should throw error - ExecutionException e = assertThrows(ExecutionException.class, - ()-> future.get(30,TimeUnit.SECONDS)); - - UpgradeException ue = assertExpectedError(e,wsocket,instanceOf(UpgradeException.class)); - assertThat("UpgradeException.requestURI",ue.getRequestURI(),notNullValue()); - assertThat("UpgradeException.requestURI",ue.getRequestURI().toASCIIString(),is(wsUri.toASCIIString())); - assertThat("UpgradeException.responseStatusCode",ue.getResponseStatusCode(),is(200)); - } - - @Test - public void testBadHandshake_GetOK_WithSecWebSocketAccept() throws Exception - { - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - - // Force 200 response, no response body content, incomplete websocket response headers, no actual upgrade for this test - server.setRequestHandling((req, resp) -> { - String key = req.getHeader(HttpHeader.SEC_WEBSOCKET_KEY.toString()); - resp.setStatus(HttpServletResponse.SC_OK); - resp.setHeader(HttpHeader.SEC_WEBSOCKET_ACCEPT.toString(), AcceptHash.hashKey(key)); - return true; - }); - - URI wsUri = server.getWsUri(); - Future future = client.connect(wsocket,wsUri); - - // The attempt to get upgrade response future should throw error - ExecutionException e = assertThrows(ExecutionException.class, - ()-> future.get(30,TimeUnit.SECONDS)); - - UpgradeException ue = assertExpectedError(e,wsocket,instanceOf(UpgradeException.class)); - assertThat("UpgradeException.requestURI",ue.getRequestURI(),notNullValue()); - assertThat("UpgradeException.requestURI",ue.getRequestURI().toASCIIString(),is(wsUri.toASCIIString())); - assertThat("UpgradeException.responseStatusCode",ue.getResponseStatusCode(),is(200)); - } - - @Test - public void testBadHandshake_SwitchingProtocols_InvalidConnectionHeader() throws Exception - { - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - - // Force 101 response, with invalid Connection header, invalid handshake - server.setRequestHandling((req, resp) -> { - String key = req.getHeader(HttpHeader.SEC_WEBSOCKET_KEY.toString()); - resp.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS); - resp.setHeader(HttpHeader.CONNECTION.toString(), "close"); - resp.setHeader(HttpHeader.SEC_WEBSOCKET_ACCEPT.toString(), AcceptHash.hashKey(key)); - return true; - }); - - URI wsUri = server.getWsUri(); - Future future = client.connect(wsocket,wsUri); - - // The attempt to get upgrade response future should throw error - ExecutionException e = assertThrows(ExecutionException.class, - ()-> future.get(30,TimeUnit.SECONDS)); - - UpgradeException ue = assertExpectedError(e,wsocket,instanceOf(UpgradeException.class)); - assertThat("UpgradeException.requestURI",ue.getRequestURI(),notNullValue()); - assertThat("UpgradeException.requestURI",ue.getRequestURI().toASCIIString(),is(wsUri.toASCIIString())); - assertThat("UpgradeException.responseStatusCode",ue.getResponseStatusCode(),is(101)); - } - - @Test - public void testBadHandshake_SwitchingProtocols_NoConnectionHeader() throws Exception - { - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - - // Force 101 response, with no Connection header, invalid handshake - server.setRequestHandling((req, resp) -> { - String key = req.getHeader(HttpHeader.SEC_WEBSOCKET_KEY.toString()); - resp.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS); - // Intentionally leave out Connection header - resp.setHeader(HttpHeader.SEC_WEBSOCKET_ACCEPT.toString(), AcceptHash.hashKey(key)); - return true; - }); - - URI wsUri = server.getWsUri(); - Future future = client.connect(wsocket,wsUri); - - // The attempt to get upgrade response future should throw error - ExecutionException e = assertThrows(ExecutionException.class, - ()-> future.get(30,TimeUnit.SECONDS)); - - UpgradeException ue = assertExpectedError(e,wsocket,instanceOf(UpgradeException.class)); - assertThat("UpgradeException.requestURI",ue.getRequestURI(),notNullValue()); - assertThat("UpgradeException.requestURI",ue.getRequestURI().toASCIIString(),is(wsUri.toASCIIString())); - assertThat("UpgradeException.responseStatusCode",ue.getResponseStatusCode(),is(101)); - } - - @Test - public void testBadUpgrade() throws Exception - { - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - - // Force 101 response, with invalid response accept header - server.setRequestHandling((req, resp) -> { - resp.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS); - resp.setHeader(HttpHeader.SEC_WEBSOCKET_ACCEPT.toString(), "rubbish"); - return true; - }); - - URI wsUri = server.getWsUri(); - Future future = client.connect(wsocket,wsUri); - - // The attempt to get upgrade response future should throw error - ExecutionException e = assertThrows(ExecutionException.class, - ()-> future.get(30,TimeUnit.SECONDS)); - - UpgradeException ue = assertExpectedError(e,wsocket,instanceOf(UpgradeException.class)); - assertThat("UpgradeException.requestURI",ue.getRequestURI(),notNullValue()); - assertThat("UpgradeException.requestURI",ue.getRequestURI().toASCIIString(),is(wsUri.toASCIIString())); - assertThat("UpgradeException.responseStatusCode",ue.getResponseStatusCode(),is(101)); - } - - @Test - public void testConnectionNotAccepted() throws Exception - { - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - - try(ServerSocket serverSocket = new ServerSocket()) - { - InetAddress addr = InetAddress.getByName("localhost"); - InetSocketAddress endpoint = new InetSocketAddress(addr, 0); - serverSocket.bind(endpoint, 1); - int port = serverSocket.getLocalPort(); - URI wsUri = URI.create(String.format("ws://%s:%d/", addr.getHostAddress(), port)); - Future future = client.connect(wsocket, wsUri); - - // Intentionally not accept incoming socket. - // serverSocket.accept(); - - try - { - future.get(3, TimeUnit.SECONDS); - fail("Should have Timed Out"); - } - catch (ExecutionException e) - { - assertExpectedError(e, wsocket, instanceOf(UpgradeException.class)); - // Possible Passing Path (active session wait timeout) - wsocket.assertNotOpened(); - } - catch (TimeoutException e) - { - // Possible Passing Path (concurrency timeout) - wsocket.assertNotOpened(); - } - } - } - - @Test - public void testConnectionRefused() throws Exception - { - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - - // Intentionally bad port with nothing listening on it - URI wsUri = new URI("ws://127.0.0.1:1"); - - try - { - Future future = client.connect(wsocket,wsUri); - - // The attempt to get upgrade response future should throw error - future.get(3,TimeUnit.SECONDS); - fail("Expected ExecutionException -> ConnectException"); - } - catch (ConnectException e) - { - Throwable t = wsocket.errorQueue.remove(); - assertThat("Error Queue[0]",t,instanceOf(ConnectException.class)); - wsocket.assertNotOpened(); - } - catch (ExecutionException e) - { - assertExpectedError(e, wsocket, - anyOf( - instanceOf(UpgradeException.class), - instanceOf(SocketTimeoutException.class), - instanceOf(ConnectException.class))); - } - } - - @Test - public void testConnectionTimeout_Concurrent() throws Exception - { - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - - try(ServerSocket serverSocket = new ServerSocket()) - { - InetAddress addr = InetAddress.getByName("localhost"); - InetSocketAddress endpoint = new InetSocketAddress(addr, 0); - serverSocket.bind(endpoint, 1); - int port = serverSocket.getLocalPort(); - URI wsUri = URI.create(String.format("ws://%s:%d/", addr.getHostAddress(), port)); - Future future = client.connect(wsocket, wsUri); - - // Accept the connection, but do nothing on it (no response, no upgrade, etc) - serverSocket.accept(); - - // The attempt to get upgrade response future should throw error - Exception e = assertThrows(Exception.class, - ()-> future.get(3, TimeUnit.SECONDS)); - - if (e instanceof ExecutionException) - { - assertExpectedError((ExecutionException) e, wsocket, anyOf( - instanceOf(ConnectException.class), - instanceOf(UpgradeException.class) - )); - } - else - { - assertThat("Should have been a TimeoutException", e, instanceOf(TimeoutException.class)); - } - } - } -} diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ConnectionManagerTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ConnectionManagerTest.java deleted file mode 100644 index 0c5a4ae73cb..00000000000 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ConnectionManagerTest.java +++ /dev/null @@ -1,78 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.client; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; - -import java.net.InetSocketAddress; -import java.net.URI; -import java.net.URISyntaxException; - -import org.eclipse.jetty.websocket.client.io.ConnectionManager; - -import org.junit.jupiter.api.Test; - -public class ConnectionManagerTest -{ - private void assertToSocketAddress(String uriStr, String expectedHost, int expectedPort) throws URISyntaxException - { - URI uri = new URI(uriStr); - - InetSocketAddress addr = ConnectionManager.toSocketAddress(uri); - assertThat("URI (" + uri + ").host",addr.getHostName(),is(expectedHost)); - assertThat("URI (" + uri + ").port",addr.getPort(),is(expectedPort)); - } - - @Test - public void testToSocketAddress_AltWsPort() throws Exception - { - assertToSocketAddress("ws://localhost:8099","localhost",8099); - } - - @Test - public void testToSocketAddress_AltWssPort() throws Exception - { - assertToSocketAddress("wss://localhost","localhost",443); - } - - @Test - public void testToSocketAddress_DefaultWsPort() throws Exception - { - assertToSocketAddress("ws://localhost","localhost",80); - } - - @Test - public void testToSocketAddress_DefaultWsPort_Path() throws Exception - { - assertToSocketAddress("ws://localhost/sockets/chat","localhost",80); - } - - @Test - public void testToSocketAddress_DefaultWssPort() throws Exception - { - assertToSocketAddress("wss://localhost:9443","localhost",9443); - } - - @Test - public void testToSocketAddress_DefaultWssPort_Path() throws Exception - { - assertToSocketAddress("wss://localhost/sockets/chat","localhost",443); - } -} diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/CookieTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/CookieTest.java deleted file mode 100644 index d869d88ce8e..00000000000 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/CookieTest.java +++ /dev/null @@ -1,212 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.client; - -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.net.CookieManager; -import java.net.HttpCookie; -import java.util.Collections; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - -import org.eclipse.jetty.http.HttpField; -import org.eclipse.jetty.http.HttpFields; -import org.eclipse.jetty.http.HttpHeader; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.StatusCode; -import org.eclipse.jetty.websocket.api.WebSocketAdapter; -import org.eclipse.jetty.websocket.common.CloseInfo; -import org.eclipse.jetty.websocket.common.frames.TextFrame; -import org.eclipse.jetty.websocket.common.test.BlockheadConnection; -import org.eclipse.jetty.websocket.common.test.BlockheadServer; -import org.eclipse.jetty.websocket.common.test.Timeouts; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.AfterAll; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -public class CookieTest -{ - private static final Logger LOG = Log.getLogger(CookieTest.class); - - public static class CookieTrackingSocket extends WebSocketAdapter - { - public LinkedBlockingQueue messageQueue = new LinkedBlockingQueue<>(); - public LinkedBlockingQueue errorQueue = new LinkedBlockingQueue<>(); - private CountDownLatch openLatch = new CountDownLatch(1); - - @Override - public void onWebSocketConnect(Session sess) - { - openLatch.countDown(); - super.onWebSocketConnect(sess); - } - - @Override - public void onWebSocketText(String message) - { - System.err.printf("onTEXT - %s%n",message); - messageQueue.add(message); - } - - @Override - public void onWebSocketError(Throwable cause) - { - System.err.printf("onERROR - %s%n",cause); - errorQueue.add(cause); - } - - public void awaitOpen(int duration, TimeUnit unit) throws InterruptedException - { - assertTrue(openLatch.await(duration,unit), "Open Latch"); - } - } - - private static BlockheadServer server; - private WebSocketClient client; - - @BeforeEach - public void startClient() throws Exception - { - client = new WebSocketClient(); - client.start(); - } - - @BeforeAll - public static void startServer() throws Exception - { - server = new BlockheadServer(); - server.start(); - } - - @AfterEach - public void stopClient() throws Exception - { - if (client.isRunning()) - { - client.stop(); - } - } - - @AfterAll - public static void stopServer() throws Exception - { - server.stop(); - } - - @Test - public void testViaCookieManager() throws Exception - { - // Setup client - CookieManager cookieMgr = new CookieManager(); - client.setCookieStore(cookieMgr.getCookieStore()); - HttpCookie cookie = new HttpCookie("hello","world"); - cookie.setPath("/"); - cookie.setVersion(0); - cookie.setMaxAge(100000); - cookieMgr.getCookieStore().add(server.getWsUri(),cookie); - - cookie = new HttpCookie("foo","bar is the word"); - cookie.setPath("/"); - cookie.setMaxAge(100000); - cookieMgr.getCookieStore().add(server.getWsUri(),cookie); - - // Hook into server connection creation - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - // Client connects - CookieTrackingSocket clientSocket = new CookieTrackingSocket(); - Future clientConnectFuture = client.connect(clientSocket,server.getWsUri()); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - // client confirms upgrade and receipt of frame - String serverCookies = confirmClientUpgradeAndCookies(clientSocket, clientConnectFuture, serverConn); - - assertThat("Cookies seen at server side", serverCookies, containsString("hello=world")); - assertThat("Cookies seen at server side", serverCookies, containsString("foo=bar is the word")); - } - } - - @Test - public void testViaServletUpgradeRequest() throws Exception - { - // Setup client - HttpCookie cookie = new HttpCookie("hello","world"); - cookie.setPath("/"); - cookie.setMaxAge(100000); - - ClientUpgradeRequest request = new ClientUpgradeRequest(); - request.setCookies(Collections.singletonList(cookie)); - - // Hook into server connection creation - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - // Client connects - CookieTrackingSocket clientSocket = new CookieTrackingSocket(); - Future clientConnectFuture = client.connect(clientSocket,server.getWsUri(),request); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - // client confirms upgrade and receipt of frame - String serverCookies = confirmClientUpgradeAndCookies(clientSocket, clientConnectFuture, serverConn); - - assertThat("Cookies seen at server side", serverCookies, containsString("hello=world")); - } - } - - private String confirmClientUpgradeAndCookies(CookieTrackingSocket clientSocket, Future clientConnectFuture, BlockheadConnection serverConn) - throws Exception - { - // Server side upgrade information - HttpFields upgradeRequestHeaders = serverConn.getUpgradeRequestHeaders(); - HttpField cookieField = upgradeRequestHeaders.getField(HttpHeader.COOKIE); - - // Server responds with cookies it knows about - TextFrame serverCookieFrame = new TextFrame(); - serverCookieFrame.setFin(true); - serverCookieFrame.setPayload(cookieField.getValue()); - serverConn.write(serverCookieFrame); - - // Confirm client connect on future - clientConnectFuture.get(10,TimeUnit.SECONDS); - clientSocket.awaitOpen(2,TimeUnit.SECONDS); - - // Wait for client receipt of cookie frame via client websocket - String cookies = clientSocket.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - LOG.debug("Cookies seen at server: {}",cookies); - - // Server closes connection - serverConn.write(new CloseInfo(StatusCode.NORMAL).asFrame()); - - return cookies; - } -} diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/JettyTrackingSocket.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/JettyTrackingSocket.java deleted file mode 100644 index 246010401bb..00000000000 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/JettyTrackingSocket.java +++ /dev/null @@ -1,178 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.client; - -import static org.hamcrest.Matchers.greaterThanOrEqualTo; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Exchanger; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.UpgradeRequest; -import org.eclipse.jetty.websocket.api.UpgradeResponse; -import org.eclipse.jetty.websocket.api.WebSocketAdapter; -import org.eclipse.jetty.websocket.common.test.Timeouts; - - -/** - * Testing Socket used on client side WebSocket testing. - */ -public class JettyTrackingSocket extends WebSocketAdapter -{ - private static final Logger LOG = Log.getLogger(JettyTrackingSocket.class); - - public int closeCode = -1; - public Exchanger messageExchanger; - public UpgradeRequest connectUpgradeRequest; - public UpgradeResponse connectUpgradeResponse; - public StringBuilder closeMessage = new StringBuilder(); - public CountDownLatch openLatch = new CountDownLatch(1); - public CountDownLatch closeLatch = new CountDownLatch(1); - public CountDownLatch dataLatch = new CountDownLatch(1); - public LinkedBlockingQueue messageQueue = new LinkedBlockingQueue<>(); - public LinkedBlockingQueue errorQueue = new LinkedBlockingQueue<>(); - - public void assertClose(int expectedStatusCode, String expectedReason) throws InterruptedException - { - assertCloseCode(expectedStatusCode); - assertCloseReason(expectedReason); - } - - public void assertCloseCode(int expectedCode) throws InterruptedException - { - assertThat("Was Closed",closeLatch.await(50,TimeUnit.MILLISECONDS),is(true)); - assertThat("Close Code / Received [" + closeMessage + "]",closeCode,is(expectedCode)); - } - - private void assertCloseReason(String expectedReason) - { - assertThat("Close Reason",closeMessage.toString(),is(expectedReason)); - } - - public void assertIsOpen() throws InterruptedException - { - assertWasOpened(); - assertNotClosed(); - } - - public void assertNotClosed() - { - LOG.debug("assertNotClosed() - {}", closeLatch.getCount()); - assertThat("Closed Latch",closeLatch.getCount(),greaterThanOrEqualTo(1L)); - } - - public void assertNotOpened() - { - LOG.debug("assertNotOpened() - {}", openLatch.getCount()); - assertThat("Open Latch",openLatch.getCount(),greaterThanOrEqualTo(1L)); - } - - public void assertWasOpened() throws InterruptedException - { - LOG.debug("assertWasOpened() - {}", openLatch.getCount()); - assertThat("Was Opened",openLatch.await(30,TimeUnit.SECONDS),is(true)); - } - - public void clear() - { - messageQueue.clear(); - } - - @Override - public void onWebSocketBinary(byte[] payload, int offset, int len) - { - LOG.debug("onWebSocketBinary()"); - dataLatch.countDown(); - } - - @Override - public void onWebSocketClose(int statusCode, String reason) - { - LOG.debug("onWebSocketClose({},{})",statusCode,reason); - super.onWebSocketClose(statusCode,reason); - closeCode = statusCode; - closeMessage.append(reason); - closeLatch.countDown(); - } - - @Override - public void onWebSocketConnect(Session session) - { - super.onWebSocketConnect(session); - assertThat("Session", session, notNullValue()); - connectUpgradeRequest = session.getUpgradeRequest(); - connectUpgradeResponse = session.getUpgradeResponse(); - openLatch.countDown(); - } - - @Override - public void onWebSocketError(Throwable cause) - { - LOG.debug("onWebSocketError",cause); - assertThat("Error capture",errorQueue.offer(cause),is(true)); - } - - @Override - public void onWebSocketText(String message) - { - LOG.debug("onWebSocketText({})",message); - messageQueue.offer(message); - dataLatch.countDown(); - - if (messageExchanger != null) - { - try - { - messageExchanger.exchange(message); - } - catch (InterruptedException e) - { - LOG.debug(e); - } - } - } - - public void waitForClose(int timeoutDuration, TimeUnit timeoutUnit) throws InterruptedException - { - assertThat("Client Socket Closed",closeLatch.await(timeoutDuration,timeoutUnit),is(true)); - } - - public void waitForConnected() throws InterruptedException - { - assertThat("Client Socket Connected",openLatch.await(Timeouts.CONNECT,Timeouts.CONNECT_UNIT),is(true)); - } - - public void waitForMessage(int timeoutDuration, TimeUnit timeoutUnit) throws InterruptedException - { - LOG.debug("Waiting for message"); - assertThat("Message Received",dataLatch.await(timeoutDuration,timeoutUnit),is(true)); - } - - public void close() - { - getSession().close(); - } -} diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/SessionTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/SessionTest.java deleted file mode 100644 index ca553545db3..00000000000 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/SessionTest.java +++ /dev/null @@ -1,135 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.client; - -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; - -import java.net.URI; -import java.util.Collection; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -import org.eclipse.jetty.websocket.api.BatchMode; -import org.eclipse.jetty.websocket.api.RemoteEndpoint; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.WebSocketSession; -import org.eclipse.jetty.websocket.common.test.BlockheadConnection; -import org.eclipse.jetty.websocket.common.test.BlockheadServer; -import org.eclipse.jetty.websocket.common.test.Timeouts; -import org.junit.jupiter.api.AfterAll; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -public class SessionTest -{ - private static BlockheadServer server; - - @BeforeAll - public static void startServer() throws Exception - { - server = new BlockheadServer(); - server.start(); - } - - @AfterAll - public static void stopServer() throws Exception - { - server.stop(); - } - - @Test - @Disabled // TODO fix frequent failure - public void testBasicEcho_FromClient() throws Exception - { - WebSocketClient client = new WebSocketClient(); - client.start(); - try - { - JettyTrackingSocket cliSock = new JettyTrackingSocket(); - - // Hook into server connection creation - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - client.getPolicy().setIdleTimeout(10000); - - URI wsUri = server.getWsUri(); - ClientUpgradeRequest request = new ClientUpgradeRequest(); - request.setSubProtocols("echo"); - Future future = client.connect(cliSock,wsUri,request); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - // Setup echo of frames on server side - serverConn.setIncomingFrameConsumer((frame)->{ - WebSocketFrame copy = WebSocketFrame.copy(frame); - serverConn.write(copy); - }); - - Session sess = future.get(30000, TimeUnit.MILLISECONDS); - assertThat("Session", sess, notNullValue()); - assertThat("Session.open", sess.isOpen(), is(true)); - assertThat("Session.upgradeRequest", sess.getUpgradeRequest(), notNullValue()); - assertThat("Session.upgradeResponse", sess.getUpgradeResponse(), notNullValue()); - - cliSock.assertWasOpened(); - cliSock.assertNotClosed(); - - Collection sessions = client.getBeans(WebSocketSession.class); - assertThat("client.connectionManager.sessions.size", sessions.size(), is(1)); - - RemoteEndpoint remote = cliSock.getSession().getRemote(); - remote.sendStringByFuture("Hello World!"); - if (remote.getBatchMode() == BatchMode.ON) - { - remote.flush(); - } - - // wait for response from server - cliSock.waitForMessage(30000, TimeUnit.MILLISECONDS); - - Set open = client.getOpenSessions(); - assertThat("(Before Close) Open Sessions.size", open.size(), is(1)); - - String received = cliSock.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - assertThat("Message", received, containsString("Hello World!")); - - cliSock.close(); - } - - cliSock.waitForClose(30000, TimeUnit.MILLISECONDS); - Set open = client.getOpenSessions(); - - // TODO this sometimes fails! - assertThat("(After Close) Open Sessions.size", open.size(), is(0)); - } - finally - { - client.stop(); - } - } -} diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/SlowClientTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/SlowClientTest.java deleted file mode 100644 index 1cac5b5e889..00000000000 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/SlowClientTest.java +++ /dev/null @@ -1,133 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.client; - -import static org.hamcrest.Matchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.net.URI; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.StatusCode; -import org.eclipse.jetty.websocket.common.CloseInfo; -import org.eclipse.jetty.websocket.common.OpCode; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.test.BlockheadConnection; -import org.eclipse.jetty.websocket.common.test.BlockheadServer; -import org.eclipse.jetty.websocket.common.test.Timeouts; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.AfterAll; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class SlowClientTest -{ - private static BlockheadServer server; - private WebSocketClient client; - - @BeforeEach - public void startClient() throws Exception - { - client = new WebSocketClient(); - client.getPolicy().setIdleTimeout(60000); - client.start(); - } - - @BeforeAll - public static void startServer() throws Exception - { - server = new BlockheadServer(); - server.start(); - } - - @AfterEach - public void stopClient() throws Exception - { - client.stop(); - } - - @AfterAll - public static void stopServer() throws Exception - { - server.stop(); - } - - @Test - public void testClientSlowToSend() throws Exception - { - JettyTrackingSocket tsocket = new JettyTrackingSocket(); - client.getPolicy().setIdleTimeout(60000); - - URI wsUri = server.getWsUri(); - Future future = client.connect(tsocket, wsUri); - - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - // Confirm connected - future.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); - tsocket.waitForConnected(); - - int messageCount = 10; - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - // Have client write slowly. - ClientWriteThread writer = new ClientWriteThread(tsocket.getSession()); - writer.setMessageCount(messageCount); - writer.setMessage("Hello"); - writer.setSlowness(10); - writer.start(); - writer.join(); - - LinkedBlockingQueue serverFrames = serverConn.getFrameQueue(); - - for (int i = 0; i < messageCount; i++) - { - WebSocketFrame serverFrame = serverFrames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - String prefix = "Server frame[" + i + "]"; - assertThat(prefix + ".opcode", serverFrame.getOpCode(), is(OpCode.TEXT)); - assertThat(prefix + ".payload", serverFrame.getPayloadAsUTF8(), is("Hello/" + i + "/")); - } - - // Close - tsocket.getSession().close(StatusCode.NORMAL, "Done"); - - // confirm close received on server - WebSocketFrame serverFrame = serverFrames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - assertThat("close frame", serverFrame.getOpCode(), is(OpCode.CLOSE)); - CloseInfo closeInfo = new CloseInfo(serverFrame); - assertThat("close info", closeInfo.getStatusCode(), is(StatusCode.NORMAL)); - WebSocketFrame respClose = WebSocketFrame.copy(serverFrame); - respClose.setMask(null); // remove client mask (if present) - serverConn.write(respClose); - - // Verify server response - assertTrue(tsocket.closeLatch.await(3, TimeUnit.MINUTES), "Client Socket Closed"); - tsocket.assertCloseCode(StatusCode.NORMAL); - } - } -} diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/SlowServerTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/SlowServerTest.java deleted file mode 100644 index 08ce4d1b029..00000000000 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/SlowServerTest.java +++ /dev/null @@ -1,160 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.client; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; - -import java.net.URI; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.client.masks.ZeroMasker; -import org.eclipse.jetty.websocket.common.OpCode; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.test.BlockheadConnection; -import org.eclipse.jetty.websocket.common.test.BlockheadServer; -import org.eclipse.jetty.websocket.common.test.Timeouts; -import org.junit.jupiter.api.AfterEach; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class SlowServerTest -{ - private BlockheadServer server; - private WebSocketClient client; - - @BeforeEach - public void startClient() throws Exception - { - client = new WebSocketClient(); - client.setMaxIdleTimeout(60000); - client.start(); - } - - @BeforeEach - public void startServer() throws Exception - { - server = new BlockheadServer(); - server.start(); - } - - @AfterEach - public void stopClient() throws Exception - { - client.stop(); - } - - @AfterEach - public void stopServer() throws Exception - { - server.stop(); - } - - @Test - public void testServerSlowToRead() throws Exception - { - JettyTrackingSocket tsocket = new JettyTrackingSocket(); - client.setMasker(new ZeroMasker()); - client.setMaxIdleTimeout(60000); - - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - URI wsUri = server.getWsUri(); - Future future = client.connect(tsocket,wsUri); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - // slow down reads - serverConn.setIncomingFrameConsumer((frame)-> { - try - { - TimeUnit.MILLISECONDS.sleep(100); - } - catch (InterruptedException ignore) - { - } - }); - - // Confirm connected - future.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); - tsocket.waitForConnected(); - - int messageCount = 10; - - // Have client write as quickly as it can. - ClientWriteThread writer = new ClientWriteThread(tsocket.getSession()); - writer.setMessageCount(messageCount); - writer.setMessage("Hello"); - writer.setSlowness(-1); // disable slowness - writer.start(); - writer.join(); - - // Verify receive - LinkedBlockingQueue serverFrames = serverConn.getFrameQueue(); - for(int i=0; i< messageCount; i++) - { - WebSocketFrame serverFrame = serverFrames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - String prefix = "Server Frame[" + i + "]"; - assertThat(prefix, serverFrame, is(notNullValue())); - assertThat(prefix + ".opCode", serverFrame.getOpCode(), is(OpCode.TEXT)); - assertThat(prefix + ".payload", serverFrame.getPayloadAsUTF8(), is("Hello/" + i + "/")); - } - } - } - - @Test - public void testServerSlowToSend() throws Exception - { - JettyTrackingSocket clientSocket = new JettyTrackingSocket(); - client.setMaxIdleTimeout(60000); - - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - URI wsUri = server.getWsUri(); - Future clientConnectFuture = client.connect(clientSocket,wsUri); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - // Confirm connected - clientConnectFuture.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); - clientSocket.waitForConnected(); - - // Have server write slowly. - int messageCount = 1000; - - ServerWriteThread writer = new ServerWriteThread(serverConn); - writer.setMessageCount(messageCount); - writer.setMessage("Hello"); - writer.setSlowness(10); - writer.start(); - writer.join(); - - // Verify receive - assertThat("Message Receive Count", clientSocket.messageQueue.size(), is(messageCount)); - } - } -} diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/WebSocketClientTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/WebSocketClientTest.java deleted file mode 100644 index 4208baf7d1a..00000000000 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/WebSocketClientTest.java +++ /dev/null @@ -1,328 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2018 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.client; - -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.URI; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -import org.eclipse.jetty.util.StringUtil; -import org.eclipse.jetty.websocket.api.BatchMode; -import org.eclipse.jetty.websocket.api.RemoteEndpoint; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.UpgradeRequest; -import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.WebSocketSession; -import org.eclipse.jetty.websocket.common.frames.TextFrame; -import org.eclipse.jetty.websocket.common.io.FutureWriteCallback; -import org.eclipse.jetty.websocket.common.test.BlockheadConnection; -import org.eclipse.jetty.websocket.common.test.BlockheadServer; -import org.eclipse.jetty.websocket.common.test.Timeouts; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -public class WebSocketClientTest -{ - private static BlockheadServer server; - private WebSocketClient client; - - @BeforeEach - public void startClient() throws Exception - { - client = new WebSocketClient(); - client.start(); - } - - @BeforeAll - public static void startServer() throws Exception - { - server = new BlockheadServer(); - server.getPolicy().setMaxTextMessageSize(200 * 1024); - server.getPolicy().setMaxBinaryMessageSize(200 * 1024); - server.start(); - } - - @AfterEach - public void stopClient() throws Exception - { - client.stop(); - } - - @AfterAll - public static void stopServer() throws Exception - { - server.stop(); - } - - @Test - public void testAddExtension_NotInstalled() throws Exception - { - JettyTrackingSocket cliSock = new JettyTrackingSocket(); - - client.getPolicy().setIdleTimeout(10000); - - URI wsUri = server.getWsUri(); - ClientUpgradeRequest request = new ClientUpgradeRequest(); - request.setSubProtocols("echo"); - request.addExtensions("x-bad"); - - assertThrows(IllegalArgumentException.class, ()-> { - // Should trigger failure on bad extension - client.connect(cliSock, wsUri, request); - }); - } - - @Test - public void testBasicEcho_FromClient() throws Exception - { - JettyTrackingSocket cliSock = new JettyTrackingSocket(); - - client.getPolicy().setIdleTimeout(10000); - - // Hook into server connection creation - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - URI wsUri = server.getWsUri(); - ClientUpgradeRequest request = new ClientUpgradeRequest(); - request.setSubProtocols("echo"); - Future future = client.connect(cliSock,wsUri,request); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - // Setup echo of frames on server side - serverConn.setIncomingFrameConsumer((frame)->{ - WebSocketFrame copy = WebSocketFrame.copy(frame); - copy.setMask(null); // strip client mask (if present) - serverConn.write(copy); - }); - - Session sess = future.get(30,TimeUnit.SECONDS); - assertThat("Session",sess,notNullValue()); - assertThat("Session.open",sess.isOpen(),is(true)); - assertThat("Session.upgradeRequest",sess.getUpgradeRequest(),notNullValue()); - assertThat("Session.upgradeResponse",sess.getUpgradeResponse(),notNullValue()); - - cliSock.assertWasOpened(); - cliSock.assertNotClosed(); - - Collection sessions = client.getOpenSessions(); - assertThat("client.connectionManager.sessions.size",sessions.size(),is(1)); - - RemoteEndpoint remote = cliSock.getSession().getRemote(); - remote.sendStringByFuture("Hello World!"); - if (remote.getBatchMode() == BatchMode.ON) - remote.flush(); - - // wait for response from server - String received = cliSock.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - assertThat("Message", received, containsString("Hello World")); - } - } - - @Test - public void testBasicEcho_UsingCallback() throws Exception - { - client.setMaxIdleTimeout(160000); - JettyTrackingSocket cliSock = new JettyTrackingSocket(); - - // Hook into server connection creation - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - URI wsUri = server.getWsUri(); - ClientUpgradeRequest request = new ClientUpgradeRequest(); - request.setSubProtocols("echo"); - Future future = client.connect(cliSock,wsUri,request); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - Session sess = future.get(30, TimeUnit.SECONDS); - assertThat("Session", sess, notNullValue()); - assertThat("Session.open", sess.isOpen(), is(true)); - assertThat("Session.upgradeRequest", sess.getUpgradeRequest(), notNullValue()); - assertThat("Session.upgradeResponse", sess.getUpgradeResponse(), notNullValue()); - - cliSock.assertWasOpened(); - cliSock.assertNotClosed(); - - Collection sessions = client.getBeans(WebSocketSession.class); - assertThat("client.connectionManager.sessions.size", sessions.size(), is(1)); - - FutureWriteCallback callback = new FutureWriteCallback(); - - cliSock.getSession().getRemote().sendString("Hello World!", callback); - callback.get(1, TimeUnit.SECONDS); - } - } - - @Test - public void testBasicEcho_FromServer() throws Exception - { - // Hook into server connection creation - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - Future future = client.connect(wsocket,server.getWsUri()); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - // Validate connect - Session sess = future.get(30, TimeUnit.SECONDS); - assertThat("Session", sess, notNullValue()); - assertThat("Session.open", sess.isOpen(), is(true)); - assertThat("Session.upgradeRequest", sess.getUpgradeRequest(), notNullValue()); - assertThat("Session.upgradeResponse", sess.getUpgradeResponse(), notNullValue()); - - // Have server send initial message - serverConn.write(new TextFrame().setPayload("Hello World")); - - // Verify connect - future.get(30, TimeUnit.SECONDS); - wsocket.assertWasOpened(); - - String received = wsocket.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - assertThat("Message", received, containsString("Hello World")); - } - } - - @Test - public void testLocalRemoteAddress() throws Exception - { - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - - URI wsUri = server.getWsUri(); - Future future = client.connect(wsocket,wsUri); - - future.get(30,TimeUnit.SECONDS); - - assertTrue(wsocket.openLatch.await(1,TimeUnit.SECONDS)); - - InetSocketAddress local = wsocket.getSession().getLocalAddress(); - InetSocketAddress remote = wsocket.getSession().getRemoteAddress(); - - assertThat("Local Socket Address",local,notNullValue()); - assertThat("Remote Socket Address",remote,notNullValue()); - - // Hard to validate (in a portable unit test) the local address that was used/bound in the low level Jetty Endpoint - assertThat("Local Socket Address / Host",local.getAddress().getHostAddress(),notNullValue()); - assertThat("Local Socket Address / Port",local.getPort(),greaterThan(0)); - - String uriHostAddress = InetAddress.getByName(wsUri.getHost()).getHostAddress(); - assertThat("Remote Socket Address / Host",remote.getAddress().getHostAddress(),is(uriHostAddress)); - assertThat("Remote Socket Address / Port",remote.getPort(),greaterThan(0)); - } - - /** - * Ensure that @WebSocket(maxTextMessageSize = 100*1024) behaves as expected. - * - * @throws Exception - * on test failure - */ - @Test - public void testMaxMessageSize() throws Exception - { - MaxMessageSocket wsocket = new MaxMessageSocket(); - - // Hook into server connection creation - CompletableFuture serverConnFut = new CompletableFuture<>(); - server.addConnectFuture(serverConnFut); - - URI wsUri = server.getWsUri(); - Future future = client.connect(wsocket,wsUri); - - try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) - { - // Setup echo of frames on server side - serverConn.setIncomingFrameConsumer((frame)->{ - WebSocketFrame copy = WebSocketFrame.copy(frame); - copy.setMask(null); // strip client mask (if present) - serverConn.write(copy); - }); - - wsocket.awaitConnect(1,TimeUnit.SECONDS); - - Session sess = future.get(30,TimeUnit.SECONDS); - assertThat("Session",sess,notNullValue()); - assertThat("Session.open",sess.isOpen(),is(true)); - - // Create string that is larger than default size of 64k - // but smaller than maxMessageSize of 100k - byte buf[] = new byte[80 * 1024]; - Arrays.fill(buf,(byte)'x'); - String msg = StringUtil.toUTF8String(buf,0,buf.length); - - wsocket.getSession().getRemote().sendStringByFuture(msg); - - // wait for response from server - wsocket.waitForMessage(1, TimeUnit.SECONDS); - - wsocket.assertMessage(msg); - - assertTrue(wsocket.dataLatch.await(2, TimeUnit.SECONDS)); - } - } - - @Test - public void testParameterMap() throws Exception - { - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - - URI wsUri = server.getWsUri().resolve("/test?snack=cashews&amount=handful&brand=off"); - Future future = client.connect(wsocket,wsUri); - - future.get(30,TimeUnit.SECONDS); - - assertTrue(wsocket.openLatch.await(1,TimeUnit.SECONDS)); - - Session session = wsocket.getSession(); - UpgradeRequest req = session.getUpgradeRequest(); - assertThat("Upgrade Request",req,notNullValue()); - - Map> parameterMap = req.getParameterMap(); - assertThat("Parameter Map",parameterMap,notNullValue()); - - assertThat("Parameter[snack]",parameterMap.get("snack"),is(Arrays.asList(new String[] { "cashews" }))); - assertThat("Parameter[amount]",parameterMap.get("amount"),is(Arrays.asList(new String[] { "handful" }))); - assertThat("Parameter[brand]",parameterMap.get("brand"),is(Arrays.asList(new String[] { "off" }))); - - assertThat("Parameter[cost]",parameterMap.get("cost"),nullValue()); - } -}