From 753c8be6ebe63fe32eceb8ba2080550aa0a9b5a0 Mon Sep 17 00:00:00 2001 From: Lachlan Roberts Date: Tue, 2 Jun 2020 15:32:36 +1000 Subject: [PATCH] Issue #4919 - test graceful stop for jetty and javax ws containers Signed-off-by: Lachlan Roberts --- .../javax/tests/GracefulCloseTest.java | 127 ++++++++++++++++++ .../websocket/tests/GracefulCloseTest.java | 110 +++++++++++++++ 2 files changed, 237 insertions(+) create mode 100644 jetty-websocket/websocket-javax-tests/src/test/java/org/eclipse/jetty/websocket/javax/tests/GracefulCloseTest.java create mode 100644 jetty-websocket/websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/GracefulCloseTest.java diff --git a/jetty-websocket/websocket-javax-tests/src/test/java/org/eclipse/jetty/websocket/javax/tests/GracefulCloseTest.java b/jetty-websocket/websocket-javax-tests/src/test/java/org/eclipse/jetty/websocket/javax/tests/GracefulCloseTest.java new file mode 100644 index 00000000000..bb9593db2a6 --- /dev/null +++ b/jetty-websocket/websocket-javax-tests/src/test/java/org/eclipse/jetty/websocket/javax/tests/GracefulCloseTest.java @@ -0,0 +1,127 @@ +// +// ======================================================================== +// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under +// the terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0 +// +// This Source Code may also be made available under the following +// Secondary Licenses when the conditions for such availability set +// forth in the Eclipse Public License, v. 2.0 are satisfied: +// the Apache License v2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.websocket.javax.tests; + +import java.net.URI; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import javax.websocket.CloseReason; +import javax.websocket.EndpointConfig; +import javax.websocket.Session; +import javax.websocket.server.ServerEndpoint; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.util.BlockingArrayQueue; +import org.eclipse.jetty.websocket.javax.client.internal.JavaxWebSocketClientContainer; +import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class GracefulCloseTest +{ + private static final BlockingArrayQueue serverEndpoints = new BlockingArrayQueue<>(); + private Server server; + private URI serverUri; + private JavaxWebSocketClientContainer client; + + @BeforeEach + public void before() throws Exception + { + server = new Server(); + ServerConnector connector = new ServerConnector(server); + server.addConnector(connector); + + ServletContextHandler contextHandler = new ServletContextHandler(); + contextHandler.setContextPath("/"); + server.setHandler(contextHandler); + JavaxWebSocketServletContainerInitializer.configure(contextHandler, (context, container) -> + container.addEndpoint(ServerSocket.class)); + server.start(); + serverUri = WSURI.toWebsocket(server.getURI()); + + client = new JavaxWebSocketClientContainer(); + client.start(); + } + + @AfterEach + public void after() throws Exception + { + client.stop(); + server.stop(); + } + + @ServerEndpoint("/") + public static class ServerSocket extends EventSocket.EchoSocket + { + @Override + public void onOpen(Session session, EndpointConfig endpointConfig) + { + serverEndpoints.add(this); + super.onOpen(session, endpointConfig); + } + } + + @Test + public void testClientStop() throws Exception + { + EventSocket clientEndpoint = new EventSocket(); + client.connectToServer(clientEndpoint, serverUri); + EventSocket serverEndpoint = Objects.requireNonNull(serverEndpoints.poll(5, TimeUnit.SECONDS)); + + client.stop(); + + // Check that the client endpoint was closed with the correct status code and no error. + assertTrue(clientEndpoint.closeLatch.await(5, TimeUnit.SECONDS)); + assertThat(clientEndpoint.closeReason.getCloseCode(), is(CloseReason.CloseCodes.GOING_AWAY)); + assertNull(clientEndpoint.error); + + // Check that the server endpoint was closed with the correct status code and no error. + assertTrue(serverEndpoint.closeLatch.await(5, TimeUnit.SECONDS)); + assertThat(serverEndpoint.closeReason.getCloseCode(), is(CloseReason.CloseCodes.GOING_AWAY)); + assertNull(serverEndpoint.error); + } + + @Test + public void testServerStop() throws Exception + { + EventSocket clientEndpoint = new EventSocket(); + client.connectToServer(clientEndpoint, serverUri); + EventSocket serverEndpoint = Objects.requireNonNull(serverEndpoints.poll(5, TimeUnit.SECONDS)); + + server.stop(); + + // Check that the client endpoint was closed with the correct status code and no error. + assertTrue(clientEndpoint.closeLatch.await(5, TimeUnit.SECONDS)); + assertThat(clientEndpoint.closeReason.getCloseCode(), is(CloseReason.CloseCodes.GOING_AWAY)); + assertNull(clientEndpoint.error); + + // Check that the server endpoint was closed with the correct status code and no error. + assertTrue(serverEndpoint.closeLatch.await(5, TimeUnit.SECONDS)); + assertThat(serverEndpoint.closeReason.getCloseCode(), is(CloseReason.CloseCodes.GOING_AWAY)); + assertNull(serverEndpoint.error); + } +} diff --git a/jetty-websocket/websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/GracefulCloseTest.java b/jetty-websocket/websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/GracefulCloseTest.java new file mode 100644 index 00000000000..326af686528 --- /dev/null +++ b/jetty-websocket/websocket-jetty-tests/src/test/java/org/eclipse/jetty/websocket/tests/GracefulCloseTest.java @@ -0,0 +1,110 @@ +// +// ======================================================================== +// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others. +// +// This program and the accompanying materials are made available under +// the terms of the Eclipse Public License 2.0 which is available at +// https://www.eclipse.org/legal/epl-2.0 +// +// This Source Code may also be made available under the following +// Secondary Licenses when the conditions for such availability set +// forth in the Eclipse Public License, v. 2.0 are satisfied: +// the Apache License v2.0 which is available at +// https://www.apache.org/licenses/LICENSE-2.0 +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// ======================================================================== +// + +package org.eclipse.jetty.websocket.tests; + +import java.net.URI; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.websocket.api.StatusCode; +import org.eclipse.jetty.websocket.api.util.WSURI; +import org.eclipse.jetty.websocket.client.WebSocketClient; +import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class GracefulCloseTest +{ + private final EventSocket serverEndpoint = new EchoSocket(); + private Server server; + private URI serverUri; + private WebSocketClient client; + + @BeforeEach + public void before() throws Exception + { + server = new Server(); + ServerConnector connector = new ServerConnector(server); + server.addConnector(connector); + + ServletContextHandler contextHandler = new ServletContextHandler(); + contextHandler.setContextPath("/"); + server.setHandler(contextHandler); + JettyWebSocketServletContainerInitializer.configure(contextHandler, (context, container) -> + container.addMapping("/", ((req, resp) -> serverEndpoint))); + server.start(); + serverUri = WSURI.toWebsocket(server.getURI()); + + client = new WebSocketClient(); + client.start(); + } + + @AfterEach + public void after() throws Exception + { + client.stop(); + server.stop(); + } + + @Test + public void testClientStop() throws Exception + { + EventSocket clientEndpoint = new EventSocket(); + client.connect(clientEndpoint, serverUri).get(5, TimeUnit.SECONDS); + + client.stop(); + + // Check that the client endpoint was closed with the correct status code and no error. + assertTrue(clientEndpoint.closeLatch.await(5, TimeUnit.SECONDS)); + assertThat(clientEndpoint.closeCode, is(StatusCode.SHUTDOWN)); + assertNull(clientEndpoint.error); + + // Check that the server endpoint was closed with the correct status code and no error. + assertTrue(serverEndpoint.closeLatch.await(5, TimeUnit.SECONDS)); + assertThat(serverEndpoint.closeCode, is(StatusCode.SHUTDOWN)); + assertNull(serverEndpoint.error); + } + + @Test + public void testServerStop() throws Exception + { + EventSocket clientEndpoint = new EventSocket(); + client.connect(clientEndpoint, serverUri).get(5, TimeUnit.SECONDS); + + server.stop(); + + // Check that the client endpoint was closed with the correct status code and no error. + assertTrue(clientEndpoint.closeLatch.await(5, TimeUnit.SECONDS)); + assertThat(clientEndpoint.closeCode, is(StatusCode.SHUTDOWN)); + assertNull(clientEndpoint.error); + + // Check that the server endpoint was closed with the correct status code and no error. + assertTrue(serverEndpoint.closeLatch.await(5, TimeUnit.SECONDS)); + assertThat(serverEndpoint.closeCode, is(StatusCode.SHUTDOWN)); + assertNull(serverEndpoint.error); + } +}