| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.tomcat.websocket; |
| |
| import java.io.IOException; |
| import java.net.URI; |
| import java.nio.ByteBuffer; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.concurrent.CountDownLatch; |
| |
| import javax.websocket.ClientEndpoint; |
| import javax.websocket.ClientEndpointConfig; |
| import javax.websocket.ContainerProvider; |
| import javax.websocket.Endpoint; |
| import javax.websocket.Extension; |
| import javax.websocket.OnClose; |
| import javax.websocket.OnError; |
| import javax.websocket.OnMessage; |
| import javax.websocket.Session; |
| import javax.websocket.WebSocketContainer; |
| |
| import org.apache.tomcat.util.ExceptionUtils; |
| import org.apache.tomcat.websocket.pojo.PojoEndpointClient; |
| |
| /** |
| * Runs the Autobahn test suite in client mode for testing the WebSocket client |
| * implementation. |
| */ |
| public class TesterWsClientAutobahn { |
| |
| private static final String HOST = "localhost"; |
| private static final int PORT = 9001; |
| private static final String USER_AGENT = "ApacheTomcat8WebSocketClient"; |
| |
| |
| public static void main(String[] args) throws Exception { |
| |
| WebSocketContainer wsc = ContainerProvider.getWebSocketContainer(); |
| |
| int testCaseCount = getTestCaseCount(wsc); |
| System.out.println("There are " + testCaseCount + " test cases"); |
| for (int testCase = 1; testCase <= testCaseCount; testCase++) { |
| if (testCase % 50 == 0) { |
| System.out.println(testCase); |
| } else { |
| System.out.print('.'); |
| } |
| try { |
| executeTestCase(wsc, testCase); |
| } catch (Throwable t) { |
| ExceptionUtils.handleThrowable(t); |
| t.printStackTrace(); |
| } |
| |
| } |
| System.out.println("Testing complete"); |
| updateReports(wsc); |
| } |
| |
| |
| private static int getTestCaseCount(WebSocketContainer wsc) |
| throws Exception { |
| |
| URI uri = new URI("ws://" + HOST + ":" + PORT + "/getCaseCount"); |
| CaseCountClient caseCountClient = new CaseCountClient(); |
| wsc.connectToServer(caseCountClient, uri); |
| return caseCountClient.getCaseCount(); |
| } |
| |
| |
| private static void executeTestCase(WebSocketContainer wsc, int testCase) |
| throws Exception { |
| URI uri = new URI("ws://" + HOST + ":" + PORT + "/runCase?case=" + |
| testCase + "&agent=" + USER_AGENT); |
| TestCaseClient testCaseClient = new TestCaseClient(); |
| |
| Extension permessageDeflate = new WsExtension("permessage-deflate"); |
| // Advertise support for client_max_window_bits |
| // Client only supports some values so there will be some failures here |
| // Note Autobahn returns a 400 response if you provide a value for |
| // client_max_window_bits |
| permessageDeflate.getParameters().add( |
| new WsExtensionParameter("client_max_window_bits", null)); |
| List<Extension> extensions = new ArrayList<>(1); |
| extensions.add(permessageDeflate); |
| |
| Endpoint ep = new PojoEndpointClient(testCaseClient, null); |
| ClientEndpointConfig.Builder builder = ClientEndpointConfig.Builder.create(); |
| ClientEndpointConfig config = builder.extensions(extensions).build(); |
| |
| wsc.connectToServer(ep, config, uri); |
| testCaseClient.waitForClose(); |
| } |
| |
| |
| private static void updateReports(WebSocketContainer wsc) |
| throws Exception { |
| |
| URI uri = new URI("ws://" + HOST + ":" + PORT + |
| "/updateReports?agent=" + USER_AGENT); |
| UpdateReportsClient updateReportsClient = new UpdateReportsClient(); |
| wsc.connectToServer(updateReportsClient, uri); |
| } |
| |
| |
| @ClientEndpoint |
| public static class CaseCountClient { |
| |
| private final CountDownLatch latch = new CountDownLatch(1); |
| private volatile int caseCount = 0; |
| |
| // Need to wait for message |
| public int getCaseCount() throws InterruptedException { |
| latch.await(); |
| return caseCount; |
| } |
| |
| @OnMessage |
| public void onMessage(String msg) { |
| latch.countDown(); |
| caseCount = Integer.parseInt(msg); |
| } |
| |
| |
| @OnError |
| public void onError(Throwable t) { |
| latch.countDown(); |
| t.printStackTrace(); |
| } |
| } |
| |
| |
| @ClientEndpoint |
| public static class TestCaseClient { |
| |
| private final CountDownLatch latch = new CountDownLatch(1); |
| |
| public void waitForClose() throws InterruptedException { |
| latch.await(); |
| } |
| |
| @OnMessage |
| public void echoTextMessage(Session session, String msg, boolean last) { |
| try { |
| if (session.isOpen()) { |
| session.getBasicRemote().sendText(msg, last); |
| } |
| } catch (IOException e) { |
| try { |
| session.close(); |
| } catch (IOException e1) { |
| // Ignore |
| } |
| } |
| } |
| |
| @OnMessage |
| public void echoBinaryMessage(Session session, ByteBuffer bb, |
| boolean last) { |
| try { |
| if (session.isOpen()) { |
| session.getBasicRemote().sendBinary(bb, last); |
| } |
| } catch (IOException e) { |
| try { |
| session.close(); |
| } catch (IOException e1) { |
| // Ignore |
| } |
| } |
| } |
| |
| @OnClose |
| public void releaseLatch() { |
| latch.countDown(); |
| } |
| } |
| |
| |
| @ClientEndpoint |
| public static class UpdateReportsClient { |
| |
| private final CountDownLatch latch = new CountDownLatch(1); |
| |
| public void waitForClose() throws InterruptedException { |
| latch.await(); |
| } |
| |
| @OnClose |
| public void onClose() { |
| latch.countDown(); |
| } |
| } |
| } |