From 1373025dffa15b25153dd44702e31629bddfab91 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Mon, 5 Mar 2018 17:52:23 -0600 Subject: [PATCH 1/7] Issue #2282 - removing EventQueue from websocket tests --- .../jsr356/DecoderReaderManySmallTest.java | 11 +- .../websocket/jsr356/DecoderReaderTest.java | 21 +- .../jetty/websocket/jsr356/EncoderTest.java | 68 ++-- .../jsr356/endpoints/OnCloseTest.java | 8 +- .../jsr356/endpoints/TrackingSocket.java | 16 +- .../test/resources/jetty-logging.properties | 2 +- .../jsr356/server/AltFilterTest.java | 7 +- .../server/AnnotatedServerEndpointTest.java | 8 +- .../jsr356/server/BasicEndpointTest.java | 7 +- .../jsr356/server/ConfiguratorTest.java | 44 +- .../jsr356/server/EchoClientSocket.java | 14 - .../websocket/jsr356/server/EchoTest.java | 13 +- .../jsr356/server/IdleTimeoutTest.java | 14 +- .../jsr356/server/JettyEchoSocket.java | 13 +- .../jsr356/server/LargeAnnotatedTest.java | 7 +- .../jsr356/server/LargeContainerTest.java | 7 +- .../websocket/jsr356/server/PingPongTest.java | 37 +- .../websocket/jsr356/server/SessionTest.java | 6 +- .../jsr356/server/TrackingSocket.java | 16 +- .../samples/echo/EchoReturnEndpoint.java | 5 +- .../websocket/client/ClientCloseTest.java | 379 ++++++++++-------- .../jetty/websocket/client/CookieTest.java | 23 +- .../websocket/client/JettyTrackingSocket.java | 20 +- .../websocket/client/MaxMessageSocket.java | 6 +- .../websocket/client/ServerReadThread.java | 9 +- .../jetty/websocket/client/SessionTest.java | 55 ++- .../websocket/client/WebSocketClientTest.java | 101 +++-- .../test/resources/jetty-logging.properties | 1 + .../websocket/common/events/EventCapture.java | 9 +- .../message/TrackingInputStreamSocket.java | 6 +- .../common/message/TrackingSocket.java | 12 +- .../common/test/BlockheadClient.java | 9 +- .../test/BlockheadServerConnection.java | 139 ++----- .../jetty/websocket/common/test/Fuzzer.java | 14 +- .../common/test/IBlockheadClient.java | 4 +- .../test/IBlockheadServerConnection.java | 45 +-- .../common/test/IncomingFramesCapture.java | 6 +- .../jetty/websocket/common/test/Timeouts.java | 27 ++ .../test/resources/jetty-logging.properties | 1 + .../server/AnnotatedMaxMessageSizeTest.java | 12 +- .../jetty/websocket/server/ChromeTest.java | 8 +- .../server/DecoratorsLegacyTest.java | 7 +- .../websocket/server/DecoratorsTest.java | 7 +- .../jetty/websocket/server/FirefoxTest.java | 7 +- .../server/FragmentExtensionTest.java | 7 +- .../server/IdentityExtensionTest.java | 7 +- .../websocket/server/IdleTimeoutTest.java | 7 +- .../server/ManyConnectionsCleanupTest.java | 16 +- .../PerMessageDeflateExtensionTest.java | 4 +- .../websocket/server/SubProtocolTest.java | 7 +- .../websocket/server/SuspendResumeTest.java | 9 +- .../websocket/server/TooFastClientTest.java | 14 +- .../websocket/server/WebSocketCloseTest.java | 27 +- .../server/WebSocketOverSSLTest.java | 18 +- .../server/WebSocketServerSessionTest.java | 13 +- .../server/WebSocketServletRFCTest.java | 28 +- .../server/WebSocketUpgradeFilterTest.java | 25 +- .../server/helper/CaptureSocket.java | 9 +- .../misbehaving/MisbehavingClassTest.java | 16 +- 59 files changed, 713 insertions(+), 725 deletions(-) create mode 100644 jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Timeouts.java diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderManySmallTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderManySmallTest.java index 39dd9dd07ec..3402fb5b582 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderManySmallTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderManySmallTest.java @@ -24,6 +24,7 @@ import java.io.Reader; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import javax.websocket.ClientEndpoint; @@ -36,7 +37,6 @@ import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.WebSocketContainer; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.log.Log; @@ -44,6 +44,7 @@ import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadServer; import org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -90,7 +91,7 @@ public class DecoderReaderManySmallTest @ClientEndpoint(decoders = { EventIdDecoder.class }) public static class EventIdSocket { - public EventQueue messageQueue = new EventQueue<>(); + public LinkedBlockingQueue messageQueue = new LinkedBlockingQueue<>(); private CountDownLatch closeLatch = new CountDownLatch(1); @OnClose @@ -102,7 +103,7 @@ public class DecoderReaderManySmallTest @OnMessage public void onMessage(EventId msg) { - messageQueue.add(msg); + messageQueue.offer(msg); } public void awaitClose() throws InterruptedException @@ -208,12 +209,12 @@ public class DecoderReaderManySmallTest idserver.writeSequentialIds(from,to); idserver.close(); int count = from - to; - ids.messageQueue.awaitEventCount(count,4,TimeUnit.SECONDS); ids.awaitClose(); // collect seen ids List seen = new ArrayList<>(); - for(EventId id: ids.messageQueue) + for(int i=0; i messageQueue = new EventQueue<>(); + public LinkedBlockingQueue messageQueue = new LinkedBlockingQueue<>(); private CountDownLatch closeLatch = new CountDownLatch(1); @OnClose @@ -139,7 +140,7 @@ public class DecoderReaderTest public synchronized void onMessage(Quotes msg) { Integer h=hashCode(); - messageQueue.add(msg); + messageQueue.offer(msg); System.out.printf("%x: Quotes from: %s%n",h,msg.author); for (String quote : msg.quotes) { @@ -259,7 +260,7 @@ public class DecoderReaderTest server.stop(); } - // TODO analyse and fix + // TODO analyse and fix @Ignore @Test public void testSingleQuotes() throws Exception @@ -270,15 +271,14 @@ public class DecoderReaderTest client.connectToServer(quoter,server.getWsUri()); qserver.awaitConnect(); qserver.writeQuotes("quotes-ben.txt"); - quoter.messageQueue.awaitEventCount(1,1000,TimeUnit.MILLISECONDS); qserver.close(); quoter.awaitClose(); - Quotes quotes = quoter.messageQueue.poll(); + Quotes quotes = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Quotes Author",quotes.author,is("Benjamin Franklin")); Assert.assertThat("Quotes Count",quotes.quotes.size(),is(3)); } - // TODO analyse and fix + // TODO analyse and fix @Test @Ignore ("Quotes appear to be able to arrive in any order?") public void testTwoQuotes() throws Exception @@ -290,11 +290,12 @@ public class DecoderReaderTest qserver.awaitConnect(); qserver.writeQuotes("quotes-ben.txt"); qserver.writeQuotes("quotes-twain.txt"); - quoter.messageQueue.awaitEventCount(2,1000,TimeUnit.MILLISECONDS); qserver.close(); quoter.awaitClose(); - Quotes quotes = quoter.messageQueue.poll(); + Quotes quotes = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Quotes Author",quotes.author,is("Benjamin Franklin")); Assert.assertThat("Quotes Count",quotes.quotes.size(),is(3)); + quotes = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + Assert.assertThat("Quotes Author",quotes.author,is("Mark Twain")); } } diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java index e7eeb7edc80..d8ac993af07 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java @@ -26,8 +26,9 @@ import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.LinkedBlockingQueue; import javax.websocket.ClientEndpointConfig; import javax.websocket.ContainerProvider; @@ -39,7 +40,6 @@ import javax.websocket.MessageHandler; import javax.websocket.Session; import javax.websocket.WebSocketContainer; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.util.component.LifeCycle; @@ -47,6 +47,7 @@ import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.common.test.BlockheadServer; import org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -55,9 +56,8 @@ import org.junit.Test; public class EncoderTest { - private static class EchoServer implements Runnable + private static class EchoServer { - private Thread thread; private BlockheadServer server; private IBlockheadServerConnection sconnection; private CountDownLatch connectLatch = new CountDownLatch(1); @@ -67,37 +67,32 @@ public class EncoderTest this.server = server; } - @Override - public void run() - { - try - { - sconnection = server.accept(); - sconnection.setSoTimeout(60000); - sconnection.upgrade(); - sconnection.startEcho(); - } - catch (Exception e) - { - LOG.warn(e); - } - finally - { - connectLatch.countDown(); - } - } - public void start() { - this.thread = new Thread(this,"EchoServer"); - this.thread.start(); + CompletableFuture.runAsync(() -> { + try + { + sconnection = server.accept(); + sconnection.setSoTimeout(10000); + sconnection.upgrade(); + sconnection.enableIncomingEcho(true); + sconnection.startReadThread(); + } + catch (Exception e) + { + LOG.warn(e); + } + finally + { + connectLatch.countDown(); + } + }); } public void stop() { if (this.sconnection != null) { - this.sconnection.stopEcho(); try { this.sconnection.close(); @@ -166,12 +161,12 @@ public class EncoderTest public static class QuotesSocket extends Endpoint implements MessageHandler.Whole { private Session session; - private EventQueue messageQueue = new EventQueue<>(); + private LinkedBlockingQueue messageQueue = new LinkedBlockingQueue<>(); @Override public void onMessage(String message) { - messageQueue.add(message); + messageQueue.offer(message); } @Override @@ -236,6 +231,7 @@ public class EncoderTest public void initClient() { client = ContainerProvider.getWebSocketContainer(); + client.setDefaultMaxSessionIdleTimeout(10000); } @After @@ -257,7 +253,7 @@ public class EncoderTest server.stop(); } - @Test + @Test(timeout = 10000) public void testSingleQuotes() throws Exception { EchoServer eserver = new EchoServer(server); @@ -277,9 +273,7 @@ public class EncoderTest Quotes ben = getQuotes("quotes-ben.txt"); quoter.write(ben); - quoter.messageQueue.awaitEventCount(1,1000,TimeUnit.MILLISECONDS); - - String result = quoter.messageQueue.poll(); + String result = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertReceivedQuotes(result,ben); } finally @@ -288,7 +282,7 @@ public class EncoderTest } } - @Test + @Test(timeout = 10000) public void testTwoQuotes() throws Exception { EchoServer eserver = new EchoServer(server); @@ -309,11 +303,9 @@ public class EncoderTest quoter.write(ben); quoter.write(twain); - quoter.messageQueue.awaitEventCount(2,1000,TimeUnit.MILLISECONDS); - - String result = quoter.messageQueue.poll(); + String result = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertReceivedQuotes(result,ben); - result = quoter.messageQueue.poll(); + result = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertReceivedQuotes(result,twain); } finally diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/OnCloseTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/OnCloseTest.java index bfb37f34ed3..446871fbcb8 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/OnCloseTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/OnCloseTest.java @@ -23,15 +23,16 @@ import static org.hamcrest.Matchers.is; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; import javax.websocket.ClientEndpoint; import javax.websocket.ClientEndpointConfig; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.events.EventDriver; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.jsr356.ClientContainer; import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner; import org.eclipse.jetty.websocket.jsr356.annotations.JsrEvents; @@ -118,9 +119,8 @@ public class OnCloseTest driver.onClose(new CloseInfo(StatusCode.NORMAL,"normal")); // Test captured event - EventQueue events = endpoint.eventQueue; - Assert.assertThat("Number of Events Captured",events.size(),is(1)); - String closeEvent = events.poll(); + LinkedBlockingQueue events = endpoint.eventQueue; + String closeEvent = events.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Close Event",closeEvent,is(testcase.expectedCloseEvent)); } } diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/TrackingSocket.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/TrackingSocket.java index 5cf017729e2..29db50c9989 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/TrackingSocket.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/TrackingSocket.java @@ -23,12 +23,12 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import javax.websocket.CloseReason; import javax.websocket.CloseReason.CloseCode; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.junit.Assert; @@ -41,8 +41,8 @@ public abstract class TrackingSocket private static final Logger LOG = Log.getLogger(TrackingSocket.class); public CloseReason closeReason; - public EventQueue eventQueue = new EventQueue(); - public EventQueue errorQueue = new EventQueue<>(); + public LinkedBlockingQueue eventQueue = new LinkedBlockingQueue<>(); + public LinkedBlockingQueue errorQueue = new LinkedBlockingQueue<>(); public CountDownLatch openLatch = new CountDownLatch(1); public CountDownLatch closeLatch = new CountDownLatch(1); public CountDownLatch dataLatch = new CountDownLatch(1); @@ -50,12 +50,12 @@ public abstract class TrackingSocket protected void addError(Throwable t) { LOG.warn(t); - errorQueue.add(t); + errorQueue.offer(t); } protected void addEvent(String format, Object... args) { - eventQueue.add(String.format(format,args)); + eventQueue.offer(String.format(format,args)); } public void assertClose(CloseCode expectedCode, String expectedReason) throws InterruptedException @@ -76,12 +76,6 @@ public abstract class TrackingSocket Assert.assertThat("Close Reason",closeReason.getReasonPhrase(),is(expectedReason)); } - public void assertEvent(String expected) - { - String actual = eventQueue.poll(); - Assert.assertEquals("Event",expected,actual); - } - public void assertIsOpen() throws InterruptedException { assertWasOpened(); diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/resources/jetty-logging.properties b/jetty-websocket/javax-websocket-client-impl/src/test/resources/jetty-logging.properties index 3acadb6cade..2b8dfa9b594 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/resources/jetty-logging.properties +++ b/jetty-websocket/javax-websocket-client-impl/src/test/resources/jetty-logging.properties @@ -1,6 +1,6 @@ org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog org.eclipse.jetty.LEVEL=WARN -# org.eclipse.jetty.websocket.LEVEL=INFO +# org.eclipse.jetty.websocket.LEVEL=DEBUG # org.eclipse.jetty.websocket.LEVEL=ALL # org.eclipse.jetty.websocket.jsr356.LEVEL=DEBUG diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/AltFilterTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/AltFilterTest.java index 9890e54f543..b8321115a29 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/AltFilterTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/AltFilterTest.java @@ -23,8 +23,8 @@ import static org.hamcrest.CoreMatchers.nullValue; import static org.junit.Assert.assertThat; import java.net.URI; -import java.util.Queue; import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.io.ByteBufferPool; @@ -34,6 +34,7 @@ import org.eclipse.jetty.toolchain.test.TestingDir; import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.client.WebSocketClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.jsr356.server.samples.echo.BasicEchoSocket; import org.junit.Assert; import org.junit.Rule; @@ -81,8 +82,8 @@ public class AltFilterTest // wait for connect future.get(1,TimeUnit.SECONDS); clientEcho.sendMessage("Hello Echo"); - Queue msgs = clientEcho.awaitMessages(1); - Assert.assertEquals("Expected message","Hello Echo",msgs.poll()); + LinkedBlockingQueue msgs = clientEcho.incomingMessages; + Assert.assertEquals("Expected message","Hello Echo",msgs.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT)); } finally { diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/AnnotatedServerEndpointTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/AnnotatedServerEndpointTest.java index ba959f6348f..607eb45d35b 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/AnnotatedServerEndpointTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/AnnotatedServerEndpointTest.java @@ -22,8 +22,8 @@ import static org.hamcrest.Matchers.containsString; import java.io.File; import java.net.URI; -import java.util.Queue; import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.io.ByteBufferPool; @@ -33,6 +33,7 @@ import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; import org.eclipse.jetty.websocket.client.WebSocketClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.jsr356.server.samples.beans.DateDecoder; import org.eclipse.jetty.websocket.jsr356.server.samples.beans.TimeEncoder; import org.eclipse.jetty.websocket.jsr356.server.samples.echo.ConfiguredEchoSocket; @@ -40,7 +41,6 @@ import org.eclipse.jetty.websocket.jsr356.server.samples.echo.EchoSocketConfigur import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; -import org.junit.Rule; import org.junit.Test; /** @@ -90,9 +90,9 @@ public class AnnotatedServerEndpointTest foo.get(1,TimeUnit.SECONDS); clientEcho.sendMessage(message); - Queue msgs = clientEcho.awaitMessages(1); + LinkedBlockingQueue msgs = clientEcho.incomingMessages; - String response = msgs.poll(); + String response = msgs.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); for (String expected : expectedTexts) { Assert.assertThat("Expected message",response,containsString(expected)); diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/BasicEndpointTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/BasicEndpointTest.java index 35a26b2a368..ccd4f40c1aa 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/BasicEndpointTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/BasicEndpointTest.java @@ -19,8 +19,8 @@ package org.eclipse.jetty.websocket.jsr356.server; import java.net.URI; -import java.util.Queue; import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.io.ByteBufferPool; @@ -29,6 +29,7 @@ import org.eclipse.jetty.toolchain.test.TestingDir; import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.client.WebSocketClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.jsr356.server.samples.echo.BasicEchoEndpoint; import org.eclipse.jetty.websocket.jsr356.server.samples.echo.BasicEchoEndpointConfigContextListener; import org.junit.Assert; @@ -73,8 +74,8 @@ public class BasicEndpointTest // wait for connect future.get(1,TimeUnit.SECONDS); clientEcho.sendMessage("Hello World"); - Queue msgs = clientEcho.awaitMessages(1); - Assert.assertEquals("Expected message","Hello World",msgs.poll()); + LinkedBlockingQueue msgs = clientEcho.incomingMessages; + Assert.assertEquals("Expected message","Hello World",msgs.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT)); } finally { diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java index a3c08093be1..9042d4f4a4b 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java @@ -35,7 +35,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TimeZone; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; @@ -54,7 +54,6 @@ import javax.websocket.server.ServerEndpointConfig; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.util.QuoteUtil; @@ -63,6 +62,7 @@ import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; import org.eclipse.jetty.websocket.common.test.HttpResponse; import org.eclipse.jetty.websocket.common.test.IBlockheadClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer; import org.junit.AfterClass; import org.junit.Assert; @@ -437,8 +437,8 @@ public class ConfiguratorTest assertThat("response.extensions", response.getExtensionsHeader(), nullValue()); client.write(new TextFrame().setPayload("NegoExts")); - EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("Frame Response", frame.getPayloadAsUTF8(), is("negotiatedExtensions=[]")); } } @@ -456,8 +456,8 @@ public class ConfiguratorTest client.expectUpgradeResponse(); client.write(new TextFrame().setPayload("X-Dummy")); - EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Request Header [X-Dummy]: \"Bogus\"")); } } @@ -475,8 +475,8 @@ public class ConfiguratorTest client.expectUpgradeResponse(); client.write(new TextFrame().setPayload("apple")); - EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested User Property: [apple] = \"fruit from tree\"")); } @@ -489,8 +489,8 @@ public class ConfiguratorTest client.write(new TextFrame().setPayload("apple")); client.write(new TextFrame().setPayload("blueberry")); - EventQueue frames = client.readFrames(2, 1, TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); // should have no value Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested User Property: [apple] = ")); @@ -515,8 +515,8 @@ public class ConfiguratorTest InetSocketAddress expectedRemote = client.getRemoteSocketAddress(); client.write(new TextFrame().setPayload("addr")); - EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); StringWriter expected = new StringWriter(); PrintWriter out = new PrintWriter(expected); @@ -548,8 +548,8 @@ public class ConfiguratorTest client.expectUpgradeResponse(); client.write(new TextFrame().setPayload("getProtocols")); - EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\"]")); } } @@ -572,8 +572,8 @@ public class ConfiguratorTest client.expectUpgradeResponse(); client.write(new TextFrame().setPayload("getProtocols")); - EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]")); } } @@ -596,8 +596,8 @@ public class ConfiguratorTest client.expectUpgradeResponse(); client.write(new TextFrame().setPayload("getProtocols")); - EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]")); } } @@ -620,8 +620,8 @@ public class ConfiguratorTest client.expectUpgradeResponse(); client.write(new TextFrame().setPayload("getProtocols")); - EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]")); } } @@ -642,8 +642,8 @@ public class ConfiguratorTest client.expectUpgradeResponse(); client.write(new TextFrame().setPayload("2016-06-20T14:27:44")); - EventQueue frames = client.readFrames(1, 1, TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("cal=2016.06.20 AD at 14:27:44 +0000")); } } diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/EchoClientSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/EchoClientSocket.java index 5c0b8929a68..519928c44ed 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/EchoClientSocket.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/EchoClientSocket.java @@ -20,8 +20,6 @@ package org.eclipse.jetty.websocket.jsr356.server; import java.io.IOException; import java.nio.ByteBuffer; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; import javax.websocket.ClientEndpoint; import javax.websocket.CloseReason; @@ -38,15 +36,9 @@ import org.eclipse.jetty.util.BufferUtil; @ClientEndpoint public class EchoClientSocket extends TrackingSocket { - public final CountDownLatch eventCountLatch; private Session session; private Basic remote; - public EchoClientSocket(int expectedEventCount) - { - this.eventCountLatch = new CountDownLatch(expectedEventCount); - } - public void close() throws IOException { if (session != null) @@ -88,12 +80,6 @@ public class EchoClientSocket extends TrackingSocket public void onText(String text) { addEvent(text); - eventCountLatch.countDown(); - } - - public boolean awaitAllEvents(long timeout, TimeUnit unit) throws InterruptedException - { - return eventCountLatch.await(timeout,unit); } public void sendObject(Object obj) throws IOException, EncodeException diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/EchoTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/EchoTest.java index 5169c45a32a..b4b95d9c803 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/EchoTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/EchoTest.java @@ -18,22 +18,23 @@ package org.eclipse.jetty.websocket.jsr356.server; -import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsString; import java.io.File; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import javax.websocket.ContainerProvider; import javax.websocket.WebSocketContainer; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.webapp.WebAppContext; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.jsr356.server.EchoCase.PartialBinary; import org.eclipse.jetty.websocket.jsr356.server.EchoCase.PartialText; import org.eclipse.jetty.websocket.jsr356.server.samples.binary.ByteBufferSocket; @@ -255,7 +256,7 @@ public class EchoTest public void testEcho() throws Exception { int messageCount = testcase.getMessageCount(); - EchoClientSocket socket = new EchoClientSocket(messageCount); + EchoClientSocket socket = new EchoClientSocket(); URI toUri = serverUri.resolve(testcase.path.substring(1)); try @@ -284,13 +285,13 @@ public class EchoTest } // Collect Responses - socket.awaitAllEvents(1,TimeUnit.SECONDS); - EventQueue received = socket.eventQueue; + LinkedBlockingQueue received = socket.eventQueue; // Validate Responses for (String expected : testcase.expectedStrings) { - Assert.assertThat("Received Echo Responses",received,contains(expected)); + String actual = received.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + Assert.assertThat("Received Echo Responses",actual,containsString(expected)); } } finally diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/IdleTimeoutTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/IdleTimeoutTest.java index b24d799b02b..42e8583bf3c 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/IdleTimeoutTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/IdleTimeoutTest.java @@ -18,15 +18,14 @@ package org.eclipse.jetty.websocket.jsr356.server; -import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; import java.net.URI; -import java.util.Queue; import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.log.Log; @@ -35,6 +34,7 @@ import org.eclipse.jetty.util.log.StacklessLogging; import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.client.WebSocketClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.jsr356.annotations.JsrEvents; import org.eclipse.jetty.websocket.jsr356.server.samples.idletimeout.IdleTimeoutContextListener; import org.eclipse.jetty.websocket.jsr356.server.samples.idletimeout.OnOpenIdleTimeoutEndpoint; @@ -100,10 +100,12 @@ public class IdleTimeoutTest clientEcho.sendMessage("You shouldn't be there"); try { - Queue msgs = clientEcho.awaitMessages(1); - assertThat("Should not have received messages echoed back",msgs,is(empty())); + LinkedBlockingQueue msgs = clientEcho.incomingMessages; + // should not have a message. + String received = msgs.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + assertThat("Should not have received messages echoed back",received,is(nullValue())); } - catch (TimeoutException | InterruptedException e) + catch (InterruptedException e) { // valid success path } diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/JettyEchoSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/JettyEchoSocket.java index b26e90e64bb..721be5fd487 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/JettyEchoSocket.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/JettyEchoSocket.java @@ -19,13 +19,10 @@ package org.eclipse.jetty.websocket.jsr356.server; import java.io.IOException; -import java.util.Queue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.BatchMode; @@ -50,13 +47,7 @@ public class JettyEchoSocket private Session session; private Lock remoteLock = new ReentrantLock(); private RemoteEndpoint remote; - private EventQueue incomingMessages = new EventQueue<>(); - - public Queue awaitMessages(int expected) throws TimeoutException, InterruptedException - { - incomingMessages.awaitEventCount(expected,2,TimeUnit.SECONDS); - return incomingMessages; - } + public LinkedBlockingQueue incomingMessages = new LinkedBlockingQueue<>(); public boolean getClosed() { diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/LargeAnnotatedTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/LargeAnnotatedTest.java index aeaff1a2605..f9ea5de8dfb 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/LargeAnnotatedTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/LargeAnnotatedTest.java @@ -21,8 +21,8 @@ package org.eclipse.jetty.websocket.jsr356.server; import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.Arrays; -import java.util.Queue; import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.io.ByteBufferPool; @@ -31,6 +31,7 @@ import org.eclipse.jetty.toolchain.test.TestingDir; import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.client.WebSocketClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.jsr356.server.samples.echo.LargeEchoConfiguredSocket; import org.junit.Assert; import org.junit.Ignore; @@ -78,8 +79,8 @@ public class LargeAnnotatedTest Arrays.fill(txt,(byte)'o'); String msg = new String(txt,StandardCharsets.UTF_8); clientEcho.sendMessage(msg); - Queue msgs = clientEcho.awaitMessages(1); - Assert.assertEquals("Expected message",msg,msgs.poll()); + LinkedBlockingQueue msgs = clientEcho.incomingMessages; + Assert.assertEquals("Expected message",msg,msgs.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT)); } finally { diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/LargeContainerTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/LargeContainerTest.java index 304844cc18e..0bdf3f6a5a4 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/LargeContainerTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/LargeContainerTest.java @@ -21,8 +21,8 @@ package org.eclipse.jetty.websocket.jsr356.server; import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.Arrays; -import java.util.Queue; import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.io.ByteBufferPool; @@ -31,6 +31,7 @@ import org.eclipse.jetty.toolchain.test.TestingDir; import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.client.WebSocketClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.jsr356.server.samples.echo.LargeEchoDefaultSocket; import org.junit.Assert; import org.junit.Ignore; @@ -78,8 +79,8 @@ public class LargeContainerTest Arrays.fill(txt,(byte)'o'); String msg = new String(txt,StandardCharsets.UTF_8); clientEcho.sendMessage(msg); - Queue msgs = clientEcho.awaitMessages(1); - Assert.assertEquals("Expected message",msg,msgs.poll()); + LinkedBlockingQueue msgs = clientEcho.incomingMessages; + Assert.assertEquals("Expected message",msg,msgs.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT)); } finally { diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/PingPongTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/PingPongTest.java index 7f7ec875cd3..524afb8cd71 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/PingPongTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/PingPongTest.java @@ -18,7 +18,6 @@ package org.eclipse.jetty.websocket.jsr356.server; -import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; import java.io.File; @@ -28,9 +27,9 @@ import java.util.concurrent.TimeUnit; import javax.websocket.ContainerProvider; import javax.websocket.WebSocketContainer; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.webapp.WebAppContext; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.jsr356.server.samples.pong.PongContextListener; import org.eclipse.jetty.websocket.jsr356.server.samples.pong.PongMessageEndpoint; import org.eclipse.jetty.websocket.jsr356.server.samples.pong.PongSocket; @@ -78,7 +77,7 @@ public class PingPongTest @Test(timeout = 2000) public void testPingEndpoint() throws Exception { - EchoClientSocket socket = new EchoClientSocket(1); + EchoClientSocket socket = new EchoClientSocket(); URI toUri = serverUri.resolve("ping"); try @@ -91,12 +90,8 @@ public class PingPongTest String msg = "hello"; socket.sendPing(msg); - // Collect Responses - socket.awaitAllEvents(1,TimeUnit.SECONDS); - EventQueue received = socket.eventQueue; - // Validate Responses - String actual = received.poll(); + String actual = socket.eventQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Received Ping Response",actual,containsString("PongMessage[/ping]:" + msg)); } finally @@ -109,7 +104,7 @@ public class PingPongTest @Test(timeout = 2000) public void testPongEndpoint() throws Exception { - EchoClientSocket socket = new EchoClientSocket(1); + EchoClientSocket socket = new EchoClientSocket(); URI toUri = serverUri.resolve("pong"); try @@ -122,12 +117,9 @@ public class PingPongTest String msg = "hello"; socket.sendPong(msg); - // Collect Responses - socket.awaitAllEvents(1,TimeUnit.SECONDS); - EventQueue received = socket.eventQueue; - // Validate Responses - Assert.assertThat("Received Ping Responses",received,contains("PongMessage[/pong]:" + msg)); + String received = socket.eventQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + Assert.assertThat("Received Ping Responses",received,containsString("PongMessage[/pong]:" + msg)); } finally { @@ -139,7 +131,7 @@ public class PingPongTest @Test(timeout = 2000) public void testPingSocket() throws Exception { - EchoClientSocket socket = new EchoClientSocket(1); + EchoClientSocket socket = new EchoClientSocket(); URI toUri = serverUri.resolve("ping-socket"); try @@ -152,12 +144,8 @@ public class PingPongTest String msg = "hello"; socket.sendPing(msg); - // Collect Responses - socket.awaitAllEvents(1,TimeUnit.SECONDS); - EventQueue received = socket.eventQueue; - // Validate Responses - String actual = received.poll(); + String actual = socket.eventQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Received Ping Response",actual,containsString("@OnMessage(PongMessage)[/ping-socket]:" + msg)); } finally @@ -170,7 +158,7 @@ public class PingPongTest @Test(timeout = 2000) public void testPongSocket() throws Exception { - EchoClientSocket socket = new EchoClientSocket(1); + EchoClientSocket socket = new EchoClientSocket(); URI toUri = serverUri.resolve("pong-socket"); try @@ -183,12 +171,9 @@ public class PingPongTest String msg = "hello"; socket.sendPong(msg); - // Collect Responses - socket.awaitAllEvents(1,TimeUnit.SECONDS); - EventQueue received = socket.eventQueue; - // Validate Responses - Assert.assertThat("Received Ping Responses",received,contains("@OnMessage(PongMessage)[/pong-socket]:" + msg)); + String received = socket.eventQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + Assert.assertThat("Received Ping Responses",received,containsString("@OnMessage(PongMessage)[/pong-socket]:" + msg)); } finally { diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/SessionTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/SessionTest.java index f45338dc54a..57d81d14444 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/SessionTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/SessionTest.java @@ -30,8 +30,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; -import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.webapp.WebAppContext; @@ -101,8 +99,6 @@ public class SessionTest return cases; } - public ByteBufferPool bufferPool = new MappedByteBufferPool(); - private final Case testcase; private final static AtomicInteger ID = new AtomicInteger(0); private WSServer server; @@ -136,7 +132,7 @@ public class SessionTest private void assertResponse(String requestPath, String requestMessage, String expectedResponse) throws Exception { - WebSocketClient client = new WebSocketClient(bufferPool); + WebSocketClient client = new WebSocketClient(); try { client.start(); diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/TrackingSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/TrackingSocket.java index c9038199583..6343af16033 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/TrackingSocket.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/TrackingSocket.java @@ -23,12 +23,12 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import javax.websocket.CloseReason; import javax.websocket.CloseReason.CloseCode; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.junit.Assert; @@ -41,8 +41,8 @@ public abstract class TrackingSocket private static final Logger LOG = Log.getLogger(TrackingSocket.class); public CloseReason closeReason; - public EventQueue eventQueue = new EventQueue(); - public EventQueue errorQueue = new EventQueue<>(); + public LinkedBlockingQueue eventQueue = new LinkedBlockingQueue<>(); + public LinkedBlockingQueue errorQueue = new LinkedBlockingQueue<>(); public CountDownLatch openLatch = new CountDownLatch(1); public CountDownLatch closeLatch = new CountDownLatch(1); public CountDownLatch dataLatch = new CountDownLatch(1); @@ -50,12 +50,12 @@ public abstract class TrackingSocket protected void addError(Throwable t) { LOG.warn(t); - errorQueue.add(t); + errorQueue.offer(t); } protected void addEvent(String format, Object... args) { - eventQueue.add(String.format(format,args)); + eventQueue.offer(String.format(format,args)); } public void assertClose(CloseCode expectedCode, String expectedReason) throws InterruptedException @@ -76,12 +76,6 @@ public abstract class TrackingSocket Assert.assertThat("Close Reason",closeReason.getReasonPhrase(),is(expectedReason)); } - public void assertEvent(String expected) - { - String actual = eventQueue.poll(); - Assert.assertEquals("Event",expected,actual); - } - public void assertIsOpen() throws InterruptedException { assertWasOpened(); diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/EchoReturnEndpoint.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/EchoReturnEndpoint.java index 37679cdcaab..1a3affc3880 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/EchoReturnEndpoint.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/echo/EchoReturnEndpoint.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.websocket.jsr356.server.samples.echo; import java.io.IOException; +import java.util.concurrent.LinkedBlockingQueue; import javax.websocket.CloseReason; import javax.websocket.OnMessage; @@ -26,14 +27,12 @@ import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; -import org.eclipse.jetty.toolchain.test.EventQueue; - @ServerEndpoint(value = "/echoreturn") public class EchoReturnEndpoint { private Session session = null; public CloseReason close = null; - public EventQueue messageQueue = new EventQueue<>(); + public LinkedBlockingQueue messageQueue = new LinkedBlockingQueue<>(); public void onClose(CloseReason close) { 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 index c90a8be9a28..2b7ffe5e1e8 100644 --- 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 @@ -37,6 +37,7 @@ import java.nio.channels.SocketChannel; import java.util.Arrays; 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; @@ -50,7 +51,6 @@ 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.toolchain.test.EventQueue; import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; @@ -70,8 +70,8 @@ import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection; import org.eclipse.jetty.websocket.common.test.BlockheadServer; import org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection; -import org.eclipse.jetty.websocket.common.test.IncomingFramesCapture; import org.eclipse.jetty.websocket.common.test.RawFrameBuilder; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.hamcrest.Matcher; import org.junit.After; import org.junit.Before; @@ -94,7 +94,7 @@ public class ClientCloseTest public CountDownLatch openLatch = new CountDownLatch(1); public CountDownLatch errorLatch = new CountDownLatch(1); - public EventQueue messageQueue = new EventQueue<>(); + public LinkedBlockingQueue messageQueue = new LinkedBlockingQueue<>(); public AtomicReference error = new AtomicReference<>(); public void assertNoCloseEvent() @@ -198,25 +198,22 @@ public class ClientCloseTest final String echoMsg = "echo-test"; Future testFut = clientSocket.getRemote().sendStringByFuture(echoMsg); + serverConns.startReadThread(); + // Wait for send future testFut.get(30,TimeUnit.SECONDS); // Read Frame on server side - IncomingFramesCapture serverCapture = serverConns.readFrames(1,30,TimeUnit.SECONDS); - serverCapture.assertNoErrors(); - serverCapture.assertFrameCount(1); - WebSocketFrame frame = serverCapture.getFrames().poll(); + 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)); - // Wait for received echo - clientSocket.messageQueue.awaitEventCount(1,1,TimeUnit.SECONDS); - // Verify received message - String recvMsg = clientSocket.messageQueue.poll(); + String recvMsg = clientSocket.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("Received message",recvMsg,is(echoMsg)); // Verify that there are no errors @@ -228,14 +225,11 @@ public class ClientCloseTest } } - private void confirmServerReceivedCloseFrame(IBlockheadServerConnection serverConn, int expectedCloseCode, Matcher closeReasonMatcher) throws IOException, - TimeoutException + private void confirmServerReceivedCloseFrame(IBlockheadServerConnection serverConn, int expectedCloseCode, Matcher closeReasonMatcher) throws InterruptedException { - IncomingFramesCapture serverCapture = serverConn.readFrames(1,30,TimeUnit.SECONDS); - serverCapture.assertNoErrors(); - serverCapture.assertFrameCount(1); - serverCapture.assertHasFrame(OpCode.CLOSE,1); - WebSocketFrame frame = serverCapture.getFrames().poll(); + 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)); @@ -316,7 +310,7 @@ public class ClientCloseTest public void testHalfClose() throws Exception { // Set client timeout - final int timeout = 1000; + final int timeout = 5000; client.setMaxIdleTimeout(timeout); // Client connects @@ -327,38 +321,42 @@ public class ClientCloseTest IBlockheadServerConnection serverConn = server.accept(); serverConn.upgrade(); - // client confirms connection via echo - confirmConnection(clientSocket,clientConnectFuture,serverConn); + try + { + // 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); + // 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 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 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()); + // server sends close frame (code 1000, no reason) + CloseInfo sclose = new CloseInfo(StatusCode.NORMAL, "From Server"); + serverConn.write(sclose.asFrame()); - // client receives 2 messages - clientSocket.messageQueue.awaitEventCount(2,1,TimeUnit.SECONDS); + // 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 received messages - String recvMsg = clientSocket.messageQueue.poll(); - assertThat("Received message 1",recvMsg,is("Hello")); - recvMsg = clientSocket.messageQueue.poll(); - assertThat("Received message 2",recvMsg,is("World")); + // Verify that there are no errors + assertThat("Error events", clientSocket.error.get(), nullValue()); - // 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")); + // client close event on ws-endpoint + clientSocket.assertReceivedCloseEvent(timeout, is(StatusCode.NORMAL), containsString("From Server")); + } + finally + { + serverConn.disconnect(); + } } @Ignore("Need sbordet's help here") @@ -377,35 +375,42 @@ public class ClientCloseTest IBlockheadServerConnection serverConn = server.accept(); serverConn.upgrade(); - // 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()) + try { - 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); + // client confirms connection via echo + confirmConnection(clientSocket, clientConnectFuture, serverConn); - // Verify timeout error - assertThat("OnError Latch", clientSocket.errorLatch.await(2, TimeUnit.SECONDS), is(true)); - assertThat("OnError", clientSocket.error.get(), instanceOf(SocketTimeoutException.class)); + // 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)); + } + finally + { + serverConn.disconnect(); + } } @Test @@ -423,36 +428,41 @@ public class ClientCloseTest IBlockheadServerConnection serverConn = server.accept(); serverConn.upgrade(); - // 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 quiet = new StacklessLogging(Parser.class)) + try { - serverConn.write(bad); + // client confirms connection via echo + confirmConnection(clientSocket, clientConnectFuture, serverConn); - // 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 should not have received close message (yet) + clientSocket.assertNoCloseEvent(); - // client parse invalid frame, notifies server of close (protocol error) - confirmServerReceivedCloseFrame(serverConn,StatusCode.PROTOCOL,allOf(containsString("Invalid control frame"),containsString("length"))); + // 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 quiet = new StacklessLogging(Parser.class)) + { + serverConn.write(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"))); + } + } + finally + { + // server disconnects + serverConn.disconnect(); } - - // server disconnects - serverConn.disconnect(); // client triggers close event on client ws-endpoint clientSocket.assertReceivedCloseEvent(timeout,is(StatusCode.PROTOCOL),allOf(containsString("Invalid control frame"),containsString("length"))); @@ -473,29 +483,36 @@ public class ClientCloseTest IBlockheadServerConnection serverConn = server.accept(); serverConn.upgrade(); - // client confirms connection via echo - confirmConnection(clientSocket,clientConnectFuture,serverConn); + try + { + // client confirms connection via echo + confirmConnection(clientSocket, clientConnectFuture, serverConn); - // client sends close frame - final String origCloseReason = "Normal Close"; - clientSocket.getSession().close(StatusCode.NORMAL,origCloseReason); + // 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)); + // server receives close frame + confirmServerReceivedCloseFrame(serverConn, StatusCode.NORMAL, is(origCloseReason)); - // client should not have received close message (yet) - clientSocket.assertNoCloseEvent(); + // client should not have received close message (yet) + clientSocket.assertNoCloseEvent(); - // server shuts down connection (no frame reply) - serverConn.disconnect(); + // server shuts down connection (no frame reply) + serverConn.disconnect(); - // client reads -1 (EOF) - // client triggers close event on client ws-endpoint - clientSocket.assertReceivedCloseEvent(timeout,is(StatusCode.ABNORMAL), - anyOf( - containsString("EOF"), - containsString("Disconnected") - )); + // client reads -1 (EOF) + // client triggers close event on client ws-endpoint + clientSocket.assertReceivedCloseEvent(timeout, is(StatusCode.ABNORMAL), + anyOf( + containsString("EOF"), + containsString("Disconnected") + )); + } + finally + { + serverConn.disconnect(); + } } @Test @@ -513,25 +530,32 @@ public class ClientCloseTest IBlockheadServerConnection serverConn = server.accept(); serverConn.upgrade(); - // client confirms connection via echo - confirmConnection(clientSocket,clientConnectFuture,serverConn); + try + { + // client confirms connection via echo + confirmConnection(clientSocket, clientConnectFuture, serverConn); - // client sends close frame - final String origCloseReason = "Normal Close"; - clientSocket.getSession().close(StatusCode.NORMAL,origCloseReason); + // 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)); + // server receives close frame + confirmServerReceivedCloseFrame(serverConn, StatusCode.NORMAL, is(origCloseReason)); - // client should not have received close message (yet) - clientSocket.assertNoCloseEvent(); + // client should not have received close message (yet) + clientSocket.assertNoCloseEvent(); - // server never sends close frame handshake - // server sits idle + // 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 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)); + } + finally + { + serverConn.disconnect(); + } } @Test(timeout = 5000L) @@ -545,35 +569,45 @@ public class ClientCloseTest CloseTrackingSocket clientSockets[] = new CloseTrackingSocket[clientCount]; IBlockheadServerConnection serverConns[] = new IBlockheadServerConnection[clientCount]; - // Connect Multiple Clients - for (int i = 0; i < clientCount; i++) + try { - // Client Request Upgrade - clientSockets[i] = new CloseTrackingSocket(); - Future clientConnectFuture = client.connect(clientSockets[i],server.getWsUri()); + // Connect Multiple Clients + for (int i = 0; i < clientCount; i++) + { + // Client Request Upgrade + clientSockets[i] = new CloseTrackingSocket(); + Future clientConnectFuture = client.connect(clientSockets[i], server.getWsUri()); - // Server accepts connection - serverConns[i] = server.accept(); - serverConns[i].upgrade(); + // Server accepts connection + serverConns[i] = server.accept(); + serverConns[i].upgrade(); - // client confirms connection via echo - confirmConnection(clientSockets[i],clientConnectFuture,serverConns[i]); + // client confirms connection via echo + confirmConnection(clientSockets[i], clientConnectFuture, serverConns[i]); + } + + // client lifecycle stop + client.stop(); + + // clients send close frames (code 1001, shutdown) + for (int i = 0; i < clientCount; i++) + { + // server receives close frame + confirmServerReceivedCloseFrame(serverConns[i], StatusCode.SHUTDOWN, containsString("Shutdown")); + } + + // clients disconnect + for (int i = 0; i < clientCount; i++) + { + clientSockets[i].assertReceivedCloseEvent(timeout, is(StatusCode.SHUTDOWN), containsString("Shutdown")); + } } - - // client lifecycle stop - client.stop(); - - // clients send close frames (code 1001, shutdown) - for (int i = 0; i < clientCount; i++) + finally { - // server receives close frame - confirmServerReceivedCloseFrame(serverConns[i],StatusCode.SHUTDOWN,containsString("Shutdown")); - } - - // clients disconnect - for (int i = 0; i < clientCount; i++) - { - clientSockets[i].assertReceivedCloseEvent(timeout,is(StatusCode.SHUTDOWN),containsString("Shutdown")); + for(IBlockheadServerConnection serverConn: serverConns) + { + serverConn.disconnect(); + } } } @@ -592,24 +626,31 @@ public class ClientCloseTest IBlockheadServerConnection serverConn = server.accept(); serverConn.upgrade(); - // client confirms connection via echo - confirmConnection(clientSocket,clientConnectFuture,serverConn); + try + { + // client confirms connection via echo + confirmConnection(clientSocket, clientConnectFuture, serverConn); - // setup client endpoint for write failure (test only) - EndPoint endp = clientSocket.getEndPoint(); - endp.shutdownOutput(); + // 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 enqueue close frame + // client write failure + final String origCloseReason = "Normal Close"; + clientSocket.getSession().close(StatusCode.NORMAL, origCloseReason); - // 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("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")); + } + finally + { + serverConn.disconnect(); + } } } 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 index 06ec0555587..18f827598d0 100644 --- 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 @@ -19,7 +19,6 @@ package org.eclipse.jetty.websocket.client; import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -29,10 +28,9 @@ import java.util.Collections; import java.util.List; 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 org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.Session; @@ -42,6 +40,7 @@ import org.eclipse.jetty.websocket.api.util.QuoteUtil; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadServer; import org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -53,8 +52,8 @@ public class CookieTest public static class CookieTrackingSocket extends WebSocketAdapter { - public EventQueue messageQueue = new EventQueue<>(); - public EventQueue errorQueue = new EventQueue<>(); + public LinkedBlockingQueue messageQueue = new LinkedBlockingQueue<>(); + public LinkedBlockingQueue errorQueue = new LinkedBlockingQueue<>(); private CountDownLatch openLatch = new CountDownLatch(1); @Override @@ -189,18 +188,8 @@ public class CookieTest clientConnectFuture.get(10,TimeUnit.SECONDS); clientSocket.awaitOpen(2,TimeUnit.SECONDS); - try - { - // Wait for client receipt of cookie frame via client websocket - clientSocket.messageQueue.awaitEventCount(1, 3, TimeUnit.SECONDS); - } - catch (TimeoutException e) - { - e.printStackTrace(System.err); - assertThat("Message Count", clientSocket.messageQueue.size(), is(1)); - } - - String cookies = clientSocket.messageQueue.poll(); + // 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 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 index 4f32deedf7b..7a2162c1ee1 100644 --- 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 @@ -25,15 +25,14 @@ import static org.junit.Assert.assertThat; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Exchanger; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import org.eclipse.jetty.toolchain.test.EventQueue; 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.Session; import org.eclipse.jetty.websocket.api.WebSocketAdapter; import org.junit.Assert; @@ -52,8 +51,8 @@ public class JettyTrackingSocket extends WebSocketAdapter public CountDownLatch openLatch = new CountDownLatch(1); public CountDownLatch closeLatch = new CountDownLatch(1); public CountDownLatch dataLatch = new CountDownLatch(1); - public EventQueue messageQueue = new EventQueue<>(); - public EventQueue errorQueue = new EventQueue<>(); + public LinkedBlockingQueue messageQueue = new LinkedBlockingQueue<>(); + public LinkedBlockingQueue errorQueue = new LinkedBlockingQueue<>(); public void assertClose(int expectedStatusCode, String expectedReason) throws InterruptedException { @@ -78,12 +77,6 @@ public class JettyTrackingSocket extends WebSocketAdapter assertNotClosed(); } - public void assertMessage(String expected) - { - String actual = messageQueue.poll(); - Assert.assertEquals("Message",expected,actual); - } - public void assertNotClosed() { LOG.debug("assertNotClosed() - {}", closeLatch.getCount()); @@ -102,11 +95,6 @@ public class JettyTrackingSocket extends WebSocketAdapter Assert.assertThat("Was Opened",openLatch.await(30,TimeUnit.SECONDS),is(true)); } - public void awaitMessage(int expectedMessageCount, TimeUnit timeoutUnit, int timeoutDuration) throws TimeoutException, InterruptedException - { - messageQueue.awaitEventCount(expectedMessageCount,timeoutDuration,timeoutUnit); - } - public void clear() { messageQueue.clear(); diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/MaxMessageSocket.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/MaxMessageSocket.java index 1fb0407666a..5e71a96933f 100644 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/MaxMessageSocket.java +++ b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/MaxMessageSocket.java @@ -21,9 +21,9 @@ package org.eclipse.jetty.websocket.client; import static org.hamcrest.Matchers.is; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.Session; @@ -42,8 +42,8 @@ public class MaxMessageSocket public CountDownLatch openLatch = new CountDownLatch(1); public CountDownLatch closeLatch = new CountDownLatch(1); public CountDownLatch dataLatch = new CountDownLatch(1); - public EventQueue messageQueue = new EventQueue<>(); - public EventQueue errorQueue = new EventQueue<>(); + public LinkedBlockingQueue messageQueue = new LinkedBlockingQueue<>(); + public LinkedBlockingQueue errorQueue = new LinkedBlockingQueue<>(); public int closeCode = -1; public StringBuilder closeMessage = new StringBuilder(); diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerReadThread.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerReadThread.java index a170ce9ffc5..82a3e3cbb70 100644 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerReadThread.java +++ b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerReadThread.java @@ -18,12 +18,12 @@ package org.eclipse.jetty.websocket.client; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; import java.io.IOException; import java.nio.ByteBuffer; -import java.util.Queue; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -35,6 +35,7 @@ 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.IBlockheadServerConnection; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.Assert; public class ServerReadThread extends Thread @@ -89,9 +90,9 @@ public class ServerReadThread extends Thread conn.getParser().parse(buf); } - Queue frames = conn.getIncomingFrames().getFrames(); + LinkedBlockingQueue frames = conn.getFrameQueue(); WebSocketFrame frame; - while ((frame = frames.poll()) != null) + while ((frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT)) != null) { frameCount.incrementAndGet(); if (frame.getOpCode() == OpCode.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 index 08aea0f82c7..ea6eef03f9c 100644 --- 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 @@ -18,7 +18,10 @@ package org.eclipse.jetty.websocket.client; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertThat; import java.net.URI; import java.util.Collection; @@ -32,6 +35,7 @@ import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.test.BlockheadServer; import org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -74,18 +78,17 @@ public class SessionTest final IBlockheadServerConnection srvSock = server.accept(); srvSock.upgrade(); - - Session sess = future.get(30000,TimeUnit.MILLISECONDS); - Assert.assertThat("Session",sess,notNullValue()); - Assert.assertThat("Session.open",sess.isOpen(),is(true)); - Assert.assertThat("Session.upgradeRequest",sess.getUpgradeRequest(),notNullValue()); - Assert.assertThat("Session.upgradeResponse",sess.getUpgradeResponse(),notNullValue()); + Session sess = future.get(30000, TimeUnit.MILLISECONDS); + Assert.assertThat("Session", sess, notNullValue()); + Assert.assertThat("Session.open", sess.isOpen(), is(true)); + Assert.assertThat("Session.upgradeRequest", sess.getUpgradeRequest(), notNullValue()); + Assert.assertThat("Session.upgradeResponse", sess.getUpgradeResponse(), notNullValue()); cliSock.assertWasOpened(); cliSock.assertNotClosed(); Collection sessions = client.getBeans(WebSocketSession.class); - Assert.assertThat("client.connectionManager.sessions.size",sessions.size(),is(1)); + Assert.assertThat("client.connectionManager.sessions.size", sessions.size(), is(1)); RemoteEndpoint remote = cliSock.getSession().getRemote(); remote.sendStringByFuture("Hello World!"); @@ -93,19 +96,31 @@ public class SessionTest { remote.flush(); } - srvSock.echoMessage(1,30000,TimeUnit.MILLISECONDS); - // wait for response from server - cliSock.waitForMessage(30000,TimeUnit.MILLISECONDS); - - Set open = client.getOpenSessions(); - Assert.assertThat("(Before Close) Open Sessions.size", open.size(), is(1)); - cliSock.assertMessage("Hello World!"); - cliSock.close(); - srvSock.close(); - - cliSock.waitForClose(30000,TimeUnit.MILLISECONDS); - open = client.getOpenSessions(); + try + { + srvSock.enableIncomingEcho(true); + srvSock.startReadThread(); + // wait for response from server + cliSock.waitForMessage(30000, TimeUnit.MILLISECONDS); + + Set open = client.getOpenSessions(); + Assert.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(); + srvSock.close(); + } + finally + { + srvSock.disconnect(); + } + + cliSock.waitForClose(30000, TimeUnit.MILLISECONDS); + Set open = client.getOpenSessions(); + // TODO this sometimes fails! Assert.assertThat("(After Close) Open Sessions.size", open.size(), is(0)); } 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 index 35b61ccad16..90fe11e4da5 100644 --- 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 @@ -18,10 +18,12 @@ 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.junit.Assert.assertThat; import java.net.InetSocketAddress; import java.net.URI; @@ -43,6 +45,7 @@ import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.io.FutureWriteCallback; import org.eclipse.jetty.websocket.common.test.BlockheadServer; import org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -103,26 +106,36 @@ public class WebSocketClientTest srvSock.upgrade(); Session sess = future.get(30,TimeUnit.SECONDS); - Assert.assertThat("Session",sess,notNullValue()); - Assert.assertThat("Session.open",sess.isOpen(),is(true)); - Assert.assertThat("Session.upgradeRequest",sess.getUpgradeRequest(),notNullValue()); - Assert.assertThat("Session.upgradeResponse",sess.getUpgradeResponse(),notNullValue()); + 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(); - Assert.assertThat("client.connectionManager.sessions.size",sessions.size(),is(1)); + 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(); - srvSock.echoMessage(1,30,TimeUnit.SECONDS); - // wait for response from server - cliSock.waitForMessage(30,TimeUnit.SECONDS); - cliSock.assertMessage("Hello World!"); + try + { + srvSock.enableIncomingEcho(true); + srvSock.startReadThread(); + + // wait for response from server + String received = cliSock.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + assertThat("Message", received, containsString("Hello World")); + } + finally + { + srvSock.close(); + srvSock.disconnect(); + } } @Test @@ -140,16 +153,16 @@ public class WebSocketClientTest srvSock.upgrade(); Session sess = future.get(30,TimeUnit.SECONDS); - Assert.assertThat("Session",sess,notNullValue()); - Assert.assertThat("Session.open",sess.isOpen(),is(true)); - Assert.assertThat("Session.upgradeRequest",sess.getUpgradeRequest(),notNullValue()); - Assert.assertThat("Session.upgradeResponse",sess.getUpgradeResponse(),notNullValue()); + 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); - Assert.assertThat("client.connectionManager.sessions.size",sessions.size(),is(1)); + assertThat("client.connectionManager.sessions.size",sessions.size(),is(1)); FutureWriteCallback callback = new FutureWriteCallback(); @@ -169,10 +182,10 @@ public class WebSocketClientTest // Validate connect Session sess = future.get(30,TimeUnit.SECONDS); - Assert.assertThat("Session",sess,notNullValue()); - Assert.assertThat("Session.open",sess.isOpen(),is(true)); - Assert.assertThat("Session.upgradeRequest",sess.getUpgradeRequest(),notNullValue()); - Assert.assertThat("Session.upgradeResponse",sess.getUpgradeResponse(),notNullValue()); + 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 srvSock.write(new TextFrame().setPayload("Hello World")); @@ -180,9 +193,9 @@ public class WebSocketClientTest // Verify connect future.get(30,TimeUnit.SECONDS); wsocket.assertWasOpened(); - wsocket.awaitMessage(1,TimeUnit.SECONDS,2); - wsocket.assertMessage("Hello World"); + String received = wsocket.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + assertThat("Message", received, containsString("Hello World")); } @Test @@ -203,15 +216,15 @@ public class WebSocketClientTest InetSocketAddress local = wsocket.getSession().getLocalAddress(); InetSocketAddress remote = wsocket.getSession().getRemoteAddress(); - Assert.assertThat("Local Socket Address",local,notNullValue()); - Assert.assertThat("Remote Socket Address",remote,notNullValue()); + 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 - Assert.assertThat("Local Socket Address / Host",local.getAddress().getHostAddress(),notNullValue()); - Assert.assertThat("Local Socket Address / Port",local.getPort(),greaterThan(0)); + assertThat("Local Socket Address / Host",local.getAddress().getHostAddress(),notNullValue()); + assertThat("Local Socket Address / Port",local.getPort(),greaterThan(0)); - Assert.assertThat("Remote Socket Address / Host",remote.getAddress().getHostAddress(),is(wsUri.getHost())); - Assert.assertThat("Remote Socket Address / Port",remote.getPort(),greaterThan(0)); + assertThat("Remote Socket Address / Host",remote.getAddress().getHostAddress(),is(wsUri.getHost())); + assertThat("Remote Socket Address / Port",remote.getPort(),greaterThan(0)); } @Test @@ -265,8 +278,8 @@ public class WebSocketClientTest wsocket.awaitConnect(1,TimeUnit.SECONDS); Session sess = future.get(30,TimeUnit.SECONDS); - Assert.assertThat("Session",sess,notNullValue()); - Assert.assertThat("Session.open",sess.isOpen(),is(true)); + 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 @@ -275,13 +288,23 @@ public class WebSocketClientTest String msg = StringUtil.toUTF8String(buf,0,buf.length); wsocket.getSession().getRemote().sendStringByFuture(msg); - ssocket.echoMessage(1,2,TimeUnit.SECONDS); - // wait for response from server - wsocket.waitForMessage(1,TimeUnit.SECONDS); + try + { + ssocket.enableIncomingEcho(true); + ssocket.startReadThread(); - wsocket.assertMessage(msg); + // wait for response from server + wsocket.waitForMessage(1, TimeUnit.SECONDS); - Assert.assertTrue(wsocket.dataLatch.await(2,TimeUnit.SECONDS)); + wsocket.assertMessage(msg); + + Assert.assertTrue(wsocket.dataLatch.await(2, TimeUnit.SECONDS)); + } + finally + { + ssocket.close(); + ssocket.disconnect(); + } } @Test @@ -301,15 +324,15 @@ public class WebSocketClientTest Session session = wsocket.getSession(); UpgradeRequest req = session.getUpgradeRequest(); - Assert.assertThat("Upgrade Request",req,notNullValue()); + assertThat("Upgrade Request",req,notNullValue()); Map> parameterMap = req.getParameterMap(); - Assert.assertThat("Parameter Map",parameterMap,notNullValue()); + assertThat("Parameter Map",parameterMap,notNullValue()); - Assert.assertThat("Parameter[snack]",parameterMap.get("snack"),is(Arrays.asList(new String[] { "cashews" }))); - Assert.assertThat("Parameter[amount]",parameterMap.get("amount"),is(Arrays.asList(new String[] { "handful" }))); - Assert.assertThat("Parameter[brand]",parameterMap.get("brand"),is(Arrays.asList(new String[] { "off" }))); + 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" }))); - Assert.assertThat("Parameter[cost]",parameterMap.get("cost"),nullValue()); + assertThat("Parameter[cost]",parameterMap.get("cost"),nullValue()); } } diff --git a/jetty-websocket/websocket-client/src/test/resources/jetty-logging.properties b/jetty-websocket/websocket-client/src/test/resources/jetty-logging.properties index 880f5fcf070..35d2326510d 100644 --- a/jetty-websocket/websocket-client/src/test/resources/jetty-logging.properties +++ b/jetty-websocket/websocket-client/src/test/resources/jetty-logging.properties @@ -10,6 +10,7 @@ org.eclipse.jetty.LEVEL=WARN # org.eclipse.jetty.websocket.client.ClientCloseTest.LEVEL=DEBUG # org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.LEVEL=DEBUG # org.eclipse.jetty.websocket.common.io.IOState.LEVEL=DEBUG +# org.eclipse.jetty.websocket.common.test.LEVEL=DEBUG # org.eclipse.jetty.websocket.common.Generator.LEVEL=DEBUG # org.eclipse.jetty.websocket.common.Parser.LEVEL=DEBUG diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventCapture.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventCapture.java index 85bb4543898..8a140fafd8f 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventCapture.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventCapture.java @@ -22,15 +22,19 @@ import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.startsWith; +import java.util.concurrent.LinkedBlockingQueue; import java.util.regex.Pattern; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.junit.Assert; +/** + * @deprecated should refactor away. + */ @SuppressWarnings("serial") -public class EventCapture extends EventQueue +@Deprecated +public class EventCapture extends LinkedBlockingQueue { private static final Logger LOG = Log.getLogger(EventCapture.class); @@ -74,6 +78,7 @@ public class EventCapture extends EventQueue public Assertable pop() { + // TODO: poll should have timeout. return new Assertable(super.poll()); } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/TrackingInputStreamSocket.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/TrackingInputStreamSocket.java index 97f75704824..9730a0f0b9c 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/TrackingInputStreamSocket.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/TrackingInputStreamSocket.java @@ -23,9 +23,9 @@ import static org.hamcrest.Matchers.is; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -43,8 +43,8 @@ public class TrackingInputStreamSocket public int closeCode = -1; public StringBuilder closeMessage = new StringBuilder(); public CountDownLatch closeLatch = new CountDownLatch(1); - public EventQueue messageQueue = new EventQueue<>(); - public EventQueue errorQueue = new EventQueue<>(); + public LinkedBlockingQueue messageQueue = new LinkedBlockingQueue<>(); + public LinkedBlockingQueue errorQueue = new LinkedBlockingQueue<>(); public TrackingInputStreamSocket() { diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/TrackingSocket.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/TrackingSocket.java index 40a2db3ba36..bd52cf5e01e 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/TrackingSocket.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/TrackingSocket.java @@ -22,10 +22,9 @@ import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.is; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.Session; @@ -45,8 +44,8 @@ public class TrackingSocket extends WebSocketAdapter public CountDownLatch openLatch = new CountDownLatch(1); public CountDownLatch closeLatch = new CountDownLatch(1); public CountDownLatch dataLatch = new CountDownLatch(1); - public EventQueue messageQueue = new EventQueue<>(); - public EventQueue errorQueue = new EventQueue<>(); + public LinkedBlockingQueue messageQueue = new LinkedBlockingQueue<>(); + public LinkedBlockingQueue errorQueue = new LinkedBlockingQueue<>(); public TrackingSocket() { @@ -102,11 +101,6 @@ public class TrackingSocket extends WebSocketAdapter Assert.assertThat("Was Opened",openLatch.await(30,TimeUnit.SECONDS),is(true)); } - public void awaitMessage(int expectedMessageCount, TimeUnit timeoutUnit, int timeoutDuration) throws TimeoutException, InterruptedException - { - messageQueue.awaitEventCount(expectedMessageCount,timeoutDuration,timeoutUnit); - } - public void clear() { messageQueue.clear(); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java index 889379c9da1..e7bca7d02af 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java @@ -41,13 +41,13 @@ import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import javax.net.ssl.HttpsURLConnection; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.StringUtil; @@ -96,8 +96,8 @@ public class BlockheadClient implements OutgoingFrames, ConnectionStateListener, public long totalReadOps = 0; public long totalParseOps = 0; - public EventQueue frames = new EventQueue<>(); - public EventQueue errors = new EventQueue<>(); + public LinkedBlockingQueue frames = new LinkedBlockingQueue<>(); + public LinkedBlockingQueue errors = new LinkedBlockingQueue<>(); @Override public void run() @@ -630,9 +630,8 @@ public class BlockheadClient implements OutgoingFrames, ConnectionStateListener, } @Override - public EventQueue readFrames(int expectedFrameCount, int timeoutDuration, TimeUnit timeoutUnit) throws Exception + public LinkedBlockingQueue getFrameQueue() { - frameReader.frames.awaitEventCount(expectedFrameCount,timeoutDuration,timeoutUnit); return frameReader.frames; } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java index 026df3cdf10..6ab10df9091 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java @@ -18,7 +18,8 @@ package org.eclipse.jetty.websocket.common.test; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import java.io.BufferedReader; import java.io.IOException; @@ -32,8 +33,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +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.regex.Matcher; @@ -50,9 +51,9 @@ import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.WriteCallback; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.Frame.Type; import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; -import org.eclipse.jetty.websocket.api.extensions.Frame.Type; import org.eclipse.jetty.websocket.common.AcceptHash; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.Generator; @@ -73,13 +74,15 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames private final Socket socket; private final ByteBufferPool bufferPool; private final WebSocketPolicy policy; - private final IncomingFramesCapture incomingFrames; + private final LinkedBlockingQueue incomingFrames = new LinkedBlockingQueue<>(); + private final LinkedBlockingQueue incomingErrors = new LinkedBlockingQueue<>(); private final Parser parser; private final Generator generator; private final AtomicInteger parseCount; private final WebSocketExtensionFactory extensionRegistry; private final AtomicBoolean echoing = new AtomicBoolean(false); - private Thread echoThread; + private final AtomicBoolean reading = new AtomicBoolean(false); + private Thread readThread; /** Set to true to disable timeouts (for debugging reasons) */ private boolean debug = false; @@ -92,7 +95,6 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames public BlockheadServerConnection(Socket socket) { this.socket = socket; - this.incomingFrames = new IncomingFramesCapture(); this.policy = WebSocketPolicy.newServerPolicy(); this.policy.setMaxBinaryMessageSize(100000); this.policy.setMaxTextMessageSize(100000); @@ -140,6 +142,7 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames public void disconnect() { LOG.debug("disconnect"); + reading.set(false); IO.close(in); IO.close(out); if (socket != null) @@ -154,19 +157,6 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames } } } - - @Override - public void echoMessage(int expectedFrames, int timeoutDuration, TimeUnit timeoutUnit) throws IOException, TimeoutException - { - LOG.debug("Echo Frames [expecting {}]",expectedFrames); - IncomingFramesCapture cap = readFrames(expectedFrames,timeoutDuration,timeoutUnit); - // now echo them back. - for (Frame frame : cap.getFrames()) - { - write(WebSocketFrame.copy(frame).setMasked(false)); - } - } - @Override public void flush() throws IOException { @@ -179,12 +169,6 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames return bufferPool; } - @Override - public IncomingFramesCapture getIncomingFrames() - { - return incomingFrames; - } - public InputStream getInputStream() throws IOException { if (in == null) @@ -217,19 +201,19 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames @Override public void incomingError(Throwable e) { - incomingFrames.incomingError(e); + incomingErrors.offer(e); } @Override public void incomingFrame(Frame frame) { - LOG.debug("incoming({})",frame); + LOG.debug("incomingFrame({})",frame); int count = parseCount.incrementAndGet(); if ((count % 10) == 0) { LOG.info("Server parsed {} frames",count); } - incomingFrames.incomingFrame(WebSocketFrame.copy(frame)); + incomingFrames.offer(WebSocketFrame.copy(frame)); if (frame.getOpCode() == OpCode.CLOSE) { @@ -238,6 +222,7 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames } Type type = frame.getType(); + if (echoing.get() && (type.isData() || type.isContinuation())) { try @@ -329,52 +314,8 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames } @Override - public IncomingFramesCapture readFrames(int expectedCount, int timeoutDuration, TimeUnit timeoutUnit) throws IOException, TimeoutException + public LinkedBlockingQueue getFrameQueue() { - LOG.debug("Read: waiting for {} frame(s) from client",expectedCount); - int startCount = incomingFrames.size(); - - ByteBuffer buf = bufferPool.acquire(BUFFER_SIZE,false); - BufferUtil.clearToFill(buf); - try - { - long msDur = TimeUnit.MILLISECONDS.convert(timeoutDuration,timeoutUnit); - long now = System.currentTimeMillis(); - long expireOn = now + msDur; - LOG.debug("Now: {} - expireOn: {} ({} ms)",now,expireOn,msDur); - - int len = 0; - while (incomingFrames.size() < (startCount + expectedCount)) - { - BufferUtil.clearToFill(buf); - len = read(buf); - if (len > 0) - { - LOG.debug("Read {} bytes",len); - BufferUtil.flipToFlush(buf,0); - parser.parse(buf); - } - try - { - TimeUnit.MILLISECONDS.sleep(20); - } - catch (InterruptedException gnore) - { - /* ignore */ - } - if (!debug && (System.currentTimeMillis() > expireOn)) - { - incomingFrames.dump(); - throw new TimeoutException(String.format("Timeout reading all %d expected frames. (managed to only read %d frame(s))",expectedCount, - incomingFrames.size())); - } - } - } - finally - { - bufferPool.release(buf); - } - return incomingFrames; } @@ -457,20 +398,19 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames { LOG.debug("Entering echo thread"); - ByteBuffer buf = bufferPool.acquire(BUFFER_SIZE,false); - BufferUtil.clearToFill(buf); - long readBytes = 0; - try + long totalReadBytes = 0; + ByteBuffer buf = bufferPool.acquire(BUFFER_SIZE, false); + while(reading.get()) { - while (echoing.get()) + try { BufferUtil.clearToFill(buf); long len = read(buf); if (len > 0) { - readBytes += len; - LOG.debug("Read {} bytes",len); - BufferUtil.flipToFlush(buf,0); + totalReadBytes += len; + LOG.debug("Read {} bytes", len); + BufferUtil.flipToFlush(buf, 0); parser.parse(buf); } @@ -483,16 +423,18 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames /* ignore */ } } + catch (IOException e) + { + LOG.debug("Exception during echo loop", e); + } + catch (Throwable t) + { + LOG.warn("Exception during echo loop", t); + } } - catch (IOException e) - { - LOG.debug("Exception during echo loop",e); - } - finally - { - LOG.debug("Read {} bytes",readBytes); - bufferPool.release(buf); - } + + LOG.debug("Read {} total bytes (exiting)",totalReadBytes); + bufferPool.release(buf); } @Override @@ -502,21 +444,22 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames } @Override - public void startEcho() + public void startReadThread() { - if (echoThread != null) + if (readThread != null) { - throw new IllegalStateException("Echo thread already declared!"); + throw new IllegalStateException("Read thread already declared/started!"); } - echoThread = new Thread(this,"BlockheadServer/Echo"); - echoing.set(true); - echoThread.start(); + readThread = new Thread(this,"BlockheadServer/Read"); + LOG.debug("Starting Read Thread: {}", readThread); + reading.set(true); + readThread.start(); } @Override - public void stopEcho() + public void enableIncomingEcho(boolean enabled) { - echoing.set(false); + echoing.set(enabled); } @Override diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java index af932f72ce2..87c74d437e4 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java @@ -27,9 +27,9 @@ import java.nio.ByteBuffer; import java.util.Collections; import java.util.List; import java.util.Locale; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -146,19 +146,27 @@ public class Fuzzer implements AutoCloseable expect(expect,10,TimeUnit.SECONDS); } + /** + * Read the response frames and validate them against the expected frame list + * + * @param expect the list of expected frames + * @param duration the timeout duration to wait for each read frame + * @param unit the timeout unit to wait for each read frame + * @throws Exception if unable to validate expectations + */ public void expect(List expect, int duration, TimeUnit unit) throws Exception { int expectedCount = expect.size(); LOG.debug("expect() {} frame(s)",expect.size()); // Read frames - EventQueue frames = client.readFrames(expect.size(),duration,unit); + LinkedBlockingQueue frames = client.getFrameQueue(); String prefix = ""; for (int i = 0; i < expectedCount; i++) { WebSocketFrame expected = expect.get(i); - WebSocketFrame actual = frames.poll(); + WebSocketFrame actual = frames.poll(duration,unit); prefix = "Frame[" + i + "]"; diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadClient.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadClient.java index a2321ba6429..743e718fda1 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadClient.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadClient.java @@ -21,9 +21,9 @@ package org.eclipse.jetty.websocket.common.test; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.websocket.common.WebSocketFrame; /** @@ -56,7 +56,7 @@ public interface IBlockheadClient extends AutoCloseable public InetSocketAddress getRemoteSocketAddress(); - public EventQueue readFrames(int expectedFrameCount, int timeoutDuration, TimeUnit timeoutUnit) throws Exception; + public LinkedBlockingQueue getFrameQueue(); public HttpResponse readResponseHeader() throws IOException; diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadServerConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadServerConnection.java index 9c799171db6..d5dceebd266 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadServerConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadServerConnection.java @@ -22,47 +22,46 @@ import java.io.IOException; import java.net.SocketException; import java.nio.ByteBuffer; import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import java.util.concurrent.LinkedBlockingQueue; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.Parser; +import org.eclipse.jetty.websocket.common.WebSocketFrame; public interface IBlockheadServerConnection { public void close() throws IOException; - public void close(int statusCode) throws IOException; - - public void write(Frame frame) throws IOException; - - public List upgrade() throws IOException; - public void disconnect(); - public IncomingFramesCapture readFrames(int expectedCount, int timeoutDuration, TimeUnit timeoutUnit) throws IOException, TimeoutException; + public void write(Frame frame) throws IOException; public void write(ByteBuffer buf) throws IOException; + public void write(int b) throws IOException; + public void flush() throws IOException; + + public LinkedBlockingQueue getFrameQueue(); + + public void enableIncomingEcho(boolean enabled); + public void startReadThread(); + + public String readRequest() throws IOException; public List readRequestLines() throws IOException; public String parseWebSocketKey(List requestLines); - public void respond(String rawstr) throws IOException; - public String readRequest() throws IOException; - public List regexFind(List lines, String pattern); - public void echoMessage(int expectedFrames, int timeoutDuration, TimeUnit timeoutUnit) throws IOException, TimeoutException; - public void setSoTimeout(int ms) throws SocketException; - public ByteBufferPool getBufferPool(); - public int read(ByteBuffer buf) throws IOException; - public Parser getParser(); - public IncomingFramesCapture getIncomingFrames(); - public void flush() throws IOException; - public void write(int b) throws IOException; - public void startEcho(); - public void stopEcho(); - /** * Add an extra header for the upgrade response (from the server). No extra work is done to ensure the key and value are sane for http. * @param rawkey the raw key * @param rawvalue the raw value */ public void addResponseHeader(String rawkey, String rawvalue); + public List upgrade() throws IOException; + public void setSoTimeout(int ms) throws SocketException; + + public void respond(String rawstr) throws IOException; + public List regexFind(List lines, String pattern); + public ByteBufferPool getBufferPool(); + public Parser getParser(); + + @Deprecated + public int read(ByteBuffer buf) throws IOException; } \ No newline at end of file diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IncomingFramesCapture.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IncomingFramesCapture.java index ed01e8597ff..e9835591cce 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IncomingFramesCapture.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IncomingFramesCapture.java @@ -22,8 +22,8 @@ import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.is; import java.util.Queue; +import java.util.concurrent.LinkedBlockingQueue; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -37,8 +37,8 @@ import org.junit.Assert; public class IncomingFramesCapture implements IncomingFrames { private static final Logger LOG = Log.getLogger(IncomingFramesCapture.class); - private EventQueue frames = new EventQueue<>(); - private EventQueue errors = new EventQueue<>(); + private LinkedBlockingQueue frames = new LinkedBlockingQueue<>(); + private LinkedBlockingQueue errors = new LinkedBlockingQueue<>(); public void assertErrorCount(int expectedCount) { diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Timeouts.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Timeouts.java new file mode 100644 index 00000000000..fa3321e2f18 --- /dev/null +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Timeouts.java @@ -0,0 +1,27 @@ +// +// ======================================================================== +// 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.common.test; + +import java.util.concurrent.TimeUnit; + +public class Timeouts +{ + public static long POLL_EVENT = 2; + public static TimeUnit POLL_EVENT_UNIT = TimeUnit.SECONDS; +} diff --git a/jetty-websocket/websocket-common/src/test/resources/jetty-logging.properties b/jetty-websocket/websocket-common/src/test/resources/jetty-logging.properties index 683b76a631f..525226380f0 100644 --- a/jetty-websocket/websocket-common/src/test/resources/jetty-logging.properties +++ b/jetty-websocket/websocket-common/src/test/resources/jetty-logging.properties @@ -1,6 +1,7 @@ org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog org.eclipse.jetty.LEVEL=WARN # org.eclipse.jetty.websocket.LEVEL=DEBUG +# org.eclipse.jetty.websocket.common.test.LEVEL=DEBUG # org.eclipse.jetty.websocket.protocol.Parser.LEVEL=DEBUG # org.eclipse.jetty.websocket.protocol.LEVEL=DEBUG # org.eclipse.jetty.websocket.io.payload.LEVEL=DEBUG diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/AnnotatedMaxMessageSizeTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/AnnotatedMaxMessageSizeTest.java index 240d10755b9..f24fa3465db 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/AnnotatedMaxMessageSizeTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/AnnotatedMaxMessageSizeTest.java @@ -24,11 +24,10 @@ import java.io.IOException; import java.net.URI; import java.nio.ByteBuffer; import java.util.Arrays; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.LinkedBlockingQueue; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.util.log.StacklessLogging; import org.eclipse.jetty.websocket.api.StatusCode; @@ -38,6 +37,7 @@ import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.examples.echo.BigEchoSocket; import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; import org.junit.AfterClass; @@ -105,8 +105,8 @@ public class AnnotatedMaxMessageSizeTest client.write(new TextFrame().setPayload(msg)); // Read frame (hopefully text frame) - EventQueue frames = client.readFrames(1,30,TimeUnit.SECONDS); - WebSocketFrame tf = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame.status code",tf.getPayloadAsUTF8(),is(msg)); } finally @@ -133,8 +133,8 @@ public class AnnotatedMaxMessageSizeTest client.write(new TextFrame().setPayload(ByteBuffer.wrap(buf))); // Read frame (hopefully close frame saying its too large) - EventQueue frames = client.readFrames(1,30,TimeUnit.SECONDS); - WebSocketFrame tf = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame is close", tf.getOpCode(), is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(tf); Assert.assertThat("Close Code", close.getStatusCode(), is(StatusCode.MESSAGE_TOO_LARGE)); diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ChromeTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ChromeTest.java index f16a5bd3b5d..aa3437c9255 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ChromeTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ChromeTest.java @@ -21,13 +21,13 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.LinkedBlockingQueue; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; import org.eclipse.jetty.websocket.common.test.HttpResponse; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.examples.MyEchoServlet; import org.junit.AfterClass; import org.junit.Assert; @@ -73,8 +73,8 @@ public class ChromeTest client.write(new TextFrame().setPayload(msg)); // Read frame (hopefully text frame) - EventQueue frames = client.readFrames(1,30,TimeUnit.SECONDS); - WebSocketFrame tf = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame.status code",tf.getPayloadAsUTF8(),is(msg)); } finally diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsLegacyTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsLegacyTest.java index 4dbcd08a4cf..8dbf77587a3 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsLegacyTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsLegacyTest.java @@ -24,18 +24,19 @@ import static org.junit.Assert.assertThat; import java.io.PrintWriter; import java.io.StringWriter; import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import javax.servlet.ServletContext; import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.DecoratedObjectFactory; import org.eclipse.jetty.util.Decorator; import org.eclipse.jetty.websocket.api.WebSocketAdapter; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; import org.eclipse.jetty.websocket.servlet.WebSocketCreator; @@ -167,8 +168,8 @@ public class DecoratorsLegacyTest client.write(new TextFrame().setPayload("info")); - EventQueue frames = client.readFrames(1,1,TimeUnit.SECONDS); - WebSocketFrame resp = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame resp = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); String textMsg = resp.getPayloadAsUTF8(); assertThat("DecoratedObjectFactory", textMsg, containsString("Object is a DecoratedObjectFactory")); diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsTest.java index 8734a3d9ef6..3753d360e56 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsTest.java @@ -24,18 +24,19 @@ import static org.junit.Assert.assertThat; import java.io.PrintWriter; import java.io.StringWriter; import java.util.List; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import javax.servlet.ServletContext; import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.DecoratedObjectFactory; import org.eclipse.jetty.util.Decorator; import org.eclipse.jetty.websocket.api.WebSocketAdapter; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; import org.eclipse.jetty.websocket.servlet.WebSocketCreator; @@ -165,8 +166,8 @@ public class DecoratorsTest client.write(new TextFrame().setPayload("info")); - EventQueue frames = client.readFrames(1,1,TimeUnit.SECONDS); - WebSocketFrame resp = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame resp = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); String textMsg = resp.getPayloadAsUTF8(); assertThat("DecoratedObjectFactory", textMsg, containsString("Object is a DecoratedObjectFactory")); diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FirefoxTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FirefoxTest.java index 2a0950a9a95..bebbf78aa14 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FirefoxTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FirefoxTest.java @@ -18,11 +18,10 @@ package org.eclipse.jetty.websocket.server; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.LinkedBlockingQueue; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; @@ -66,7 +65,7 @@ public class FirefoxTest client.write(new TextFrame().setPayload(msg)); // Read frame (hopefully text frame) - EventQueue frames = client.readFrames(1, 30, TimeUnit.SECONDS); + LinkedBlockingQueue frames = client.getFrameQueue(); WebSocketFrame tf = frames.poll(); Assert.assertThat("Text Frame.status code", tf.getPayloadAsUTF8(), is(msg)); } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FragmentExtensionTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FragmentExtensionTest.java index 45d12c59f8b..de089f26845 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FragmentExtensionTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FragmentExtensionTest.java @@ -21,13 +21,14 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; import org.eclipse.jetty.websocket.common.test.HttpResponse; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.helper.EchoServlet; import org.junit.AfterClass; import org.junit.Assert; @@ -89,10 +90,10 @@ public class FragmentExtensionTest client.write(new TextFrame().setPayload(msg)); String parts[] = split(msg,fragSize); - EventQueue frames = client.readFrames(parts.length,1000,TimeUnit.MILLISECONDS); + LinkedBlockingQueue frames = client.getFrameQueue(); for (int i = 0; i < parts.length; i++) { - WebSocketFrame frame = frames.poll(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("text[" + i + "].payload",frame.getPayloadAsUTF8(),is(parts[i])); } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdentityExtensionTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdentityExtensionTest.java index 62e15d6746a..49c4b268553 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdentityExtensionTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdentityExtensionTest.java @@ -21,13 +21,14 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; import org.eclipse.jetty.websocket.common.test.HttpResponse; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.helper.EchoServlet; import org.junit.AfterClass; import org.junit.Assert; @@ -72,8 +73,8 @@ public class IdentityExtensionTest client.write(new TextFrame().setPayload("Hello")); - EventQueue frames = client.readFrames(1,1000,TimeUnit.MILLISECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("TEXT.payload",frame.getPayloadAsUTF8(),is("Hello")); } finally diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java index a6c95950171..9174d1e8ab0 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java @@ -21,15 +21,16 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.EventQueue; 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.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.helper.RFCSocket; import org.eclipse.jetty.websocket.servlet.WebSocketServlet; import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; @@ -94,8 +95,8 @@ public class IdleTimeoutTest client.write(new TextFrame().setPayload("Hello")); // Expect server to have closed due to its own timeout - EventQueue frames = client.readFrames(1,30,TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("frame opcode",frame.getOpCode(),is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(frame); Assert.assertThat("close code",close.getStatusCode(),is(StatusCode.SHUTDOWN)); diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ManyConnectionsCleanupTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ManyConnectionsCleanupTest.java index bf33a79746e..0e819ec7d68 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ManyConnectionsCleanupTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ManyConnectionsCleanupTest.java @@ -25,10 +25,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.StacklessLogging; @@ -43,6 +43,7 @@ import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; import org.eclipse.jetty.websocket.common.test.IBlockheadClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.helper.RFCSocket; import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; @@ -272,21 +273,21 @@ public class ManyConnectionsCleanupTest client.write(new TextFrame().setPayload("calls")); client.write(new TextFrame().setPayload("openSessions")); - EventQueue frames = client.readFrames(3,6,TimeUnit.SECONDS); + LinkedBlockingQueue frames = client.getFrameQueue(); WebSocketFrame frame; String resp; - frame = frames.poll(); + frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("frames[0].opcode",frame.getOpCode(),is(OpCode.TEXT)); resp = frame.getPayloadAsUTF8(); assertThat("Should only have 1 open session",resp,containsString("calls=" + ((iterationCount * 2) + 1))); - frame = frames.poll(); + frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("frames[1].opcode",frame.getOpCode(),is(OpCode.TEXT)); resp = frame.getPayloadAsUTF8(); assertThat("Should only have 1 open session",resp,containsString("openSessions.size=1\n")); - frame = frames.poll(); + frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("frames[2].opcode",frame.getOpCode(),is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(frame); assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.NORMAL)); @@ -310,8 +311,9 @@ public class ManyConnectionsCleanupTest client.connect(); client.sendStandardRequest(); client.expectUpgradeResponse(); - - client.readFrames(1,1,TimeUnit.SECONDS); + + LinkedBlockingQueue frames = client.getFrameQueue(); + frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); CloseInfo close = new CloseInfo(StatusCode.NORMAL,"Normal"); assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.NORMAL)); diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/PerMessageDeflateExtensionTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/PerMessageDeflateExtensionTest.java index 5f908648e54..ee689e47ea1 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/PerMessageDeflateExtensionTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/PerMessageDeflateExtensionTest.java @@ -34,6 +34,7 @@ import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; import org.eclipse.jetty.websocket.client.WebSocketClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.common.util.Sha1Sum; import org.eclipse.jetty.websocket.server.helper.CaptureSocket; import org.eclipse.jetty.websocket.server.helper.EchoServlet; @@ -166,8 +167,7 @@ public class PerMessageDeflateExtensionTest // Client sends first message session.getRemote().sendBytes(ByteBuffer.wrap(msg)); - clientSocket.messages.awaitEventCount(1,5,TimeUnit.SECONDS); - String echoMsg = clientSocket.messages.poll(); + String echoMsg = clientSocket.messages.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Echo'd Message",echoMsg,is("binary[sha1="+sha1+"]")); } finally diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SubProtocolTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SubProtocolTest.java index 36b141047dc..3beb3869427 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SubProtocolTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SubProtocolTest.java @@ -21,9 +21,9 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; @@ -31,6 +31,7 @@ import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; import org.eclipse.jetty.websocket.servlet.WebSocketCreator; @@ -129,8 +130,8 @@ public class SubProtocolTest client.expectUpgradeResponse(); client.write(new TextFrame().setPayload("showme")); - EventQueue frames = client.readFrames(1, 30, TimeUnit.SECONDS); - WebSocketFrame tf = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat(ProtocolEchoSocket.class.getSimpleName() + ".onMessage()", tf.getPayloadAsUTF8(), is("acceptedSubprotocol=" + acceptedSubProtocols)); } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SuspendResumeTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SuspendResumeTest.java index 1fe8fa3716b..09f2cd2c5a3 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SuspendResumeTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SuspendResumeTest.java @@ -21,9 +21,9 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.SuspendToken; import org.eclipse.jetty.websocket.api.WriteCallback; @@ -33,6 +33,7 @@ import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; import org.eclipse.jetty.websocket.servlet.WebSocketCreator; @@ -128,10 +129,10 @@ public class SuspendResumeTest client.write(new TextFrame().setPayload("echo1")); client.write(new TextFrame().setPayload("echo2")); - EventQueue frames = client.readFrames(2, 30, TimeUnit.SECONDS); - WebSocketFrame tf = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat(EchoSocket.class.getSimpleName() + ".onMessage()", tf.getPayloadAsUTF8(), is("echo1")); - tf = frames.poll(); + tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat(EchoSocket.class.getSimpleName() + ".onMessage()", tf.getPayloadAsUTF8(), is("echo2")); } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/TooFastClientTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/TooFastClientTest.java index 01e453799fa..bf2de13101e 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/TooFastClientTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/TooFastClientTest.java @@ -23,17 +23,17 @@ import static org.hamcrest.Matchers.is; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Arrays; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.LinkedBlockingQueue; import org.eclipse.jetty.io.LeakTrackingByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.examples.MyEchoServlet; import org.junit.AfterClass; import org.junit.Assert; @@ -108,10 +108,10 @@ public class TooFastClientTest client.expectUpgradeResponse(); // Read frames (hopefully text frames) - EventQueue frames = client.readFrames(2,1,TimeUnit.SECONDS); - WebSocketFrame tf = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame/msg1",tf.getPayloadAsUTF8(),is(msg1)); - tf = frames.poll(); + tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame/msg2",tf.getPayloadAsUTF8(),is(msg2)); } finally @@ -167,9 +167,9 @@ public class TooFastClientTest client.expectUpgradeResponse(); // Read frames (hopefully text frames) - EventQueue frames = client.readFrames(1,1,TimeUnit.SECONDS); + LinkedBlockingQueue frames = client.getFrameQueue(); - WebSocketFrame tf = frames.poll(); + WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame/msg1",tf.getPayloadAsUTF8(),is(bigMsg)); } finally diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java index 95f47383b9c..5ead761e174 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java @@ -26,9 +26,9 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.StacklessLogging; @@ -42,6 +42,7 @@ import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; import org.eclipse.jetty.websocket.common.test.IBlockheadClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.helper.RFCSocket; import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; @@ -231,8 +232,8 @@ public class WebSocketCloseTest client.expectUpgradeResponse(); // Verify that client got close frame - EventQueue frames = client.readFrames(1,5,TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("frames[0].opcode",frame.getOpCode(),is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(frame); assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.NORMAL)); @@ -265,8 +266,8 @@ public class WebSocketCloseTest client.sendStandardRequest(); client.expectUpgradeResponse(); - EventQueue frames = client.readFrames(1,5,TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("frames[0].opcode",frame.getOpCode(),is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(frame); assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.SERVER_ERROR)); @@ -306,14 +307,14 @@ public class WebSocketCloseTest text.setPayload("openSessions"); client.write(text); - EventQueue frames = client.readFrames(2,1,TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("frames[0].opcode",frame.getOpCode(),is(OpCode.TEXT)); String resp = frame.getPayloadAsUTF8(); assertThat("Should only have 1 open session",resp,containsString("openSessions.size=1\n")); - frame = frames.poll(); + frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("frames[1].opcode",frame.getOpCode(),is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(frame); assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.NORMAL)); @@ -338,8 +339,9 @@ public class WebSocketCloseTest client.connect(); client.sendStandardRequest(); client.expectUpgradeResponse(); - - client.readFrames(1,1,TimeUnit.SECONDS); + + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame received = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); CloseInfo close = new CloseInfo(StatusCode.NORMAL,"Normal"); assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.NORMAL)); @@ -365,8 +367,9 @@ public class WebSocketCloseTest client.connect(); client.sendStandardRequest(); client.expectUpgradeResponse(); - - client.readFrames(1,1,TimeUnit.SECONDS); + + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame received = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); CloseInfo close = new CloseInfo(StatusCode.NORMAL,"Normal"); client.write(close.asFrame()); // respond with close diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java index e8ef9b3cb60..623a14f78b0 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java @@ -22,16 +22,17 @@ import static org.hamcrest.Matchers.is; import java.net.URI; import java.util.concurrent.Future; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.toolchain.test.TestTracker; 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.client.WebSocketClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.helper.CaptureSocket; import org.eclipse.jetty.websocket.server.helper.SessionServlet; import org.junit.AfterClass; @@ -94,9 +95,8 @@ public class WebSocketOverSSLTest remote.flush(); // Read frame (hopefully text frame) - clientSocket.messages.awaitEventCount(1,30,TimeUnit.SECONDS); - EventQueue captured = clientSocket.messages; - Assert.assertThat("Text Message",captured.poll(),is(msg)); + LinkedBlockingQueue captured = clientSocket.messages; + Assert.assertThat("Text Message",captured.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT),is(msg)); // Shutdown the socket clientSocket.close(); @@ -136,9 +136,8 @@ public class WebSocketOverSSLTest remote.flush(); // Read frame (hopefully text frame) - clientSocket.messages.awaitEventCount(1,30,TimeUnit.SECONDS); - EventQueue captured = clientSocket.messages; - Assert.assertThat("Server.session.isSecure",captured.poll(),is("session.isSecure=true")); + LinkedBlockingQueue captured = clientSocket.messages; + Assert.assertThat("Server.session.isSecure",captured.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT),is("session.isSecure=true")); // Shutdown the socket clientSocket.close(); @@ -178,10 +177,9 @@ public class WebSocketOverSSLTest remote.flush(); // Read frame (hopefully text frame) - clientSocket.messages.awaitEventCount(1,30,TimeUnit.SECONDS); - EventQueue captured = clientSocket.messages; + LinkedBlockingQueue captured = clientSocket.messages; String expected = String.format("session.upgradeRequest.requestURI=%s",requestUri.toASCIIString()); - Assert.assertThat("session.upgradeRequest.requestURI",captured.poll(),is(expected)); + Assert.assertThat("session.upgradeRequest.requestURI",captured.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT),is(expected)); // Shutdown the socket clientSocket.close(); diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServerSessionTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServerSessionTest.java index c278ed6b83a..ad5c2144fb5 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServerSessionTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServerSessionTest.java @@ -21,14 +21,15 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.is; import java.net.URI; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.toolchain.test.AdvancedRunner; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; import org.eclipse.jetty.websocket.common.test.IBlockheadClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.helper.SessionServlet; import org.junit.AfterClass; import org.junit.Assert; @@ -90,14 +91,14 @@ public class WebSocketServerSessionTest client.write(new TextFrame().setPayload("getParameterMap|cost")); // intentionally invalid // Read frame (hopefully text frame) - EventQueue frames = client.readFrames(4,5,TimeUnit.SECONDS); - WebSocketFrame tf = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Parameter Map[snack]", tf.getPayloadAsUTF8(), is("[cashews]")); - tf = frames.poll(); + tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Parameter Map[amount]", tf.getPayloadAsUTF8(), is("[handful]")); - tf = frames.poll(); + tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Parameter Map[brand]", tf.getPayloadAsUTF8(), is("[off]")); - tf = frames.poll(); + tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Parameter Map[cost]", tf.getPayloadAsUTF8(), is("")); } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java index b3f6eb29044..994128476a2 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java @@ -22,10 +22,9 @@ import static org.hamcrest.Matchers.is; import java.nio.ByteBuffer; import java.util.Arrays; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.LinkedBlockingQueue; import org.eclipse.jetty.toolchain.test.AdvancedRunner; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.Utf8Appendable.NotUtf8Exception; import org.eclipse.jetty.util.Utf8StringBuilder; import org.eclipse.jetty.util.log.StacklessLogging; @@ -42,6 +41,7 @@ import org.eclipse.jetty.websocket.common.frames.BinaryFrame; import org.eclipse.jetty.websocket.common.frames.ContinuationFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.common.test.UnitGenerator; import org.eclipse.jetty.websocket.common.util.Hex; import org.eclipse.jetty.websocket.server.helper.RFCServlet; @@ -124,8 +124,8 @@ public class WebSocketServletRFCTest client.write(bin); // write buf3 (fin=true) // Read frame echo'd back (hopefully a single binary frame) - EventQueue frames = client.readFrames(1,30,TimeUnit.SECONDS); - Frame binmsg = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + Frame binmsg = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); int expectedSize = buf1.length + buf2.length + buf3.length; Assert.assertThat("BinaryFrame.payloadLength",binmsg.getPayloadLength(),is(expectedSize)); @@ -191,8 +191,8 @@ public class WebSocketServletRFCTest client.write(new TextFrame().setPayload(msg)); // Read frame (hopefully text frame) - EventQueue frames = client.readFrames(1,30,TimeUnit.SECONDS); - WebSocketFrame tf = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame.status code",tf.getPayloadAsUTF8(),is(msg)); } finally @@ -222,8 +222,8 @@ public class WebSocketServletRFCTest client.write(new TextFrame().setPayload("CRASH")); // Read frame (hopefully close frame) - EventQueue frames = client.readFrames(1,30,TimeUnit.SECONDS); - Frame cf = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + Frame cf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); CloseInfo close = new CloseInfo(cf); Assert.assertThat("Close Frame.status code",close.getStatusCode(),is(StatusCode.SERVER_ERROR)); } @@ -263,8 +263,8 @@ public class WebSocketServletRFCTest client.write(new TextFrame().setPayload(msg)); // Read frame (hopefully text frame) - EventQueue frames = client.readFrames(1,30,TimeUnit.SECONDS); - WebSocketFrame tf = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame.status code",tf.getPayloadAsUTF8(),is(msg)); } finally @@ -293,8 +293,8 @@ public class WebSocketServletRFCTest client.writeRaw(bbHeader); client.writeRaw(txt.getPayload()); - EventQueue frames = client.readFrames(1,30,TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("frames[0].opcode",frame.getOpCode(),is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(frame); Assert.assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.BAD_PAYLOAD)); @@ -334,8 +334,8 @@ public class WebSocketServletRFCTest client.write(new TextFrame().setPayload(msg)); // Read frame (hopefully text frame) - EventQueue frames = client.readFrames(1,30,TimeUnit.SECONDS); - WebSocketFrame tf = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame.status code",tf.getPayloadAsUTF8(),is(msg)); } finally diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilterTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilterTest.java index 1fd592843fb..784aa8609ae 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilterTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilterTest.java @@ -27,7 +27,7 @@ import java.net.URI; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicInteger; import javax.servlet.DispatcherType; @@ -36,12 +36,12 @@ import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.servlet.WebSocketCreator; import org.junit.Ignore; import org.junit.Test; @@ -314,8 +314,9 @@ public class WebSocketUpgradeFilterTest client.write(new TextFrame().setPayload("hello")); - EventQueue frames = client.readFrames(1, 1000, TimeUnit.MILLISECONDS); - String payload = frames.poll().getPayloadAsUTF8(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame received = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + String payload = received.getPayloadAsUTF8(); // If we can connect and send a text message, we know that the endpoint was // added properly, and the response will help us verify the policy configuration too @@ -336,9 +337,11 @@ public class WebSocketUpgradeFilterTest client.write(new TextFrame().setPayload("hello 1")); - EventQueue frames = client.readFrames(1, 1000, TimeUnit.MILLISECONDS); - String payload = frames.poll().getPayloadAsUTF8(); - + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame received = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + String payload = received.getPayloadAsUTF8(); + + // If we can connect and send a text message, we know that the endpoint was // added properly, and the response will help us verify the policy configuration too assertThat("payload", payload, containsString("session.maxTextMessageSize=" + (10 * 1024 * 1024))); @@ -355,9 +358,11 @@ public class WebSocketUpgradeFilterTest client.write(new TextFrame().setPayload("hello 2")); - EventQueue frames = client.readFrames(1, 1000, TimeUnit.MILLISECONDS); - String payload = frames.poll().getPayloadAsUTF8(); - + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame received = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + String payload = received.getPayloadAsUTF8(); + + // If we can connect and send a text message, we know that the endpoint was // added properly, and the response will help us verify the policy configuration too assertThat("payload", payload, containsString("session.maxTextMessageSize=" + (10 * 1024 * 1024))); diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/CaptureSocket.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/CaptureSocket.java index 554000e0a92..7715f9ed539 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/CaptureSocket.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/helper/CaptureSocket.java @@ -20,9 +20,9 @@ package org.eclipse.jetty.websocket.server.helper; import java.security.NoSuchAlgorithmException; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.WebSocketAdapter; import org.eclipse.jetty.websocket.common.util.Sha1Sum; @@ -30,12 +30,7 @@ import org.eclipse.jetty.websocket.common.util.Sha1Sum; public class CaptureSocket extends WebSocketAdapter { private final CountDownLatch latch = new CountDownLatch(1); - public EventQueue messages; - - public CaptureSocket() - { - messages = new EventQueue(); - } + public LinkedBlockingQueue messages = new LinkedBlockingQueue<>(); public boolean awaitConnected(long timeout) throws InterruptedException { diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/misbehaving/MisbehavingClassTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/misbehaving/MisbehavingClassTest.java index 57da5b71e77..bc5db0c678c 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/misbehaving/MisbehavingClassTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/misbehaving/MisbehavingClassTest.java @@ -21,9 +21,10 @@ package org.eclipse.jetty.websocket.server.misbehaving; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; + +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.EventQueue; import org.eclipse.jetty.util.log.StacklessLogging; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.common.CloseInfo; @@ -32,15 +33,12 @@ import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.test.BlockheadClient; import org.eclipse.jetty.websocket.common.test.IBlockheadClient; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.SimpleServletServer; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - /** * Testing badly behaving Socket class implementations to get the best * error messages and state out of the websocket implementation. @@ -80,8 +78,8 @@ public class MisbehavingClassTest client.sendStandardRequest(); client.expectUpgradeResponse(); - EventQueue frames = client.readFrames(1,1,TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("frames[0].opcode",frame.getOpCode(),is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(frame); assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.SERVER_ERROR)); @@ -115,8 +113,8 @@ public class MisbehavingClassTest client.sendStandardRequest(); client.expectUpgradeResponse(); - EventQueue frames = client.readFrames(1,1,TimeUnit.SECONDS); - WebSocketFrame frame = frames.poll(); + LinkedBlockingQueue frames = client.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("frames[0].opcode",frame.getOpCode(),is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(frame); assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.SERVER_ERROR)); From e4ad88aaf1e16f5a5d2408bc7eafcadc779495de Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Tue, 6 Mar 2018 09:18:18 -0600 Subject: [PATCH 2/7] Issue #2282 - simplifying EventCapture --- .../examples/AdapterConnectCloseSocket.java | 4 +- .../examples/AnnotatedBinaryArraySocket.java | 6 +- .../examples/AnnotatedBinaryStreamSocket.java | 6 +- .../java/examples/AnnotatedFramesSocket.java | 6 +- .../examples/AnnotatedStreamingSocket.java | 4 +- .../java/examples/AnnotatedTextSocket.java | 8 +-- .../examples/AnnotatedTextStreamSocket.java | 6 +- .../java/examples/ListenerBasicSocket.java | 10 +-- .../java/examples/ListenerFrameSocket.java | 8 +-- .../java/examples/ListenerPartialSocket.java | 10 +-- .../java/examples/ListenerPingPongSocket.java | 10 +-- .../websocket/common/events/EventCapture.java | 59 ++------------- .../common/events/EventDriverTest.java | 72 +++++++++---------- .../websocket/common/test/MoreMatchers.java | 39 ++++++++++ 14 files changed, 118 insertions(+), 130 deletions(-) create mode 100644 jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/MoreMatchers.java diff --git a/jetty-websocket/websocket-common/src/test/java/examples/AdapterConnectCloseSocket.java b/jetty-websocket/websocket-common/src/test/java/examples/AdapterConnectCloseSocket.java index 7c7d2a4c022..744dfb2784b 100644 --- a/jetty-websocket/websocket-common/src/test/java/examples/AdapterConnectCloseSocket.java +++ b/jetty-websocket/websocket-common/src/test/java/examples/AdapterConnectCloseSocket.java @@ -29,12 +29,12 @@ public class AdapterConnectCloseSocket extends WebSocketAdapter @Override public void onWebSocketClose(int statusCode, String reason) { - capture.add("onWebSocketClose(%d, %s)",statusCode,capture.q(reason)); + capture.offer("onWebSocketClose(%d, %s)",statusCode,capture.q(reason)); } @Override public void onWebSocketConnect(Session sess) { - capture.add("onWebSocketConnect(%s)",sess); + capture.offer("onWebSocketConnect(%s)",sess); } } diff --git a/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedBinaryArraySocket.java b/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedBinaryArraySocket.java index 860cd5860b1..9fcb4575c56 100644 --- a/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedBinaryArraySocket.java +++ b/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedBinaryArraySocket.java @@ -33,19 +33,19 @@ public class AnnotatedBinaryArraySocket @OnWebSocketMessage public void onBinary(byte payload[], int offset, int length) { - capture.add("onBinary([%d],%d,%d)",payload.length,offset,length); + capture.offer("onBinary([%d],%d,%d)",payload.length,offset,length); } @OnWebSocketClose public void onClose(int statusCode, String reason) { - capture.add("onClose(%d, %s)",statusCode,capture.q(reason)); + capture.offer("onClose(%d, %s)",statusCode,capture.q(reason)); } @OnWebSocketConnect public void onConnect(Session sess) { - capture.add("onConnect(%s)",sess); + capture.offer("onConnect(%s)",sess); } } diff --git a/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedBinaryStreamSocket.java b/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedBinaryStreamSocket.java index 89d874a2ac3..9910f78db96 100644 --- a/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedBinaryStreamSocket.java +++ b/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedBinaryStreamSocket.java @@ -39,18 +39,18 @@ public class AnnotatedBinaryStreamSocket { new RuntimeException("Stream cannot be null").printStackTrace(System.err); } - capture.add("onBinary(%s)",stream); + capture.offer("onBinary(%s)",stream); } @OnWebSocketClose public void onClose(int statusCode, String reason) { - capture.add("onClose(%d, %s)",statusCode,capture.q(reason)); + capture.offer("onClose(%d, %s)",statusCode,capture.q(reason)); } @OnWebSocketConnect public void onConnect(Session sess) { - capture.add("onConnect(%s)",sess); + capture.offer("onConnect(%s)",sess); } } diff --git a/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedFramesSocket.java b/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedFramesSocket.java index 85339f4a990..ccc9b738bba 100644 --- a/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedFramesSocket.java +++ b/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedFramesSocket.java @@ -34,18 +34,18 @@ public class AnnotatedFramesSocket @OnWebSocketClose public void onClose(int statusCode, String reason) { - capture.add("onClose(%d, %s)",statusCode,capture.q(reason)); + capture.offer("onClose(%d, %s)",statusCode,capture.q(reason)); } @OnWebSocketConnect public void onConnect(Session sess) { - capture.add("onConnect(%s)",sess); + capture.offer("onConnect(%s)",sess); } @OnWebSocketFrame public void onFrame(Frame frame) { - capture.add("onFrame(%s)",frame); + capture.offer("onFrame(%s)",frame); } } diff --git a/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedStreamingSocket.java b/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedStreamingSocket.java index dee874d58a6..58b02d7ae35 100644 --- a/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedStreamingSocket.java +++ b/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedStreamingSocket.java @@ -38,13 +38,13 @@ public class AnnotatedStreamingSocket @OnWebSocketClose public void onClose(int statusCode, String reason) { - capture.add("onClose(%d, %s)",statusCode,capture.q(reason)); + capture.offer("onClose(%d, %s)",statusCode,capture.q(reason)); } @OnWebSocketConnect public void onConnect(Session sess) { - capture.add("onConnect(%s)",sess); + capture.offer("onConnect(%s)",sess); } @OnWebSocketFrame diff --git a/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedTextSocket.java b/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedTextSocket.java index e6569680195..02a11d77482 100644 --- a/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedTextSocket.java +++ b/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedTextSocket.java @@ -34,24 +34,24 @@ public class AnnotatedTextSocket @OnWebSocketClose public void onClose(int statusCode, String reason) { - capture.add("onClose(%d, %s)",statusCode,capture.q(reason)); + capture.offer("onClose(%d, %s)",statusCode,capture.q(reason)); } @OnWebSocketConnect public void onConnect(Session sess) { - capture.add("onConnect(%s)",sess); + capture.offer("onConnect(%s)",sess); } @OnWebSocketError public void onError(Throwable cause) { - capture.add("onError(%s: %s)",cause.getClass().getSimpleName(),cause.getMessage()); + capture.offer("onError(%s: %s)",cause.getClass().getSimpleName(),cause.getMessage()); } @OnWebSocketMessage public void onText(String message) { - capture.add("onText(%s)",capture.q(message)); + capture.offer("onText(%s)",capture.q(message)); } } diff --git a/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedTextStreamSocket.java b/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedTextStreamSocket.java index 037b8d9d38a..cf6576df8ab 100644 --- a/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedTextStreamSocket.java +++ b/jetty-websocket/websocket-common/src/test/java/examples/AnnotatedTextStreamSocket.java @@ -35,18 +35,18 @@ public class AnnotatedTextStreamSocket @OnWebSocketClose public void onClose(int statusCode, String reason) { - capture.add("onClose(%d, %s)",statusCode,capture.q(reason)); + capture.offer("onClose(%d, %s)",statusCode,capture.q(reason)); } @OnWebSocketConnect public void onConnect(Session sess) { - capture.add("onConnect(%s)",sess); + capture.offer("onConnect(%s)",sess); } @OnWebSocketMessage public void onText(Reader reader) { - capture.add("onText(%s)",reader); + capture.offer("onText(%s)",reader); } } diff --git a/jetty-websocket/websocket-common/src/test/java/examples/ListenerBasicSocket.java b/jetty-websocket/websocket-common/src/test/java/examples/ListenerBasicSocket.java index 4dcb4132694..10d36f35206 100644 --- a/jetty-websocket/websocket-common/src/test/java/examples/ListenerBasicSocket.java +++ b/jetty-websocket/websocket-common/src/test/java/examples/ListenerBasicSocket.java @@ -29,30 +29,30 @@ public class ListenerBasicSocket implements WebSocketListener @Override public void onWebSocketBinary(byte[] payload, int offset, int len) { - capture.add("onWebSocketBinary([%d], %d, %d)",payload.length,offset,len); + capture.offer("onWebSocketBinary([%d], %d, %d)",payload.length,offset,len); } @Override public void onWebSocketClose(int statusCode, String reason) { - capture.add("onWebSocketClose(%d, %s)",statusCode,capture.q(reason)); + capture.offer("onWebSocketClose(%d, %s)",statusCode,capture.q(reason)); } @Override public void onWebSocketConnect(Session session) { - capture.add("onWebSocketConnect(%s)",session); + capture.offer("onWebSocketConnect(%s)",session); } @Override public void onWebSocketError(Throwable cause) { - capture.add("onWebSocketError((%s) %s)",cause.getClass().getSimpleName(),cause.getMessage()); + capture.offer("onWebSocketError((%s) %s)",cause.getClass().getSimpleName(),cause.getMessage()); } @Override public void onWebSocketText(String message) { - capture.add("onWebSocketText(%s)",capture.q(message)); + capture.offer("onWebSocketText(%s)",capture.q(message)); } } diff --git a/jetty-websocket/websocket-common/src/test/java/examples/ListenerFrameSocket.java b/jetty-websocket/websocket-common/src/test/java/examples/ListenerFrameSocket.java index a3b6eb6f7c6..f42f2552440 100644 --- a/jetty-websocket/websocket-common/src/test/java/examples/ListenerFrameSocket.java +++ b/jetty-websocket/websocket-common/src/test/java/examples/ListenerFrameSocket.java @@ -30,24 +30,24 @@ public class ListenerFrameSocket implements WebSocketFrameListener @Override public void onWebSocketClose(int statusCode, String reason) { - capture.add("onWebSocketClose(%d, %s)",statusCode,capture.q(reason)); + capture.offer("onWebSocketClose(%d, %s)",statusCode,capture.q(reason)); } @Override public void onWebSocketConnect(Session session) { - capture.add("onWebSocketConnect(%s)",session); + capture.offer("onWebSocketConnect(%s)",session); } @Override public void onWebSocketError(Throwable cause) { - capture.add("onWebSocketError((%s) %s)",cause.getClass().getSimpleName(),cause.getMessage()); + capture.offer("onWebSocketError((%s) %s)",cause.getClass().getSimpleName(),cause.getMessage()); } @Override public void onWebSocketFrame(Frame frame) { - capture.add("onWebSocketFrame(%s, %d, %b)", frame.getType(), frame.getPayload().remaining(), frame.isFin()); + capture.offer("onWebSocketFrame(%s, %d, %b)", frame.getType(), frame.getPayload().remaining(), frame.isFin()); } } diff --git a/jetty-websocket/websocket-common/src/test/java/examples/ListenerPartialSocket.java b/jetty-websocket/websocket-common/src/test/java/examples/ListenerPartialSocket.java index 5f29b8d5ca7..2e7b89e1f49 100644 --- a/jetty-websocket/websocket-common/src/test/java/examples/ListenerPartialSocket.java +++ b/jetty-websocket/websocket-common/src/test/java/examples/ListenerPartialSocket.java @@ -31,30 +31,30 @@ public class ListenerPartialSocket implements WebSocketPartialListener @Override public void onWebSocketClose(int statusCode, String reason) { - capture.add("onWebSocketClose(%d, %s)",statusCode,capture.q(reason)); + capture.offer("onWebSocketClose(%d, %s)",statusCode,capture.q(reason)); } @Override public void onWebSocketConnect(Session session) { - capture.add("onWebSocketConnect(%s)",session); + capture.offer("onWebSocketConnect(%s)",session); } @Override public void onWebSocketError(Throwable cause) { - capture.add("onWebSocketError((%s) %s)",cause.getClass().getSimpleName(),cause.getMessage()); + capture.offer("onWebSocketError((%s) %s)",cause.getClass().getSimpleName(),cause.getMessage()); } @Override public void onWebSocketPartialText(String payload, boolean fin) { - capture.add("onWebSocketPartialText('%s', %b)",payload,fin); + capture.offer("onWebSocketPartialText('%s', %b)",payload,fin); } @Override public void onWebSocketPartialBinary(ByteBuffer payload, boolean fin) { - capture.add("onWebSocketPartialBinary(%s [%d], %b)",payload,payload.remaining(),fin); + capture.offer("onWebSocketPartialBinary(%s [%d], %b)",payload,payload.remaining(),fin); } } diff --git a/jetty-websocket/websocket-common/src/test/java/examples/ListenerPingPongSocket.java b/jetty-websocket/websocket-common/src/test/java/examples/ListenerPingPongSocket.java index a7152bc214d..9f3692dafb8 100644 --- a/jetty-websocket/websocket-common/src/test/java/examples/ListenerPingPongSocket.java +++ b/jetty-websocket/websocket-common/src/test/java/examples/ListenerPingPongSocket.java @@ -31,30 +31,30 @@ public class ListenerPingPongSocket implements WebSocketPingPongListener @Override public void onWebSocketClose(int statusCode, String reason) { - capture.add("onWebSocketClose(%d, %s)",statusCode,capture.q(reason)); + capture.offer("onWebSocketClose(%d, %s)",statusCode,capture.q(reason)); } @Override public void onWebSocketConnect(Session session) { - capture.add("onWebSocketConnect(%s)",session); + capture.offer("onWebSocketConnect(%s)",session); } @Override public void onWebSocketError(Throwable cause) { - capture.add("onWebSocketError((%s) %s)",cause.getClass().getSimpleName(),cause.getMessage()); + capture.offer("onWebSocketError((%s) %s)",cause.getClass().getSimpleName(),cause.getMessage()); } @Override public void onWebSocketPing(ByteBuffer payload) { - capture.add("onWebSocketPing(%d)",payload.remaining()); + capture.offer("onWebSocketPing(%d)",payload.remaining()); } @Override public void onWebSocketPong(ByteBuffer payload) { - capture.add("onWebSocketPong(%d)",payload.remaining()); + capture.offer("onWebSocketPong(%d)",payload.remaining()); } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventCapture.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventCapture.java index 8a140fafd8f..b05265841f9 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventCapture.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventCapture.java @@ -18,57 +18,18 @@ package org.eclipse.jetty.websocket.common.events; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.startsWith; - import java.util.concurrent.LinkedBlockingQueue; -import java.util.regex.Pattern; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; -import org.junit.Assert; +import org.eclipse.jetty.websocket.common.test.Timeouts; -/** - * @deprecated should refactor away. - */ @SuppressWarnings("serial") -@Deprecated public class EventCapture extends LinkedBlockingQueue { private static final Logger LOG = Log.getLogger(EventCapture.class); - public static class Assertable - { - private final String event; - - public Assertable(String event) - { - this.event = event; - } - - public void assertEventContains(String expected) - { - Assert.assertThat("Event",event,containsString(expected)); - } - - public void assertEventRegex(String regex) - { - Assert.assertTrue("Event: regex:[" + regex + "] in [" + event + "]",Pattern.matches(regex,event)); - } - - public void assertEventStartsWith(String expected) - { - Assert.assertThat("Event",event,startsWith(expected)); - } - - public void assertEvent(String expected) - { - Assert.assertThat("Event",event,is(expected)); - } - } - - public void add(String format, Object... args) + public void offer(String format, Object... args) { String msg = String.format(format,args); if (LOG.isDebugEnabled()) @@ -76,17 +37,6 @@ public class EventCapture extends LinkedBlockingQueue super.offer(msg); } - public Assertable pop() - { - // TODO: poll should have timeout. - return new Assertable(super.poll()); - } - - public void assertEventCount(int expectedCount) - { - Assert.assertThat("Event Count",size(),is(expectedCount)); - } - public String q(String str) { if (str == null) @@ -95,4 +45,9 @@ public class EventCapture extends LinkedBlockingQueue } return '"' + str + '"'; } + + public String safePoll() throws InterruptedException + { + return poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverTest.java index 75cd41a9d63..67e78647843 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventDriverTest.java @@ -18,8 +18,10 @@ package org.eclipse.jetty.websocket.common.events; -import java.io.IOException; -import java.util.concurrent.TimeoutException; +import static org.eclipse.jetty.websocket.common.test.MoreMatchers.regex; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.startsWith; +import static org.junit.Assert.assertThat; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; @@ -80,9 +82,8 @@ public class EventDriverTest conn.open(); driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); - socket.capture.assertEventCount(2); - socket.capture.pop().assertEventStartsWith("onWebSocketConnect"); - socket.capture.pop().assertEventStartsWith("onWebSocketClose"); + assertThat(socket.capture.safePoll(), startsWith("onWebSocketConnect")); + assertThat(socket.capture.safePoll(), startsWith("onWebSocketClose")); } } @@ -98,10 +99,9 @@ public class EventDriverTest driver.incomingFrame(makeBinaryFrame("Hello World",true)); driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); - socket.capture.assertEventCount(3); - socket.capture.pop().assertEventStartsWith("onConnect"); - socket.capture.pop().assertEvent("onBinary([11],0,11)"); - socket.capture.pop().assertEventStartsWith("onClose(1000,"); + assertThat(socket.capture.safePoll(), startsWith("onConnect")); + assertThat(socket.capture.safePoll(), containsString("onBinary([11],0,11)")); + assertThat(socket.capture.safePoll(), startsWith("onClose(1000,")); } } @@ -117,10 +117,9 @@ public class EventDriverTest driver.incomingError(new WebSocketException("oof")); driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); - socket.capture.assertEventCount(3); - socket.capture.pop().assertEventStartsWith("onConnect"); - socket.capture.pop().assertEventStartsWith("onError(WebSocketException: oof)"); - socket.capture.pop().assertEventStartsWith("onClose(1000,"); + assertThat(socket.capture.safePoll(), startsWith("onConnect")); + assertThat(socket.capture.safePoll(), startsWith("onError(WebSocketException: oof)")); + assertThat(socket.capture.safePoll(), startsWith("onClose(1000,")); } } @@ -138,18 +137,17 @@ public class EventDriverTest driver.incomingFrame(new BinaryFrame().setPayload("Hello Bin")); driver.incomingFrame(new CloseInfo(StatusCode.SHUTDOWN,"testcase").asFrame()); - socket.capture.assertEventCount(6); - socket.capture.pop().assertEventStartsWith("onConnect("); - socket.capture.pop().assertEventStartsWith("onFrame(PING["); - socket.capture.pop().assertEventStartsWith("onFrame(TEXT["); - socket.capture.pop().assertEventStartsWith("onFrame(BINARY["); - socket.capture.pop().assertEventStartsWith("onFrame(CLOSE["); - socket.capture.pop().assertEventStartsWith("onClose(1001,"); + assertThat(socket.capture.safePoll(), startsWith("onConnect(")); + assertThat(socket.capture.safePoll(), startsWith("onFrame(PING[")); + assertThat(socket.capture.safePoll(), startsWith("onFrame(TEXT[")); + assertThat(socket.capture.safePoll(), startsWith("onFrame(BINARY[")); + assertThat(socket.capture.safePoll(), startsWith("onFrame(CLOSE[")); + assertThat(socket.capture.safePoll(), startsWith("onClose(1001,")); } } @Test - public void testAnnotated_InputStream() throws IOException, TimeoutException, InterruptedException + public void testAnnotated_InputStream() throws InterruptedException { AnnotatedBinaryStreamSocket socket = new AnnotatedBinaryStreamSocket(); EventDriver driver = wrap(socket); @@ -160,10 +158,9 @@ public class EventDriverTest driver.incomingFrame(makeBinaryFrame("Hello World",true)); driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); - socket.capture.assertEventCount(3); - socket.capture.pop().assertEventStartsWith("onConnect"); - socket.capture.pop().assertEventRegex("^onBinary\\(.*InputStream.*"); - socket.capture.pop().assertEventStartsWith("onClose(1000,"); + assertThat(socket.capture.safePoll(), startsWith("onConnect")); + assertThat(socket.capture.safePoll(), regex("^onBinary\\(.*InputStream.*")); + assertThat(socket.capture.safePoll(), startsWith("onClose(1000,")); } } @@ -180,10 +177,9 @@ public class EventDriverTest driver.incomingFrame(new TextFrame().setPayload("Hello World")); driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); - socket.capture.assertEventCount(3); - socket.capture.pop().assertEventStartsWith("onWebSocketConnect"); - socket.capture.pop().assertEventStartsWith("onWebSocketText(\"Hello World\")"); - socket.capture.pop().assertEventStartsWith("onWebSocketClose(1000,"); + assertThat(socket.capture.safePoll(), startsWith("onWebSocketConnect")); + assertThat(socket.capture.safePoll(), startsWith("onWebSocketText(\"Hello World\")")); + assertThat(socket.capture.safePoll(), startsWith("onWebSocketClose(1000,")); } } @@ -201,11 +197,10 @@ public class EventDriverTest driver.incomingFrame(new PongFrame().setPayload("PONG")); driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); - socket.capture.assertEventCount(4); - socket.capture.pop().assertEventStartsWith("onWebSocketConnect"); - socket.capture.pop().assertEventStartsWith("onWebSocketPing("); - socket.capture.pop().assertEventStartsWith("onWebSocketPong("); - socket.capture.pop().assertEventStartsWith("onWebSocketClose(1000,"); + assertThat(socket.capture.safePoll(), startsWith("onWebSocketConnect")); + assertThat(socket.capture.safePoll(), startsWith("onWebSocketPing(")); + assertThat(socket.capture.safePoll(), startsWith("onWebSocketPong(")); + assertThat(socket.capture.safePoll(), startsWith("onWebSocketClose(1000,")); } } @@ -223,11 +218,10 @@ public class EventDriverTest driver.incomingFrame(new PongFrame()); driver.incomingFrame(new CloseInfo(StatusCode.NORMAL).asFrame()); - socket.capture.assertEventCount(4); - socket.capture.pop().assertEventStartsWith("onWebSocketConnect"); - socket.capture.pop().assertEventStartsWith("onWebSocketPing("); - socket.capture.pop().assertEventStartsWith("onWebSocketPong("); - socket.capture.pop().assertEventStartsWith("onWebSocketClose(1000,"); + assertThat(socket.capture.safePoll(), startsWith("onWebSocketConnect")); + assertThat(socket.capture.safePoll(), startsWith("onWebSocketPing(")); + assertThat(socket.capture.safePoll(), startsWith("onWebSocketPong(")); + assertThat(socket.capture.safePoll(), startsWith("onWebSocketClose(1000,")); } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/MoreMatchers.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/MoreMatchers.java new file mode 100644 index 00000000000..a185e872ee2 --- /dev/null +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/MoreMatchers.java @@ -0,0 +1,39 @@ +// +// ======================================================================== +// 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.common.test; + +import org.eclipse.jetty.toolchain.test.matchers.RegexMatcher; + +public class MoreMatchers +{ + /** + * Create a matcher for {@link String} that matches against a regex pattern. + * + *

+ * Returns success based on {@code java.util.regex.Pattern.matcher(input).matches();} + *

+ * + * @param pattern the {@link java.util.regex.Pattern} syntax pattern to match against. + * @return the Regex Matcher + */ + public static org.hamcrest.Matcher regex(String pattern) + { + return new RegexMatcher(pattern); + } +} From dd57cf0bf602692edbdc87a6ff85506b636e239c Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Tue, 6 Mar 2018 21:01:39 -0600 Subject: [PATCH 3/7] Issue #2282 - Simplifying BlockheadClient to drastically reduce CPU load during testing --- .../jsr356/DecoderReaderManySmallTest.java | 5 - .../websocket/jsr356/DecoderReaderTest.java | 5 - .../jetty/websocket/jsr356/EncoderTest.java | 4 - .../jsr356/server/ConfiguratorTest.java | 204 +++-- .../websocket/jsr356/server/EchoTest.java | 1 - ...tedEndpointScanner_GoodSignaturesTest.java | 1 - .../websocket/client/BadNetworkTest.java | 5 - .../websocket/client/ClientCloseTest.java | 5 - .../websocket/client/ClientConnectTest.java | 5 - .../client/ConnectionManagerTest.java | 5 - .../websocket/client/SlowClientTest.java | 9 +- .../websocket/client/SlowServerTest.java | 10 - .../client/WebSocketClientBadUriTest.java | 5 - .../websocket/client/WebSocketClientTest.java | 3 - jetty-websocket/websocket-common/pom.xml | 6 + .../websocket/common/ab/TestABCase3.java | 5 - .../io/http/HttpResponseHeaderParserTest.java | 5 - .../message/MessageOutputStreamTest.java | 4 - .../common/message/MessageWriterTest.java | 4 - .../common/test/BlockheadClient.java | 832 +----------------- .../test/BlockheadClientConnection.java | 48 + .../test/BlockheadClientConstructionTest.java | 72 -- .../common/test/BlockheadClientRequest.java | 252 ++++++ .../common/test/BlockheadConnection.java | 373 ++++++++ .../test/BlockheadServerConnection.java | 4 +- .../jetty/websocket/common/test/Fuzzer.java | 109 +-- .../test/IBlockheadServerConnection.java | 1 + .../jetty/websocket/common/test/Timeouts.java | 7 +- .../common/test/WriteCallbackDelegate.java | 46 + .../server/AnnotatedMaxMessageSizeTest.java | 75 +- .../jetty/websocket/server/ChromeTest.java | 54 +- .../server/DecoratorsLegacyTest.java | 55 +- .../websocket/server/DecoratorsTest.java | 39 +- .../jetty/websocket/server/FirefoxTest.java | 36 +- .../server/FragmentExtensionTest.java | 57 +- .../server/IdentityExtensionTest.java | 53 +- .../websocket/server/IdleTimeoutTest.java | 51 +- .../server/ManyConnectionsCleanupTest.java | 159 ++-- .../websocket/server/RequestHeadersTest.java | 57 +- .../websocket/server/SubProtocolTest.java | 40 +- .../websocket/server/SuspendResumeTest.java | 36 +- .../websocket/server/TooFastClientTest.java | 157 ++-- .../websocket/server/WebSocketCloseTest.java | 187 ++-- .../server/WebSocketInvalidVersionTest.java | 59 +- .../server/WebSocketOverSSLTest.java | 5 - .../server/WebSocketServerSessionTest.java | 59 +- .../server/WebSocketServletRFCTest.java | 197 ++--- .../server/WebSocketUpgradeFilterTest.java | 76 +- .../websocket/server/ab/TestABCase2.java | 3 - .../websocket/server/ab/TestABCase4.java | 3 - .../websocket/server/ab/TestABCase5.java | 7 +- .../websocket/server/ab/TestABCase6.java | 8 - .../websocket/server/ab/TestABCase7.java | 5 - .../websocket/server/ab/TestABCase9.java | 40 - .../server/examples/MyEchoSocket.java | 3 - .../misbehaving/MisbehavingClassTest.java | 72 +- 56 files changed, 1783 insertions(+), 1845 deletions(-) create mode 100644 jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientConnection.java delete mode 100644 jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientConstructionTest.java create mode 100644 jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java create mode 100644 jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java create mode 100644 jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/WriteCallbackDelegate.java diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderManySmallTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderManySmallTest.java index 3402fb5b582..1500064c44b 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderManySmallTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderManySmallTest.java @@ -37,7 +37,6 @@ import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.WebSocketContainer; -import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -49,7 +48,6 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; -import org.junit.Rule; import org.junit.Test; @Ignore("Not working atm") @@ -165,9 +163,6 @@ public class DecoderReaderManySmallTest private static final Logger LOG = Log.getLogger(DecoderReaderManySmallTest.class); - @Rule - public TestTracker tt = new TestTracker(); - private BlockheadServer server; private WebSocketContainer client; diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderTest.java index c3ffc6909ca..56792c47554 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderTest.java @@ -42,7 +42,6 @@ import javax.websocket.OnMessage; import javax.websocket.WebSocketContainer; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; -import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.log.Log; @@ -57,7 +56,6 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; -import org.junit.Rule; import org.junit.Test; public class DecoderReaderTest @@ -229,9 +227,6 @@ public class DecoderReaderTest private static final Logger LOG = Log.getLogger(DecoderReaderTest.class); - @Rule - public TestTracker tt = new TestTracker(); - private BlockheadServer server; private WebSocketContainer client; diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java index d8ac993af07..807ca8444e2 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java @@ -41,7 +41,6 @@ import javax.websocket.Session; import javax.websocket.WebSocketContainer; import org.eclipse.jetty.toolchain.test.MavenTestingUtils; -import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -51,7 +50,6 @@ import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; public class EncoderTest @@ -186,8 +184,6 @@ public class EncoderTest private static final Logger LOG = Log.getLogger(EncoderTest.class); - @Rule - public TestTracker tt = new TestTracker(); private BlockheadServer server; private WebSocketContainer client; diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java index 9042d4f4a4b..93ac72667c0 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java @@ -35,7 +35,9 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TimeZone; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; @@ -51,6 +53,9 @@ import javax.websocket.server.HandshakeRequest; import javax.websocket.server.ServerEndpoint; import javax.websocket.server.ServerEndpointConfig; +import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.servlet.ServletContextHandler; @@ -60,8 +65,8 @@ import org.eclipse.jetty.websocket.api.util.QuoteUtil; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; -import org.eclipse.jetty.websocket.common.test.HttpResponse; -import org.eclipse.jetty.websocket.common.test.IBlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer; import org.junit.AfterClass; @@ -356,7 +361,8 @@ public class ConfiguratorTest return dateFormat; } } - + + private static BlockheadClient client; private static Server server; private static URI baseServerUri; @@ -408,18 +414,35 @@ public class ConfiguratorTest server.stop(); } + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + @Test public void testEmptyConfigurator() throws Exception { URI uri = baseServerUri.resolve("/empty"); - try (IBlockheadClient client = new BlockheadClient(uri)) + BlockheadClientRequest request = client.newWsRequest(uri); + request.header(HttpHeader.SEC_WEBSOCKET_EXTENSIONS, "identity"); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.addExtensions("identity"); - client.connect(); - client.sendStandardRequest(); - HttpResponse response = client.readResponseHeader(); - Assert.assertThat("response.extensions", response.getExtensionsHeader(), is("identity")); + HttpFields responseHeaders = clientConn.getUpgradeResponseHeaders(); + HttpField extensionHeader = responseHeaders.getField(HttpHeader.SEC_WEBSOCKET_EXTENSIONS); + Assert.assertThat("response.extensions", extensionHeader.getValue(), is("identity")); } } @@ -428,16 +451,19 @@ public class ConfiguratorTest { URI uri = baseServerUri.resolve("/no-extensions"); - try (IBlockheadClient client = new BlockheadClient(uri)) + BlockheadClientRequest request = client.newWsRequest(uri); + request.header(HttpHeader.SEC_WEBSOCKET_EXTENSIONS, "identity"); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.addExtensions("identity"); - client.connect(); - client.sendStandardRequest(); - HttpResponse response = client.expectUpgradeResponse(); - assertThat("response.extensions", response.getExtensionsHeader(), nullValue()); + HttpFields responseHeaders = clientConn.getUpgradeResponseHeaders(); + HttpField extensionHeader = responseHeaders.getField(HttpHeader.SEC_WEBSOCKET_EXTENSIONS); + assertThat("response.extensions", extensionHeader, is(nullValue())); - client.write(new TextFrame().setPayload("NegoExts")); - LinkedBlockingQueue frames = client.getFrameQueue(); + clientConn.write(new TextFrame().setPayload("NegoExts")); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("Frame Response", frame.getPayloadAsUTF8(), is("negotiatedExtensions=[]")); } @@ -448,15 +474,15 @@ public class ConfiguratorTest { URI uri = baseServerUri.resolve("/capture-request-headers"); - try (IBlockheadClient client = new BlockheadClient(uri)) - { - client.addHeader("X-Dummy: Bogus\r\n"); - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(uri); + request.header("X-Dummy", "Bogus"); - client.write(new TextFrame().setPayload("X-Dummy")); - LinkedBlockingQueue frames = client.getFrameQueue(); + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + clientConn.write(new TextFrame().setPayload("X-Dummy")); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Request Header [X-Dummy]: \"Bogus\"")); } @@ -468,33 +494,32 @@ public class ConfiguratorTest URI uri = baseServerUri.resolve("/unique-user-props"); // First request - try (IBlockheadClient client = new BlockheadClient(uri)) - { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(uri); + Future connFut = request.sendAsync(); - client.write(new TextFrame().setPayload("apple")); - LinkedBlockingQueue frames = client.getFrameQueue(); + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + clientConn.write(new TextFrame().setPayload("apple")); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested User Property: [apple] = \"fruit from tree\"")); } // Second request - try (IBlockheadClient client = new BlockheadClient(uri)) - { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); - client.write(new TextFrame().setPayload("apple")); - client.write(new TextFrame().setPayload("blueberry")); - LinkedBlockingQueue frames = client.getFrameQueue(); + request = client.newWsRequest(uri); + connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + clientConn.write(new TextFrame().setPayload("apple")); + clientConn.write(new TextFrame().setPayload("blueberry")); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); // should have no value Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested User Property: [apple] = ")); - frame = frames.poll(); + frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested User Property: [blueberry] = \"fruit from bush\"")); } } @@ -504,18 +529,16 @@ public class ConfiguratorTest { URI uri = baseServerUri.resolve("/addr"); - // First request - try (IBlockheadClient client = new BlockheadClient(uri)) - { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); - - InetSocketAddress expectedLocal = client.getLocalSocketAddress(); - InetSocketAddress expectedRemote = client.getRemoteSocketAddress(); + BlockheadClientRequest request = client.newWsRequest(uri); + Future connFut = request.sendAsync(); - client.write(new TextFrame().setPayload("addr")); - LinkedBlockingQueue frames = client.getFrameQueue(); + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + InetSocketAddress expectedLocal = clientConn.getLocalSocketAddress(); + InetSocketAddress expectedRemote = clientConn.getRemoteSocketAddress(); + + clientConn.write(new TextFrame().setPayload("addr")); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); StringWriter expected = new StringWriter(); @@ -540,15 +563,14 @@ public class ConfiguratorTest URI uri = baseServerUri.resolve("/protocols"); ProtocolsConfigurator.seenProtocols.set(null); - try (IBlockheadClient client = new BlockheadClient(uri)) - { - client.addHeader("Sec-WebSocket-Protocol: echo\r\n"); - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(uri); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "echo"); + Future connFut = request.sendAsync(); - client.write(new TextFrame().setPayload("getProtocols")); - LinkedBlockingQueue frames = client.getFrameQueue(); + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + clientConn.write(new TextFrame().setPayload("getProtocols")); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\"]")); } @@ -564,15 +586,14 @@ public class ConfiguratorTest URI uri = baseServerUri.resolve("/protocols"); ProtocolsConfigurator.seenProtocols.set(null); - try (IBlockheadClient client = new BlockheadClient(uri)) - { - client.addHeader("Sec-WebSocket-Protocol: echo, chat, status\r\n"); - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(uri); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "echo, chat, status"); + Future connFut = request.sendAsync(); - client.write(new TextFrame().setPayload("getProtocols")); - LinkedBlockingQueue frames = client.getFrameQueue(); + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + clientConn.write(new TextFrame().setPayload("getProtocols")); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]")); } @@ -588,15 +609,14 @@ public class ConfiguratorTest URI uri = baseServerUri.resolve("/protocols"); ProtocolsConfigurator.seenProtocols.set(null); - try (IBlockheadClient client = new BlockheadClient(uri)) - { - client.addHeader("sec-websocket-protocol: echo, chat, status\r\n"); - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(uri); + request.header("sec-websocket-protocol", "echo, chat, status"); + Future connFut = request.sendAsync(); - client.write(new TextFrame().setPayload("getProtocols")); - LinkedBlockingQueue frames = client.getFrameQueue(); + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + clientConn.write(new TextFrame().setPayload("getProtocols")); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]")); } @@ -612,15 +632,15 @@ public class ConfiguratorTest URI uri = baseServerUri.resolve("/protocols"); ProtocolsConfigurator.seenProtocols.set(null); - try (IBlockheadClient client = new BlockheadClient(uri)) - { - client.addHeader("Sec-Websocket-Protocol: echo, chat, status\r\n"); - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(uri); + // We see "Websocket" (no capital "S" often) + request.header("Sec-Websocket-Protocol", "echo, chat, status"); + Future connFut = request.sendAsync(); - client.write(new TextFrame().setPayload("getProtocols")); - LinkedBlockingQueue frames = client.getFrameQueue(); + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + clientConn.write(new TextFrame().setPayload("getProtocols")); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]")); } @@ -634,15 +654,15 @@ public class ConfiguratorTest { URI uri = baseServerUri.resolve("/timedecoder"); - try (BlockheadClient client = new BlockheadClient(uri)) - { - client.addHeader("Sec-Websocket-Protocol: gmt\r\n"); - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(uri); + // We see "Websocket" (no capital "S" often) + request.header("SeC-WeBsOcKeT-PrOtOcOl", "gmt"); + Future connFut = request.sendAsync(); - client.write(new TextFrame().setPayload("2016-06-20T14:27:44")); - LinkedBlockingQueue frames = client.getFrameQueue(); + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + clientConn.write(new TextFrame().setPayload("2016-06-20T14:27:44")); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("cal=2016.06.20 AD at 14:27:44 +0000")); } diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/EchoTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/EchoTest.java index b4b95d9c803..b836c4dcb8a 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/EchoTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/EchoTest.java @@ -249,7 +249,6 @@ public class EchoTest public EchoTest(EchoCase testcase) { this.testcase = testcase; - System.err.println(testcase); } @Test(timeout=2000) diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScanner_GoodSignaturesTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScanner_GoodSignaturesTest.java index 0c168b60381..80a1a51bf72 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScanner_GoodSignaturesTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScanner_GoodSignaturesTest.java @@ -179,7 +179,6 @@ public class ServerAnnotatedEndpointScanner_GoodSignaturesTest public ServerAnnotatedEndpointScanner_GoodSignaturesTest(Case testcase) { this.testcase = testcase; - System.err.printf("Testing signature of %s%n",testcase.pojo.getName()); } @Test diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/BadNetworkTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/BadNetworkTest.java index 94cd12c0b6e..85a26b59156 100644 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/BadNetworkTest.java +++ b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/BadNetworkTest.java @@ -24,14 +24,12 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; -import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.common.test.BlockheadServer; import org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection; import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; /** @@ -39,9 +37,6 @@ import org.junit.Test; */ public class BadNetworkTest { - @Rule - public TestTracker tt = new TestTracker(); - public ByteBufferPool bufferPool = new MappedByteBufferPool(); private BlockheadServer server; 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 index 2b7ffe5e1e8..62da4dd5f7e 100644 --- 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 @@ -51,7 +51,6 @@ 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.toolchain.test.TestTracker; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -76,7 +75,6 @@ import org.hamcrest.Matcher; import org.junit.After; import org.junit.Before; import org.junit.Ignore; -import org.junit.Rule; import org.junit.Test; public class ClientCloseTest @@ -178,9 +176,6 @@ public class ClientCloseTest } } - @Rule - public TestTracker tt = new TestTracker(); - private BlockheadServer server; private WebSocketClient client; 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 index e1c842df49f..5b570fb4053 100644 --- 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 @@ -39,7 +39,6 @@ import java.util.concurrent.TimeoutException; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; -import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.UpgradeException; import org.eclipse.jetty.websocket.common.AcceptHash; @@ -49,7 +48,6 @@ import org.hamcrest.Matcher; import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; /** @@ -58,9 +56,6 @@ import org.junit.Test; @SuppressWarnings("Duplicates") public class ClientConnectTest { - @Rule - public TestTracker tt = new TestTracker(); - public ByteBufferPool bufferPool = new MappedByteBufferPool(); private final int timeout = 500; 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 index 205c221855d..77511c95d31 100644 --- 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 @@ -24,17 +24,12 @@ import java.net.InetSocketAddress; import java.net.URI; import java.net.URISyntaxException; -import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.websocket.client.io.ConnectionManager; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; public class ConnectionManagerTest { - @Rule - public TestTracker tt = new TestTracker(); - private void assertToSocketAddress(String uriStr, String expectedHost, int expectedPort) throws URISyntaxException { URI uri = new URI(uriStr); 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 index 7dde15b797f..d727c44b176 100644 --- 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 @@ -18,14 +18,12 @@ package org.eclipse.jetty.websocket.client; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.is; import java.net.URI; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.TestTracker; -import org.eclipse.jetty.toolchain.test.annotation.Slow; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.common.test.BlockheadServer; @@ -33,14 +31,10 @@ import org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection; import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; public class SlowClientTest { - @Rule - public TestTracker tt = new TestTracker(); - private BlockheadServer server; private WebSocketClient client; @@ -72,7 +66,6 @@ public class SlowClientTest } @Test - @Slow public void testClientSlowToSend() throws Exception { JettyTrackingSocket tsocket = new JettyTrackingSocket(); 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 index 101d0eae04d..09050221515 100644 --- 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 @@ -24,8 +24,6 @@ import java.net.URI; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.TestTracker; -import org.eclipse.jetty.toolchain.test.annotation.Slow; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.client.masks.ZeroMasker; @@ -34,16 +32,10 @@ import org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection; import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; -import org.junit.Rule; import org.junit.Test; -@Ignore("TODO: Flappy Test") public class SlowServerTest { - @Rule - public TestTracker tt = new TestTracker(); - private BlockheadServer server; private WebSocketClient client; @@ -75,7 +67,6 @@ public class SlowServerTest } @Test - @Slow public void testServerSlowToRead() throws Exception { JettyTrackingSocket tsocket = new JettyTrackingSocket(); @@ -122,7 +113,6 @@ public class SlowServerTest } @Test - @Slow public void testServerSlowToSend() throws Exception { JettyTrackingSocket clientSocket = new JettyTrackingSocket(); diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/WebSocketClientBadUriTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/WebSocketClientBadUriTest.java index 028083949a5..02e7c31317e 100644 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/WebSocketClientBadUriTest.java +++ b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/WebSocketClientBadUriTest.java @@ -23,11 +23,9 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import org.eclipse.jetty.toolchain.test.TestTracker; import org.junit.After; import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -56,9 +54,6 @@ public class WebSocketClientBadUriTest return data; } - @Rule - public TestTracker tt = new TestTracker(); - private WebSocketClient client; private final String uriStr; private final URI uri; 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 index 90fe11e4da5..b22e3646d93 100644 --- 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 @@ -34,7 +34,6 @@ import java.util.Map; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.AdvancedRunner; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.websocket.api.BatchMode; import org.eclipse.jetty.websocket.api.RemoteEndpoint; @@ -50,9 +49,7 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -@RunWith(AdvancedRunner.class) public class WebSocketClientTest { private BlockheadServer server; diff --git a/jetty-websocket/websocket-common/pom.xml b/jetty-websocket/websocket-common/pom.xml index a3bac53190d..2e7e2393291 100644 --- a/jetty-websocket/websocket-common/pom.xml +++ b/jetty-websocket/websocket-common/pom.xml @@ -30,6 +30,12 @@ jetty-io ${project.version} + + org.eclipse.jetty + jetty-client + ${project.version} + test + org.eclipse.jetty.toolchain jetty-test-helper diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase3.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase3.java index c8c2d6ee9cc..ab4dec13fe5 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase3.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/ab/TestABCase3.java @@ -22,14 +22,12 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.websocket.api.ProtocolException; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.PingFrame; import org.eclipse.jetty.websocket.common.frames.PongFrame; import org.eclipse.jetty.websocket.common.test.UnitGenerator; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -74,9 +72,6 @@ public class TestABCase3 return data; } - @Rule - public TestTracker tt = new TestTracker(); - private WebSocketFrame invalidFrame; public TestABCase3(WebSocketFrame invalidFrame) diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/http/HttpResponseHeaderParserTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/http/HttpResponseHeaderParserTest.java index 96453c9b022..e9a4d36814e 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/http/HttpResponseHeaderParserTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/http/HttpResponseHeaderParserTest.java @@ -28,18 +28,13 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; -import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.StringUtil; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; public class HttpResponseHeaderParserTest { - @Rule - public TestTracker tt = new TestTracker(); - private void appendUtf8(ByteBuffer buf, String line) { buf.put(ByteBuffer.wrap(StringUtil.getUtf8Bytes(line))); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageOutputStreamTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageOutputStreamTest.java index 0060f58c4b3..6e3aa82a3b3 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageOutputStreamTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageOutputStreamTest.java @@ -26,7 +26,6 @@ import java.util.Arrays; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; -import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.WebSocketPolicy; @@ -48,9 +47,6 @@ public class MessageOutputStreamTest { private static final Logger LOG = Log.getLogger(MessageOutputStreamTest.class); - @Rule - public TestTracker testtracker = new TestTracker(); - @Rule public TestName testname = new TestName(); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageWriterTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageWriterTest.java index ec77b8d176a..e4c6c99bced 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageWriterTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageWriterTest.java @@ -24,7 +24,6 @@ import java.util.Arrays; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; -import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.WebSocketPolicy; @@ -46,9 +45,6 @@ public class MessageWriterTest { private static final Logger LOG = Log.getLogger(MessageWriterTest.class); - @Rule - public TestTracker testtracker = new TestTracker(); - @Rule public TestName testname = new TestName(); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java index e7bca7d02af..3dba1c72bb0 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java @@ -18,833 +18,67 @@ package org.eclipse.jetty.websocket.common.test; -import static org.hamcrest.Matchers.anyOf; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketAddress; -import java.net.SocketTimeoutException; import java.net.URI; -import java.net.URISyntaxException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - -import javax.net.ssl.HttpsURLConnection; +import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; -import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.util.IO; -import org.eclipse.jetty.util.StringUtil; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.websocket.api.BatchMode; +import org.eclipse.jetty.util.DecoratedObjectFactory; +import org.eclipse.jetty.websocket.api.WebSocketBehavior; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.WriteCallback; -import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; -import org.eclipse.jetty.websocket.api.extensions.Frame; -import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; -import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; -import org.eclipse.jetty.websocket.api.util.WSURI; -import org.eclipse.jetty.websocket.common.AcceptHash; -import org.eclipse.jetty.websocket.common.CloseInfo; -import org.eclipse.jetty.websocket.common.ConnectionState; -import org.eclipse.jetty.websocket.common.Generator; -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.extensions.ExtensionStack; +import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory; +import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory; -import org.eclipse.jetty.websocket.common.io.IOState; -import org.eclipse.jetty.websocket.common.io.IOState.ConnectionStateListener; -import org.eclipse.jetty.websocket.common.io.http.HttpResponseHeaderParser; -import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope; -import org.junit.Assert; +import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; -/** - * A simple websocket client for performing unit tests with. - *

- * This client will use {@link HttpURLConnection} and {@link HttpsURLConnection} with standard blocking calls to perform websocket requests. - *

- * This client is NOT intended to be performant or follow the websocket spec religiously. In fact, being able to deviate from the websocket spec at will - * is desired for this client to operate properly for the unit testing within this module. - *

- * The BlockheadClient should never validate frames or bytes being sent for validity, against any sort of spec, or even sanity. It should, however be honest - * with regards to basic IO behavior, a write should work as expected, a read should work as expected, but what byte it sends or reads is not within its - * scope. - */ -public class BlockheadClient implements OutgoingFrames, ConnectionStateListener, AutoCloseable, IBlockheadClient +public class BlockheadClient extends HttpClient implements WebSocketContainerScope { - private class FrameReadingThread extends Thread implements Runnable, IncomingFrames + private WebSocketPolicy policy; + private ByteBufferPool bufferPool; + private ExtensionFactory extensionFactory; + private DecoratedObjectFactory objectFactory; + + public BlockheadClient() { - public long totalBytes = 0; - public long totalReadOps = 0; - public long totalParseOps = 0; - - public LinkedBlockingQueue frames = new LinkedBlockingQueue<>(); - public LinkedBlockingQueue errors = new LinkedBlockingQueue<>(); - - @Override - public void run() - { - LOG.debug("Reading frames from server"); - - byte buf[] = new byte[BUFFER_SIZE]; - try - { - if ((remainingBuffer != null) && (remainingBuffer.remaining() > 0)) - { - LOG.debug("Reading bytes received during response header parse: {}",BufferUtil.toDetailString(remainingBuffer)); - totalBytes += remainingBuffer.remaining(); - totalReadOps++; - parser.parse(remainingBuffer); - } - - int len = 0; - int available = 0; - while (!eof) - { - available = in.available(); - len = in.read(buf,0,Math.min(available,buf.length)); - totalReadOps++; - if (len < 0) - { - eof = true; - break; - } - else if (len > 0) - { - totalBytes += len; - ByteBuffer bbuf = ByteBuffer.wrap(buf,0,len); - if (LOG.isDebugEnabled()) - { - LOG.debug("Read {} bytes: {}",len,BufferUtil.toDetailString(bbuf)); - } - totalParseOps++; - parser.parse(bbuf); - } - } - } - catch (IOException e) - { - LOG.debug(e); - } - } - - @Override - public String toString() - { - StringBuilder str = new StringBuilder(); - str.append("FrameReadingThread["); - str.append(",frames=" + frames.size()); - str.append(",errors=" + errors.size()); - str.append(String.format(",totalBytes=%,d",totalBytes)); - str.append(String.format(",totalReadOps=%,d",totalReadOps)); - str.append(String.format(",totalParseOps=%,d",totalParseOps)); - str.append("]"); - return str.toString(); - } - - @Override - public synchronized void incomingError(Throwable t) - { - this.errors.add(t); - } - - @Override - public synchronized void incomingFrame(Frame frame) - { - this.frames.add(WebSocketFrame.copy(frame)); - } - - public synchronized void clear() - { - this.frames.clear(); - this.errors.clear(); - } + super(null); + setName("Blockhead-CLIENT"); + this.policy = new WebSocketPolicy(WebSocketBehavior.CLIENT); + this.bufferPool = new MappedByteBufferPool(); + this.extensionFactory = new WebSocketExtensionFactory(this); + this.objectFactory = new DecoratedObjectFactory(); } - private static final String REQUEST_HASH_KEY = "dGhlIHNhbXBsZSBub25jZQ=="; - private static final int BUFFER_SIZE = 64 * 1024; - private static final Logger LOG = Log.getLogger(BlockheadClient.class); - private final URI destHttpURI; - private final URI destWebsocketURI; - private final ByteBufferPool bufferPool; - private final Generator generator; - private final Parser parser; - - private final WebSocketExtensionFactory extensionFactory; - private FrameReadingThread frameReader; - - private ExecutorService executor; - private Socket socket; - private OutputStream out; - private InputStream in; - private int version = 13; // default to RFC-6455 - private String protocols; - private List extensions = new ArrayList<>(); - private List headers = new ArrayList<>(); - private byte[] clientmask = new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF }; - private int timeout = 1000; - private OutgoingFrames outgoing = this; - private boolean eof = false; - private ExtensionStack extensionStack; - private IOState ioState; - private CountDownLatch disconnectedLatch = new CountDownLatch(1); - private ByteBuffer remainingBuffer; - - private String connectionValue = "Upgrade"; - - public BlockheadClient(URI destWebsocketURI) throws URISyntaxException + public ByteBufferPool getBufferPool() { - this(WebSocketPolicy.newClientPolicy(),destWebsocketURI); - } - - public BlockheadClient(WebSocketPolicy policy, URI destWebsocketURI) throws URISyntaxException - { - Assert.assertThat("Websocket URI scheme",destWebsocketURI.getScheme(),anyOf(is("ws"),is("wss"))); - this.destWebsocketURI = destWebsocketURI; - if (destWebsocketURI.getScheme().equals("wss")) - { - throw new RuntimeException("Sorry, BlockheadClient does not support SSL"); - } - this.destHttpURI = WSURI.toHttp(destWebsocketURI); - - LOG.debug("WebSocket URI: {}",destWebsocketURI); - LOG.debug(" HTTP URI: {}",destHttpURI); - - // This is a blockhead client, no point tracking leaks on this object. - this.bufferPool = new MappedByteBufferPool(8192); - this.generator = new Generator(policy,bufferPool); - this.parser = new Parser(policy,bufferPool); - - this.extensionFactory = new WebSocketExtensionFactory(new SimpleContainerScope(policy,bufferPool)); - this.ioState = new IOState(); - this.ioState.addListener(this); - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#addExtensions(java.lang.String) - */ - @Override - public void addExtensions(String xtension) - { - this.extensions.add(xtension); - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#addHeader(java.lang.String) - */ - @Override - public void addHeader(String header) - { - this.headers.add(header); - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#awaitDisconnect(long, java.util.concurrent.TimeUnit) - */ - @Override - public boolean awaitDisconnect(long timeout, TimeUnit unit) throws InterruptedException - { - return disconnectedLatch.await(timeout,unit); - } - - public void clearCaptured() - { - frameReader.clear(); - } - - public void clearExtensions() - { - extensions.clear(); - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#close() - */ - @Override - public void close() - { - LOG.debug("close()"); - close(-1,null); - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#close(int, java.lang.String) - */ - @Override - public void close(int statusCode, String message) - { - LOG.debug("close({},{})",statusCode,message); - CloseInfo close = new CloseInfo(statusCode,message); - - if (!ioState.isClosed()) - { - ioState.onCloseLocal(close); - } - else - { - LOG.debug("Not issuing close. ioState = {}",ioState); - } - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#connect() - */ - @Override - public void connect() throws IOException - { - InetAddress destAddr = InetAddress.getByName(destHttpURI.getHost()); - int port = destHttpURI.getPort(); - - SocketAddress endpoint = new InetSocketAddress(destAddr,port); - - socket = new Socket(); - socket.setSoTimeout(timeout); - socket.connect(endpoint); - - out = socket.getOutputStream(); - in = socket.getInputStream(); + return bufferPool; } @Override - public void disconnect() + public DecoratedObjectFactory getObjectFactory() { - LOG.debug("disconnect"); - IO.close(in); - IO.close(out); - disconnectedLatch.countDown(); - if (frameReader != null) - { - frameReader.interrupt(); - } - if (socket != null) - { - try - { - socket.close(); - } - catch (IOException ignore) - { - /* ignore */ - } - } + return objectFactory; } - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#expectServerDisconnect() - */ - @Override - public void expectServerDisconnect() + public ExtensionFactory getExtensionFactory() { - if (eof) - { - return; - } - - try - { - int len = in.read(); - if (len == (-1)) - { - // we are disconnected - eof = true; - return; - } - - Assert.assertThat("Expecting no data and proper socket disconnect (issued from server)",len,is(-1)); - } - catch (SocketTimeoutException e) - { - LOG.warn(e); - Assert.fail("Expected a server initiated disconnect, instead the read timed out"); - } - catch (IOException e) - { - // acceptable path - } + return extensionFactory; } - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#expectUpgradeResponse() - */ - @Override - public HttpResponse expectUpgradeResponse() throws IOException + public WebSocketPolicy getPolicy() { - HttpResponse response = readResponseHeader(); - - if (LOG.isDebugEnabled()) - { - LOG.debug("Response Header: {}{}",'\n',response); - } - - Assert.assertThat("Response Status Code",response.getStatusCode(),is(101)); - Assert.assertThat("Response Status Reason",response.getStatusReason(),is("Switching Protocols")); - Assert.assertThat("Response Header[Upgrade]",response.getHeader("Upgrade"),is("WebSocket")); - Assert.assertThat("Response Header[Connection]",response.getHeader("Connection"),is("Upgrade")); - - // Validate the Sec-WebSocket-Accept - String acceptKey = response.getHeader("Sec-WebSocket-Accept"); - Assert.assertThat("Response Header[Sec-WebSocket-Accept Exists]",acceptKey,notNullValue()); - - String reqKey = REQUEST_HASH_KEY; - String expectedHash = AcceptHash.hashKey(reqKey); - - Assert.assertThat("Valid Sec-WebSocket-Accept Hash?",acceptKey,is(expectedHash)); - - // collect extensions configured in response header - List configs = getExtensionConfigs(response); - extensionStack = new ExtensionStack(this.extensionFactory); - extensionStack.negotiate(configs); - - // Setup Frame Reader - this.frameReader = new FrameReadingThread(); - this.frameReader.start(); - - // Start with default routing - extensionStack.setNextIncoming(frameReader); // the websocket layer - extensionStack.setNextOutgoing(outgoing); // the network layer - - // Configure Parser / Generator - extensionStack.configure(parser); - extensionStack.configure(generator); - - // Start Stack - try - { - extensionStack.start(); - } - catch (Exception e) - { - throw new IOException("Unable to start Extension Stack"); - } - - // configure parser - parser.setIncomingFramesHandler(extensionStack); - ioState.onOpened(); - - LOG.debug("outgoing = {}",outgoing); - LOG.debug("incoming = {}",extensionStack); - - return response; + return policy; } - public void flush() throws IOException + public BlockheadClientRequest newWsRequest(URI destURI) { - out.flush(); - } - - public String getConnectionValue() - { - return connectionValue; - } - - public ExecutorService getExecutor() - { - if (executor == null) - { - executor = Executors.newCachedThreadPool(); - } - return executor; - } - - private List getExtensionConfigs(HttpResponse response) - { - List configs = new ArrayList<>(); - - String econf = response.getHeader("Sec-WebSocket-Extensions"); - if (econf != null) - { - LOG.debug("Found Extension Response: {}",econf); - ExtensionConfig config = ExtensionConfig.parse(econf); - configs.add(config); - } - return configs; - } - - public List getExtensions() - { - return extensions; - } - - public URI getHttpURI() - { - return destHttpURI; + return new BlockheadClientRequest(this, destURI); } @Override - public InetSocketAddress getLocalSocketAddress() - { - return (InetSocketAddress)socket.getLocalSocketAddress(); - } - - public IOState getIOState() - { - return ioState; - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#getProtocols() - */ - @Override - public String getProtocols() - { - return protocols; - } - + public void onSessionOpened(WebSocketSession session) + { /* ignored */ } @Override - public InetSocketAddress getRemoteSocketAddress() - { - return (InetSocketAddress)socket.getRemoteSocketAddress(); - } - - public String getRequestHost() - { - if (destHttpURI.getPort() > 0) - { - return String.format("%s:%d",destHttpURI.getHost(),destHttpURI.getPort()); - } - else - { - return destHttpURI.getHost(); - } - } - - public String getRequestPath() - { - StringBuilder path = new StringBuilder(); - path.append(destHttpURI.getPath()); - if (StringUtil.isNotBlank(destHttpURI.getQuery())) - { - path.append('?').append(destHttpURI.getRawQuery()); - } - return path.toString(); - } - - public String getRequestWebSocketKey() - { - return REQUEST_HASH_KEY; - } - - public String getRequestWebSocketOrigin() - { - return destWebsocketURI.toASCIIString(); - } - - public int getVersion() - { - return version; - } - - public URI getWebsocketURI() - { - return destWebsocketURI; - } - - public boolean isConnected() - { - return (socket != null) && (socket.isConnected()); - } - - @Override - public void onConnectionStateChange(ConnectionState state) - { - LOG.debug("CLIENT onConnectionStateChange() - {}",state); - switch (state) - { - case CLOSED: - // Per Spec, client should not initiate disconnect on its own - // this.disconnect(); - break; - case CLOSING: - CloseInfo close = ioState.getCloseInfo(); - - WebSocketFrame frame = close.asFrame(); - LOG.debug("Issuing: {}",frame); - try - { - write(frame); - } - catch (IOException e) - { - LOG.debug(e); - } - break; - default: - /* do nothing */ - break; - } - } - - @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) - { - ByteBuffer headerBuf = generator.generateHeaderBytes(frame); - if (LOG.isDebugEnabled()) - { - LOG.debug("writing out: {}",BufferUtil.toDetailString(headerBuf)); - } - try - { - BufferUtil.writeTo(headerBuf,out); - BufferUtil.writeTo(frame.getPayload(),out); - out.flush(); - if (callback != null) - { - callback.writeSuccess(); - } - } - catch (IOException e) - { - if (callback != null) - { - callback.writeFailed(e); - } - } - finally - { - bufferPool.release(headerBuf); - } - - if (frame.getOpCode() == OpCode.CLOSE) - { - disconnect(); - } - } - - @Override - public LinkedBlockingQueue getFrameQueue() - { - return frameReader.frames; - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#readResponseHeader() - */ - @Override - public HttpResponse readResponseHeader() throws IOException - { - HttpResponse response = new HttpResponse(); - HttpResponseHeaderParser respParser = new HttpResponseHeaderParser(response); - - byte buf[] = new byte[512]; - - while (!eof) - { - int available = in.available(); - int len = in.read(buf,0,Math.min(available,buf.length)); - if (len < 0) - { - eof = true; - break; - } - else if (len > 0) - { - ByteBuffer bbuf = ByteBuffer.wrap(buf,0,len); - if (LOG.isDebugEnabled()) - { - LOG.debug("Read {} bytes: {}",len,BufferUtil.toDetailString(bbuf)); - } - if (respParser.parse(bbuf) != null) - { - break; - } - } - } - - remainingBuffer = response.getRemainingBuffer(); - - return response; - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#sendStandardRequest() - */ - @Override - public void sendStandardRequest() throws IOException - { - StringBuilder req = generateUpgradeRequest(); - writeRaw(req.toString()); - } - - public StringBuilder generateUpgradeRequest() - { - StringBuilder req = new StringBuilder(); - req.append("GET ").append(getRequestPath()).append(" HTTP/1.1\r\n"); - req.append("Host: ").append(getRequestHost()).append("\r\n"); - req.append("Upgrade: websocket\r\n"); - req.append("User-Agent: BlockheadClient/JettyTests\r\n"); - req.append("Connection: ").append(connectionValue).append("\r\n"); - for (String header : headers) - { - req.append(header); - } - req.append("Sec-WebSocket-Key: ").append(getRequestWebSocketKey()).append("\r\n"); - req.append("Sec-WebSocket-Origin: ").append(getRequestWebSocketOrigin()).append("\r\n"); - if (StringUtil.isNotBlank(protocols)) - { - req.append("Sec-WebSocket-Protocol: ").append(protocols).append("\r\n"); - } - - for (String xtension : extensions) - { - req.append("Sec-WebSocket-Extensions: ").append(xtension).append("\r\n"); - } - req.append("Sec-WebSocket-Version: ").append(version).append("\r\n"); - req.append("\r\n"); - return req; - } - - @Override - public void setConnectionValue(String connectionValue) - { - this.connectionValue = connectionValue; - } - - public void setExecutor(ExecutorService executor) - { - this.executor = executor; - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#setProtocols(java.lang.String) - */ - @Override - public void setProtocols(String protocols) - { - this.protocols = protocols; - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#setTimeout(int, java.util.concurrent.TimeUnit) - */ - @Override - public void setTimeout(int duration, TimeUnit unit) - { - this.timeout = (int)TimeUnit.MILLISECONDS.convert(duration,unit); - } - - public void setVersion(int version) - { - this.version = version; - } - - public void skipTo(String string) throws IOException - { - int state = 0; - - while (true) - { - int b = in.read(); - if (b < 0) - { - throw new EOFException(); - } - - if (b == string.charAt(state)) - { - state++; - if (state == string.length()) - { - break; - } - } - else - { - state = 0; - } - } - } - - public void sleep(TimeUnit unit, int duration) throws InterruptedException - { - LOG.info("Sleeping for {} {}",duration,unit); - unit.sleep(duration); - LOG.info("Waking up from sleep"); - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#write(org.eclipse.jetty.websocket.common.WebSocketFrame) - */ - @Override - public void write(WebSocketFrame frame) throws IOException - { - if (!ioState.isOpen()) - { - LOG.debug("IO Not Open / Not Writing: {}",frame); - return; - } - LOG.debug("write(Frame->{}) to {}",frame,outgoing); - if (LOG.isDebugEnabled()) - { - frame.setMask(new byte[] { 0x00, 0x00, 0x00, 0x00 }); - } - else - { - frame.setMask(clientmask); - } - extensionStack.outgoingFrame(frame,null,BatchMode.OFF); - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#writeRaw(java.nio.ByteBuffer) - */ - @Override - public void writeRaw(ByteBuffer buf) throws IOException - { - LOG.debug("write(ByteBuffer) {}",BufferUtil.toDetailString(buf)); - BufferUtil.writeTo(buf,out); - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#writeRaw(java.nio.ByteBuffer, int) - */ - @Override - public void writeRaw(ByteBuffer buf, int numBytes) throws IOException - { - int len = Math.min(numBytes,buf.remaining()); - byte arr[] = new byte[len]; - buf.get(arr,0,len); - out.write(arr); - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#writeRaw(java.lang.String) - */ - @Override - public void writeRaw(String str) throws IOException - { - LOG.debug("write((String)[{}]){}{})",str.length(),'\n',str); - out.write(str.getBytes(StandardCharsets.ISO_8859_1)); - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadClient#writeRawSlowly(java.nio.ByteBuffer, int) - */ - @Override - public void writeRawSlowly(ByteBuffer buf, int segmentSize) throws IOException - { - while (buf.remaining() > 0) - { - writeRaw(buf,segmentSize); - flush(); - } - } + public void onSessionClosed(WebSocketSession session) + { /* ignored */ } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientConnection.java new file mode 100644 index 00000000000..72d7ff2c859 --- /dev/null +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientConnection.java @@ -0,0 +1,48 @@ +// +// ======================================================================== +// 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.common.test; + +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadLocalRandom; + +import org.eclipse.jetty.io.ByteBufferPool; +import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.common.extensions.ExtensionStack; + +public class BlockheadClientConnection extends BlockheadConnection +{ + public BlockheadClientConnection(WebSocketPolicy policy, ByteBufferPool bufferPool, ExtensionStack extensionStack, EndPoint endp, Executor executor) + { + super(policy, bufferPool, extensionStack, endp, executor); + } + + @Override + public void write(WebSocketFrame frame) + { + if (frame.getMask() == null) + { + byte mask[] = new byte[4]; + ThreadLocalRandom.current().nextBytes(mask); + frame.setMask(mask); + } + super.write(frame); + } +} \ No newline at end of file diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientConstructionTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientConstructionTest.java deleted file mode 100644 index 87ebe51ba0f..00000000000 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientConstructionTest.java +++ /dev/null @@ -1,72 +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.common.test; - -import static org.hamcrest.Matchers.is; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -/** - * Gotta test some basic constructors of the BlockheadClient. - */ -@RunWith(value = Parameterized.class) -public class BlockheadClientConstructionTest -{ - @Parameters - public static Collection data() - { - List data = new ArrayList<>(); - // @formatter:off - data.add(new Object[] { "ws://localhost/", "http://localhost/" }); - data.add(new Object[] { "ws://localhost:8080/", "http://localhost:8080/" }); - data.add(new Object[] { "ws://webtide.com/", "http://webtide.com/" }); - data.add(new Object[] { "ws://www.webtide.com/sockets/chat", "http://www.webtide.com/sockets/chat" }); - // @formatter:on - return data; - } - - private URI expectedWsUri; - private URI expectedHttpUri; - - public BlockheadClientConstructionTest(String wsuri, String httpuri) - { - this.expectedWsUri = URI.create(wsuri); - this.expectedHttpUri = URI.create(httpuri); - } - - @Test - public void testURIs() throws URISyntaxException - { - @SuppressWarnings("resource") - BlockheadClient client = new BlockheadClient(expectedWsUri); - Assert.assertThat("Websocket URI",client.getWebsocketURI(),is(expectedWsUri)); - Assert.assertThat("Websocket URI",client.getHttpURI(),is(expectedHttpUri)); - } - -} diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java new file mode 100644 index 00000000000..8dd9b2801f9 --- /dev/null +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java @@ -0,0 +1,252 @@ +// +// ======================================================================== +// 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.common.test; + +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeoutException; + +import org.eclipse.jetty.client.HttpConversation; +import org.eclipse.jetty.client.HttpRequest; +import org.eclipse.jetty.client.HttpResponse; +import org.eclipse.jetty.client.HttpResponseException; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Response; +import org.eclipse.jetty.client.api.Result; +import org.eclipse.jetty.client.http.HttpConnectionOverHTTP; +import org.eclipse.jetty.client.http.HttpConnectionUpgrader; +import org.eclipse.jetty.client.util.ByteBufferContentProvider; +import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.util.B64Code; +import org.eclipse.jetty.util.QuotedStringTokenizer; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.UpgradeException; +import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.common.AcceptHash; +import org.eclipse.jetty.websocket.common.extensions.ExtensionStack; + +public class BlockheadClientRequest extends HttpRequest implements Response.CompleteListener, HttpConnectionUpgrader +{ + private static final Logger LOG = Log.getLogger(BlockheadClientRequest.class); + private final BlockheadClient client; + private final CompletableFuture fut; + + protected BlockheadClientRequest(BlockheadClient client, URI uri) + { + super(client, new HttpConversation(), uri); + this.client = client; + this.fut = new CompletableFuture<>(); + } + + public void setInitialBytes(ByteBuffer initialBytes) + { + content(new RawBytesProvider(initialBytes)); + } + + private final String genRandomKey() + { + byte[] bytes = new byte[16]; + ThreadLocalRandom.current().nextBytes(bytes); + return new String(B64Code.encode(bytes)); + } + + private void initWebSocketHeaders() + { + method(HttpMethod.GET); + version(HttpVersion.HTTP_1_1); + + HttpFields fields = getHeaders(); + + // The Upgrade Headers + if (!fields.contains(HttpHeader.UPGRADE)) + header(HttpHeader.UPGRADE, "websocket"); + if (!fields.contains(HttpHeader.CONNECTION)) + header(HttpHeader.CONNECTION, "Upgrade"); + + // The WebSocket Headers + if (!fields.contains(HttpHeader.SEC_WEBSOCKET_KEY)) + header(HttpHeader.SEC_WEBSOCKET_KEY, genRandomKey()); + if (!fields.contains(HttpHeader.SEC_WEBSOCKET_VERSION)) + header(HttpHeader.SEC_WEBSOCKET_VERSION, "13"); + + // (Per the hybi list): Add no-cache headers to avoid compatibility issue. + // There are some proxies that rewrite "Connection: upgrade" + // to "Connection: close" in the response if a request doesn't contain + // these headers. + if (!fields.contains(HttpHeader.PRAGMA)) + header(HttpHeader.PRAGMA, "no-cache"); + if (!fields.contains(HttpHeader.CACHE_CONTROL)) + header(HttpHeader.CACHE_CONTROL, "no-cache"); + } + + @Override + public ContentResponse send() throws InterruptedException, TimeoutException, ExecutionException + { + throw new RuntimeException("Working with raw ContentResponse is invalid for WebSocket"); + } + + @Override + public void send(final Response.CompleteListener listener) + { + initWebSocketHeaders(); + super.send(listener); + } + + public CompletableFuture sendAsync() + { + send(this); + return fut; + } + + @Override + public void onComplete(Result result) + { + if (LOG.isDebugEnabled()) + { + LOG.debug("onComplete() - {}", result); + } + + URI requestURI = result.getRequest().getURI(); + Response response = result.getResponse(); + int responseStatusCode = response.getStatus(); + String responseLine = responseStatusCode + " " + response.getReason(); + + if (result.isFailed()) + { + if (LOG.isDebugEnabled()) + { + if (result.getFailure() != null) + LOG.debug("General Failure", result.getFailure()); + if (result.getRequestFailure() != null) + LOG.debug("Request Failure", result.getRequestFailure()); + if (result.getResponseFailure() != null) + LOG.debug("Response Failure", result.getResponseFailure()); + } + + Throwable failure = result.getFailure(); + if ((failure instanceof java.net.ConnectException) || (failure instanceof UpgradeException)) + { + // handle as-is + handleException(failure); + } + else + { + // wrap in UpgradeException + handleException(new UpgradeException(requestURI, responseStatusCode, responseLine, failure)); + } + } + + if (responseStatusCode != HttpStatus.SWITCHING_PROTOCOLS_101) + { + // Failed to upgrade (other reason) + handleException(new UpgradeException(requestURI, responseStatusCode, responseLine)); + } + } + + private void handleException(Throwable failure) + { + fut.completeExceptionally(failure); + } + + @Override + public void upgrade(HttpResponse response, HttpConnectionOverHTTP oldConn) + { + if (!this.getHeaders().get(HttpHeader.UPGRADE).equalsIgnoreCase("websocket")) + { + // Not my upgrade + throw new HttpResponseException("Not WebSocket Upgrade", response); + } + + // Check the Accept hash + String reqKey = this.getHeaders().get(HttpHeader.SEC_WEBSOCKET_KEY); + String expectedHash = AcceptHash.hashKey(reqKey); + String respHash = response.getHeaders().get(HttpHeader.SEC_WEBSOCKET_ACCEPT); + + if (expectedHash.equalsIgnoreCase(respHash) == false) + { + throw new HttpResponseException("Invalid Sec-WebSocket-Accept hash", response); + } + + // We can upgrade + EndPoint endp = oldConn.getEndPoint(); + + ExtensionStack extensionStack = new ExtensionStack(client.getExtensionFactory()); + List extensions = new ArrayList<>(); + HttpField extField = response.getHeaders().getField(HttpHeader.SEC_WEBSOCKET_EXTENSIONS); + if (extField != null) + { + String[] extValues = extField.getValues(); + if (extValues != null) + { + for (String extVal : extValues) + { + QuotedStringTokenizer tok = new QuotedStringTokenizer(extVal, ","); + while (tok.hasMoreTokens()) + { + extensions.add(ExtensionConfig.parse(tok.nextToken())); + } + } + } + } + extensionStack.negotiate(extensions); + + BlockheadClientConnection connection = new BlockheadClientConnection( + client.getPolicy(), + client.getBufferPool(), + extensionStack, + endp, + client.getExecutor()); + + connection.setUpgradeResponseHeaders(response.getHeaders()); + + // Now swap out the connection + endp.upgrade(connection); + + fut.complete(connection); + } + + /** + * Raw Bytes Content Provider (intentionally without a Content-Type) + */ + public static class RawBytesProvider extends ByteBufferContentProvider + { + public RawBytesProvider(ByteBuffer buf) + { + super(buf); + } + + @Override + public String getContentType() + { + return null; + } + } +} diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java new file mode 100644 index 00000000000..2269e7f3f14 --- /dev/null +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java @@ -0,0 +1,373 @@ +// +// ======================================================================== +// 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.common.test; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.util.concurrent.Executor; +import java.util.concurrent.LinkedBlockingQueue; + +import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.io.AbstractConnection; +import org.eclipse.jetty.io.ByteBufferPool; +import org.eclipse.jetty.io.Connection; +import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.util.BufferUtil; +import org.eclipse.jetty.util.Callback; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.BatchMode; +import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.WriteCallback; +import org.eclipse.jetty.websocket.api.extensions.Frame; +import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; +import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; +import org.eclipse.jetty.websocket.common.Generator; +import org.eclipse.jetty.websocket.common.Parser; +import org.eclipse.jetty.websocket.common.WebSocketFrame; +import org.eclipse.jetty.websocket.common.extensions.ExtensionStack; + +public class BlockheadConnection extends AbstractConnection implements Connection.UpgradeTo +{ + private final static int BUFFER_SIZE = 4096; + public static final String STATIC_REQUEST_HASH_KEY = "dGhlIHNhbXBsZSBub25jZQ=="; + private final Logger LOG; + private final WebSocketPolicy policy; + private final ByteBufferPool bufferPool; + private final Parser parser; + private final Generator generator; + private final ExtensionStack extensionStack; + private final OutgoingNetwork networkOutgoing; + private final IncomingCapture incomingCapture; + private ByteBuffer networkBuffer; + private HttpFields upgradeResponseHeaders; + + public BlockheadConnection(WebSocketPolicy policy, ByteBufferPool bufferPool, ExtensionStack extensionStack, EndPoint endp, Executor executor) + { + super(endp, executor); + this.LOG = Log.getLogger(this.getClass()); + this.policy = policy; + this.bufferPool = bufferPool; + this.parser = new Parser(policy, bufferPool); + this.generator = new Generator(policy, bufferPool, false); + this.extensionStack = extensionStack; + + this.extensionStack.configure(this.parser); + this.extensionStack.configure(this.generator); + + // Wire up incoming frames (network -> extensionStack -> connection) + this.parser.setIncomingFramesHandler(extensionStack); + this.incomingCapture = new IncomingCapture(); + this.extensionStack.setNextIncoming(incomingCapture); + + // Wire up outgoing frames (connection -> extensionStack -> network) + this.networkOutgoing = new OutgoingNetwork(); + extensionStack.setNextOutgoing(networkOutgoing); + + try + { + extensionStack.start(); + } + catch (Exception e) + { + throw new RuntimeException("Unable to start ExtensionStack", e); + } + } + + public void abort() + { + EndPoint endPoint = getEndPoint(); + // We need to gently close first, to allow + // SSL close alerts to be sent by Jetty + endPoint.shutdownOutput(); + endPoint.close(); + } + + @Override + public void fillInterested() + { + // Handle situation where initial/prefill buffer (from upgrade) has created network buffer, + // but there is no actual read interest (yet) + if (BufferUtil.hasContent(networkBuffer)) + { + fillAndParse(); + } + else + { + super.fillInterested(); + } + } + + public LinkedBlockingQueue getFrameQueue() + { + return incomingCapture.incomingFrames; + } + + public Generator getGenerator() + { + return generator; + } + + public InetSocketAddress getLocalSocketAddress() + { + return getEndPoint().getLocalAddress(); + } + + public Parser getParser() + { + return parser; + } + + public InetSocketAddress getRemoteSocketAddress() + { + return getEndPoint().getRemoteAddress(); + } + + public HttpFields getUpgradeResponseHeaders() + { + return upgradeResponseHeaders; + } + + public boolean isOpen() + { + return getEndPoint().isOpen(); + } + + @Override + public void onFillable() + { + getNetworkBuffer(); + fillAndParse(); + } + + @Override + public void onUpgradeTo(ByteBuffer prefilled) + { + setInitialBuffer(prefilled); + } + + @Override + public void onOpen() + { + super.onOpen(); + fillInterested(); + } + + public void processConnectionError(Throwable cause) + { + LOG.warn("Connection Error", cause); + } + + public void setUpgradeResponseHeaders(HttpFields upgradeResponseHeaders) + { + this.upgradeResponseHeaders = upgradeResponseHeaders; + } + + public void write(WebSocketFrame frame) + { + networkOutgoing.outgoingFrame(frame, null, BatchMode.OFF); + } + + public void writeRaw(ByteBuffer buf) throws IOException + { + getEndPoint().flush(buf); + } + + public void writeRaw(ByteBuffer buf, int numBytes) throws IOException + { + int len = Math.min(numBytes, buf.remaining()); + ByteBuffer slice = buf.slice(); + buf.position(len); + try + { + getEndPoint().flush(slice); + } + catch (IOException e) + { + throw e; + } + finally + { + buf.position(buf.position() + len); + } + } + + public void writeRawSlowly(ByteBuffer buf, int segmentSize) throws IOException + { + while (buf.remaining() > 0) + { + writeRaw(buf, segmentSize); + } + } + + /** + * Extra bytes from the initial HTTP upgrade that need to + * be processed by the websocket parser before starting + * to read bytes from the connection + * + * @param prefilled the bytes of prefilled content encountered during upgrade + */ + protected void setInitialBuffer(ByteBuffer prefilled) + { + if (LOG.isDebugEnabled()) + { + LOG.debug("set Initial Buffer - {}", BufferUtil.toDetailString(prefilled)); + } + + if ((prefilled != null) && (prefilled.hasRemaining())) + { + networkBuffer = bufferPool.acquire(prefilled.remaining(), true); + BufferUtil.clearToFill(networkBuffer); + BufferUtil.put(prefilled, networkBuffer); + BufferUtil.flipToFlush(networkBuffer, 0); + } + } + + private void fillAndParse() + { + boolean interested = false; + + try + { + while (getEndPoint().isOpen()) + { + ByteBuffer nBuffer = getNetworkBuffer(); + + parser.parse(nBuffer); + + // Shouldn't reach this point if buffer has un-parsed bytes + assert (!nBuffer.hasRemaining()); + + int filled = getEndPoint().fill(nBuffer); + + if (LOG.isDebugEnabled()) + LOG.debug("endpointFill() filled={}: {}", filled, BufferUtil.toDetailString(nBuffer)); + + if (filled < 0) + { + releaseNetworkBuffer(nBuffer); + return; + } + + if (filled == 0) + { + releaseNetworkBuffer(nBuffer); + interested = true; + return; + } + } + } + catch (Throwable t) + { + processConnectionError(t); + } + finally + { + if (interested) + fillInterested(); + } + } + + private ByteBuffer getNetworkBuffer() + { + synchronized (this) + { + if (networkBuffer == null) + { + networkBuffer = bufferPool.acquire(BUFFER_SIZE, true); + } + return networkBuffer; + } + } + + private void releaseNetworkBuffer(ByteBuffer buffer) + { + synchronized (this) + { + assert (!buffer.hasRemaining()); + bufferPool.release(buffer); + networkBuffer = null; + } + } + + public class IncomingCapture implements IncomingFrames + { + public final LinkedBlockingQueue incomingFrames = new LinkedBlockingQueue<>(); + public final LinkedBlockingQueue incomingErrors = new LinkedBlockingQueue<>(); + + @Override + public void incomingError(Throwable cause) + { + incomingErrors.offer(cause); + } + + @Override + public void incomingFrame(Frame frame) + { + incomingFrames.offer(WebSocketFrame.copy(frame)); + } + } + + public class OutgoingNetwork implements OutgoingFrames + { + /** + * Last step for networkOutgoing frames before the network buffer. + *

+ * if ExtensionStack is in play, this should be wired up to the output from + * the ExtensionStack. + *

+ * + * @param frame the frame to eventually write to the network layer. + * @param callback the callback to notify when the frame is written. + * @param batchMode ignored by BlockheadConnections + */ + @Override + public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) + { + ByteBuffer header = generator.generateHeaderBytes(frame); + ByteBuffer payload = frame.getPayload(); + if (payload == null) + payload = BufferUtil.EMPTY_BUFFER; + + Callback jettyCallback = asJettyCallback(callback); + try + { + getEndPoint().flush(header, payload); + jettyCallback.succeeded(); + } + catch (IOException e) + { + jettyCallback.failed(e); + } + } + + private Callback asJettyCallback(final WriteCallback writeCallback) + { + if (writeCallback instanceof org.eclipse.jetty.util.Callback) + { + return (org.eclipse.jetty.util.Callback) writeCallback; + } + else + { + return new WriteCallbackDelegate(writeCallback); + } + } + } +} diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java index 6ab10df9091..b1a9d910198 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java @@ -396,7 +396,7 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames @Override public void run() { - LOG.debug("Entering echo thread"); + LOG.debug("Entering read thread"); long totalReadBytes = 0; ByteBuffer buf = bufferPool.acquire(BUFFER_SIZE, false); @@ -450,7 +450,7 @@ public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames { throw new IllegalStateException("Read thread already declared/started!"); } - readThread = new Thread(this,"BlockheadServer/Read"); + readThread = new Thread(this,"Blockhead-Server-Read"); LOG.debug("Starting Read Thread: {}", readThread); reading.set(true); readThread.start(); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java index 87c74d437e4..26910fcf0e4 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java @@ -27,19 +27,20 @@ import java.nio.ByteBuffer; import java.util.Collections; import java.util.List; import java.util.Locale; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; -import org.eclipse.jetty.websocket.common.io.IOState; import org.junit.Assert; /** @@ -47,28 +48,13 @@ import org.junit.Assert; */ public class Fuzzer implements AutoCloseable { - public static enum CloseState - { - OPEN, - REMOTE_INITIATED, - LOCAL_INITIATED - } - - public static enum SendMode + public enum SendMode { BULK, PER_FRAME, SLOW } - public static enum DisconnectMode - { - /** Disconnect occurred after a proper close handshake */ - CLEAN, - /** Disconnect occurred in a harsh manner, without a close handshake */ - UNCLEAN - } - private static final int KBYTE = 1024; private static final int MBYTE = KBYTE * KBYTE; @@ -78,24 +64,26 @@ public class Fuzzer implements AutoCloseable protected static final byte[] MASK = { 0x11, 0x22, 0x33, 0x44 }; + private final Fuzzed testcase; private final BlockheadClient client; private final Generator generator; private final String testname; + private BlockheadConnection clientConnection; private SendMode sendMode = SendMode.BULK; private int slowSendSegmentSize = 5; public Fuzzer(Fuzzed testcase) throws Exception { - WebSocketPolicy policy = WebSocketPolicy.newClientPolicy(); - + this.testcase = testcase; + this.client = new BlockheadClient(); int bigMessageSize = 20 * MBYTE; - policy.setMaxTextMessageSize(bigMessageSize); - policy.setMaxBinaryMessageSize(bigMessageSize); - policy.setIdleTimeout(5000); + client.getPolicy().setMaxTextMessageSize(bigMessageSize); + client.getPolicy().setMaxBinaryMessageSize(bigMessageSize); + client.getPolicy().setIdleTimeout(5000); + + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); - this.client = new BlockheadClient(policy,testcase.getServerURI()); - this.client.setTimeout(2,TimeUnit.SECONDS); this.generator = testcase.getLaxGenerator(); this.testname = testcase.getTestMethodName(); } @@ -120,30 +108,43 @@ public class Fuzzer implements AutoCloseable } @Override - public void close() throws Exception + public void close() { - this.client.disconnect(); + this.clientConnection.close(); } public void disconnect() { - this.client.disconnect(); + this.clientConnection.abort(); } public void connect() throws IOException { - if (!client.isConnected()) + BlockheadClientRequest request = this.client.newWsRequest(testcase.getServerURI()); + request.header("X-TestCase", testname); + Future connFut = request.sendAsync(); + + try { - client.connect(); - client.addHeader("X-TestCase: " + testname + "\r\n"); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + this.clientConnection = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); + } + catch (InterruptedException e) + { + throw new IOException("Connect interrupted", e); + } + catch (ExecutionException e) + { + throw new IOException("Connect execution failed", e); + } + catch (TimeoutException e) + { + throw new IOException("Connect timed out", e); } } public void expect(List expect) throws Exception { - expect(expect,10,TimeUnit.SECONDS); + expect(expect, Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); } /** @@ -154,13 +155,13 @@ public class Fuzzer implements AutoCloseable * @param unit the timeout unit to wait for each read frame * @throws Exception if unable to validate expectations */ - public void expect(List expect, int duration, TimeUnit unit) throws Exception + public void expect(List expect, long duration, TimeUnit unit) throws Exception { int expectedCount = expect.size(); LOG.debug("expect() {} frame(s)",expect.size()); // Read frames - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConnection.getFrameQueue(); String prefix = ""; for (int i = 0; i < expectedCount; i++) @@ -198,24 +199,6 @@ public class Fuzzer implements AutoCloseable // TODO Should test for no more frames. success if connection closed. } - public CloseState getCloseState() - { - IOState ios = client.getIOState(); - - if (ios.wasLocalCloseInitiated()) - { - return CloseState.LOCAL_INITIATED; - } - else if (ios.wasRemoteCloseInitiated()) - { - return CloseState.REMOTE_INITIATED; - } - else - { - return CloseState.OPEN; - } - } - public SendMode getSendMode() { return sendMode; @@ -228,27 +211,26 @@ public class Fuzzer implements AutoCloseable public void send(ByteBuffer buf) throws IOException { - Assert.assertThat("Client connected",client.isConnected(),is(true)); + Assert.assertThat("Client connected",clientConnection.isOpen(),is(true)); LOG.debug("Sending bytes {}",BufferUtil.toDetailString(buf)); if (sendMode == SendMode.SLOW) { - client.writeRawSlowly(buf,slowSendSegmentSize); + clientConnection.writeRawSlowly(buf,slowSendSegmentSize); } else { - client.writeRaw(buf); + clientConnection.writeRaw(buf); } } public void send(ByteBuffer buf, int numBytes) throws IOException { - client.writeRaw(buf,numBytes); - client.flush(); + clientConnection.writeRaw(buf, numBytes); } public void send(List send) throws IOException { - Assert.assertThat("Client connected",client.isConnected(),is(true)); + Assert.assertThat("Client connected",clientConnection.isOpen(),is(true)); LOG.debug("[{}] Sending {} frames (mode {})",testname,send.size(),sendMode); if ((sendMode == SendMode.BULK) || (sendMode == SendMode.SLOW)) { @@ -275,10 +257,10 @@ public class Fuzzer implements AutoCloseable switch (sendMode) { case BULK: - client.writeRaw(buf); + clientConnection.writeRaw(buf); break; case SLOW: - client.writeRawSlowly(buf,slowSendSegmentSize); + clientConnection.writeRawSlowly(buf,slowSendSegmentSize); break; default: throw new RuntimeException("Whoops, unsupported sendMode: " + sendMode); @@ -294,8 +276,7 @@ public class Fuzzer implements AutoCloseable BufferUtil.clearToFill(fullframe); generator.generateWholeFrame(f,fullframe); BufferUtil.flipToFlush(fullframe,0); - client.writeRaw(fullframe); - client.flush(); + clientConnection.writeRaw(fullframe); } } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadServerConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadServerConnection.java index d5dceebd266..a44ec00e6dd 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadServerConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadServerConnection.java @@ -29,6 +29,7 @@ import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.WebSocketFrame; +@Deprecated public interface IBlockheadServerConnection { public void close() throws IOException; diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Timeouts.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Timeouts.java index fa3321e2f18..b9092fbc6a5 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Timeouts.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Timeouts.java @@ -22,6 +22,9 @@ import java.util.concurrent.TimeUnit; public class Timeouts { - public static long POLL_EVENT = 2; - public static TimeUnit POLL_EVENT_UNIT = TimeUnit.SECONDS; + public static final long CONNECT = 2; + public static final TimeUnit CONNECT_UNIT = TimeUnit.SECONDS; + + public static final long POLL_EVENT = 2; + public static final TimeUnit POLL_EVENT_UNIT = TimeUnit.SECONDS; } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/WriteCallbackDelegate.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/WriteCallbackDelegate.java new file mode 100644 index 00000000000..0d906c294d1 --- /dev/null +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/WriteCallbackDelegate.java @@ -0,0 +1,46 @@ +// +// ======================================================================== +// 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.common.test; + +import org.eclipse.jetty.util.Callback; +import org.eclipse.jetty.websocket.api.WriteCallback; + +public class WriteCallbackDelegate implements Callback +{ + private final WriteCallback delegate; + + public WriteCallbackDelegate(WriteCallback delegate) + { + this.delegate = delegate; + } + + @Override + public void succeeded() + { + if (this.delegate != null) + this.delegate.writeSuccess(); + } + + @Override + public void failed(Throwable x) + { + if (this.delegate != null) + this.delegate.writeFailed(x); + } +} diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/AnnotatedMaxMessageSizeTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/AnnotatedMaxMessageSizeTest.java index f24fa3465db..eef290e3ab9 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/AnnotatedMaxMessageSizeTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/AnnotatedMaxMessageSizeTest.java @@ -20,15 +20,16 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.is; -import java.io.IOException; import java.net.URI; import java.nio.ByteBuffer; import java.util.Arrays; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; +import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.util.log.StacklessLogging; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.common.CloseInfo; @@ -37,20 +38,19 @@ import org.eclipse.jetty.websocket.common.Parser; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.examples.echo.BigEchoSocket; import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; -import org.junit.Rule; import org.junit.Test; public class AnnotatedMaxMessageSizeTest { - @Rule - public TestTracker tracker = new TestTracker(); - + private static BlockheadClient client; private static Server server; private static ServerConnector connector; private static URI serverUri; @@ -89,59 +89,64 @@ public class AnnotatedMaxMessageSizeTest server.stop(); } - @Test - public void testEchoGood() throws IOException, Exception + @BeforeClass + public static void startClient() throws Exception { - BlockheadClient client = new BlockheadClient(serverUri); - try - { - client.setProtocols("echo"); - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + + @Test + public void testEchoGood() throws Exception + { + BlockheadClientRequest request = client.newWsRequest(serverUri); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "echo"); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { // Generate text frame String msg = "this is an echo ... cho ... ho ... o"; - client.write(new TextFrame().setPayload(msg)); + clientConn.write(new TextFrame().setPayload(msg)); // Read frame (hopefully text frame) - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame.status code",tf.getPayloadAsUTF8(),is(msg)); } - finally - { - client.close(); - } } @Test(timeout=8000) - public void testEchoTooBig() throws IOException, Exception + public void testEchoTooBig() throws Exception { - BlockheadClient client = new BlockheadClient(serverUri); - try(StacklessLogging logging = new StacklessLogging(Parser.class)) - { - client.setProtocols("echo"); - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(serverUri); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "echo"); + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); + StacklessLogging ignore = new StacklessLogging(Parser.class)) + { // Generate text frame int size = 120 * 1024; byte buf[] = new byte[size]; // buffer bigger than maxMessageSize Arrays.fill(buf,(byte)'x'); - client.write(new TextFrame().setPayload(ByteBuffer.wrap(buf))); + clientConn.write(new TextFrame().setPayload(ByteBuffer.wrap(buf))); // Read frame (hopefully close frame saying its too large) - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Frame is close", tf.getOpCode(), is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(tf); Assert.assertThat("Close Code", close.getStatusCode(), is(StatusCode.MESSAGE_TOO_LARGE)); } - finally - { - client.close(); - } } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ChromeTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ChromeTest.java index aa3437c9255..cb67178343e 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ChromeTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ChromeTest.java @@ -21,12 +21,18 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; +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.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; -import org.eclipse.jetty.websocket.common.test.HttpResponse; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.examples.MyEchoServlet; import org.junit.AfterClass; @@ -37,6 +43,7 @@ import org.junit.Test; public class ChromeTest { + private static BlockheadClient client; private static SimpleServletServer server; @BeforeClass @@ -52,34 +59,49 @@ public class ChromeTest server.stop(); } + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + @Test public void testUpgradeWithWebkitDeflateExtension() throws Exception { Assume.assumeTrue("Server has x-webkit-deflate-frame registered", server.getWebSocketServletFactory().getExtensionFactory().isAvailable("x-webkit-deflate-frame")); - - BlockheadClient client = new BlockheadClient(server.getServerUri()); - try + + Assume.assumeTrue("Client has x-webkit-deflate-frame registered", + client.getExtensionFactory().isAvailable("x-webkit-deflate-frame")); + + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_EXTENSIONS, "x-webkit-deflate-frame"); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "chat"); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.addExtensions("x-webkit-deflate-frame"); - client.setProtocols("chat"); - client.connect(); - client.sendStandardRequest(); - HttpResponse response = client.expectUpgradeResponse(); - Assert.assertThat("Response",response.getExtensionsHeader(),containsString("x-webkit-deflate-frame")); + HttpFields responseFields = clientConn.getUpgradeResponseHeaders(); + HttpField extensionField = responseFields.getField(HttpHeader.SEC_WEBSOCKET_EXTENSIONS); + Assert.assertThat("Response", extensionField.getValue(),containsString("x-webkit-deflate-frame")); // Generate text frame String msg = "this is an echo ... cho ... ho ... o"; - client.write(new TextFrame().setPayload(msg)); + clientConn.write(new TextFrame().setPayload(msg)); // Read frame (hopefully text frame) - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame.status code",tf.getPayloadAsUTF8(),is(msg)); } - finally - { - client.close(); - } } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsLegacyTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsLegacyTest.java index 8dbf77587a3..45b37b1685d 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsLegacyTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsLegacyTest.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertThat; import java.io.PrintWriter; import java.io.StringWriter; import java.util.List; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -36,6 +37,8 @@ import org.eclipse.jetty.websocket.api.WebSocketAdapter; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; @@ -50,29 +53,30 @@ import org.junit.Test; @Ignore("Unstable - see Issue #1815") public class DecoratorsLegacyTest { + private static class DecoratorsSocket extends WebSocketAdapter { private final DecoratedObjectFactory objFactory; - + public DecoratorsSocket(DecoratedObjectFactory objFactory) { this.objFactory = objFactory; } - + @Override public void onWebSocketText(String message) { StringWriter str = new StringWriter(); PrintWriter out = new PrintWriter(str); - + if (objFactory != null) { out.printf("Object is a DecoratedObjectFactory%n"); List decorators = objFactory.getDecorators(); - out.printf("Decorators.size = [%d]%n",decorators.size()); + out.printf("Decorators.size = [%d]%n", decorators.size()); for (Decorator decorator : decorators) { - out.printf(" decorator[] = %s%n",decorator.getClass().getName()); + out.printf(" decorator[] = %s%n", decorator.getClass().getName()); } } else @@ -90,7 +94,7 @@ public class DecoratorsLegacyTest public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp) { ServletContext servletContext = req.getHttpServletRequest().getServletContext(); - DecoratedObjectFactory objFactory = (DecoratedObjectFactory)servletContext.getAttribute(DecoratedObjectFactory.ATTR); + DecoratedObjectFactory objFactory = (DecoratedObjectFactory) servletContext.getAttribute(DecoratedObjectFactory.ATTR); return new DecoratorsSocket(objFactory); } } @@ -111,7 +115,7 @@ public class DecoratorsLegacyTest factory.setCreator(this.creator); } } - + @SuppressWarnings("deprecation") private static class DummyLegacyDecorator implements org.eclipse.jetty.servlet.ServletContextHandler.Decorator { @@ -127,6 +131,7 @@ public class DecoratorsLegacyTest } } + private static BlockheadClient client; private static SimpleServletServer server; private static DecoratorsCreator decoratorsCreator; @@ -154,31 +159,39 @@ public class DecoratorsLegacyTest server.stop(); } + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + @Test public void testAccessRequestCookies() throws Exception { - BlockheadClient client = new BlockheadClient(server.getServerUri()); - client.setTimeout(1,TimeUnit.SECONDS); + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.idleTimeout(1, TimeUnit.SECONDS); - try + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); - - client.write(new TextFrame().setPayload("info")); + clientConn.write(new TextFrame().setPayload("info")); - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame resp = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); String textMsg = resp.getPayloadAsUTF8(); - + assertThat("DecoratedObjectFactory", textMsg, containsString("Object is a DecoratedObjectFactory")); assertThat("decorators.size", textMsg, containsString("Decorators.size = [1]")); assertThat("decorator type", textMsg, containsString("decorator[] = " + DummyLegacyDecorator.class.getName())); } - finally - { - client.close(); - } } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsTest.java index 3753d360e56..1428aea3029 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/DecoratorsTest.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertThat; import java.io.PrintWriter; import java.io.StringWriter; import java.util.List; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -36,6 +37,8 @@ import org.eclipse.jetty.websocket.api.WebSocketAdapter; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; @@ -44,10 +47,8 @@ import org.eclipse.jetty.websocket.servlet.WebSocketServlet; import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; -@Ignore public class DecoratorsTest { private static class DecoratorsSocket extends WebSocketAdapter @@ -126,6 +127,7 @@ public class DecoratorsTest } } + private static BlockheadClient client; private static SimpleServletServer server; private static DecoratorsCreator decoratorsCreator; @@ -152,21 +154,32 @@ public class DecoratorsTest server.stop(); } + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + @Test public void testAccessRequestCookies() throws Exception { - BlockheadClient client = new BlockheadClient(server.getServerUri()); - client.setTimeout(1,TimeUnit.SECONDS); + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); - try + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); - - client.write(new TextFrame().setPayload("info")); + clientConn.write(new TextFrame().setPayload("info")); - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame resp = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); String textMsg = resp.getPayloadAsUTF8(); @@ -174,9 +187,5 @@ public class DecoratorsTest assertThat("decorators.size", textMsg, containsString("Decorators.size = [1]")); assertThat("decorator type", textMsg, containsString("decorator[] = " + DummyUtilDecorator.class.getName())); } - finally - { - client.close(); - } } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FirefoxTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FirefoxTest.java index bebbf78aa14..e8b6661425d 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FirefoxTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FirefoxTest.java @@ -20,12 +20,16 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.is; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; +import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; -import org.eclipse.jetty.websocket.common.test.IBlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.examples.MyEchoServlet; import org.junit.AfterClass; import org.junit.Assert; @@ -34,39 +38,45 @@ import org.junit.Test; public class FirefoxTest { + private static BlockheadClient client; private static SimpleServletServer server; @BeforeClass - public static void startServer() throws Exception + public static void startContainers() throws Exception { server = new SimpleServletServer(new MyEchoServlet()); server.start(); + + client = new BlockheadClient(); + client.start(); } @AfterClass - public static void stopServer() + public static void stopContainers() throws Exception { + client.stop(); server.stop(); } @Test public void testConnectionKeepAlive() throws Exception { - try (IBlockheadClient client = new BlockheadClient(server.getServerUri())) - { - // Odd Connection Header value seen in Firefox - client.setConnectionValue("keep-alive, Upgrade"); - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + // Odd Connection Header value seen in older Firefox versions + request.header(HttpHeader.CONNECTION, "keep-alive, Upgrade"); + + Future connFut = request.sendAsync(); + + try(BlockheadConnection conn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { // Generate text frame String msg = "this is an echo ... cho ... ho ... o"; - client.write(new TextFrame().setPayload(msg)); + conn.write(new TextFrame().setPayload(msg)); // Read frame (hopefully text frame) - LinkedBlockingQueue frames = client.getFrameQueue(); - WebSocketFrame tf = frames.poll(); + LinkedBlockingQueue frames = conn.getFrameQueue(); + WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame.status code", tf.getPayloadAsUTF8(), is(msg)); } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FragmentExtensionTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FragmentExtensionTest.java index de089f26845..4bd4e9af557 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FragmentExtensionTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/FragmentExtensionTest.java @@ -21,23 +21,30 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; +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.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; -import org.eclipse.jetty.websocket.common.test.HttpResponse; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.helper.EchoServlet; import org.junit.AfterClass; import org.junit.Assert; +import org.junit.Assume; import org.junit.BeforeClass; import org.junit.Test; public class FragmentExtensionTest { private static SimpleServletServer server; + private static BlockheadClient client; @BeforeClass public static void startServer() throws Exception @@ -52,6 +59,20 @@ public class FragmentExtensionTest server.stop(); } + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + private String[] split(String str, int partSize) { int strLength = str.length(); @@ -69,37 +90,39 @@ public class FragmentExtensionTest @Test public void testFragmentExtension() throws Exception { + Assume.assumeTrue("Server has fragment registered", + server.getWebSocketServletFactory().getExtensionFactory().isAvailable("fragment")); + + Assume.assumeTrue("Client has fragment registered", + client.getExtensionFactory().isAvailable("fragment")); + int fragSize = 4; - BlockheadClient client = new BlockheadClient(server.getServerUri()); - client.clearExtensions(); - client.addExtensions("fragment;maxLength=" + fragSize); - client.setProtocols("onConnect"); + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_EXTENSIONS, "fragment;maxLength=" + fragSize); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "onConnect"); + request.idleTimeout(1, TimeUnit.SECONDS); - try + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { // Make sure the read times out if there are problems with the implementation - client.setTimeout(1,TimeUnit.SECONDS); - client.connect(); - client.sendStandardRequest(); - HttpResponse resp = client.expectUpgradeResponse(); + HttpFields responseHeaders = clientConn.getUpgradeResponseHeaders(); + HttpField extensionHeader = responseHeaders.getField(HttpHeader.SEC_WEBSOCKET_EXTENSIONS); - Assert.assertThat("Response",resp.getExtensionsHeader(),containsString("fragment")); + Assert.assertThat("Response",extensionHeader.getValue(),containsString("fragment")); String msg = "Sent as a long message that should be split"; - client.write(new TextFrame().setPayload(msg)); + clientConn.write(new TextFrame().setPayload(msg)); String parts[] = split(msg,fragSize); - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); for (int i = 0; i < parts.length; i++) { WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("text[" + i + "].payload",frame.getPayloadAsUTF8(),is(parts[i])); } } - finally - { - client.close(); - } } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdentityExtensionTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdentityExtensionTest.java index 49c4b268553..9ea5577186e 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdentityExtensionTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdentityExtensionTest.java @@ -21,13 +21,18 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; +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.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; -import org.eclipse.jetty.websocket.common.test.HttpResponse; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.helper.EchoServlet; import org.junit.AfterClass; @@ -38,6 +43,7 @@ import org.junit.Test; public class IdentityExtensionTest { private static SimpleServletServer server; + private static BlockheadClient client; @BeforeClass public static void startServer() throws Exception @@ -52,34 +58,43 @@ public class IdentityExtensionTest server.stop(); } + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + @Test public void testIdentityExtension() throws Exception { - BlockheadClient client = new BlockheadClient(server.getServerUri()); - client.clearExtensions(); - client.addExtensions("identity;param=0"); - client.addExtensions("identity;param=1, identity ; param = '2' ; other = ' some = value '"); - client.setProtocols("onConnect"); + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_EXTENSIONS, "identity;param=0"); + request.header(HttpHeader.SEC_WEBSOCKET_EXTENSIONS, "identity;param=1, identity ; param = '2' ; other = ' some = value '"); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "onConnect"); + request.idleTimeout(1, TimeUnit.SECONDS); - try + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - // Make sure the read times out if there are problems with the implementation - client.setTimeout(1,TimeUnit.SECONDS); - client.connect(); - client.sendStandardRequest(); - HttpResponse resp = client.expectUpgradeResponse(); + HttpFields responseHeaders = clientConn.getUpgradeResponseHeaders(); + HttpField extensionHeader = responseHeaders.getField(HttpHeader.SEC_WEBSOCKET_EXTENSIONS); - Assert.assertThat("Response",resp.getExtensionsHeader(),containsString("identity")); + Assert.assertThat("Response", extensionHeader.getValue(), containsString("identity")); - client.write(new TextFrame().setPayload("Hello")); + clientConn.write(new TextFrame().setPayload("Hello")); - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("TEXT.payload",frame.getPayloadAsUTF8(),is("Hello")); } - finally - { - client.close(); - } } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java index 9174d1e8ab0..704527f1b1f 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/IdleTimeoutTest.java @@ -21,15 +21,19 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; +import org.eclipse.jetty.http.HttpHeader; 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.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.helper.RFCSocket; import org.eclipse.jetty.websocket.servlet.WebSocketServlet; @@ -41,17 +45,23 @@ import org.junit.Test; public class IdleTimeoutTest { + + public static final int IDLE_TIMEOUT_MS_WEBSOCKET_SERVER = 500; + public static final int IDLE_TIMEOUT_ON_SERVER = 1000; + public static final int IDLE_TIMEOUT_MS_WEBSOCKET_CLIENT = 2500; + @SuppressWarnings("serial") public static class TimeoutServlet extends WebSocketServlet { @Override public void configure(WebSocketServletFactory factory) { - factory.getPolicy().setIdleTimeout(500); + factory.getPolicy().setIdleTimeout(IDLE_TIMEOUT_MS_WEBSOCKET_SERVER); factory.register(RFCSocket.class); } } + private static BlockheadClient client; private static SimpleServletServer server; @BeforeClass @@ -67,6 +77,20 @@ public class IdleTimeoutTest server.stop(); } + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + /** * Test IdleTimeout on server. * @throws Exception on test failure @@ -74,37 +98,32 @@ public class IdleTimeoutTest @Test public void testIdleTimeout() throws Exception { - BlockheadClient client = new BlockheadClient(server.getServerUri()); - client.setProtocols("onConnect"); - client.setTimeout(2500,TimeUnit.MILLISECONDS); - try - { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "onConnect"); + request.idleTimeout(IDLE_TIMEOUT_MS_WEBSOCKET_CLIENT, TimeUnit.MILLISECONDS); + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { // This wait should be shorter than client timeout above, but // longer than server timeout configured in TimeoutServlet - client.sleep(TimeUnit.MILLISECONDS,1000); + TimeUnit.MILLISECONDS.sleep(IDLE_TIMEOUT_ON_SERVER); // Write to server // This action is possible, but does nothing. // Server could be in a half-closed state at this point. // Where the server read is closed (due to timeout), but the server write is still open. // The server could not read this frame, if it is in this half closed state - client.write(new TextFrame().setPayload("Hello")); + clientConn.write(new TextFrame().setPayload("Hello")); // Expect server to have closed due to its own timeout - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("frame opcode",frame.getOpCode(),is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(frame); Assert.assertThat("close code",close.getStatusCode(),is(StatusCode.SHUTDOWN)); Assert.assertThat("close reason",close.getReason(),containsString("Timeout")); } - finally - { - client.close(); - } } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ManyConnectionsCleanupTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ManyConnectionsCleanupTest.java index 0e819ec7d68..6b2b03231fd 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ManyConnectionsCleanupTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ManyConnectionsCleanupTest.java @@ -18,21 +18,23 @@ package org.eclipse.jetty.websocket.server; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import org.eclipse.jetty.http.HttpHeader; 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.log.StdErrLog; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.WebSocketAdapter; @@ -42,7 +44,8 @@ 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.test.BlockheadClient; -import org.eclipse.jetty.websocket.common.test.IBlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.helper.RFCSocket; import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; @@ -52,13 +55,11 @@ import org.eclipse.jetty.websocket.servlet.WebSocketServlet; import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; /** * Tests various close scenarios that should result in Open Session cleanup */ -@Ignore public class ManyConnectionsCleanupTest { static class AbstractCloseSocket extends WebSocketAdapter @@ -220,6 +221,7 @@ public class ManyConnectionsCleanupTest private static final Logger LOG = Log.getLogger(ManyConnectionsCleanupTest.class); + private static BlockheadClient client; private static SimpleServletServer server; private static AbstractCloseSocket closeSocket; @@ -236,6 +238,20 @@ public class ManyConnectionsCleanupTest server.stop(); } + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + /** * Test session open session cleanup (bug #474936) * @@ -245,35 +261,31 @@ public class ManyConnectionsCleanupTest @Test public void testOpenSessionCleanup() throws Exception { - int iterationCount = 100; - - StdErrLog.getLogger(FastFailSocket.class).setLevel(StdErrLog.LEVEL_OFF); - - StdErrLog sessLog = StdErrLog.getLogger(WebSocketSession.class); - int oldLevel = sessLog.getLevel(); - sessLog.setLevel(StdErrLog.LEVEL_OFF); - - for (int requests = 0; requests < iterationCount; requests++) + int iterationCount = 20; + + // TODO: consider a SilentLogging alternative class + try(StacklessLogging ignore = new StacklessLogging(FastFailSocket.class, WebSocketSession.class)) { - fastFail(); - fastClose(); - dropConnection(); + for (int requests = 0; requests < iterationCount; requests++) + { + fastFail(); + fastClose(); + dropConnection(); + } } - sessLog.setLevel(oldLevel); + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "container"); + request.idleTimeout(1, TimeUnit.SECONDS); - try (IBlockheadClient client = new BlockheadClient(server.getServerUri())) + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.setProtocols("container"); - client.setTimeout(1,TimeUnit.SECONDS); - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); - - client.write(new TextFrame().setPayload("calls")); - client.write(new TextFrame().setPayload("openSessions")); + clientConn.write(new TextFrame().setPayload("calls")); + clientConn.write(new TextFrame().setPayload("openSessions")); - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame; String resp; @@ -291,7 +303,7 @@ public class ManyConnectionsCleanupTest assertThat("frames[2].opcode",frame.getOpCode(),is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(frame); assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.NORMAL)); - client.write(close.asFrame()); // respond with close + clientConn.write(close.asFrame()); // respond with close // ensure server socket got close event assertThat("Open Sessions Latch",closeSocket.closeLatch.await(1,TimeUnit.SECONDS),is(true)); @@ -302,70 +314,63 @@ public class ManyConnectionsCleanupTest private void fastClose() throws Exception { - try (IBlockheadClient client = new BlockheadClient(server.getServerUri())) + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "fastclose"); + request.idleTimeout(1, TimeUnit.SECONDS); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); + StacklessLogging ignore = new StacklessLogging(WebSocketSession.class)) { - client.setProtocols("fastclose"); - client.setTimeout(1,TimeUnit.SECONDS); - try (StacklessLogging scope = new StacklessLogging(WebSocketSession.class)) - { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); + frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - LinkedBlockingQueue frames = client.getFrameQueue(); - frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + CloseInfo close = new CloseInfo(StatusCode.NORMAL,"Normal"); + assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.NORMAL)); - CloseInfo close = new CloseInfo(StatusCode.NORMAL,"Normal"); - assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.NORMAL)); + // Notify server of close handshake + clientConn.write(close.asFrame()); // respond with close - // Notify server of close handshake - client.write(close.asFrame()); // respond with close - - // ensure server socket got close event - assertThat("Fast Close Latch",closeSocket.closeLatch.await(1,TimeUnit.SECONDS),is(true)); - assertThat("Fast Close.statusCode",closeSocket.closeStatusCode,is(StatusCode.NORMAL)); - } + // ensure server socket got close event + assertThat("Fast Close Latch",closeSocket.closeLatch.await(1,TimeUnit.SECONDS),is(true)); + assertThat("Fast Close.statusCode",closeSocket.closeStatusCode,is(StatusCode.NORMAL)); } } private void fastFail() throws Exception { - try (IBlockheadClient client = new BlockheadClient(server.getServerUri())) + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "fastfail"); + request.idleTimeout(1, TimeUnit.SECONDS); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); + StacklessLogging ignore = new StacklessLogging(WebSocketSession.class)) { - client.setProtocols("fastfail"); - client.setTimeout(1,TimeUnit.SECONDS); - try (StacklessLogging scope = new StacklessLogging(WebSocketSession.class)) - { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); - - // client.readFrames(1,2,TimeUnit.SECONDS); + CloseInfo close = new CloseInfo(StatusCode.NORMAL,"Normal"); + clientConn.write(close.asFrame()); // respond with close - CloseInfo close = new CloseInfo(StatusCode.NORMAL,"Normal"); - client.write(close.asFrame()); // respond with close - - // ensure server socket got close event - assertThat("Fast Fail Latch",closeSocket.closeLatch.await(1,TimeUnit.SECONDS),is(true)); - assertThat("Fast Fail.statusCode",closeSocket.closeStatusCode,is(StatusCode.SERVER_ERROR)); - assertThat("Fast Fail.errors",closeSocket.errors.size(),is(1)); - } + // ensure server socket got close event + assertThat("Fast Fail Latch",closeSocket.closeLatch.await(1,TimeUnit.SECONDS),is(true)); + assertThat("Fast Fail.statusCode",closeSocket.closeStatusCode,is(StatusCode.SERVER_ERROR)); + assertThat("Fast Fail.errors",closeSocket.errors.size(),is(1)); } } private void dropConnection() throws Exception { - try (IBlockheadClient client = new BlockheadClient(server.getServerUri())) + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "container"); + request.idleTimeout(1, TimeUnit.SECONDS); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); + StacklessLogging ignore = new StacklessLogging(WebSocketSession.class)) { - client.setProtocols("container"); - client.setTimeout(1,TimeUnit.SECONDS); - try (StacklessLogging scope = new StacklessLogging(WebSocketSession.class)) - { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); - client.disconnect(); - } + clientConn.abort(); } } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/RequestHeadersTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/RequestHeadersTest.java index d8a5c24e311..292136afa81 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/RequestHeadersTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/RequestHeadersTest.java @@ -26,11 +26,16 @@ import static org.junit.Assert.assertThat; import java.net.HttpCookie; import java.net.URI; import java.util.List; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; +import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.websocket.api.UpgradeRequest; import org.eclipse.jetty.websocket.api.UpgradeResponse; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.helper.EchoSocket; import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; @@ -43,6 +48,7 @@ import org.junit.Test; public class RequestHeadersTest { + private static class EchoCreator implements WebSocketCreator { private UpgradeRequest lastRequest; @@ -86,6 +92,7 @@ public class RequestHeadersTest } } + private static BlockheadClient client; private static SimpleServletServer server; private static EchoCreator echoCreator; @@ -103,19 +110,31 @@ public class RequestHeadersTest server.stop(); } + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + @Test public void testAccessRequestCookies() throws Exception { - BlockheadClient client = new BlockheadClient(server.getServerUri()); - client.setTimeout(1,TimeUnit.SECONDS); + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.idleTimeout(1, TimeUnit.SECONDS); + request.header(HttpHeader.COOKIE, "fruit=Pear; type=Anjou"); - try + Future connFut = request.sendAsync(); + + try (BlockheadConnection ignore = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.connect(); - client.addHeader("Cookie: fruit=Pear; type=Anjou\r\n"); - client.sendStandardRequest(); - client.expectUpgradeResponse(); - UpgradeRequest req = echoCreator.getLastRequest(); assertThat("Last Request",req,notNullValue()); List cookies = req.getCookies(); @@ -127,25 +146,19 @@ public class RequestHeadersTest assertThat("Cookie value",cookie.getValue(),anyOf(is("Pear"),is("Anjou"))); } } - finally - { - client.close(); - } } @Test public void testRequestURI() throws Exception { URI destUri = server.getServerUri().resolve("/?abc=x%20z&breakfast=bacon%26eggs&2*2%3d5=false"); - BlockheadClient client = new BlockheadClient(destUri); - client.setTimeout(1,TimeUnit.SECONDS); - - try + BlockheadClientRequest request = client.newWsRequest(destUri); + request.idleTimeout(1, TimeUnit.SECONDS); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection ignore = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); - UpgradeRequest req = echoCreator.getLastRequest(); assertThat("Last Request",req,notNullValue()); assertThat("Request.host", req.getHost(), is(server.getServerUri().getHost())); @@ -154,9 +167,5 @@ public class RequestHeadersTest assertThat("Request.uri.rawQuery", req.getRequestURI().getRawQuery(), is("abc=x%20z&breakfast=bacon%26eggs&2*2%3d5=false")); assertThat("Request.uri.query", req.getRequestURI().getQuery(), is("abc=x z&breakfast=bacon&eggs&2*2=5=false")); } - finally - { - client.close(); - } } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SubProtocolTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SubProtocolTest.java index 3beb3869427..277a3460e8c 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SubProtocolTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SubProtocolTest.java @@ -21,9 +21,11 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; +import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; @@ -31,6 +33,8 @@ import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; @@ -90,7 +94,8 @@ public class SubProtocolTest factory.setCreator(new ProtocolCreator()); } } - + + private static BlockheadClient client; private static SimpleServletServer server; @BeforeClass @@ -105,6 +110,20 @@ public class SubProtocolTest { server.stop(); } + + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } @Test public void testSingleProtocol() throws Exception @@ -120,17 +139,16 @@ public class SubProtocolTest private void testSubProtocol(String requestProtocols, String acceptedSubProtocols) throws Exception { - try (BlockheadClient client = new BlockheadClient(server.getServerUri())) + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, requestProtocols); + request.idleTimeout(1, TimeUnit.SECONDS); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.setTimeout(1, TimeUnit.SECONDS); - - client.connect(); - client.addHeader("Sec-WebSocket-Protocol: "+ requestProtocols + "\r\n"); - client.sendStandardRequest(); - client.expectUpgradeResponse(); - - client.write(new TextFrame().setPayload("showme")); - LinkedBlockingQueue frames = client.getFrameQueue(); + clientConn.write(new TextFrame().setPayload("showme")); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat(ProtocolEchoSocket.class.getSimpleName() + ".onMessage()", tf.getPayloadAsUTF8(), is("acceptedSubprotocol=" + acceptedSubProtocols)); diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SuspendResumeTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SuspendResumeTest.java index 09f2cd2c5a3..d8060ec7f5b 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SuspendResumeTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/SuspendResumeTest.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -33,6 +34,8 @@ import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse; @@ -101,6 +104,7 @@ public class SuspendResumeTest } private static SimpleServletServer server; + private static BlockheadClient client; @BeforeClass public static void startServer() throws Exception @@ -108,7 +112,21 @@ public class SuspendResumeTest server = new SimpleServletServer(new EchoServlet()); server.start(); } + + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + @AfterClass public static void stopServer() { @@ -118,18 +136,16 @@ public class SuspendResumeTest @Test public void testSuspendResume() throws Exception { - try (BlockheadClient client = new BlockheadClient(server.getServerUri())) + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.setTimeout(1, TimeUnit.SECONDS); + clientConn.write(new TextFrame().setPayload("echo1")); + clientConn.write(new TextFrame().setPayload("echo2")); - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); - - client.write(new TextFrame().setPayload("echo1")); - client.write(new TextFrame().setPayload("echo2")); - - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat(EchoSocket.class.getSimpleName() + ".onMessage()", tf.getPayloadAsUTF8(), is("echo1")); tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/TooFastClientTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/TooFastClientTest.java index bf2de13101e..6b2aa39ff4a 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/TooFastClientTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/TooFastClientTest.java @@ -23,9 +23,10 @@ import static org.hamcrest.Matchers.is; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.io.LeakTrackingByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.websocket.api.WebSocketPolicy; @@ -33,12 +34,13 @@ import org.eclipse.jetty.websocket.common.Generator; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.examples.MyEchoServlet; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; /** @@ -50,6 +52,7 @@ import org.junit.Test; public class TooFastClientTest { private static SimpleServletServer server; + private static BlockheadClient client; @BeforeClass public static void startServer() throws Exception @@ -64,119 +67,93 @@ public class TooFastClientTest server.stop(); } + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + + private ByteBuffer createInitialPacket(String... msgs) + { + int len = Arrays.stream(msgs).mapToInt((str)->str.length() + Generator.MAX_HEADER_LENGTH).sum(); + ByteBuffer initialPacket = ByteBuffer.allocate(len); + + BufferUtil.clearToFill(initialPacket); + Generator generator = new Generator(WebSocketPolicy.newClientPolicy(), + new MappedByteBufferPool()); + + for (String msg : msgs) + { + TextFrame frame = new TextFrame().setPayload(msg); + byte mask[] = new byte[]{0x11, 0x22, 0x33, 0x44}; + frame.setMask(mask); + generator.generateWholeFrame(frame, initialPacket); + } + + BufferUtil.flipToFlush(initialPacket, 0); + return initialPacket; + } + @Test - @Ignore("RELEASE") public void testUpgradeWithSmallFrames() throws Exception { - BlockheadClient client = new BlockheadClient(server.getServerUri()); - try + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + + String msg1 = "Echo 1"; + String msg2 = "This is also an echooooo!"; + + ByteBuffer initialPacket = createInitialPacket(msg1, msg2); + request.setInitialBytes(initialPacket); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.connect(); - - // Create ByteBuffer representing the initial opening network packet from the client - ByteBuffer initialPacket = ByteBuffer.allocate(4096); - BufferUtil.clearToFill(initialPacket); - - // Add upgrade request to packet - StringBuilder upgradeRequest = client.generateUpgradeRequest(); - ByteBuffer upgradeBuffer = BufferUtil.toBuffer(upgradeRequest.toString(),StandardCharsets.UTF_8); - initialPacket.put(upgradeBuffer); - - // Add text frames - Generator generator = new Generator(WebSocketPolicy.newClientPolicy(), - new MappedByteBufferPool()); - - String msg1 = "Echo 1"; - String msg2 = "This is also an echooooo!"; - - TextFrame frame1 = new TextFrame().setPayload(msg1); - TextFrame frame2 = new TextFrame().setPayload(msg2); - - // Need to set frame mask (as these are client frames) - byte mask[] = new byte[] { 0x11, 0x22, 0x33, 0x44 }; - frame1.setMask(mask); - frame2.setMask(mask); - - generator.generateWholeFrame(frame1,initialPacket); - generator.generateWholeFrame(frame2,initialPacket); - - // Write packet to network - BufferUtil.flipToFlush(initialPacket,0); - client.writeRaw(initialPacket); - - // Expect upgrade - client.expectUpgradeResponse(); - // Read frames (hopefully text frames) - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame/msg1",tf.getPayloadAsUTF8(),is(msg1)); tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame/msg2",tf.getPayloadAsUTF8(),is(msg2)); } - finally - { - client.close(); - } } - + /** * Test where were a client sends a HTTP Upgrade to websocket AND enough websocket frame(s) * to completely overfill the {@link org.eclipse.jetty.io.AbstractConnection#getInputBufferSize()} - * to test a situation where the WebSocket connection opens with prefill that exceeds + * to test a situation where the WebSocket connection opens with prefill that exceeds * the normal input buffer sizes. * @throws Exception on test failure */ @Test - @Ignore("RELEASE") public void testUpgradeWithLargeFrame() throws Exception { - BlockheadClient client = new BlockheadClient(server.getServerUri()); - try + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + + byte bigMsgBytes[] = new byte[64*1024]; + Arrays.fill(bigMsgBytes,(byte)'x'); + String bigMsg = new String(bigMsgBytes, StandardCharsets.UTF_8); + + ByteBuffer initialPacket = createInitialPacket(bigMsg); + request.setInitialBytes(initialPacket); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.connect(); - - // Create ByteBuffer representing the initial opening network packet from the client - ByteBuffer initialPacket = ByteBuffer.allocate(100 * 1024); - BufferUtil.clearToFill(initialPacket); - - // Add upgrade request to packet - StringBuilder upgradeRequest = client.generateUpgradeRequest(); - ByteBuffer upgradeBuffer = BufferUtil.toBuffer(upgradeRequest.toString(),StandardCharsets.UTF_8); - initialPacket.put(upgradeBuffer); - - // Add text frames - Generator generator = new Generator(WebSocketPolicy.newClientPolicy(), - new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged())); - - byte bigMsgBytes[] = new byte[64*1024]; - Arrays.fill(bigMsgBytes,(byte)'x'); - String bigMsg = new String(bigMsgBytes, StandardCharsets.UTF_8); - - // Need to set frame mask (as these are client frames) - byte mask[] = new byte[] { 0x11, 0x22, 0x33, 0x44 }; - TextFrame frame = new TextFrame().setPayload(bigMsg); - frame.setMask(mask); - generator.generateWholeFrame(frame,initialPacket); - - // Write packet to network - BufferUtil.flipToFlush(initialPacket,0); - client.writeRaw(initialPacket); - - // Expect upgrade - client.expectUpgradeResponse(); - // Read frames (hopefully text frames) - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame/msg1",tf.getPayloadAsUTF8(),is(bigMsg)); } - finally - { - client.close(); - } } - - } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java index 5ead761e174..75dbb333d09 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java @@ -26,9 +26,11 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; 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.HttpHeader; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.StacklessLogging; @@ -41,7 +43,8 @@ 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.test.BlockheadClient; -import org.eclipse.jetty.websocket.common.test.IBlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.helper.RFCSocket; import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest; @@ -51,13 +54,11 @@ import org.eclipse.jetty.websocket.servlet.WebSocketServlet; import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; /** * Tests various close scenarios */ -@Ignore public class WebSocketCloseTest { static class AbstractCloseSocket extends WebSocketAdapter @@ -198,6 +199,7 @@ public class WebSocketCloseTest private static final Logger LOG = Log.getLogger(WebSocketCloseTest.class); + private static BlockheadClient client; private static SimpleServletServer server; private static AbstractCloseSocket closeSocket; @@ -214,6 +216,20 @@ public class WebSocketCloseTest server.stop(); } + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + /** * Test fast close (bug #403817) * @@ -223,23 +239,23 @@ public class WebSocketCloseTest @Test public void testFastClose() throws Exception { - try (IBlockheadClient client = new BlockheadClient(server.getServerUri())) - { - client.setProtocols("fastclose"); - client.setTimeout(5,TimeUnit.SECONDS); - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "fastclose"); + request.idleTimeout(5,TimeUnit.SECONDS); + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { // Verify that client got close frame - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("frames[0].opcode",frame.getOpCode(),is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(frame); assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.NORMAL)); // Notify server of close handshake - client.write(close.asFrame()); // respond with close + clientConn.write(close.asFrame()); // respond with close // ensure server socket got close event assertThat("Fast Close Latch",closeSocket.closeLatch.await(5,TimeUnit.SECONDS),is(true)); @@ -256,29 +272,27 @@ public class WebSocketCloseTest @Test public void testFastFail() throws Exception { - try (IBlockheadClient client = new BlockheadClient(server.getServerUri())) + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "fastfail"); + request.idleTimeout(5,TimeUnit.SECONDS); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); + StacklessLogging ignore = new StacklessLogging(FastFailSocket.class, WebSocketSession.class)) { - client.setProtocols("fastfail"); - client.setTimeout(5,TimeUnit.SECONDS); - try (StacklessLogging scope = new StacklessLogging(FastFailSocket.class, WebSocketSession.class)) - { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); + WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + assertThat("frames[0].opcode",frame.getOpCode(),is(OpCode.CLOSE)); + CloseInfo close = new CloseInfo(frame); + assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.SERVER_ERROR)); - LinkedBlockingQueue frames = client.getFrameQueue(); - WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - assertThat("frames[0].opcode",frame.getOpCode(),is(OpCode.CLOSE)); - CloseInfo close = new CloseInfo(frame); - assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.SERVER_ERROR)); + clientConn.write(close.asFrame()); // respond with close - client.write(close.asFrame()); // respond with close - - // ensure server socket got close event - assertThat("Fast Fail Latch",closeSocket.closeLatch.await(5,TimeUnit.SECONDS),is(true)); - assertThat("Fast Fail.statusCode",closeSocket.closeStatusCode,is(StatusCode.SERVER_ERROR)); - assertThat("Fast Fail.errors",closeSocket.errors.size(),is(1)); - } + // ensure server socket got close event + assertThat("Fast Fail Latch",closeSocket.closeLatch.await(5,TimeUnit.SECONDS),is(true)); + assertThat("Fast Fail.statusCode",closeSocket.closeStatusCode,is(StatusCode.SERVER_ERROR)); + assertThat("Fast Fail.errors",closeSocket.errors.size(),is(1)); } } @@ -295,19 +309,19 @@ public class WebSocketCloseTest fastClose(); dropConnection(); - try (IBlockheadClient client = new BlockheadClient(server.getServerUri())) - { - client.setProtocols("container"); - client.setTimeout(1,TimeUnit.SECONDS); - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "container"); + request.idleTimeout(1,TimeUnit.SECONDS); + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { TextFrame text = new TextFrame(); text.setPayload("openSessions"); - client.write(text); + clientConn.write(text); - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("frames[0].opcode",frame.getOpCode(),is(OpCode.TEXT)); @@ -318,7 +332,7 @@ public class WebSocketCloseTest assertThat("frames[1].opcode",frame.getOpCode(),is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(frame); assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.NORMAL)); - client.write(close.asFrame()); // respond with close + clientConn.write(close.asFrame()); // respond with close // ensure server socket got close event assertThat("Open Sessions Latch",closeSocket.closeLatch.await(1,TimeUnit.SECONDS),is(true)); @@ -330,72 +344,67 @@ public class WebSocketCloseTest @SuppressWarnings("Duplicates") private void fastClose() throws Exception { - try (IBlockheadClient client = new BlockheadClient(server.getServerUri())) + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "fastclose"); + request.idleTimeout(1,TimeUnit.SECONDS); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); + StacklessLogging ignore = new StacklessLogging(WebSocketSession.class)) { - client.setProtocols("fastclose"); - client.setTimeout(1,TimeUnit.SECONDS); - try (StacklessLogging scope = new StacklessLogging(WebSocketSession.class)) - { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); + WebSocketFrame received = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - LinkedBlockingQueue frames = client.getFrameQueue(); - WebSocketFrame received = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + CloseInfo close = new CloseInfo(StatusCode.NORMAL,"Normal"); + assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.NORMAL)); - CloseInfo close = new CloseInfo(StatusCode.NORMAL,"Normal"); - assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.NORMAL)); + // Notify server of close handshake + clientConn.write(close.asFrame()); // respond with close - // Notify server of close handshake - client.write(close.asFrame()); // respond with close - - // ensure server socket got close event - assertThat("Fast Close Latch",closeSocket.closeLatch.await(1,TimeUnit.SECONDS),is(true)); - assertThat("Fast Close.statusCode",closeSocket.closeStatusCode,is(StatusCode.NORMAL)); - } + // ensure server socket got close event + assertThat("Fast Close Latch",closeSocket.closeLatch.await(1,TimeUnit.SECONDS),is(true)); + assertThat("Fast Close.statusCode",closeSocket.closeStatusCode,is(StatusCode.NORMAL)); } } private void fastFail() throws Exception { - try (IBlockheadClient client = new BlockheadClient(server.getServerUri())) + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "fastfail"); + request.idleTimeout(1,TimeUnit.SECONDS); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); + StacklessLogging ignore = new StacklessLogging(WebSocketSession.class)) { - client.setProtocols("fastfail"); - client.setTimeout(1,TimeUnit.SECONDS); - try (StacklessLogging scope = new StacklessLogging(WebSocketSession.class)) - { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); + WebSocketFrame received = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - LinkedBlockingQueue frames = client.getFrameQueue(); - WebSocketFrame received = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + CloseInfo close = new CloseInfo(StatusCode.NORMAL,"Normal"); + clientConn.write(close.asFrame()); // respond with close - CloseInfo close = new CloseInfo(StatusCode.NORMAL,"Normal"); - client.write(close.asFrame()); // respond with close - - // ensure server socket got close event - assertThat("Fast Fail Latch",closeSocket.closeLatch.await(1,TimeUnit.SECONDS),is(true)); - assertThat("Fast Fail.statusCode",closeSocket.closeStatusCode,is(StatusCode.SERVER_ERROR)); - assertThat("Fast Fail.errors",closeSocket.errors.size(),is(1)); - } + // ensure server socket got close event + assertThat("Fast Fail Latch",closeSocket.closeLatch.await(1,TimeUnit.SECONDS),is(true)); + assertThat("Fast Fail.statusCode",closeSocket.closeStatusCode,is(StatusCode.SERVER_ERROR)); + assertThat("Fast Fail.errors",closeSocket.errors.size(),is(1)); } } @SuppressWarnings("Duplicates") private void dropConnection() throws Exception { - try (IBlockheadClient client = new BlockheadClient(server.getServerUri())) + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "container"); + request.idleTimeout(1,TimeUnit.SECONDS); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); + StacklessLogging ignore = new StacklessLogging(WebSocketSession.class)) { - client.setProtocols("container"); - client.setTimeout(1,TimeUnit.SECONDS); - try (StacklessLogging scope = new StacklessLogging(WebSocketSession.class)) - { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); - client.disconnect(); - } + clientConn.abort(); } } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketInvalidVersionTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketInvalidVersionTest.java index b4c1ac14b07..31a4c2e91db 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketInvalidVersionTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketInvalidVersionTest.java @@ -19,18 +19,31 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.instanceOf; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.websocket.api.UpgradeException; import org.eclipse.jetty.websocket.common.test.BlockheadClient; -import org.eclipse.jetty.websocket.common.test.HttpResponse; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.examples.MyEchoServlet; import org.junit.AfterClass; -import org.junit.Assert; import org.junit.BeforeClass; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; public class WebSocketInvalidVersionTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private static BlockheadClient client; private static SimpleServletServer server; @BeforeClass @@ -46,28 +59,40 @@ public class WebSocketInvalidVersionTest server.stop(); } + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + /** * Test the requirement of responding with an http 400 when using a Sec-WebSocket-Version that is unsupported. + * * @throws Exception on test failure */ @Test public void testRequestVersion29() throws Exception { - @SuppressWarnings("resource") - BlockheadClient client = new BlockheadClient(server.getServerUri()); - client.setVersion(29); // intentionally bad version - try + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + // intentionally bad version + request.header(HttpHeader.SEC_WEBSOCKET_VERSION, "29"); + + Future connFut = request.sendAsync(); + + expectedException.expect(ExecutionException.class); + expectedException.expectCause(instanceOf(UpgradeException.class)); + expectedException.expectMessage(containsString("400 Unsupported websocket version specification")); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.connect(); - client.sendStandardRequest(); - HttpResponse response = client.readResponseHeader(); - Assert.assertThat("Response Status Code",response.getStatusCode(),is(400)); - Assert.assertThat("Response Status Reason",response.getStatusReason(),containsString("Unsupported websocket version specification")); - Assert.assertThat("Response Versions",response.getHeader("Sec-WebSocket-Version"),is("13")); - } - finally - { - client.disconnect(); } } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java index 623a14f78b0..f19736841ac 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketOverSSLTest.java @@ -27,7 +27,6 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.MappedByteBufferPool; -import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.websocket.api.BatchMode; import org.eclipse.jetty.websocket.api.RemoteEndpoint; import org.eclipse.jetty.websocket.api.Session; @@ -38,16 +37,12 @@ import org.eclipse.jetty.websocket.server.helper.SessionServlet; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; -import org.junit.Rule; import org.junit.Test; public class WebSocketOverSSLTest { public static final int CONNECT_TIMEOUT = 15000; public static final int FUTURE_TIMEOUT_SEC = 30; - @Rule - public TestTracker tracker = new TestTracker(); - public ByteBufferPool bufferPool = new MappedByteBufferPool(); private static SimpleServletServer server; diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServerSessionTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServerSessionTest.java index ad5c2144fb5..6857f6b36a7 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServerSessionTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServerSessionTest.java @@ -21,29 +21,29 @@ package org.eclipse.jetty.websocket.server; import static org.hamcrest.Matchers.is; import java.net.URI; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.AdvancedRunner; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; -import org.eclipse.jetty.websocket.common.test.IBlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.helper.SessionServlet; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.junit.runner.RunWith; /** * Testing various aspects of the server side support for WebSocket {@link org.eclipse.jetty.websocket.api.Session} */ -@RunWith(AdvancedRunner.class) public class WebSocketServerSessionTest { private static SimpleServletServer server; + private static BlockheadClient client; @BeforeClass public static void startServer() throws Exception @@ -58,19 +58,36 @@ public class WebSocketServerSessionTest server.stop(); } + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + @Test public void testDisconnect() throws Exception { URI uri = server.getServerUri().resolve("/test/disconnect"); - try (IBlockheadClient client = new BlockheadClient(uri)) + + BlockheadClientRequest request = client.newWsRequest(uri); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + clientConn.write(new TextFrame().setPayload("harsh-disconnect")); + clientConn.write(new TextFrame().setPayload("this shouldn't be seen by server")); - client.write(new TextFrame().setPayload("harsh-disconnect")); - - client.awaitDisconnect(1, TimeUnit.SECONDS); + TimeUnit.SECONDS.sleep(10); + // clientConn.awaitDisconnect(1, TimeUnit.SECONDS); } } @@ -78,20 +95,20 @@ public class WebSocketServerSessionTest public void testUpgradeRequestResponse() throws Exception { URI uri = server.getServerUri().resolve("/test?snack=cashews&amount=handful&brand=off"); - try (IBlockheadClient client = new BlockheadClient(uri)) - { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(uri); + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { // Ask the server socket for specific parameter map info - client.write(new TextFrame().setPayload("getParameterMap|snack")); - client.write(new TextFrame().setPayload("getParameterMap|amount")); - client.write(new TextFrame().setPayload("getParameterMap|brand")); - client.write(new TextFrame().setPayload("getParameterMap|cost")); // intentionally invalid + clientConn.write(new TextFrame().setPayload("getParameterMap|snack")); + clientConn.write(new TextFrame().setPayload("getParameterMap|amount")); + clientConn.write(new TextFrame().setPayload("getParameterMap|brand")); + clientConn.write(new TextFrame().setPayload("getParameterMap|cost")); // intentionally invalid // Read frame (hopefully text frame) - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Parameter Map[snack]", tf.getPayloadAsUTF8(), is("[cashews]")); tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java index 994128476a2..31dec999088 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketServletRFCTest.java @@ -22,13 +22,15 @@ import static org.hamcrest.Matchers.is; import java.nio.ByteBuffer; import java.util.Arrays; +import java.util.Locale; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.AdvancedRunner; +import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.util.Utf8Appendable.NotUtf8Exception; import org.eclipse.jetty.util.Utf8StringBuilder; import org.eclipse.jetty.util.log.StacklessLogging; -import org.eclipse.jetty.util.log.StdErrLog; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.extensions.Frame; import org.eclipse.jetty.websocket.common.CloseInfo; @@ -41,6 +43,8 @@ import org.eclipse.jetty.websocket.common.frames.BinaryFrame; import org.eclipse.jetty.websocket.common.frames.ContinuationFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.common.test.UnitGenerator; import org.eclipse.jetty.websocket.common.util.Hex; @@ -50,16 +54,16 @@ import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.junit.runner.RunWith; /** * Test various RFC 6455 specified requirements placed on {@link WebSocketServlet} */ -@RunWith(AdvancedRunner.class) public class WebSocketServletRFCTest { + private static final String REQUEST_HASH_KEY = "dGhlIHNhbXBsZSBub25jZQ=="; private static Generator generator = new UnitGenerator(); private static SimpleServletServer server; + private static BlockheadClient client; @BeforeClass public static void startServer() throws Exception @@ -74,16 +78,18 @@ public class WebSocketServletRFCTest server.stop(); } - /** - * @param clazz the class to enable - * @param enabled true to enable the stack traces (or not) - * @deprecated use {@link StacklessLogging} in a try-with-resources block instead - */ - @Deprecated - private void enableStacks(Class clazz, boolean enabled) + @BeforeClass + public static void startClient() throws Exception { - StdErrLog log = StdErrLog.getLogger(clazz); - log.setHideStacks(!enabled); + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); } /** @@ -93,13 +99,12 @@ public class WebSocketServletRFCTest @Test public void testBinaryAggregate() throws Exception { - BlockheadClient client = new BlockheadClient(server.getServerUri()); - try - { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { // Generate binary frames byte buf1[] = new byte[128]; byte buf2[] = new byte[128]; @@ -113,18 +118,18 @@ public class WebSocketServletRFCTest bin = new BinaryFrame().setPayload(buf1).setFin(false); - client.write(bin); // write buf1 (fin=false) + clientConn.write(bin); // write buf1 (fin=false) bin = new ContinuationFrame().setPayload(buf2).setFin(false); - client.write(bin); // write buf2 (fin=false) + clientConn.write(bin); // write buf2 (fin=false) bin = new ContinuationFrame().setPayload(buf3).setFin(true); - client.write(bin); // write buf3 (fin=true) + clientConn.write(bin); // write buf3 (fin=true) // Read frame echo'd back (hopefully a single binary frame) - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); Frame binmsg = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); int expectedSize = buf1.length + buf2.length + buf3.length; Assert.assertThat("BinaryFrame.payloadLength",binmsg.getPayloadLength(),is(expectedSize)); @@ -156,10 +161,6 @@ public class WebSocketServletRFCTest Assert.assertThat("Echoed data count for 0xBB",bbCount,is(buf2.length)); Assert.assertThat("Echoed data count for 0xCC",ccCount,is(buf3.length)); } - finally - { - client.close(); - } } @Test(expected = NotUtf8Exception.class) @@ -179,26 +180,21 @@ public class WebSocketServletRFCTest @Test public void testEcho() throws Exception { - BlockheadClient client = new BlockheadClient(server.getServerUri()); - try - { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { // Generate text frame String msg = "this is an echo ... cho ... ho ... o"; - client.write(new TextFrame().setPayload(msg)); + clientConn.write(new TextFrame().setPayload(msg)); // Read frame (hopefully text frame) - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame.status code",tf.getPayloadAsUTF8(),is(msg)); } - finally - { - client.close(); - } } /** @@ -209,24 +205,21 @@ public class WebSocketServletRFCTest @Test public void testInternalError() throws Exception { - try (BlockheadClient client = new BlockheadClient(server.getServerUri()); - StacklessLogging stackless=new StacklessLogging(EventDriver.class)) + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); + StacklessLogging ignore = new StacklessLogging(EventDriver.class)) { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + // Generate text frame + clientConn.write(new TextFrame().setPayload("CRASH")); - try (StacklessLogging context = new StacklessLogging(EventDriver.class)) - { - // Generate text frame - client.write(new TextFrame().setPayload("CRASH")); - - // Read frame (hopefully close frame) - LinkedBlockingQueue frames = client.getFrameQueue(); - Frame cf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - CloseInfo close = new CloseInfo(cf); - Assert.assertThat("Close Frame.status code",close.getStatusCode(),is(StatusCode.SERVER_ERROR)); - } + // Read frame (hopefully close frame) + LinkedBlockingQueue frames = clientConn.getFrameQueue(); + Frame cf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + CloseInfo close = new CloseInfo(cf); + Assert.assertThat("Close Frame.status code",close.getStatusCode(),is(StatusCode.SERVER_ERROR)); } } @@ -239,61 +232,50 @@ public class WebSocketServletRFCTest @Test public void testLowercaseUpgrade() throws Exception { - BlockheadClient client = new BlockheadClient(server.getServerUri()); - try + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header("upgrade", "websocket"); + request.header("connection", "upgrade"); + request.header("sec-websocket-key", REQUEST_HASH_KEY); + request.header("sec-websocket-origin", server.getServerUri().toASCIIString()); + request.header("sec-websocket-protocol", "echo"); + request.header("sec-websocket-version", "13"); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.connect(); - - StringBuilder req = new StringBuilder(); - req.append("GET ").append(client.getRequestPath()).append(" HTTP/1.1\r\n"); - req.append("Host: ").append(client.getRequestHost()).append("\r\n"); - req.append("Upgrade: websocket\r\n"); - req.append("connection: upgrade\r\n"); - req.append("sec-websocket-key: ").append(client.getRequestWebSocketKey()).append("\r\n"); - req.append("sec-websocket-origin: ").append(client.getRequestWebSocketOrigin()).append("\r\n"); - req.append("sec-websocket-protocol: echo\r\n"); - req.append("sec-websocket-version: 13\r\n"); - req.append("\r\n"); - client.writeRaw(req.toString()); - - client.expectUpgradeResponse(); - // Generate text frame String msg = "this is an echo ... cho ... ho ... o"; - client.write(new TextFrame().setPayload(msg)); + clientConn.write(new TextFrame().setPayload(msg)); // Read frame (hopefully text frame) - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame.status code",tf.getPayloadAsUTF8(),is(msg)); } - finally - { - client.close(); - } } @Test public void testTextNotUTF8() throws Exception { - try (StacklessLogging stackless=new StacklessLogging(Parser.class); - BlockheadClient client = new BlockheadClient(server.getServerUri())) - { - client.setProtocols("other"); - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "other"); + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); + StacklessLogging ignore = new StacklessLogging(Parser.class)) + { byte buf[] = new byte[] { (byte)0xC2, (byte)0xC3 }; WebSocketFrame txt = new TextFrame().setPayload(ByteBuffer.wrap(buf)); txt.setMask(Hex.asByteArray("11223344")); ByteBuffer bbHeader = generator.generateHeaderBytes(txt); - client.writeRaw(bbHeader); - client.writeRaw(txt.getPayload()); + clientConn.writeRaw(bbHeader); + clientConn.writeRaw(txt.getPayload()); - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("frames[0].opcode",frame.getOpCode(),is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(frame); @@ -310,37 +292,26 @@ public class WebSocketServletRFCTest @Test public void testUppercaseUpgrade() throws Exception { - BlockheadClient client = new BlockheadClient(server.getServerUri()); - try + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header("UPGRADE", "WEBSOCKET"); + request.header("CONNECTION", "UPGRADE"); + request.header("SEC-WEBSOCKET-KEY", REQUEST_HASH_KEY.toUpperCase(Locale.US)); + request.header("SEC-WEBSOCKET-ORIGIN", server.getServerUri().toASCIIString()); + request.header("SEC-WEBSOCKET-PROTOCOL", "ECHO"); + request.header("SEC-WEBSOCKET-VERSION", "13"); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.connect(); - - StringBuilder req = new StringBuilder(); - req.append("GET ").append(client.getRequestPath()).append(" HTTP/1.1\r\n"); - req.append("HOST: ").append(client.getRequestHost()).append("\r\n"); - req.append("UPGRADE: WEBSOCKET\r\n"); - req.append("CONNECTION: UPGRADE\r\n"); - req.append("SEC-WEBSOCKET-KEY: ").append(client.getRequestWebSocketKey()).append("\r\n"); - req.append("SEC-WEBSOCKET-ORIGIN: ").append(client.getRequestWebSocketOrigin()).append("\r\n"); - req.append("SEC-WEBSOCKET-PROTOCOL: ECHO\r\n"); - req.append("SEC-WEBSOCKET-VERSION: 13\r\n"); - req.append("\r\n"); - client.writeRaw(req.toString()); - - client.expectUpgradeResponse(); - // Generate text frame String msg = "this is an echo ... cho ... ho ... o"; - client.write(new TextFrame().setPayload(msg)); + clientConn.write(new TextFrame().setPayload(msg)); // Read frame (hopefully text frame) - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame tf = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Text Frame.status code",tf.getPayloadAsUTF8(),is(msg)); } - finally - { - client.close(); - } } } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilterTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilterTest.java index 784aa8609ae..e0bb8fdae4a 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilterTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilterTest.java @@ -27,7 +27,9 @@ import java.net.URI; import java.util.ArrayList; import java.util.EnumSet; import java.util.List; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import javax.servlet.DispatcherType; @@ -41,14 +43,16 @@ import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.BlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.servlet.WebSocketCreator; -import org.junit.Ignore; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -@Ignore("Unstable - see Issue #1815") @RunWith(Parameterized.class) public class WebSocketUpgradeFilterTest { @@ -56,7 +60,23 @@ public class WebSocketUpgradeFilterTest { Server newServer() throws Exception; } - + + private static BlockheadClient client; + + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + private static AtomicInteger uniqTestDirId = new AtomicInteger(0); private static File getNewTestDir() @@ -305,16 +325,16 @@ public class WebSocketUpgradeFilterTest public void testNormalConfiguration() throws Exception { URI destUri = serverUri.resolve("/info/"); - - try (BlockheadClient client = new BlockheadClient(destUri)) + + BlockheadClientRequest request = client.newWsRequest(destUri); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + clientConn.write(new TextFrame().setPayload("hello")); - client.write(new TextFrame().setPayload("hello")); - - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame received = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); String payload = received.getPayloadAsUTF8(); @@ -328,20 +348,19 @@ public class WebSocketUpgradeFilterTest public void testStopStartOfHandler() throws Exception { URI destUri = serverUri.resolve("/info/"); - - try (BlockheadClient client = new BlockheadClient(destUri)) + + BlockheadClientRequest request = client.newWsRequest(destUri); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + clientConn.write(new TextFrame().setPayload("hello 1")); - client.write(new TextFrame().setPayload("hello 1")); - - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame received = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); String payload = received.getPayloadAsUTF8(); - // If we can connect and send a text message, we know that the endpoint was // added properly, and the response will help us verify the policy configuration too assertThat("payload", payload, containsString("session.maxTextMessageSize=" + (10 * 1024 * 1024))); @@ -349,20 +368,19 @@ public class WebSocketUpgradeFilterTest server.getHandler().stop(); server.getHandler().start(); - - try (BlockheadClient client = new BlockheadClient(destUri)) + + request = client.newWsRequest(destUri); + + connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); + clientConn.write(new TextFrame().setPayload("hello 2")); - client.write(new TextFrame().setPayload("hello 2")); - - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame received = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); String payload = received.getPayloadAsUTF8(); - // If we can connect and send a text message, we know that the endpoint was // added properly, and the response will help us verify the policy configuration too assertThat("payload", payload, containsString("session.maxTextMessageSize=" + (10 * 1024 * 1024))); diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase2.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase2.java index 5a61dfbcd41..2e75a6adb28 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase2.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase2.java @@ -23,7 +23,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.eclipse.jetty.toolchain.test.AdvancedRunner; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.StacklessLogging; import org.eclipse.jetty.websocket.api.StatusCode; @@ -35,9 +34,7 @@ import org.eclipse.jetty.websocket.common.frames.PingFrame; import org.eclipse.jetty.websocket.common.frames.PongFrame; import org.eclipse.jetty.websocket.common.test.Fuzzer; import org.junit.Test; -import org.junit.runner.RunWith; -@RunWith(AdvancedRunner.class) public class TestABCase2 extends AbstractABCase { /** diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase4.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase4.java index bafef7a354e..e3d565f595b 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase4.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase4.java @@ -22,7 +22,6 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; -import org.eclipse.jetty.toolchain.test.AdvancedRunner; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.StacklessLogging; import org.eclipse.jetty.websocket.api.StatusCode; @@ -33,12 +32,10 @@ import org.eclipse.jetty.websocket.common.frames.PingFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.Fuzzer; import org.junit.Test; -import org.junit.runner.RunWith; /** * Test various bad / forbidden opcodes (per spec) */ -@RunWith(AdvancedRunner.class) public class TestABCase4 extends AbstractABCase { /** diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase5.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase5.java index 0a7c1e74daf..780e2f90510 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase5.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase5.java @@ -22,8 +22,6 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.AdvancedRunner; -import org.eclipse.jetty.toolchain.test.annotation.Slow; import org.eclipse.jetty.util.log.StacklessLogging; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.common.CloseInfo; @@ -35,12 +33,10 @@ import org.eclipse.jetty.websocket.common.frames.PongFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.Fuzzer; import org.junit.Test; -import org.junit.runner.RunWith; /** * Fragmentation Tests */ -@RunWith(AdvancedRunner.class) public class TestABCase5 extends AbstractABCase { /** @@ -65,7 +61,7 @@ public class TestABCase5 extends AbstractABCase fuzzer.send(send); fuzzer.expect(expect); } - } + } /** * Send continuation+fin, then text+fin (framewise) @@ -301,7 +297,6 @@ public class TestABCase5 extends AbstractABCase * @throws Exception on test failure */ @Test - @Slow public void testCase5_19() throws Exception { // phase 1 diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java index 6e6084b2217..f8eef39cc37 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase6.java @@ -23,8 +23,6 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.AdvancedRunner; -import org.eclipse.jetty.toolchain.test.annotation.Slow; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.TypeUtil; @@ -39,12 +37,10 @@ import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.Fuzzer; import org.eclipse.jetty.websocket.common.util.Hex; import org.junit.Test; -import org.junit.runner.RunWith; /** * UTF-8 Tests */ -@RunWith(AdvancedRunner.class) public class TestABCase6 extends AbstractABCase { /** @@ -276,7 +272,6 @@ public class TestABCase6 extends AbstractABCase * @throws Exception on test failure */ @Test - @Slow public void testCase6_4_1() throws Exception { byte part1[] = StringUtil.getUtf8Bytes("\u03BA\u1F79\u03C3\u03BC\u03B5"); @@ -312,7 +307,6 @@ public class TestABCase6 extends AbstractABCase * @throws Exception on test failure */ @Test - @Slow public void testCase6_4_2() throws Exception { byte part1[] = Hex.asByteArray("CEBAE1BDB9CF83CEBCCEB5F4"); // split code point @@ -340,7 +334,6 @@ public class TestABCase6 extends AbstractABCase * @throws Exception on test failure */ @Test - @Slow public void testCase6_4_3() throws Exception { // Disable Long Stacks from Parser (we know this test will throw an exception) @@ -393,7 +386,6 @@ public class TestABCase6 extends AbstractABCase * @throws Exception on test failure */ @Test - @Slow public void testCase6_4_4() throws Exception { byte invalid[] = Hex.asByteArray("CEBAE1BDB9CF83CEBCCEB5F49080808080656469746564"); diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7.java index 18a20bc6d1b..eb5474e8c2f 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase7.java @@ -23,7 +23,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.log.StacklessLogging; @@ -39,7 +38,6 @@ import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection; import org.eclipse.jetty.websocket.common.test.Fuzzer; import org.eclipse.jetty.websocket.common.util.Hex; -import org.junit.Rule; import org.junit.Test; /** @@ -47,9 +45,6 @@ import org.junit.Test; */ public class TestABCase7 extends AbstractABCase { - @Rule - public TestTracker tt = new TestTracker(); - /** * Basic message then close frame, normal behavior * @throws Exception on test failure diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java index 1756f634993..210783d547d 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java @@ -24,8 +24,6 @@ import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.toolchain.test.AdvancedRunner; -import org.eclipse.jetty.toolchain.test.annotation.Stress; import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.common.CloseInfo; @@ -37,12 +35,10 @@ import org.eclipse.jetty.websocket.common.frames.DataFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.Fuzzer; import org.junit.Test; -import org.junit.runner.RunWith; /** * Big frame/message tests */ -@RunWith(AdvancedRunner.class) public class TestABCase9 extends AbstractABCase { private static final int KBYTE = 1024; @@ -246,7 +242,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_1_5() throws Exception { byte utf[] = new byte[8 * MBYTE]; @@ -275,7 +270,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_1_6() throws Exception { byte utf[] = new byte[16 * MBYTE]; @@ -359,7 +353,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_2_3() throws Exception { byte data[] = new byte[1 * MBYTE]; @@ -388,7 +381,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_2_4() throws Exception { byte data[] = new byte[4 * MBYTE]; @@ -417,7 +409,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_2_5() throws Exception { byte data[] = new byte[8 * MBYTE]; @@ -446,7 +437,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_2_6() throws Exception { byte data[] = new byte[16 * MBYTE]; @@ -475,7 +465,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_3_1() throws Exception { assertMultiFrameEcho(OpCode.TEXT,4 * MBYTE,64); @@ -486,7 +475,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_3_2() throws Exception { assertMultiFrameEcho(OpCode.TEXT,4 * MBYTE,256); @@ -497,7 +485,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_3_3() throws Exception { assertMultiFrameEcho(OpCode.TEXT,4 * MBYTE,1 * KBYTE); @@ -508,7 +495,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_3_4() throws Exception { assertMultiFrameEcho(OpCode.TEXT,4 * MBYTE,4 * KBYTE); @@ -519,7 +505,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_3_5() throws Exception { assertMultiFrameEcho(OpCode.TEXT,4 * MBYTE,16 * KBYTE); @@ -530,7 +515,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_3_6() throws Exception { assertMultiFrameEcho(OpCode.TEXT,4 * MBYTE,64 * KBYTE); @@ -541,7 +525,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_3_7() throws Exception { assertMultiFrameEcho(OpCode.TEXT,4 * MBYTE,256 * KBYTE); @@ -552,7 +535,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_3_8() throws Exception { assertMultiFrameEcho(OpCode.TEXT,4 * MBYTE,1 * MBYTE); @@ -563,7 +545,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_3_9() throws Exception { assertMultiFrameEcho(OpCode.TEXT,4 * MBYTE,4 * MBYTE); @@ -574,7 +555,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_4_1() throws Exception { assertMultiFrameEcho(OpCode.BINARY,4 * MBYTE,64); @@ -585,7 +565,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_4_2() throws Exception { assertMultiFrameEcho(OpCode.BINARY,4 * MBYTE,256); @@ -596,7 +575,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_4_3() throws Exception { assertMultiFrameEcho(OpCode.BINARY,4 * MBYTE,1 * KBYTE); @@ -607,7 +585,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_4_4() throws Exception { assertMultiFrameEcho(OpCode.BINARY,4 * MBYTE,4 * KBYTE); @@ -618,7 +595,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_4_5() throws Exception { assertMultiFrameEcho(OpCode.BINARY,4 * MBYTE,16 * KBYTE); @@ -629,7 +605,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_4_6() throws Exception { assertMultiFrameEcho(OpCode.BINARY,4 * MBYTE,64 * KBYTE); @@ -640,7 +615,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_4_7() throws Exception { assertMultiFrameEcho(OpCode.BINARY,4 * MBYTE,256 * KBYTE); @@ -651,7 +625,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_4_8() throws Exception { assertMultiFrameEcho(OpCode.BINARY,4 * MBYTE,1 * MBYTE); @@ -662,7 +635,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_4_9() throws Exception { assertMultiFrameEcho(OpCode.BINARY,4 * MBYTE,4 * MBYTE); @@ -673,7 +645,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_5_1() throws Exception { assertSlowFrameEcho(OpCode.TEXT,1 * MBYTE,64); @@ -684,7 +655,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_5_2() throws Exception { assertSlowFrameEcho(OpCode.TEXT,1 * MBYTE,128); @@ -695,7 +665,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_5_3() throws Exception { assertSlowFrameEcho(OpCode.TEXT,1 * MBYTE,256); @@ -706,7 +675,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_5_4() throws Exception { assertSlowFrameEcho(OpCode.TEXT,1 * MBYTE,512); @@ -717,7 +685,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_5_5() throws Exception { assertSlowFrameEcho(OpCode.TEXT,1 * MBYTE,1024); @@ -728,7 +695,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_5_6() throws Exception { assertSlowFrameEcho(OpCode.TEXT,1 * MBYTE,2048); @@ -739,7 +705,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_6_1() throws Exception { assertSlowFrameEcho(OpCode.BINARY,1 * MBYTE,64); @@ -750,7 +715,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_6_2() throws Exception { assertSlowFrameEcho(OpCode.BINARY,1 * MBYTE,128); @@ -761,7 +725,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_6_3() throws Exception { assertSlowFrameEcho(OpCode.BINARY,1 * MBYTE,256); @@ -772,7 +735,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_6_4() throws Exception { assertSlowFrameEcho(OpCode.BINARY,1 * MBYTE,512); @@ -783,7 +745,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_6_5() throws Exception { assertSlowFrameEcho(OpCode.BINARY,1 * MBYTE,1024); @@ -794,7 +755,6 @@ public class TestABCase9 extends AbstractABCase * @throws Exception on test failure */ @Test - @Stress("High I/O use") public void testCase9_6_6() throws Exception { assertSlowFrameEcho(OpCode.BINARY,1 * MBYTE,2048); diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/examples/MyEchoSocket.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/examples/MyEchoSocket.java index b54266ef0a0..283ee8add7e 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/examples/MyEchoSocket.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/examples/MyEchoSocket.java @@ -21,7 +21,6 @@ package org.eclipse.jetty.websocket.server.examples; import java.io.IOException; import org.eclipse.jetty.io.RuntimeIOException; -import org.eclipse.jetty.websocket.api.BatchMode; import org.eclipse.jetty.websocket.api.RemoteEndpoint; import org.eclipse.jetty.websocket.api.WebSocketAdapter; @@ -43,8 +42,6 @@ public class MyEchoSocket extends WebSocketAdapter // echo the data back RemoteEndpoint remote = getRemote(); remote.sendString(message); - if (remote.getBatchMode() == BatchMode.ON) - remote.flush(); } catch (IOException e) { diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/misbehaving/MisbehavingClassTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/misbehaving/MisbehavingClassTest.java index bc5db0c678c..4232727160a 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/misbehaving/MisbehavingClassTest.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/misbehaving/MisbehavingClassTest.java @@ -22,9 +22,11 @@ import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; +import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.util.log.StacklessLogging; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.common.CloseInfo; @@ -32,7 +34,8 @@ import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.common.test.BlockheadClient; -import org.eclipse.jetty.websocket.common.test.IBlockheadClient; +import org.eclipse.jetty.websocket.common.test.BlockheadClientRequest; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.eclipse.jetty.websocket.server.SimpleServletServer; import org.junit.AfterClass; @@ -47,6 +50,7 @@ public class MisbehavingClassTest { private static SimpleServletServer server; private static BadSocketsServlet badSocketsServlet; + private static BlockheadClient client; @BeforeClass public static void startServer() throws Exception @@ -62,29 +66,42 @@ public class MisbehavingClassTest server.stop(); } + @BeforeClass + public static void startClient() throws Exception + { + client = new BlockheadClient(); + client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + } + + @AfterClass + public static void stopClient() throws Exception + { + client.stop(); + } + @Test public void testListenerRuntimeOnConnect() throws Exception { - try (IBlockheadClient client = new BlockheadClient(server.getServerUri()); - StacklessLogging scope = new StacklessLogging(ListenerRuntimeOnConnectSocket.class, WebSocketSession.class)) + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "listener-runtime-connect"); + request.idleTimeout(1, TimeUnit.SECONDS); + + ListenerRuntimeOnConnectSocket socket = badSocketsServlet.listenerRuntimeConnect; + socket.reset(); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); + StacklessLogging ignore = new StacklessLogging(ListenerRuntimeOnConnectSocket.class, WebSocketSession.class)) { - client.setProtocols("listener-runtime-connect"); - client.setTimeout(1,TimeUnit.SECONDS); - - ListenerRuntimeOnConnectSocket socket = badSocketsServlet.listenerRuntimeConnect; - socket.reset(); - - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); - - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("frames[0].opcode",frame.getOpCode(),is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(frame); assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.SERVER_ERROR)); - client.write(close.asFrame()); // respond with close + clientConn.write(close.asFrame()); // respond with close // ensure server socket got close event assertThat("Close Latch",socket.closeLatch.await(1,TimeUnit.SECONDS),is(true)); @@ -100,26 +117,25 @@ public class MisbehavingClassTest @Test public void testAnnotatedRuntimeOnConnect() throws Exception { - try (IBlockheadClient client = new BlockheadClient(server.getServerUri()); + BlockheadClientRequest request = client.newWsRequest(server.getServerUri()); + request.header(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, "annotated-runtime-connect"); + request.idleTimeout(1, TimeUnit.SECONDS); + + AnnotatedRuntimeOnConnectSocket socket = badSocketsServlet.annotatedRuntimeConnect; + socket.reset(); + + Future connFut = request.sendAsync(); + + try (BlockheadConnection clientConn = connFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); StacklessLogging scope = new StacklessLogging(AnnotatedRuntimeOnConnectSocket.class, WebSocketSession.class)) { - client.setProtocols("annotated-runtime-connect"); - client.setTimeout(1,TimeUnit.SECONDS); - - AnnotatedRuntimeOnConnectSocket socket = badSocketsServlet.annotatedRuntimeConnect; - socket.reset(); - - client.connect(); - client.sendStandardRequest(); - client.expectUpgradeResponse(); - - LinkedBlockingQueue frames = client.getFrameQueue(); + LinkedBlockingQueue frames = clientConn.getFrameQueue(); WebSocketFrame frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertThat("frames[0].opcode",frame.getOpCode(),is(OpCode.CLOSE)); CloseInfo close = new CloseInfo(frame); assertThat("Close Status Code",close.getStatusCode(),is(StatusCode.SERVER_ERROR)); - client.write(close.asFrame()); // respond with close + clientConn.write(close.asFrame()); // respond with close // ensure server socket got close event assertThat("Close Latch",socket.closeLatch.await(1,TimeUnit.SECONDS),is(true)); From bca53be4f4e481ef7fd4dd2e00032cc91f4c1bae Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Wed, 7 Mar 2018 07:55:05 -0600 Subject: [PATCH 4/7] Fixes #2282 - Fixing Fuzzer. + Client lifecycle now honored + Slow write now possible --- .../websocket/common/test/BlockheadClientRequest.java | 2 ++ .../websocket/common/test/BlockheadConnection.java | 2 +- .../eclipse/jetty/websocket/common/test/Fuzzer.java | 11 +++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java index 8dd9b2801f9..ccd8a209412 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java @@ -225,6 +225,8 @@ public class BlockheadClientRequest extends HttpRequest implements Response.Comp endp, client.getExecutor()); + endp.setIdleTimeout(client.getIdleTimeout()); + connection.setUpgradeResponseHeaders(response.getHeaders()); // Now swap out the connection diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java index 2269e7f3f14..a8374e323b8 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java @@ -194,7 +194,7 @@ public class BlockheadConnection extends AbstractConnection implements Connectio { int len = Math.min(numBytes, buf.remaining()); ByteBuffer slice = buf.slice(); - buf.position(len); + buf.limit(len); try { getEndPoint().flush(slice); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java index 26910fcf0e4..d83ddabe863 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java @@ -84,6 +84,8 @@ public class Fuzzer implements AutoCloseable client.setIdleTimeout(TimeUnit.SECONDS.toMillis(2)); + client.start(); + this.generator = testcase.getLaxGenerator(); this.testname = testcase.getTestMethodName(); } @@ -111,6 +113,14 @@ public class Fuzzer implements AutoCloseable public void close() { this.clientConnection.close(); + try + { + this.client.stop(); + } + catch (Exception ignore) + { + LOG.ignore(ignore); + } } public void disconnect() @@ -121,6 +131,7 @@ public class Fuzzer implements AutoCloseable public void connect() throws IOException { BlockheadClientRequest request = this.client.newWsRequest(testcase.getServerURI()); + request.idleTimeout(2, TimeUnit.SECONDS); request.header("X-TestCase", testname); Future connFut = request.sendAsync(); From abf126284850366dacc122d8028f6f7ccf8507fd Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Wed, 7 Mar 2018 14:29:22 -0600 Subject: [PATCH 5/7] Issue #2282 - More work on websocket server side tests --- .../jsr356/DecoderReaderManySmallTest.java | 138 ++--- .../websocket/jsr356/DecoderReaderTest.java | 190 +++--- .../jetty/websocket/jsr356/EncoderTest.java | 168 +++--- jetty-websocket/websocket-client/pom.xml | 6 + .../websocket/client/BadNetworkTest.java | 52 +- .../websocket/client/ClientCloseTest.java | 154 +++-- .../websocket/client/ClientConnectTest.java | 288 ++++----- .../jetty/websocket/client/CookieTest.java | 68 ++- .../websocket/client/JettyTrackingSocket.java | 5 +- .../websocket/client/ServerReadThread.java | 133 ----- .../websocket/client/ServerWriteThread.java | 9 +- .../jetty/websocket/client/SessionTest.java | 75 +-- .../websocket/client/SlowClientTest.java | 80 ++- .../websocket/client/SlowServerTest.java | 119 ++-- .../client/TomcatServerQuirksTest.java | 71 ++- .../websocket/client/WebSocketClientTest.java | 233 ++++---- jetty-websocket/websocket-common/pom.xml | 6 + .../common/test/BlockheadClientRequest.java | 1 + .../common/test/BlockheadConnection.java | 32 +- .../common/test/BlockheadServer.java | 256 ++++++-- .../test/BlockheadServerConnection.java | 554 +----------------- .../test/IBlockheadServerConnection.java | 68 --- .../jetty/websocket/common/test/Timeouts.java | 9 + .../websocket/server/ab/TestABCase9.java | 1 - 24 files changed, 1102 insertions(+), 1614 deletions(-) delete mode 100644 jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerReadThread.java delete mode 100644 jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadServerConnection.java diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderManySmallTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderManySmallTest.java index 1500064c44b..1d9240ff2d1 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderManySmallTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderManySmallTest.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -40,13 +41,19 @@ import javax.websocket.WebSocketContainer; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; +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.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.IBlockheadServerConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; @@ -110,60 +117,9 @@ public class DecoderReaderManySmallTest } } - private static class EventIdServer implements Runnable - { - private BlockheadServer server; - private IBlockheadServerConnection sconnection; - private CountDownLatch connectLatch = new CountDownLatch(1); - - public EventIdServer(BlockheadServer server) - { - this.server = server; - } - - @Override - public void run() - { - try - { - sconnection = server.accept(); - sconnection.setSoTimeout(60000); - sconnection.upgrade(); - } - catch (Exception e) - { - LOG.warn(e); - } - finally - { - connectLatch.countDown(); - } - } - - public void writeSequentialIds(int from, int to) throws IOException - { - for (int id = from; id < to; id++) - { - TextFrame frame = new TextFrame(); - frame.setPayload(Integer.toString(id)); - sconnection.write(frame); - } - } - - public void close() throws IOException - { - sconnection.close(); - } - - public void awaitConnect() throws InterruptedException - { - connectLatch.await(1,TimeUnit.SECONDS); - } - } - private static final Logger LOG = Log.getLogger(DecoderReaderManySmallTest.class); - private BlockheadServer server; + private static BlockheadServer server; private WebSocketContainer client; @Before @@ -178,15 +134,15 @@ public class DecoderReaderManySmallTest ((LifeCycle)client).stop(); } - @Before - public void startServer() throws Exception + @BeforeClass + public static void startServer() throws Exception { server = new BlockheadServer(); server.start(); } - @After - public void stopServer() throws Exception + @AfterClass + public static void stopServer() throws Exception { server.stop(); } @@ -194,31 +150,55 @@ public class DecoderReaderManySmallTest @Test public void testManyIds() throws Exception { + // Hook into server connection creation + CompletableFuture serverConnFut = new CompletableFuture<>(); + server.addConnectFuture(serverConnFut); + EventIdSocket ids = new EventIdSocket(); - EventIdServer idserver = new EventIdServer(server); - new Thread(idserver).start(); client.connectToServer(ids,server.getWsUri()); - idserver.awaitConnect(); - int from = 1000; - int to = 2000; - idserver.writeSequentialIds(from,to); - idserver.close(); - int count = from - to; - ids.awaitClose(); - // collect seen ids - List seen = new ArrayList<>(); - for(int i=0; i + { + WebSocketFrame wsFrame = (WebSocketFrame) frame; + if (wsFrame.getOpCode() == OpCode.TEXT) + { + String msg = wsFrame.getPayloadAsUTF8(); + if (msg == "generate") + { + for (int id = from; id < to; id++) + { + TextFrame event = new TextFrame(); + event.setPayload(Integer.toString(id)); + serverConn.write(event); + } + serverConn.write(new CloseInfo(StatusCode.NORMAL).asFrame()); + } + } + }); + + int count = from - to; + ids.awaitClose(); + // collect seen ids + List seen = new ArrayList<>(); + for (int i = 0; i < count; i++) + { + EventId id = ids.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + // validate that ids don't repeat. + Assert.assertFalse("Already saw ID: " + id.eventId, seen.contains(id.eventId)); + seen.add(id.eventId); + } + + // validate that all expected ids have been seen (order is irrelevant here) + for (int expected = from; expected < to; expected++) + { + Assert.assertTrue("Has expected id:" + expected, seen.contains(expected)); + } } } } diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderTest.java index 56792c47554..3d0f70ae66d 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderTest.java @@ -27,6 +27,8 @@ import java.io.IOException; import java.io.Reader; import java.util.ArrayList; import java.util.List; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -49,13 +51,14 @@ import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.frames.ContinuationFrame; 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.IBlockheadServerConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; +import org.junit.BeforeClass; import org.junit.Test; public class DecoderReaderTest @@ -125,6 +128,7 @@ public class DecoderReaderTest @ClientEndpoint(decoders = { QuotesDecoder.class }) public static class QuotesSocket { + private static final Logger LOG = Log.getLogger(QuotesSocket.class); public LinkedBlockingQueue messageQueue = new LinkedBlockingQueue<>(); private CountDownLatch closeLatch = new CountDownLatch(1); @@ -137,12 +141,15 @@ public class DecoderReaderTest @OnMessage public synchronized void onMessage(Quotes msg) { - Integer h=hashCode(); messageQueue.offer(msg); - System.out.printf("%x: Quotes from: %s%n",h,msg.author); - for (String quote : msg.quotes) + if(LOG.isDebugEnabled()) { - System.out.printf("%x: - %s%n",h,quote); + String hashcode = Integer.toHexString(Objects.hashCode(this)); + LOG.debug("{}: Quotes from: {}", hashcode, msg.author); + for (String quote : msg.quotes) + { + LOG.debug("{}: - {}", hashcode, quote); + } } } @@ -152,82 +159,7 @@ public class DecoderReaderTest } } - private static class QuoteServer implements Runnable - { - private BlockheadServer server; - private IBlockheadServerConnection sconnection; - private CountDownLatch connectLatch = new CountDownLatch(1); - - public QuoteServer(BlockheadServer server) - { - this.server = server; - } - - @Override - public void run() - { - try - { - sconnection = server.accept(); - sconnection.setSoTimeout(60000); - sconnection.upgrade(); - } - catch (Exception e) - { - LOG.warn(e); - } - finally - { - connectLatch.countDown(); - } - } - - public void writeQuotes(String filename) throws IOException - { - // read file - File qfile = MavenTestingUtils.getTestResourceFile(filename); - List lines = new ArrayList<>(); - try (FileReader reader = new FileReader(qfile); BufferedReader buf = new BufferedReader(reader)) - { - String line; - while ((line = buf.readLine()) != null) - { - lines.add(line); - } - } - // write file out, each line on a separate frame, but as - // 1 whole message - for (int i = 0; i < lines.size(); i++) - { - WebSocketFrame frame; - if (i == 0) - { - frame = new TextFrame(); - } - else - { - frame = new ContinuationFrame(); - } - frame.setFin((i >= (lines.size() - 1))); - frame.setPayload(BufferUtil.toBuffer(lines.get(i) + "\n")); - sconnection.write(frame); - } - } - - public void close() throws IOException - { - sconnection.close(); - } - - public void awaitConnect() throws InterruptedException - { - connectLatch.await(1,TimeUnit.SECONDS); - } - } - - private static final Logger LOG = Log.getLogger(DecoderReaderTest.class); - - private BlockheadServer server; + private static BlockheadServer server; private WebSocketContainer client; @Before @@ -242,55 +174,91 @@ public class DecoderReaderTest ((LifeCycle)client).stop(); } - @Before - public void startServer() throws Exception + @BeforeClass + public static void startServer() throws Exception { server = new BlockheadServer(); server.start(); } - @After - public void stopServer() throws Exception + @AfterClass + public static void stopServer() throws Exception { server.stop(); } - // TODO analyse and fix - @Ignore @Test public void testSingleQuotes() throws Exception { + // Hook into server connection creation + CompletableFuture serverConnFut = new CompletableFuture<>(); + server.addConnectFuture(serverConnFut); + QuotesSocket quoter = new QuotesSocket(); - QuoteServer qserver = new QuoteServer(server); - new Thread(qserver).start(); client.connectToServer(quoter,server.getWsUri()); - qserver.awaitConnect(); - qserver.writeQuotes("quotes-ben.txt"); - qserver.close(); - quoter.awaitClose(); - Quotes quotes = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - Assert.assertThat("Quotes Author",quotes.author,is("Benjamin Franklin")); - Assert.assertThat("Quotes Count",quotes.quotes.size(),is(3)); + + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + writeQuotes(serverConn, "quotes-ben.txt"); + + Quotes quotes = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + Assert.assertThat("Quotes Author", quotes.author, is("Benjamin Franklin")); + Assert.assertThat("Quotes Count", quotes.quotes.size(), is(3)); + } } - // TODO analyse and fix @Test - @Ignore ("Quotes appear to be able to arrive in any order?") + // @Ignore ("Quotes appear to be able to arrive in any order?") public void testTwoQuotes() throws Exception { + // Hook into server connection creation + CompletableFuture serverConnFut = new CompletableFuture<>(); + server.addConnectFuture(serverConnFut); + QuotesSocket quoter = new QuotesSocket(); - QuoteServer qserver = new QuoteServer(server); - new Thread(qserver).start(); client.connectToServer(quoter,server.getWsUri()); - qserver.awaitConnect(); - qserver.writeQuotes("quotes-ben.txt"); - qserver.writeQuotes("quotes-twain.txt"); - qserver.close(); - quoter.awaitClose(); - Quotes quotes = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - Assert.assertThat("Quotes Author",quotes.author,is("Benjamin Franklin")); - Assert.assertThat("Quotes Count",quotes.quotes.size(),is(3)); - quotes = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); - Assert.assertThat("Quotes Author",quotes.author,is("Mark Twain")); + + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + writeQuotes( serverConn,"quotes-ben.txt"); + writeQuotes( serverConn,"quotes-twain.txt"); + Quotes quotes = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + Assert.assertThat("Quotes Author", quotes.author, is("Benjamin Franklin")); + Assert.assertThat("Quotes Count", quotes.quotes.size(), is(3)); + quotes = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + Assert.assertThat("Quotes Author", quotes.author, is("Mark Twain")); + } + } + + private void writeQuotes(BlockheadConnection conn, String filename) throws IOException + { + // read file + File qfile = MavenTestingUtils.getTestResourceFile(filename); + List lines = new ArrayList<>(); + try (FileReader reader = new FileReader(qfile); BufferedReader buf = new BufferedReader(reader)) + { + String line; + while ((line = buf.readLine()) != null) + { + lines.add(line); + } + } + // write file out, each line on a separate frame, but as + // 1 whole message + for (int i = 0; i < lines.size(); i++) + { + WebSocketFrame frame; + if (i == 0) + { + frame = new TextFrame(); + } + else + { + frame = new ContinuationFrame(); + } + frame.setFin((i >= (lines.size() - 1))); + frame.setPayload(BufferUtil.toBuffer(lines.get(i) + "\n")); + conn.write(frame); + } } } diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java index 807ca8444e2..8b83b999f3f 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java @@ -27,8 +27,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; +import java.util.function.Consumer; import javax.websocket.ClientEndpointConfig; import javax.websocket.ContainerProvider; @@ -44,65 +44,21 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.api.extensions.Frame; +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.IBlockheadServerConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; public class EncoderTest { - private static class EchoServer - { - private BlockheadServer server; - private IBlockheadServerConnection sconnection; - private CountDownLatch connectLatch = new CountDownLatch(1); - - public EchoServer(BlockheadServer server) - { - this.server = server; - } - - public void start() - { - CompletableFuture.runAsync(() -> { - try - { - sconnection = server.accept(); - sconnection.setSoTimeout(10000); - sconnection.upgrade(); - sconnection.enableIncomingEcho(true); - sconnection.startReadThread(); - } - catch (Exception e) - { - LOG.warn(e); - } - finally - { - connectLatch.countDown(); - } - }); - } - - public void stop() - { - if (this.sconnection != null) - { - try - { - this.sconnection.close(); - } - catch (IOException ignore) - { - /* ignore */ - } - } - } - } - public static class Quotes { private String author; @@ -184,10 +140,22 @@ public class EncoderTest private static final Logger LOG = Log.getLogger(EncoderTest.class); - private BlockheadServer server; - + private static BlockheadServer server; private WebSocketContainer client; + @BeforeClass + public static void startServer() throws Exception + { + server = new BlockheadServer(); + server.start(); + } + + @AfterClass + public static void stopServer() throws Exception + { + server.stop(); + } + private void assertReceivedQuotes(String result, Quotes quotes) { Assert.assertThat("Quote Author",result,containsString("Author: " + quotes.getAuthor())); @@ -229,42 +197,33 @@ public class EncoderTest client = ContainerProvider.getWebSocketContainer(); client.setDefaultMaxSessionIdleTimeout(10000); } - + @After public void stopClient() throws Exception { ((LifeCycle)client).stop(); } - - @Before - public void startServer() throws Exception - { - server = new BlockheadServer(); - server.start(); - } - - @After - public void stopServer() throws Exception - { - server.stop(); - } @Test(timeout = 10000) public void testSingleQuotes() throws Exception { - EchoServer eserver = new EchoServer(server); - try + // Hook into server connection creation + CompletableFuture serverConnFut = new CompletableFuture<>(); + server.addConnectFuture(serverConnFut); + + QuotesSocket quoter = new QuotesSocket(); + + ClientEndpointConfig.Builder builder = ClientEndpointConfig.Builder.create(); + List> encoders = new ArrayList<>(); + encoders.add(QuotesEncoder.class); + builder.encoders(encoders); + ClientEndpointConfig cec = builder.build(); + client.connectToServer(quoter,cec,server.getWsUri()); + + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - eserver.start(); - - QuotesSocket quoter = new QuotesSocket(); - - ClientEndpointConfig.Builder builder = ClientEndpointConfig.Builder.create(); - List> encoders = new ArrayList<>(); - encoders.add(QuotesEncoder.class); - builder.encoders(encoders); - ClientEndpointConfig cec = builder.build(); - client.connectToServer(quoter,cec,server.getWsUri()); + // Setup echo of frames on server side + serverConn.setIncomingFrameConsumer(new DataFrameEcho(serverConn)); Quotes ben = getQuotes("quotes-ben.txt"); quoter.write(ben); @@ -272,27 +231,27 @@ public class EncoderTest String result = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertReceivedQuotes(result,ben); } - finally - { - eserver.stop(); - } } @Test(timeout = 10000) public void testTwoQuotes() throws Exception { - EchoServer eserver = new EchoServer(server); - try - { - eserver.start(); + // Hook into server connection creation + CompletableFuture serverConnFut = new CompletableFuture<>(); + server.addConnectFuture(serverConnFut); - QuotesSocket quoter = new QuotesSocket(); - ClientEndpointConfig.Builder builder = ClientEndpointConfig.Builder.create(); - List> encoders = new ArrayList<>(); - encoders.add(QuotesEncoder.class); - builder.encoders(encoders); - ClientEndpointConfig cec = builder.build(); - client.connectToServer(quoter,cec,server.getWsUri()); + QuotesSocket quoter = new QuotesSocket(); + ClientEndpointConfig.Builder builder = ClientEndpointConfig.Builder.create(); + List> encoders = new ArrayList<>(); + encoders.add(QuotesEncoder.class); + builder.encoders(encoders); + ClientEndpointConfig cec = builder.build(); + client.connectToServer(quoter,cec,server.getWsUri()); + + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + // Setup echo of frames on server side + serverConn.setIncomingFrameConsumer(new DataFrameEcho(serverConn)); Quotes ben = getQuotes("quotes-ben.txt"); Quotes twain = getQuotes("quotes-twain.txt"); @@ -304,9 +263,26 @@ public class EncoderTest result = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); assertReceivedQuotes(result,twain); } - finally + } + + private static class DataFrameEcho implements Consumer + { + private final BlockheadConnection connection; + + public DataFrameEcho(BlockheadConnection connection) { - eserver.stop(); + this.connection = connection; + } + + @Override + public void accept(Frame frame) + { + if (OpCode.isDataFrame(frame.getOpCode())) + { + WebSocketFrame copy = WebSocketFrame.copy(frame); + copy.setMask(null); // remove client masking + connection.write(copy); + } } } } diff --git a/jetty-websocket/websocket-client/pom.xml b/jetty-websocket/websocket-client/pom.xml index 91cc5fd0a65..74db3b95ff8 100644 --- a/jetty-websocket/websocket-client/pom.xml +++ b/jetty-websocket/websocket-client/pom.xml @@ -40,6 +40,12 @@ websocket-common ${project.version}
+ + org.eclipse.jetty + jetty-server + ${project.version} + test + org.eclipse.jetty.websocket websocket-common diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/BadNetworkTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/BadNetworkTest.java index 85a26b59156..a556b401936 100644 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/BadNetworkTest.java +++ b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/BadNetworkTest.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.websocket.client; import java.net.URI; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; @@ -26,10 +27,13 @@ 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.StatusCode; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.BlockheadServer; -import org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.After; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; /** @@ -39,7 +43,7 @@ public class BadNetworkTest { public ByteBufferPool bufferPool = new MappedByteBufferPool(); - private BlockheadServer server; + private static BlockheadServer server; private WebSocketClient client; @Before @@ -50,8 +54,8 @@ public class BadNetworkTest client.start(); } - @Before - public void startServer() throws Exception + @BeforeClass + public static void startServer() throws Exception { server = new BlockheadServer(); server.start(); @@ -63,8 +67,8 @@ public class BadNetworkTest client.stop(); } - @After - public void stopServer() throws Exception + @AfterClass + public static void stopServer() throws Exception { server.stop(); } @@ -77,12 +81,9 @@ public class BadNetworkTest URI wsUri = server.getWsUri(); Future future = client.connect(wsocket,wsUri); - IBlockheadServerConnection ssocket = server.accept(); - ssocket.upgrade(); - // Validate that we are connected future.get(30,TimeUnit.SECONDS); - wsocket.waitForConnected(30,TimeUnit.SECONDS); + wsocket.waitForConnected(); // Have client disconnect abruptly Session session = wsocket.getSession(); @@ -102,25 +103,28 @@ public class BadNetworkTest { JettyTrackingSocket wsocket = new JettyTrackingSocket(); + CompletableFuture serverConnFut = new CompletableFuture<>(); + server.addConnectFuture(serverConnFut); + URI wsUri = server.getWsUri(); Future future = client.connect(wsocket,wsUri); - IBlockheadServerConnection ssocket = server.accept(); - ssocket.upgrade(); + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + // Validate that we are connected + future.get(30, TimeUnit.SECONDS); + wsocket.waitForConnected(); - // Validate that we are connected - future.get(30,TimeUnit.SECONDS); - wsocket.waitForConnected(30,TimeUnit.SECONDS); + // Have server disconnect abruptly + serverConn.abort(); - // Have server disconnect abruptly - ssocket.disconnect(); + // Wait for close (as response to idle timeout) + wsocket.waitForClose(10, TimeUnit.SECONDS); - // Wait for close (as response to idle timeout) - wsocket.waitForClose(10,TimeUnit.SECONDS); - - // Client Socket should see a close event, with status NO_CLOSE - // This event is automatically supplied by the underlying WebSocketClientConnection - // in the situation of a bad network connection. - wsocket.assertCloseCode(StatusCode.NO_CLOSE); + // Client Socket should see a close event, with status NO_CLOSE + // This event is automatically supplied by the underlying WebSocketClientConnection + // in the situation of a bad network connection. + wsocket.assertCloseCode(StatusCode.NO_CLOSE); + } } } 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 index 62da4dd5f7e..ef8072be26b 100644 --- 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 @@ -34,7 +34,10 @@ 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; @@ -67,13 +70,15 @@ 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.IBlockheadServerConnection; import org.eclipse.jetty.websocket.common.test.RawFrameBuilder; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.hamcrest.Matcher; import org.junit.After; +import org.junit.AfterClass; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; @@ -176,10 +181,10 @@ public class ClientCloseTest } } - private BlockheadServer server; + private static BlockheadServer server; private WebSocketClient client; - private void confirmConnection(CloseTrackingSocket clientSocket, Future clientFuture, IBlockheadServerConnection serverConns) throws Exception + private void confirmConnection(CloseTrackingSocket clientSocket, Future clientFuture, BlockheadConnection serverConns) throws Exception { // Wait for client connect on via future clientFuture.get(30,TimeUnit.SECONDS); @@ -193,10 +198,8 @@ public class ClientCloseTest final String echoMsg = "echo-test"; Future testFut = clientSocket.getRemote().sendStringByFuture(echoMsg); - serverConns.startReadThread(); - // Wait for send future - testFut.get(30,TimeUnit.SECONDS); + testFut.get(Timeouts.SEND, Timeouts.SEND_UNIT); // Read Frame on server side LinkedBlockingQueue serverCapture = serverConns.getFrameQueue(); @@ -220,7 +223,7 @@ public class ClientCloseTest } } - private void confirmServerReceivedCloseFrame(IBlockheadServerConnection serverConn, int expectedCloseCode, Matcher closeReasonMatcher) throws InterruptedException + 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); @@ -282,8 +285,8 @@ public class ClientCloseTest client.start(); } - @Before - public void startServer() throws Exception + @BeforeClass + public static void startServer() throws Exception { server = new BlockheadServer(); server.start(); @@ -295,8 +298,8 @@ public class ClientCloseTest client.stop(); } - @After - public void stopServer() throws Exception + @AfterClass + public static void stopServer() throws Exception { server.stop(); } @@ -308,15 +311,15 @@ public class ClientCloseTest 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()); - // Server accepts connect - IBlockheadServerConnection serverConn = server.accept(); - serverConn.upgrade(); - - try + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { // client confirms connection via echo confirmConnection(clientSocket, clientConnectFuture, serverConn); @@ -348,10 +351,6 @@ public class ClientCloseTest // client close event on ws-endpoint clientSocket.assertReceivedCloseEvent(timeout, is(StatusCode.NORMAL), containsString("From Server")); } - finally - { - serverConn.disconnect(); - } } @Ignore("Need sbordet's help here") @@ -362,15 +361,15 @@ public class ClientCloseTest 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()); - // Server accepts connect - IBlockheadServerConnection serverConn = server.accept(); - serverConn.upgrade(); - - try + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { // client confirms connection via echo confirmConnection(clientSocket, clientConnectFuture, serverConn); @@ -402,10 +401,6 @@ public class ClientCloseTest assertThat("OnError Latch", clientSocket.errorLatch.await(2, TimeUnit.SECONDS), is(true)); assertThat("OnError", clientSocket.error.get(), instanceOf(SocketTimeoutException.class)); } - finally - { - serverConn.disconnect(); - } } @Test @@ -415,15 +410,15 @@ public class ClientCloseTest 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()); - // Server accepts connect - IBlockheadServerConnection serverConn = server.accept(); - serverConn.upgrade(); - - try + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { // client confirms connection via echo confirmConnection(clientSocket, clientConnectFuture, serverConn); @@ -440,9 +435,10 @@ public class ClientCloseTest bad.putShort((short) StatusCode.NORMAL); bad.put(msg); BufferUtil.flipToFlush(bad, 0); - try (StacklessLogging quiet = new StacklessLogging(Parser.class)) + + try (StacklessLogging ignore = new StacklessLogging(Parser.class)) { - serverConn.write(bad); + serverConn.writeRaw(bad); // client should have noticed the error assertThat("OnError Latch", clientSocket.errorLatch.await(2, TimeUnit.SECONDS), is(true)); @@ -453,11 +449,6 @@ public class ClientCloseTest confirmServerReceivedCloseFrame(serverConn, StatusCode.PROTOCOL, allOf(containsString("Invalid control frame"), containsString("length"))); } } - finally - { - // server disconnects - serverConn.disconnect(); - } // client triggers close event on client ws-endpoint clientSocket.assertReceivedCloseEvent(timeout,is(StatusCode.PROTOCOL),allOf(containsString("Invalid control frame"),containsString("length"))); @@ -470,15 +461,15 @@ public class ClientCloseTest 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()); - // Server accepts connect - IBlockheadServerConnection serverConn = server.accept(); - serverConn.upgrade(); - - try + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { // client confirms connection via echo confirmConnection(clientSocket, clientConnectFuture, serverConn); @@ -494,7 +485,7 @@ public class ClientCloseTest clientSocket.assertNoCloseEvent(); // server shuts down connection (no frame reply) - serverConn.disconnect(); + serverConn.abort(); // client reads -1 (EOF) // client triggers close event on client ws-endpoint @@ -504,10 +495,6 @@ public class ClientCloseTest containsString("Disconnected") )); } - finally - { - serverConn.disconnect(); - } } @Test @@ -517,15 +504,15 @@ public class ClientCloseTest 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()); - // Server accepts connect - IBlockheadServerConnection serverConn = server.accept(); - serverConn.upgrade(); - - try + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { // client confirms connection via echo confirmConnection(clientSocket, clientConnectFuture, serverConn); @@ -547,10 +534,6 @@ public class ClientCloseTest assertThat("OnError Latch", clientSocket.errorLatch.await(2, TimeUnit.SECONDS), is(true)); assertThat("OnError", clientSocket.error.get(), instanceOf(TimeoutException.class)); } - finally - { - serverConn.disconnect(); - } } @Test(timeout = 5000L) @@ -561,47 +544,58 @@ public class ClientCloseTest client.setMaxIdleTimeout(timeout); int clientCount = 3; - CloseTrackingSocket clientSockets[] = new CloseTrackingSocket[clientCount]; - IBlockheadServerConnection serverConns[] = new IBlockheadServerConnection[clientCount]; + List clientSockets = new ArrayList<>(); + List> serverConnFuts = new ArrayList<>(); + List serverConns = new ArrayList<>(); try { - // Connect Multiple Clients + // Open Multiple Clients for (int i = 0; i < clientCount; i++) { // Client Request Upgrade - clientSockets[i] = new CloseTrackingSocket(); - Future clientConnectFuture = client.connect(clientSockets[i], server.getWsUri()); + CloseTrackingSocket clientSocket = new CloseTrackingSocket(); + clientSockets.add(clientSocket); + Future clientConnectFuture = client.connect(clientSocket, server.getWsUri()); // Server accepts connection - serverConns[i] = server.accept(); - serverConns[i].upgrade(); + CompletableFuture serverConnFut = new CompletableFuture<>(); + serverConnFuts.add(serverConnFut); + server.addConnectFuture(serverConnFut); + BlockheadConnection serverConn = serverConnFut.get(); + serverConns.add(serverConn); // client confirms connection via echo - confirmConnection(clientSockets[i], clientConnectFuture, serverConns[i]); + confirmConnection(clientSocket, clientConnectFuture, serverConn); } - // client lifecycle stop + // 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[i], StatusCode.SHUTDOWN, containsString("Shutdown")); + confirmServerReceivedCloseFrame(serverConns.get(i), StatusCode.SHUTDOWN, containsString("Shutdown")); } // clients disconnect for (int i = 0; i < clientCount; i++) { - clientSockets[i].assertReceivedCloseEvent(timeout, is(StatusCode.SHUTDOWN), containsString("Shutdown")); + clientSockets.get(i).assertReceivedCloseEvent(timeout, is(StatusCode.SHUTDOWN), containsString("Shutdown")); } } finally { - for(IBlockheadServerConnection serverConn: serverConns) + for(BlockheadConnection serverConn: serverConns) { - serverConn.disconnect(); + try + { + serverConn.close(); + } + catch (Exception ignore) + { + } } } } @@ -613,15 +607,15 @@ public class ClientCloseTest 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()); - // Server accepts connect - IBlockheadServerConnection serverConn = server.accept(); - serverConn.upgrade(); - - try + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { // client confirms connection via echo confirmConnection(clientSocket, clientConnectFuture, serverConn); @@ -643,9 +637,5 @@ public class ClientCloseTest // assert - close reason message contains (write failure) clientSocket.assertReceivedCloseEvent(timeout, is(StatusCode.ABNORMAL), containsString("EOF")); } - finally - { - serverConn.disconnect(); - } } } 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 index 5b570fb4053..f010f405be3 100644 --- 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 @@ -27,27 +27,37 @@ import static org.junit.Assert.assertThat; import java.io.IOException; 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.List; 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.IBlockheadServerConnection; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.hamcrest.Matcher; import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; /** @@ -58,8 +68,7 @@ public class ClientConnectTest { public ByteBufferPool bufferPool = new MappedByteBufferPool(); - private final int timeout = 500; - private BlockheadServer server; + private static BlockheadServer server; private WebSocketClient client; @SuppressWarnings("unchecked") @@ -88,25 +97,32 @@ public class ClientConnectTest { client = new WebSocketClient(); client.setBufferPool(bufferPool); - client.setConnectTimeout(timeout); + client.setConnectTimeout(Timeouts.CONNECT_UNIT.toMillis(Timeouts.CONNECT)); client.start(); } - @Before - public void startServer() throws Exception + @BeforeClass + public static void startServer() throws Exception { server = new BlockheadServer(); server.start(); } + @Before + public void resetServerHandler() + { + // for each test, reset the server request handling to default + server.resetRequestHandling(); + } + @After public void stopClient() throws Exception { client.stop(); } - @After - public void stopServer() throws Exception + @AfterClass + public static void stopServer() throws Exception { server.stop(); } @@ -119,12 +135,9 @@ public class ClientConnectTest URI wsUri = server.getWsUri(); Future future = client.connect(wsocket,wsUri); - IBlockheadServerConnection connection = server.accept(); - connection.upgrade(); - Session sess = future.get(30,TimeUnit.SECONDS); - wsocket.waitForConnected(1, TimeUnit.SECONDS); + wsocket.waitForConnected(); assertThat("Connect.UpgradeRequest", wsocket.connectUpgradeRequest, notNullValue()); assertThat("Connect.UpgradeResponse", wsocket.connectUpgradeResponse, notNullValue()); @@ -139,48 +152,56 @@ public class ClientConnectTest URI wsUri = server.getWsUri(); HttpClient httpClient = new HttpClient(); - httpClient.start(); - - WebSocketUpgradeRequest req = new WebSocketUpgradeRequest(new WebSocketClient(), httpClient, wsUri, wsocket); - req.header("X-Foo","Req"); - CompletableFuture sess = req.sendAsync(); + try + { + httpClient.start(); - sess.thenAccept((s) -> { - System.out.printf("Session: %s%n",s); - s.close(); - assertThat("Connect.UpgradeRequest",wsocket.connectUpgradeRequest,notNullValue()); - assertThat("Connect.UpgradeResponse",wsocket.connectUpgradeResponse,notNullValue()); - }); - - IBlockheadServerConnection connection = server.accept(); - connection.upgrade(); + 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", "Bogus SHA1"); Future future = client.connect(wsocket,wsUri,upgradeRequest); - - IBlockheadServerConnection connection = server.accept(); - List requestLines = connection.upgrade(); - - Session sess = future.get(30,TimeUnit.SECONDS); - sess.close(); - String authLine = requestLines.stream() - .filter((line) -> line.startsWith("Authorization:")) - .findFirst().get(); - - assertThat("Request Container Authorization", authLine, is("Authorization: Bogus SHA1")); - assertThat("Connect.UpgradeRequest", wsocket.connectUpgradeRequest, notNullValue()); - assertThat("Connect.UpgradeResponse", wsocket.connectUpgradeResponse, notNullValue()); + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + HttpFields upgradeRequestHeaders = serverConn.getUpgradeRequestHeaders(); + + Session sess = future.get(30, TimeUnit.SECONDS); + sess.close(); + + HttpField authHeader = upgradeRequestHeaders.getField(HttpHeader.AUTHORIZATION); + assertThat("Server Request Authorization Header", authHeader, is(notNullValue())); + assertThat("Server Request Authorization Value", authHeader.getValue(), is("Authorization: Bogus SHA1")); + assertThat("Connect.UpgradeRequest", wsocket.connectUpgradeRequest, notNullValue()); + assertThat("Connect.UpgradeResponse", wsocket.connectUpgradeResponse, notNullValue()); + } } @Test @@ -188,16 +209,15 @@ public class ClientConnectTest { 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); - IBlockheadServerConnection connection = server.accept(); - connection.readRequest(); - // no upgrade, just fail with a 404 error - connection.respond("HTTP/1.1 404 NOT FOUND\r\n" + - "Content-Length: 0\r\n" + - "\r\n"); - // The attempt to get upgrade response future should throw error try { @@ -219,16 +239,15 @@ public class ClientConnectTest { 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); - IBlockheadServerConnection connection = server.accept(); - connection.readRequest(); - // Send OK to GET but not upgrade - connection.respond("HTTP/1.1 200 OK\r\n" + - "Content-Length: 0\r\n" + - "\r\n"); - // The attempt to get upgrade response future should throw error try { @@ -250,22 +269,17 @@ public class ClientConnectTest { 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); - IBlockheadServerConnection connection = server.accept(); - List requestLines = connection.readRequestLines(); - String key = connection.parseWebSocketKey(requestLines); - - // Send OK to GET but not upgrade - StringBuilder resp = new StringBuilder(); - resp.append("HTTP/1.1 200 OK\r\n"); // intentionally 200 (not 101) - // Include a value accept key - resp.append("Sec-WebSocket-Accept: ").append(AcceptHash.hashKey(key)).append("\r\n"); - resp.append("Content-Length: 0\r\n"); - resp.append("\r\n"); - connection.respond(resp.toString()); - // The attempt to get upgrade response future should throw error try { @@ -287,21 +301,18 @@ public class ClientConnectTest { 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); - IBlockheadServerConnection connection = server.accept(); - List requestLines = connection.readRequestLines(); - String key = connection.parseWebSocketKey(requestLines); - - // Send Switching Protocols 101, but invalid 'Connection' header - StringBuilder resp = new StringBuilder(); - resp.append("HTTP/1.1 101 Switching Protocols\r\n"); - resp.append("Sec-WebSocket-Accept: ").append(AcceptHash.hashKey(key)).append("\r\n"); - resp.append("Connection: close\r\n"); - resp.append("\r\n"); - connection.respond(resp.toString()); - // The attempt to get upgrade response future should throw error try { @@ -323,21 +334,18 @@ public class ClientConnectTest { 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); - IBlockheadServerConnection connection = server.accept(); - List requestLines = connection.readRequestLines(); - String key = connection.parseWebSocketKey(requestLines); - - // Send Switching Protocols 101, but no 'Connection' header - StringBuilder resp = new StringBuilder(); - resp.append("HTTP/1.1 101 Switching Protocols\r\n"); - resp.append("Sec-WebSocket-Accept: ").append(AcceptHash.hashKey(key)).append("\r\n"); - // Intentionally leave out Connection header - resp.append("\r\n"); - connection.respond(resp.toString()); - // The attempt to get upgrade response future should throw error try { @@ -359,14 +367,16 @@ public class ClientConnectTest { 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); - IBlockheadServerConnection connection = server.accept(); - connection.readRequest(); - // Upgrade badly - connection.respond("HTTP/1.1 101 Upgrade\r\n" + "Sec-WebSocket-Accept: rubbish\r\n" + "\r\n"); - // The attempt to get upgrade response future should throw error try { @@ -388,27 +398,34 @@ public class ClientConnectTest { JettyTrackingSocket wsocket = new JettyTrackingSocket(); - URI wsUri = server.getWsUri(); - Future future = client.connect(wsocket,wsUri); + 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. - // server.accept(); + // Intentionally not accept incoming socket. + // serverSocket.accept(); - try - { - future.get(3,TimeUnit.SECONDS); - Assert.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(); + try + { + future.get(3, TimeUnit.SECONDS); + Assert.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(); + } } } @@ -449,24 +466,29 @@ public class ClientConnectTest { JettyTrackingSocket wsocket = new JettyTrackingSocket(); - URI wsUri = server.getWsUri(); - Future future = client.connect(wsocket,wsUri); - - IBlockheadServerConnection ssocket = server.accept(); - Assert.assertNotNull(ssocket); - // Intentionally don't upgrade - // ssocket.upgrade(); - - // The attempt to get upgrade response future should throw error - try + try(ServerSocket serverSocket = new ServerSocket()) { - future.get(3,TimeUnit.SECONDS); - Assert.fail("Expected ExecutionException -> TimeoutException"); - } - catch (ExecutionException e) - { - // Expected path - java.net.ConnectException ? - assertExpectedError(e,wsocket,instanceOf(ConnectException.class)); + 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 + try + { + future.get(3, TimeUnit.SECONDS); + Assert.fail("Expected ExecutionException -> TimeoutException"); + } + catch (ExecutionException e) + { + // Expected path - java.net.ConnectException ? + assertExpectedError(e, wsocket, instanceOf(ConnectException.class)); + } } } } 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 index 18f827598d0..59da9370884 100644 --- 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 @@ -25,25 +25,30 @@ import static org.junit.Assert.assertTrue; import java.net.CookieManager; import java.net.HttpCookie; import java.util.Collections; -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 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.api.util.QuoteUtil; +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.IBlockheadServerConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; public class CookieTest @@ -83,8 +88,8 @@ public class CookieTest } } + private static BlockheadServer server; private WebSocketClient client; - private BlockheadServer server; @Before public void startClient() throws Exception @@ -93,8 +98,8 @@ public class CookieTest client.start(); } - @Before - public void startServer() throws Exception + @BeforeClass + public static void startServer() throws Exception { server = new BlockheadServer(); server.start(); @@ -109,8 +114,8 @@ public class CookieTest } } - @After - public void stopServer() throws Exception + @AfterClass + public static void stopServer() throws Exception { server.stop(); } @@ -132,18 +137,22 @@ public class CookieTest 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()); - // Server accepts connect - IBlockheadServerConnection serverConn = server.accept(); + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + // client confirms upgrade and receipt of frame + String serverCookies = confirmClientUpgradeAndCookies(clientSocket, clientConnectFuture, serverConn); - // 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")); + assertThat("Cookies seen at server side", serverCookies, containsString("hello=world")); + assertThat("Cookies seen at server side", serverCookies, containsString("foo=bar is the word")); + } } @Test @@ -157,32 +166,35 @@ public class CookieTest 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); - // Server accepts connect - IBlockheadServerConnection serverConn = server.accept(); + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + // client confirms upgrade and receipt of frame + String serverCookies = confirmClientUpgradeAndCookies(clientSocket, clientConnectFuture, serverConn); - // client confirms upgrade and receipt of frame - String serverCookies = confirmClientUpgradeAndCookies(clientSocket,clientConnectFuture,serverConn); - - Assert.assertThat("Cookies seen at server side",serverCookies,containsString("hello=world")); + Assert.assertThat("Cookies seen at server side", serverCookies, containsString("hello=world")); + } } - private String confirmClientUpgradeAndCookies(CookieTrackingSocket clientSocket, Future clientConnectFuture, IBlockheadServerConnection serverConn) + private String confirmClientUpgradeAndCookies(CookieTrackingSocket clientSocket, Future clientConnectFuture, BlockheadConnection serverConn) throws Exception { - // Server upgrades - List upgradeRequestLines = serverConn.upgrade(); - List upgradeRequestCookies = serverConn.regexFind(upgradeRequestLines,"^Cookie: (.*)$"); + // 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(QuoteUtil.join(upgradeRequestCookies,",")); + serverCookieFrame.setPayload(cookieField.getValue()); serverConn.write(serverCookieFrame); - serverConn.flush(); // Confirm client connect on future clientConnectFuture.get(10,TimeUnit.SECONDS); @@ -193,7 +205,7 @@ public class CookieTest LOG.debug("Cookies seen at server: {}",cookies); // Server closes connection - serverConn.close(StatusCode.NORMAL); + 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 index 7a2162c1ee1..28bdc82072c 100644 --- 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 @@ -34,6 +34,7 @@ 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; import org.junit.Assert; /** @@ -159,9 +160,9 @@ public class JettyTrackingSocket extends WebSocketAdapter Assert.assertThat("Client Socket Closed",closeLatch.await(timeoutDuration,timeoutUnit),is(true)); } - public void waitForConnected(int timeoutDuration, TimeUnit timeoutUnit) throws InterruptedException + public void waitForConnected() throws InterruptedException { - Assert.assertThat("Client Socket Connected",openLatch.await(timeoutDuration,timeoutUnit),is(true)); + Assert.assertThat("Client Socket Connected",openLatch.await(Timeouts.CONNECT,Timeouts.CONNECT_UNIT),is(true)); } public void waitForMessage(int timeoutDuration, TimeUnit timeoutUnit) throws InterruptedException diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerReadThread.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerReadThread.java deleted file mode 100644 index 82a3e3cbb70..00000000000 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerReadThread.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 java.io.IOException; -import java.nio.ByteBuffer; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -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.IBlockheadServerConnection; -import org.eclipse.jetty.websocket.common.test.Timeouts; -import org.junit.Assert; - -public class ServerReadThread extends Thread -{ - private static final int BUFFER_SIZE = 8192; - private static final Logger LOG = Log.getLogger(ServerReadThread.class); - private final IBlockheadServerConnection conn; - private boolean active = true; - private int slowness = -1; // disabled is default - private final AtomicInteger frameCount = new AtomicInteger(); - private final CountDownLatch expectedMessageCount; - - public ServerReadThread(IBlockheadServerConnection sconnection, int expectedMessages) - { - this.conn = sconnection; - this.expectedMessageCount = new CountDownLatch(expectedMessages); - } - - public void cancel() - { - active = false; - } - - public int getFrameCount() - { - return frameCount.get(); - } - - public int getSlowness() - { - return slowness; - } - - @Override - public void run() - { - ByteBufferPool bufferPool = conn.getBufferPool(); - ByteBuffer buf = bufferPool.acquire(BUFFER_SIZE,false); - BufferUtil.clearToFill(buf); - - try - { - while (active) - { - BufferUtil.clearToFill(buf); - int len = conn.read(buf); - - if (len > 0) - { - LOG.debug("Read {} bytes",len); - BufferUtil.flipToFlush(buf,0); - conn.getParser().parse(buf); - } - - LinkedBlockingQueue frames = conn.getFrameQueue(); - WebSocketFrame frame; - while ((frame = frames.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT)) != null) - { - frameCount.incrementAndGet(); - if (frame.getOpCode() == OpCode.CLOSE) - { - active = false; - // automatically response to close frame - CloseInfo close = new CloseInfo(frame); - conn.close(close.getStatusCode()); - } - - expectedMessageCount.countDown(); - } - if (slowness > 0) - { - TimeUnit.MILLISECONDS.sleep(getSlowness()); - } - } - } - catch (IOException | InterruptedException e) - { - LOG.warn(e); - } - finally - { - bufferPool.release(buf); - } - } - - public void setSlowness(int slowness) - { - this.slowness = slowness; - } - - public void waitForExpectedMessageCount(int timeoutDuration, TimeUnit timeoutUnit) throws InterruptedException - { - Assert.assertThat("Expected Message Count attained",expectedMessageCount.await(timeoutDuration,timeoutUnit),is(true)); - } -} diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerWriteThread.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerWriteThread.java index 76deb81b2bd..80fd5fb510b 100644 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerWriteThread.java +++ b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ServerWriteThread.java @@ -18,24 +18,23 @@ package org.eclipse.jetty.websocket.client; -import java.io.IOException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.common.frames.TextFrame; -import org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; public class ServerWriteThread extends Thread { private static final Logger LOG = Log.getLogger(ServerWriteThread.class); - private final IBlockheadServerConnection conn; + private final BlockheadConnection conn; private int slowness = -1; private int messageCount = 100; private String message = "Hello"; - public ServerWriteThread(IBlockheadServerConnection conn) + public ServerWriteThread(BlockheadConnection conn) { this.conn = conn; } @@ -74,7 +73,7 @@ public class ServerWriteThread extends Thread } } } - catch (InterruptedException | IOException e) + catch (InterruptedException e) { LOG.warn(e); } 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 index ea6eef03f9c..a6c229482a0 100644 --- 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 @@ -26,35 +26,37 @@ import static org.junit.Assert.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.IBlockheadServerConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; -import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; -import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; public class SessionTest { - private BlockheadServer server; + private static BlockheadServer server; - @Before - public void startServer() throws Exception + @BeforeClass + public static void startServer() throws Exception { server = new BlockheadServer(); server.start(); } - @After - public void stopServer() throws Exception + @AfterClass + public static void stopServer() throws Exception { server.stop(); } @@ -69,6 +71,10 @@ public class SessionTest { JettyTrackingSocket cliSock = new JettyTrackingSocket(); + // Hook into server connection creation + CompletableFuture serverConnFut = new CompletableFuture<>(); + server.addConnectFuture(serverConnFut); + client.getPolicy().setIdleTimeout(10000); URI wsUri = server.getWsUri(); @@ -76,31 +82,33 @@ public class SessionTest request.setSubProtocols("echo"); Future future = client.connect(cliSock,wsUri,request); - final IBlockheadServerConnection srvSock = server.accept(); - srvSock.upgrade(); - Session sess = future.get(30000, TimeUnit.MILLISECONDS); - Assert.assertThat("Session", sess, notNullValue()); - Assert.assertThat("Session.open", sess.isOpen(), is(true)); - Assert.assertThat("Session.upgradeRequest", sess.getUpgradeRequest(), notNullValue()); - Assert.assertThat("Session.upgradeResponse", sess.getUpgradeResponse(), notNullValue()); - - cliSock.assertWasOpened(); - cliSock.assertNotClosed(); - - Collection sessions = client.getBeans(WebSocketSession.class); - Assert.assertThat("client.connectionManager.sessions.size", sessions.size(), is(1)); - - RemoteEndpoint remote = cliSock.getSession().getRemote(); - remote.sendStringByFuture("Hello World!"); - if (remote.getBatchMode() == BatchMode.ON) + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - remote.flush(); - } + // 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); + Assert.assertThat("Session", sess, notNullValue()); + Assert.assertThat("Session.open", sess.isOpen(), is(true)); + Assert.assertThat("Session.upgradeRequest", sess.getUpgradeRequest(), notNullValue()); + Assert.assertThat("Session.upgradeResponse", sess.getUpgradeResponse(), notNullValue()); + + cliSock.assertWasOpened(); + cliSock.assertNotClosed(); + + Collection sessions = client.getBeans(WebSocketSession.class); + Assert.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(); + } - try - { - srvSock.enableIncomingEcho(true); - srvSock.startReadThread(); // wait for response from server cliSock.waitForMessage(30000, TimeUnit.MILLISECONDS); @@ -111,11 +119,6 @@ public class SessionTest assertThat("Message", received, containsString("Hello World!")); cliSock.close(); - srvSock.close(); - } - finally - { - srvSock.disconnect(); } cliSock.waitForClose(30000, TimeUnit.MILLISECONDS); 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 index d727c44b176..58f26b225ee 100644 --- 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 @@ -19,23 +19,32 @@ package org.eclipse.jetty.websocket.client; import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; 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.IBlockheadServerConnection; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; public class SlowClientTest { - private BlockheadServer server; + private static BlockheadServer server; private WebSocketClient client; @Before @@ -46,8 +55,8 @@ public class SlowClientTest client.start(); } - @Before - public void startServer() throws Exception + @BeforeClass + public static void startServer() throws Exception { server = new BlockheadServer(); server.start(); @@ -59,8 +68,8 @@ public class SlowClientTest client.stop(); } - @After - public void stopServer() throws Exception + @AfterClass + public static void stopServer() throws Exception { server.stop(); } @@ -74,39 +83,50 @@ public class SlowClientTest URI wsUri = server.getWsUri(); Future future = client.connect(tsocket, wsUri); - IBlockheadServerConnection sconnection = server.accept(); - sconnection.setSoTimeout(60000); - sconnection.upgrade(); + CompletableFuture serverConnFut = new CompletableFuture<>(); + server.addConnectFuture(serverConnFut); // Confirm connected - future.get(30,TimeUnit.SECONDS); - tsocket.waitForConnected(30,TimeUnit.SECONDS); + future.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); + tsocket.waitForConnected(); int messageCount = 10; - // Setup server read thread - ServerReadThread reader = new ServerReadThread(sconnection, messageCount); - reader.start(); + 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(); - // 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(); - reader.waitForExpectedMessageCount(1, TimeUnit.MINUTES); + 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 + "/")); + } - // Verify receive - Assert.assertThat("Frame Receive Count", reader.getFrameCount(), is(messageCount)); + // Close + tsocket.getSession().close(StatusCode.NORMAL, "Done"); - // 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); - Assert.assertTrue("Client Socket Closed", tsocket.closeLatch.await(3, TimeUnit.MINUTES)); - tsocket.assertCloseCode(StatusCode.NORMAL); - - reader.cancel(); // stop reading + // Verify server response + Assert.assertTrue("Client Socket Closed", tsocket.closeLatch.await(3, TimeUnit.MINUTES)); + 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 index 09050221515..a20ce355200 100644 --- 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 @@ -19,16 +19,22 @@ package org.eclipse.jetty.websocket.client; 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.api.StatusCode; 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.IBlockheadServerConnection; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -73,80 +79,93 @@ public class SlowServerTest client.setMasker(new ZeroMasker()); client.setMaxIdleTimeout(60000); + CompletableFuture serverConnFut = new CompletableFuture<>(); + server.addConnectFuture(serverConnFut); + URI wsUri = server.getWsUri(); Future future = client.connect(tsocket,wsUri); - IBlockheadServerConnection sconnection = server.accept(); - sconnection.setSoTimeout(60000); - sconnection.upgrade(); + 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(30,TimeUnit.SECONDS); - tsocket.waitForConnected(30,TimeUnit.SECONDS); + // Confirm connected + future.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); + tsocket.waitForConnected(); - int messageCount = 10; + int messageCount = 10; - // Setup slow server read thread - ServerReadThread reader = new ServerReadThread(sconnection, messageCount); - reader.setSlowness(100); // slow it down - reader.start(); + // 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(); - // 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 + "]"; + Assert.assertThat(prefix, serverFrame, is(notNullValue())); + Assert.assertThat(prefix + ".opCode", serverFrame.getOpCode(), is(OpCode.TEXT)); + Assert.assertThat(prefix + ".payload", serverFrame.getPayloadAsUTF8(), is("Hello")); + } - // Verify receive - reader.waitForExpectedMessageCount(10,TimeUnit.SECONDS); - Assert.assertThat("Frame Receive Count",reader.getFrameCount(),is(messageCount)); + // Close + tsocket.getSession().close(StatusCode.NORMAL, "Done"); - // Close - tsocket.getSession().close(StatusCode.NORMAL,"Done"); - - Assert.assertTrue("Client Socket Closed",tsocket.closeLatch.await(10,TimeUnit.SECONDS)); - tsocket.assertCloseCode(StatusCode.NORMAL); - - reader.cancel(); // stop reading + Assert.assertTrue("Client Socket Closed", tsocket.closeLatch.await(10, TimeUnit.SECONDS)); + tsocket.assertCloseCode(StatusCode.NORMAL); + } } @Test public void testServerSlowToSend() throws Exception { JettyTrackingSocket clientSocket = new JettyTrackingSocket(); - client.setMasker(new ZeroMasker()); client.setMaxIdleTimeout(60000); + CompletableFuture serverConnFut = new CompletableFuture<>(); + server.addConnectFuture(serverConnFut); + URI wsUri = server.getWsUri(); Future clientConnectFuture = client.connect(clientSocket,wsUri); - IBlockheadServerConnection serverConn = server.accept(); - serverConn.setSoTimeout(60000); - serverConn.upgrade(); + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + // Confirm connected + clientConnectFuture.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT); + clientSocket.waitForConnected(); - // Confirm connected - clientConnectFuture.get(30,TimeUnit.SECONDS); - clientSocket.waitForConnected(30,TimeUnit.SECONDS); + // Have server write slowly. + int messageCount = 1000; - // 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(); - ServerWriteThread writer = new ServerWriteThread(serverConn); - writer.setMessageCount(messageCount); - writer.setMessage("Hello"); - writer.setSlowness(10); - writer.start(); - writer.join(); + // Verify receive + Assert.assertThat("Message Receive Count", clientSocket.messageQueue.size(), is(messageCount)); - // Verify receive - Assert.assertThat("Message Receive Count",clientSocket.messageQueue.size(),is(messageCount)); + // Close server connection (by exiting try-with-resources) + } - // Close - serverConn.close(StatusCode.NORMAL); - - Assert.assertTrue("Client Socket Closed",clientSocket.closeLatch.await(10,TimeUnit.SECONDS)); + Assert.assertTrue("Client Socket Closed", clientSocket.closeLatch.await(10, TimeUnit.SECONDS)); clientSocket.assertCloseCode(StatusCode.NORMAL); } } diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/TomcatServerQuirksTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/TomcatServerQuirksTest.java index 08e878ef32e..4a91c18e7cc 100644 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/TomcatServerQuirksTest.java +++ b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/TomcatServerQuirksTest.java @@ -21,15 +21,19 @@ package org.eclipse.jetty.websocket.client; import java.net.URI; import java.nio.ByteBuffer; import java.util.Arrays; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.WebSocketAdapter; +import org.eclipse.jetty.websocket.common.test.BlockheadConnection; import org.eclipse.jetty.websocket.common.test.BlockheadServer; -import org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection; +import org.eclipse.jetty.websocket.common.test.Timeouts; +import org.junit.AfterClass; import org.junit.Assert; +import org.junit.BeforeClass; import org.junit.Test; public class TomcatServerQuirksTest @@ -59,6 +63,21 @@ public class TomcatServerQuirksTest } } + private static BlockheadServer server; + + @BeforeClass + public static void startServer() throws Exception + { + server = new BlockheadServer(); + server.start(); + } + + @AfterClass + public static void stopServer() throws Exception + { + server.stop(); + } + /** * Test for when encountering a "Transfer-Encoding: chunked" on a Upgrade Response header. *
    @@ -71,57 +90,55 @@ public class TomcatServerQuirksTest @Test public void testTomcat7_0_32_WithTransferEncoding() throws Exception { - BlockheadServer server = new BlockheadServer(); WebSocketClient client = new WebSocketClient(); + server.setRequestHandling((req, resp) -> { + // Add the extra problematic header that triggers bug found in jetty-io + resp.setHeader("Transfer-Encoding", "chunked"); + return true; + }); + try { final int bufferSize = 512; - server.start(); - // Setup Client Factory client.start(); // Create End User WebSocket Class LatchedSocket websocket = new LatchedSocket(); + CompletableFuture serverConnFut = new CompletableFuture<>(); + server.addConnectFuture(serverConnFut); + // Open connection URI wsURI = server.getWsUri(); client.connect(websocket,wsURI); - // Accept incoming connection - IBlockheadServerConnection socket = server.accept(); - socket.setSoTimeout(2000); // timeout - - // Issue upgrade - // Add the extra problematic header that triggers bug found in jetty-io - socket.addResponseHeader("Transfer-Encoding","chunked"); - socket.upgrade(); - // Wait for proper upgrade Assert.assertTrue("Timed out waiting for Client side WebSocket open event",websocket.openLatch.await(1,TimeUnit.SECONDS)); - // Have server write frame. - byte payload[] = new byte[bufferSize / 2]; - Arrays.fill(payload,(byte)'x'); - ByteBuffer serverFrame = BufferUtil.allocate(bufferSize); - BufferUtil.flipToFill(serverFrame); - serverFrame.put((byte)(0x80 | 0x01)); // FIN + TEXT - serverFrame.put((byte)0x7E); // No MASK and 2 bytes length - serverFrame.put((byte)(payload.length >> 8)); // first length byte - serverFrame.put((byte)(payload.length & 0xFF)); // second length byte - serverFrame.put(payload); - BufferUtil.flipToFlush(serverFrame,0); - socket.write(serverFrame); - socket.flush(); + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) + { + // Have server write frame. + byte payload[] = new byte[bufferSize / 2]; + Arrays.fill(payload, (byte) 'x'); + ByteBuffer serverFrame = BufferUtil.allocate(bufferSize); + BufferUtil.flipToFill(serverFrame); + serverFrame.put((byte) (0x80 | 0x01)); // FIN + TEXT + serverFrame.put((byte) 0x7E); // No MASK and 2 bytes length + serverFrame.put((byte) (payload.length >> 8)); // first length byte + serverFrame.put((byte) (payload.length & 0xFF)); // second length byte + serverFrame.put(payload); + BufferUtil.flipToFlush(serverFrame, 0); + serverConn.writeRaw(serverFrame); + } Assert.assertTrue(websocket.dataLatch.await(1000,TimeUnit.SECONDS)); } finally { client.stop(); - server.stop(); } } } 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 index b22e3646d93..7b741145e56 100644 --- 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 @@ -31,6 +31,7 @@ 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; @@ -39,35 +40,48 @@ 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.IBlockheadServerConnection; import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; public class WebSocketClientTest { - private BlockheadServer server; + private static BlockheadServer server; private WebSocketClient client; @Before - public void startClientServer() throws Exception + public void startClient() throws Exception { client = new WebSocketClient(); client.start(); + } + + @BeforeClass + public static void startServer() throws Exception + { server = new BlockheadServer(); server.start(); } @After - public void stopClientServer() throws Exception + public void stopClient() throws Exception { client.stop(); + } + + @AfterClass + public void stopServer() throws Exception + { server.stop(); } @@ -94,45 +108,44 @@ public class WebSocketClientTest 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); - final IBlockheadServerConnection srvSock = server.accept(); - srvSock.upgrade(); - - 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(); - - try + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - srvSock.enableIncomingEcho(true); - srvSock.startReadThread(); + // Setup echo of frames on server side + serverConn.setIncomingFrameConsumer((frame)->{ + WebSocketFrame copy = WebSocketFrame.copy(frame); + 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")); } - finally - { - srvSock.close(); - srvSock.disconnect(); - } } @Test @@ -141,58 +154,65 @@ public class WebSocketClientTest 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); - final IBlockheadServerConnection srvSock = server.accept(); - srvSock.upgrade(); + 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()); - 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(); - cliSock.assertWasOpened(); - cliSock.assertNotClosed(); + Collection sessions = client.getBeans(WebSocketSession.class); + assertThat("client.connectionManager.sessions.size", sessions.size(), is(1)); - Collection sessions = client.getBeans(WebSocketSession.class); - assertThat("client.connectionManager.sessions.size",sessions.size(),is(1)); + FutureWriteCallback callback = new FutureWriteCallback(); - FutureWriteCallback callback = new FutureWriteCallback(); - - cliSock.getSession().getRemote().sendString("Hello World!",callback); - callback.get(1,TimeUnit.SECONDS); + 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()); - // Server - final IBlockheadServerConnection srvSock = server.accept(); - srvSock.upgrade(); + 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()); - // 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")); - // Have server send initial message - srvSock.write(new TextFrame().setPayload("Hello World")); + // Verify connect + future.get(30, TimeUnit.SECONDS); + wsocket.assertWasOpened(); - // 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")); + String received = wsocket.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); + assertThat("Message", received, containsString("Hello World")); + } } @Test @@ -203,9 +223,6 @@ public class WebSocketClientTest URI wsUri = server.getWsUri(); Future future = client.connect(wsocket,wsUri); - IBlockheadServerConnection ssocket = server.accept(); - ssocket.upgrade(); - future.get(30,TimeUnit.SECONDS); Assert.assertTrue(wsocket.openLatch.await(1,TimeUnit.SECONDS)); @@ -224,37 +241,6 @@ public class WebSocketClientTest assertThat("Remote Socket Address / Port",remote.getPort(),greaterThan(0)); } - @Test - public void testMessageBiggerThanBufferSize() throws Exception - { - int bufferSize = 512; - - JettyTrackingSocket wsocket = new JettyTrackingSocket(); - - URI wsUri = server.getWsUri(); - Future future = client.connect(wsocket,wsUri); - - IBlockheadServerConnection ssocket = server.accept(); - ssocket.upgrade(); - - future.get(30,TimeUnit.SECONDS); - - Assert.assertTrue(wsocket.openLatch.await(1,TimeUnit.SECONDS)); - - int length = bufferSize + (bufferSize / 2); // 1.5 times buffer size - ssocket.write(0x80 | 0x01); // FIN + TEXT - ssocket.write(0x7E); // No MASK and 2 bytes length - ssocket.write(length >> 8); // first length byte - ssocket.write(length & 0xFF); // second length byte - for (int i = 0; i < length; ++i) - { - ssocket.write('x'); - } - ssocket.flush(); - - Assert.assertTrue(wsocket.dataLatch.await(1000,TimeUnit.SECONDS)); - } - /** * Ensure that @WebSocket(maxTextMessageSize = 100*1024) behaves as expected. * @@ -266,29 +252,34 @@ public class WebSocketClientTest { 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); - IBlockheadServerConnection ssocket = server.accept(); - ssocket.upgrade(); - - 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); - try + try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { - ssocket.enableIncomingEcho(true); - ssocket.startReadThread(); + // Setup echo of frames on server side + serverConn.setIncomingFrameConsumer((frame)->{ + WebSocketFrame copy = WebSocketFrame.copy(frame); + 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); @@ -297,11 +288,6 @@ public class WebSocketClientTest Assert.assertTrue(wsocket.dataLatch.await(2, TimeUnit.SECONDS)); } - finally - { - ssocket.close(); - ssocket.disconnect(); - } } @Test @@ -312,9 +298,6 @@ public class WebSocketClientTest URI wsUri = server.getWsUri().resolve("/test?snack=cashews&amount=handful&brand=off"); Future future = client.connect(wsocket,wsUri); - IBlockheadServerConnection ssocket = server.accept(); - ssocket.upgrade(); - future.get(30,TimeUnit.SECONDS); Assert.assertTrue(wsocket.openLatch.await(1,TimeUnit.SECONDS)); diff --git a/jetty-websocket/websocket-common/pom.xml b/jetty-websocket/websocket-common/pom.xml index 2e7e2393291..a3340c7c432 100644 --- a/jetty-websocket/websocket-common/pom.xml +++ b/jetty-websocket/websocket-common/pom.xml @@ -36,6 +36,12 @@ ${project.version} test + + org.eclipse.jetty + jetty-server + ${project.version} + test + org.eclipse.jetty.toolchain jetty-test-helper diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java index ccd8a209412..57381ddb3db 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java @@ -227,6 +227,7 @@ public class BlockheadClientRequest extends HttpRequest implements Response.Comp endp.setIdleTimeout(client.getIdleTimeout()); + connection.setUpgradeRequestHeaders(this.getHeaders()); connection.setUpgradeResponseHeaders(response.getHeaders()); // Now swap out the connection diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java index a8374e323b8..93e5fc3c822 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java @@ -23,6 +23,7 @@ import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.util.concurrent.Executor; import java.util.concurrent.LinkedBlockingQueue; +import java.util.function.Consumer; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.io.AbstractConnection; @@ -58,6 +59,7 @@ public class BlockheadConnection extends AbstractConnection implements Connectio private final IncomingCapture incomingCapture; private ByteBuffer networkBuffer; private HttpFields upgradeResponseHeaders; + private HttpFields upgradeRequestHeaders; public BlockheadConnection(WebSocketPolicy policy, ByteBufferPool bufferPool, ExtensionStack extensionStack, EndPoint endp, Executor executor) { @@ -115,6 +117,11 @@ public class BlockheadConnection extends AbstractConnection implements Connectio } } + public ByteBufferPool getBufferPool() + { + return bufferPool; + } + public LinkedBlockingQueue getFrameQueue() { return incomingCapture.incomingFrames; @@ -140,6 +147,11 @@ public class BlockheadConnection extends AbstractConnection implements Connectio return getEndPoint().getRemoteAddress(); } + public HttpFields getUpgradeRequestHeaders() + { + return upgradeRequestHeaders; + } + public HttpFields getUpgradeResponseHeaders() { return upgradeResponseHeaders; @@ -175,11 +187,21 @@ public class BlockheadConnection extends AbstractConnection implements Connectio LOG.warn("Connection Error", cause); } + public void setUpgradeRequestHeaders(HttpFields upgradeRequestHeaders) + { + this.upgradeRequestHeaders = upgradeRequestHeaders; + } + public void setUpgradeResponseHeaders(HttpFields upgradeResponseHeaders) { this.upgradeResponseHeaders = upgradeResponseHeaders; } + public void setIncomingFrameConsumer(Consumer consumer) + { + this.incomingCapture.frameConsumer = consumer; + } + public void write(WebSocketFrame frame) { networkOutgoing.outgoingFrame(frame, null, BatchMode.OFF); @@ -197,7 +219,11 @@ public class BlockheadConnection extends AbstractConnection implements Connectio buf.limit(len); try { - getEndPoint().flush(slice); + boolean done = false; + while (!done) + { + done = getEndPoint().flush(slice); + } } catch (IOException e) { @@ -311,6 +337,7 @@ public class BlockheadConnection extends AbstractConnection implements Connectio { public final LinkedBlockingQueue incomingFrames = new LinkedBlockingQueue<>(); public final LinkedBlockingQueue incomingErrors = new LinkedBlockingQueue<>(); + public Consumer frameConsumer; @Override public void incomingError(Throwable cause) @@ -321,6 +348,9 @@ public class BlockheadConnection extends AbstractConnection implements Connectio @Override public void incomingFrame(Frame frame) { + if(frameConsumer != null) + frameConsumer.accept(frame); + incomingFrames.offer(WebSocketFrame.copy(frame)); } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServer.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServer.java index 72d1cb87828..832a15422e1 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServer.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServer.java @@ -18,45 +18,116 @@ package org.eclipse.jetty.websocket.common.test; -import static org.hamcrest.Matchers.*; - import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; import java.net.URI; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.function.BiFunction; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.io.ByteBufferPool; +import org.eclipse.jetty.io.EndPoint; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.HttpConnection; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Response; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.handler.AbstractHandler; +import org.eclipse.jetty.server.handler.DefaultHandler; +import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; -import org.junit.Assert; +import org.eclipse.jetty.websocket.api.WebSocketBehavior; +import org.eclipse.jetty.websocket.api.WebSocketPolicy; +import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; +import org.eclipse.jetty.websocket.common.AcceptHash; +import org.eclipse.jetty.websocket.common.extensions.ExtensionStack; +import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory; +import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope; +import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; /** - * A overly simplistic websocket server used during testing. + * A Server capable of WebSocket upgrade useful for testing. *

    - * This is not meant to be performant or accurate. In fact, having the server misbehave is a useful trait during testing. + * This implementation exists to allow for testing of non-standard server behaviors, + * especially around the WebSocket Upgrade process. */ public class BlockheadServer { private static final Logger LOG = Log.getLogger(BlockheadServer.class); - private ServerSocket serverSocket; + public static final String SEC_WEBSOCKET_EXTENSIONS = HttpHeader.SEC_WEBSOCKET_EXTENSIONS.toString(); + + private final Server server; + private final ServerConnector connector; + private final BlockheadServerHandler serverHandler; + private final WebSocketPolicy policy; + private final WebSocketContainerScope websocketContainer; + private final WebSocketExtensionFactory extensionFactory; private URI wsUri; - public IBlockheadServerConnection accept() throws IOException + public BlockheadServer() { - LOG.debug(".accept()"); - assertIsStarted(); - Socket socket = serverSocket.accept(); - return new BlockheadServerConnection(socket); + this.server = new Server(); + this.connector = new ServerConnector(this.server); + this.connector.setPort(0); + this.server.addConnector(connector); + + this.policy = new WebSocketPolicy(WebSocketBehavior.SERVER); + this.websocketContainer = new SimpleContainerScope(policy); + this.extensionFactory = new WebSocketExtensionFactory(websocketContainer); + + HandlerList handlers = new HandlerList(); + this.serverHandler = new BlockheadServerHandler(websocketContainer, extensionFactory); + handlers.addHandler(this.serverHandler); + handlers.addHandler(new DefaultHandler()); + this.server.setHandler(handlers); } - private void assertIsStarted() + public void addConnectFuture(CompletableFuture serverConnFut) { - Assert.assertThat("ServerSocket",serverSocket,notNullValue()); - Assert.assertThat("ServerSocket.isBound",serverSocket.isBound(),is(true)); - Assert.assertThat("ServerSocket.isClosed",serverSocket.isClosed(),is(false)); + this.serverHandler.getWSConnectionFutures().offer(serverConnFut); + } - Assert.assertThat("WsUri",wsUri,notNullValue()); + public WebSocketExtensionFactory getExtensionFactory() + { + return extensionFactory; + } + + public WebSocketPolicy getPolicy() + { + return policy; + } + + public WebSocketContainerScope getWebsocketContainer() + { + return websocketContainer; + } + + /** + * Set PRE-Request Handling function. + * + * @param requestFunction the function to handle the request (before upgrade), do whatever you want. + * Note that if you return true, the request will not process into the default Upgrade flow, + * false will allow the default Upgrade flow. + */ + public void setRequestHandling(BiFunction requestFunction) + { + this.serverHandler.setFunction(requestFunction); + } + + public void resetRequestHandling() + { + this.serverHandler.setFunction(null); } public URI getWsUri() @@ -64,28 +135,145 @@ public class BlockheadServer return wsUri; } - public void start() throws IOException + public void start() throws Exception { - InetAddress addr = InetAddress.getByName("localhost"); - serverSocket = new ServerSocket(); - InetSocketAddress endpoint = new InetSocketAddress(addr,0); - serverSocket.bind(endpoint,1); - int port = serverSocket.getLocalPort(); - String uri = String.format("ws://%s:%d/",addr.getHostAddress(),port); - wsUri = URI.create(uri); - LOG.debug("Server Started on {} -> {}",endpoint,wsUri); + this.server.start(); + + wsUri = URI.create("ws://localhost:" + this.connector.getLocalPort() + "/"); + + LOG.debug("BlockheadServer available on {}", wsUri); } - public void stop() + public void stop() throws Exception { LOG.debug("Stopping Server"); - try + this.server.stop(); + } + + public static class BlockheadServerHandler extends AbstractHandler + { + private final WebSocketContainerScope container; + private final WebSocketExtensionFactory extensionFactory; + private BiFunction requestFunction; + private LinkedBlockingQueue> futuresQueue; + + public BlockheadServerHandler(WebSocketContainerScope websocketContainer, WebSocketExtensionFactory extensionFactory) { - serverSocket.close(); + super(); + this.container = websocketContainer; + this.extensionFactory = extensionFactory; + this.futuresQueue = new LinkedBlockingQueue<>(); } - catch (IOException ignore) + + public Queue> getWSConnectionFutures() { - /* ignore */ + return futuresQueue; + } + + @Override + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + { + Response baseResponse = (Response) response; + if(requestFunction != null) + { + if(requestFunction.apply(baseRequest, baseResponse)) + { + baseRequest.setHandled(true); + return; + } + } + + CompletableFuture connFut = this.futuresQueue.poll(); + + try + { + baseRequest.setHandled(true); + + // default/simplified Upgrade flow + String key = request.getHeader("Sec-WebSocket-Key"); + + if (key == null) + { + throw new IllegalStateException("Missing request header 'Sec-WebSocket-Key'"); + } + + // build response + response.setHeader("Upgrade", "WebSocket"); + response.addHeader("Connection", "Upgrade"); + response.addHeader("Sec-WebSocket-Accept", AcceptHash.hashKey(key)); + + response.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS); + + // Initialize / Negotiate Extensions + ExtensionStack extensionStack = new ExtensionStack(extensionFactory); + + if (response.containsHeader(SEC_WEBSOCKET_EXTENSIONS)) + { + // Use pre-negotiated extension list from response + List extensionConfigs = new ArrayList<>(); + response.getHeaders(SEC_WEBSOCKET_EXTENSIONS).forEach( + (value) -> extensionConfigs.addAll(ExtensionConfig.parseList(value))); + extensionStack.negotiate(extensionConfigs); + } + else + { + // Use what was given to us + Enumeration e = request.getHeaders(SEC_WEBSOCKET_EXTENSIONS); + List extensionConfigs = ExtensionConfig.parseEnum(e); + extensionStack.negotiate(extensionConfigs); + + String negotiatedHeaderValue = ExtensionConfig.toHeaderValue(extensionStack.getNegotiatedExtensions()); + response.setHeader(SEC_WEBSOCKET_EXTENSIONS, negotiatedHeaderValue); + } + + WebSocketPolicy policy = this.container.getPolicy().clonePolicy(); + + // Get original HTTP connection + HttpConnection http = (HttpConnection) request.getAttribute("org.eclipse.jetty.server.HttpConnection"); + + EndPoint endp = http.getEndPoint(); + Connector connector = http.getConnector(); + Executor executor = connector.getExecutor(); + ByteBufferPool bufferPool = connector.getByteBufferPool(); + + // Setup websocket connection + BlockheadServerConnection wsConnection = new BlockheadServerConnection( + policy, + bufferPool, + extensionStack, + endp, + executor); + + if (LOG.isDebugEnabled()) + { + LOG.debug("HttpConnection: {}", http); + LOG.debug("BlockheadServerConnection: {}", wsConnection); + } + + wsConnection.setUpgradeRequestHeaders(baseRequest.getHttpFields()); + wsConnection.setUpgradeResponseHeaders(baseResponse.getHttpFields()); + + // Tell jetty about the new upgraded connection + request.setAttribute(HttpConnection.UPGRADE_CONNECTION_ATTRIBUTE, wsConnection); + + if (LOG.isDebugEnabled()) + LOG.debug("Websocket upgrade {} {}", request.getRequestURI(), wsConnection); + + if(connFut != null) + connFut.complete(wsConnection); + + } + catch(Throwable cause) + { + if(connFut != null) + connFut.completeExceptionally(cause); + LOG.warn(cause); + } + } + + public void setFunction(BiFunction function) + { + this.requestFunction = function; } } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java index b1a9d910198..a0a02ca77ae 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java @@ -18,561 +18,17 @@ package org.eclipse.jetty.websocket.common.test; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.Socket; -import java.net.SocketException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.concurrent.Executor; import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.io.MappedByteBufferPool; -import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.util.IO; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.websocket.api.BatchMode; +import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.api.WriteCallback; -import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig; -import org.eclipse.jetty.websocket.api.extensions.Frame; -import org.eclipse.jetty.websocket.api.extensions.Frame.Type; -import org.eclipse.jetty.websocket.api.extensions.IncomingFrames; -import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames; -import org.eclipse.jetty.websocket.common.AcceptHash; -import org.eclipse.jetty.websocket.common.CloseInfo; -import org.eclipse.jetty.websocket.common.Generator; -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.extensions.ExtensionStack; -import org.eclipse.jetty.websocket.common.extensions.WebSocketExtensionFactory; -import org.eclipse.jetty.websocket.common.frames.CloseFrame; -import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope; -import org.junit.Assert; -public class BlockheadServerConnection implements IncomingFrames, OutgoingFrames, Runnable, IBlockheadServerConnection +public class BlockheadServerConnection extends BlockheadConnection { - private static final Logger LOG = Log.getLogger(BlockheadServerConnection.class); - - private final int BUFFER_SIZE = 8192; - private final Socket socket; - private final ByteBufferPool bufferPool; - private final WebSocketPolicy policy; - private final LinkedBlockingQueue incomingFrames = new LinkedBlockingQueue<>(); - private final LinkedBlockingQueue incomingErrors = new LinkedBlockingQueue<>(); - private final Parser parser; - private final Generator generator; - private final AtomicInteger parseCount; - private final WebSocketExtensionFactory extensionRegistry; - private final AtomicBoolean echoing = new AtomicBoolean(false); - private final AtomicBoolean reading = new AtomicBoolean(false); - private Thread readThread; - - /** Set to true to disable timeouts (for debugging reasons) */ - private boolean debug = false; - private OutputStream out; - private InputStream in; - - private Map extraResponseHeaders = new HashMap<>(); - private OutgoingFrames outgoing = this; - - public BlockheadServerConnection(Socket socket) + public BlockheadServerConnection(WebSocketPolicy policy, ByteBufferPool bufferPool, ExtensionStack extensionStack, EndPoint endp, Executor executor) { - this.socket = socket; - this.policy = WebSocketPolicy.newServerPolicy(); - this.policy.setMaxBinaryMessageSize(100000); - this.policy.setMaxTextMessageSize(100000); - // This is a blockhead server connection, no point tracking leaks on this object. - this.bufferPool = new MappedByteBufferPool(BUFFER_SIZE); - this.parser = new Parser(policy,bufferPool); - this.parseCount = new AtomicInteger(0); - this.generator = new Generator(policy,bufferPool,false); - this.extensionRegistry = new WebSocketExtensionFactory(new SimpleContainerScope(policy,bufferPool)); - } - - /** - * Add an extra header for the upgrade response (from the server). No extra work is done to ensure the key and value are sane for http. - * @param rawkey the raw key - * @param rawvalue the raw value - */ - @Override - public void addResponseHeader(String rawkey, String rawvalue) - { - extraResponseHeaders.put(rawkey,rawvalue); - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection#close() - */ - @Override - public void close() throws IOException - { - write(new CloseFrame()); - flush(); - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection#close(int) - */ - @Override - public void close(int statusCode) throws IOException - { - CloseInfo close = new CloseInfo(statusCode); - write(close.asFrame()); - flush(); - } - - @Override - public void disconnect() - { - LOG.debug("disconnect"); - reading.set(false); - IO.close(in); - IO.close(out); - if (socket != null) - { - try - { - socket.close(); - } - catch (IOException ignore) - { - /* ignore */ - } - } - } - @Override - public void flush() throws IOException - { - getOutputStream().flush(); - } - - @Override - public ByteBufferPool getBufferPool() - { - return bufferPool; - } - - public InputStream getInputStream() throws IOException - { - if (in == null) - { - in = socket.getInputStream(); - } - return in; - } - - private OutputStream getOutputStream() throws IOException - { - if (out == null) - { - out = socket.getOutputStream(); - } - return out; - } - - @Override - public Parser getParser() - { - return parser; - } - - public WebSocketPolicy getPolicy() - { - return policy; - } - - @Override - public void incomingError(Throwable e) - { - incomingErrors.offer(e); - } - - @Override - public void incomingFrame(Frame frame) - { - LOG.debug("incomingFrame({})",frame); - int count = parseCount.incrementAndGet(); - if ((count % 10) == 0) - { - LOG.info("Server parsed {} frames",count); - } - incomingFrames.offer(WebSocketFrame.copy(frame)); - - if (frame.getOpCode() == OpCode.CLOSE) - { - CloseInfo close = new CloseInfo(frame); - LOG.debug("Close frame: {}",close); - } - - Type type = frame.getType(); - - if (echoing.get() && (type.isData() || type.isContinuation())) - { - try - { - write(WebSocketFrame.copy(frame).setMasked(false)); - } - catch (IOException e) - { - LOG.warn(e); - } - } - } - - @Override - public void outgoingFrame(Frame frame, WriteCallback callback, BatchMode batchMode) - { - ByteBuffer headerBuf = generator.generateHeaderBytes(frame); - if (LOG.isDebugEnabled()) - { - LOG.debug("writing out: {}",BufferUtil.toDetailString(headerBuf)); - } - - try - { - BufferUtil.writeTo(headerBuf,out); - if (frame.hasPayload()) - BufferUtil.writeTo(frame.getPayload(),out); - out.flush(); - if (callback != null) - { - callback.writeSuccess(); - } - - if (frame.getOpCode() == OpCode.CLOSE) - { - disconnect(); - } - } - catch (Throwable t) - { - if (callback != null) - { - callback.writeFailed(t); - } - } - } - - public List parseExtensions(List requestLines) - { - List extensionConfigs = new ArrayList<>(); - - List hits = regexFind(requestLines, "^Sec-WebSocket-Extensions: (.*)$"); - - for (String econf : hits) - { - // found extensions - ExtensionConfig config = ExtensionConfig.parse(econf); - extensionConfigs.add(config); - } - - return extensionConfigs; - } - - @Override - public String parseWebSocketKey(List requestLines) - { - List hits = regexFind(requestLines,"^Sec-WebSocket-Key: (.*)$"); - if (hits.size() <= 0) - { - return null; - } - - Assert.assertThat("Number of Sec-WebSocket-Key headers", hits.size(), is(1)); - - String key = hits.get(0); - return key; - } - - @Override - public int read(ByteBuffer buf) throws IOException - { - int len = 0; - while ((in.available() > 0) && (buf.remaining() > 0)) - { - buf.put((byte)in.read()); - len++; - } - return len; - } - - @Override - public LinkedBlockingQueue getFrameQueue() - { - return incomingFrames; - } - - @Override - public String readRequest() throws IOException - { - LOG.debug("Reading client request"); - StringBuilder request = new StringBuilder(); - BufferedReader in = new BufferedReader(new InputStreamReader(getInputStream())); - for (String line = in.readLine(); line != null; line = in.readLine()) - { - if (line.length() == 0) - { - break; - } - request.append(line).append("\r\n"); - LOG.debug("read line: {}",line); - } - - LOG.debug("Client Request:{}{}","\n",request); - return request.toString(); - } - - @Override - public List readRequestLines() throws IOException - { - LOG.debug("Reading client request header"); - List lines = new ArrayList<>(); - - BufferedReader in = new BufferedReader(new InputStreamReader(getInputStream())); - for (String line = in.readLine(); line != null; line = in.readLine()) - { - if (line.length() == 0) - { - break; - } - lines.add(line); - } - - return lines; - } - - @Override - public List regexFind(List lines, String pattern) - { - List hits = new ArrayList<>(); - - Pattern patKey = Pattern.compile(pattern,Pattern.CASE_INSENSITIVE); - - Matcher mat; - for (String line : lines) - { - mat = patKey.matcher(line); - if (mat.matches()) - { - if (mat.groupCount() >= 1) - { - hits.add(mat.group(1)); - } - else - { - hits.add(mat.group(0)); - } - } - } - - return hits; - } - - @Override - public void respond(String rawstr) throws IOException - { - LOG.debug("respond(){}{}","\n",rawstr); - getOutputStream().write(rawstr.getBytes()); - flush(); - } - - @Override - public void run() - { - LOG.debug("Entering read thread"); - - long totalReadBytes = 0; - ByteBuffer buf = bufferPool.acquire(BUFFER_SIZE, false); - while(reading.get()) - { - try - { - BufferUtil.clearToFill(buf); - long len = read(buf); - if (len > 0) - { - totalReadBytes += len; - LOG.debug("Read {} bytes", len); - BufferUtil.flipToFlush(buf, 0); - parser.parse(buf); - } - - try - { - TimeUnit.MILLISECONDS.sleep(20); - } - catch (InterruptedException gnore) - { - /* ignore */ - } - } - catch (IOException e) - { - LOG.debug("Exception during echo loop", e); - } - catch (Throwable t) - { - LOG.warn("Exception during echo loop", t); - } - } - - LOG.debug("Read {} total bytes (exiting)",totalReadBytes); - bufferPool.release(buf); - } - - @Override - public void setSoTimeout(int ms) throws SocketException - { - socket.setSoTimeout(ms); - } - - @Override - public void startReadThread() - { - if (readThread != null) - { - throw new IllegalStateException("Read thread already declared/started!"); - } - readThread = new Thread(this,"Blockhead-Server-Read"); - LOG.debug("Starting Read Thread: {}", readThread); - reading.set(true); - readThread.start(); - } - - @Override - public void enableIncomingEcho(boolean enabled) - { - echoing.set(enabled); - } - - @Override - public List upgrade() throws IOException - { - List requestLines = readRequestLines(); - List extensionConfigs = parseExtensions(requestLines); - String key = parseWebSocketKey(requestLines); - - LOG.debug("Client Request Extensions: {}",extensionConfigs); - LOG.debug("Client Request Key: {}",key); - - Assert.assertThat("Request: Sec-WebSocket-Key",key,notNullValue()); - - // collect extensions configured in response header - ExtensionStack extensionStack = new ExtensionStack(extensionRegistry); - extensionStack.negotiate(extensionConfigs); - - // Start with default routing - extensionStack.setNextIncoming(this); - extensionStack.setNextOutgoing(this); - - // Configure Parser / Generator - extensionStack.configure(parser); - extensionStack.configure(generator); - - // Start Stack - try - { - extensionStack.start(); - } - catch (Exception e) - { - throw new IOException("Unable to start Extension Stack"); - } - - // Configure Parser - parser.setIncomingFramesHandler(extensionStack); - - // Setup Response - StringBuilder resp = new StringBuilder(); - resp.append("HTTP/1.1 101 Upgrade\r\n"); - resp.append("Connection: upgrade\r\n"); - resp.append("Content-Length: 0\r\n"); - resp.append("Sec-WebSocket-Accept: "); - resp.append(AcceptHash.hashKey(key)).append("\r\n"); - if (extensionStack.hasNegotiatedExtensions()) - { - // Respond to used extensions - resp.append("Sec-WebSocket-Extensions: "); - boolean delim = false; - for (ExtensionConfig ext : extensionStack.getNegotiatedExtensions()) - { - if (delim) - { - resp.append(", "); - } - resp.append(ext.getParameterizedName()); - delim = true; - } - resp.append("\r\n"); - } - if (extraResponseHeaders.size() > 0) - { - for (Map.Entry xheader : extraResponseHeaders.entrySet()) - { - resp.append(xheader.getKey()); - resp.append(": "); - resp.append(xheader.getValue()); - resp.append("\r\n"); - } - } - resp.append("\r\n"); - - // Write Response - LOG.debug("Response: {}",resp.toString()); - write(resp.toString().getBytes()); - return requestLines; - } - - private void write(byte[] bytes) throws IOException - { - getOutputStream().write(bytes); - } - - public void write(byte[] buf, int offset, int length) throws IOException - { - getOutputStream().write(buf,offset,length); - } - - /* (non-Javadoc) - * @see org.eclipse.jetty.websocket.common.test.IBlockheadServerConnection#write(org.eclipse.jetty.websocket.api.extensions.Frame) - */ - @Override - public void write(Frame frame) throws IOException - { - LOG.debug("write(Frame->{}) to {}",frame,outgoing); - outgoing.outgoingFrame(frame,null,BatchMode.OFF); - } - - @Override - public void write(int b) throws IOException - { - getOutputStream().write(b); - } - - @Override - public void write(ByteBuffer buf) throws IOException - { - byte arr[] = BufferUtil.toArray(buf); - if ((arr != null) && (arr.length > 0)) - { - getOutputStream().write(arr); - } + super(policy, bufferPool, extensionStack, endp, executor); } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadServerConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadServerConnection.java deleted file mode 100644 index a44ec00e6dd..00000000000 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/IBlockheadServerConnection.java +++ /dev/null @@ -1,68 +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.common.test; - -import java.io.IOException; -import java.net.SocketException; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.LinkedBlockingQueue; - -import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.websocket.api.extensions.Frame; -import org.eclipse.jetty.websocket.common.Parser; -import org.eclipse.jetty.websocket.common.WebSocketFrame; - -@Deprecated -public interface IBlockheadServerConnection -{ - public void close() throws IOException; - public void close(int statusCode) throws IOException; - public void disconnect(); - - public void write(Frame frame) throws IOException; - public void write(ByteBuffer buf) throws IOException; - public void write(int b) throws IOException; - public void flush() throws IOException; - - public LinkedBlockingQueue getFrameQueue(); - - public void enableIncomingEcho(boolean enabled); - public void startReadThread(); - - public String readRequest() throws IOException; - public List readRequestLines() throws IOException; - public String parseWebSocketKey(List requestLines); - /** - * Add an extra header for the upgrade response (from the server). No extra work is done to ensure the key and value are sane for http. - * @param rawkey the raw key - * @param rawvalue the raw value - */ - public void addResponseHeader(String rawkey, String rawvalue); - public List upgrade() throws IOException; - public void setSoTimeout(int ms) throws SocketException; - - public void respond(String rawstr) throws IOException; - public List regexFind(List lines, String pattern); - public ByteBufferPool getBufferPool(); - public Parser getParser(); - - @Deprecated - public int read(ByteBuffer buf) throws IOException; -} \ No newline at end of file diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Timeouts.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Timeouts.java index b9092fbc6a5..d82d964bf08 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Timeouts.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Timeouts.java @@ -20,11 +20,20 @@ package org.eclipse.jetty.websocket.common.test; import java.util.concurrent.TimeUnit; +/** + * A central place for all of the various test timeouts within the websocket testing. + */ public class Timeouts { + // establish a connection timeout public static final long CONNECT = 2; public static final TimeUnit CONNECT_UNIT = TimeUnit.SECONDS; + // poll for an event timeout public static final long POLL_EVENT = 2; public static final TimeUnit POLL_EVENT_UNIT = TimeUnit.SECONDS; + + // send a message timeout + public static final long SEND = 2; + public static final TimeUnit SEND_UNIT = TimeUnit.SECONDS; } diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java index 210783d547d..998922e20d1 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java @@ -70,7 +70,6 @@ public class TestABCase9 extends AbstractABCase int offset = 0; boolean fin; ByteBuffer buf; - ; byte op = opcode; while (remaining > 0) { From e76f6d7bafe9b13c270e111941deac861dc84244 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Wed, 7 Mar 2018 17:41:45 -0600 Subject: [PATCH 6/7] Issue #2282 - more websocket test stablization Signed-off-by: Joakim Erdfelt --- .../websocket/client/ClientConnectTest.java | 7 ++++--- .../websocket/client/SlowServerTest.java | 14 +------------- .../client/TomcatServerQuirksTest.java | 2 +- .../websocket/client/WebSocketClientTest.java | 10 ++++++++-- .../test/BlockheadClientConnection.java | 10 ++++++++-- .../common/test/BlockheadClientRequest.java | 3 +-- .../common/test/BlockheadConnection.java | 19 +++++++++++++++---- .../common/test/BlockheadServer.java | 5 +---- .../test/BlockheadServerConnection.java | 10 ++++++++-- .../jetty/websocket/common/test/Fuzzer.java | 2 ++ .../websocket/server/ab/TestABCase9.java | 3 ++- 11 files changed, 51 insertions(+), 34 deletions(-) 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 index f010f405be3..a66f39bf846 100644 --- 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 @@ -186,7 +186,7 @@ public class ClientConnectTest 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", "Bogus SHA1"); + upgradeRequest.setHeader("Authorization", "Basic YWxhZGRpbjpvcGVuc2VzYW1l"); Future future = client.connect(wsocket,wsUri,upgradeRequest); try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) @@ -194,13 +194,14 @@ public class ClientConnectTest HttpFields upgradeRequestHeaders = serverConn.getUpgradeRequestHeaders(); Session sess = future.get(30, TimeUnit.SECONDS); - sess.close(); HttpField authHeader = upgradeRequestHeaders.getField(HttpHeader.AUTHORIZATION); assertThat("Server Request Authorization Header", authHeader, is(notNullValue())); - assertThat("Server Request Authorization Value", authHeader.getValue(), is("Authorization: Bogus SHA1")); + assertThat("Server Request Authorization Value", authHeader.getValue(), is("Basic YWxhZGRpbjpvcGVuc2VzYW1l")); assertThat("Connect.UpgradeRequest", wsocket.connectUpgradeRequest, notNullValue()); assertThat("Connect.UpgradeResponse", wsocket.connectUpgradeResponse, notNullValue()); + + sess.close(); } } 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 index a20ce355200..0350fcdf3f4 100644 --- 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 @@ -28,7 +28,6 @@ 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.client.masks.ZeroMasker; import org.eclipse.jetty.websocket.common.OpCode; import org.eclipse.jetty.websocket.common.WebSocketFrame; @@ -120,14 +119,8 @@ public class SlowServerTest String prefix = "Server Frame[" + i + "]"; Assert.assertThat(prefix, serverFrame, is(notNullValue())); Assert.assertThat(prefix + ".opCode", serverFrame.getOpCode(), is(OpCode.TEXT)); - Assert.assertThat(prefix + ".payload", serverFrame.getPayloadAsUTF8(), is("Hello")); + Assert.assertThat(prefix + ".payload", serverFrame.getPayloadAsUTF8(), is("Hello/" + i + "/")); } - - // Close - tsocket.getSession().close(StatusCode.NORMAL, "Done"); - - Assert.assertTrue("Client Socket Closed", tsocket.closeLatch.await(10, TimeUnit.SECONDS)); - tsocket.assertCloseCode(StatusCode.NORMAL); } } @@ -161,11 +154,6 @@ public class SlowServerTest // Verify receive Assert.assertThat("Message Receive Count", clientSocket.messageQueue.size(), is(messageCount)); - - // Close server connection (by exiting try-with-resources) } - - Assert.assertTrue("Client Socket Closed", clientSocket.closeLatch.await(10, TimeUnit.SECONDS)); - clientSocket.assertCloseCode(StatusCode.NORMAL); } } diff --git a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/TomcatServerQuirksTest.java b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/TomcatServerQuirksTest.java index 4a91c18e7cc..9dc57240b5f 100644 --- a/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/TomcatServerQuirksTest.java +++ b/jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/TomcatServerQuirksTest.java @@ -95,7 +95,7 @@ public class TomcatServerQuirksTest server.setRequestHandling((req, resp) -> { // Add the extra problematic header that triggers bug found in jetty-io resp.setHeader("Transfer-Encoding", "chunked"); - return true; + return false; }); try 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 index 7b741145e56..b4601b8b5f3 100644 --- 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 @@ -25,6 +25,7 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.URI; import java.util.Arrays; @@ -70,6 +71,8 @@ public class WebSocketClientTest public static void startServer() throws Exception { server = new BlockheadServer(); + server.getPolicy().setMaxTextMessageSize(200 * 1024); + server.getPolicy().setMaxBinaryMessageSize(200 * 1024); server.start(); } @@ -80,7 +83,7 @@ public class WebSocketClientTest } @AfterClass - public void stopServer() throws Exception + public static void stopServer() throws Exception { server.stop(); } @@ -122,6 +125,7 @@ public class WebSocketClientTest // 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); }); @@ -237,7 +241,8 @@ public class WebSocketClientTest assertThat("Local Socket Address / Host",local.getAddress().getHostAddress(),notNullValue()); assertThat("Local Socket Address / Port",local.getPort(),greaterThan(0)); - assertThat("Remote Socket Address / Host",remote.getAddress().getHostAddress(),is(wsUri.getHost())); + 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)); } @@ -264,6 +269,7 @@ public class WebSocketClientTest // 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); }); diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientConnection.java index 72d7ff2c859..75d2a40950c 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientConnection.java @@ -18,6 +18,7 @@ package org.eclipse.jetty.websocket.common.test; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.concurrent.ThreadLocalRandom; @@ -29,9 +30,14 @@ import org.eclipse.jetty.websocket.common.extensions.ExtensionStack; public class BlockheadClientConnection extends BlockheadConnection { - public BlockheadClientConnection(WebSocketPolicy policy, ByteBufferPool bufferPool, ExtensionStack extensionStack, EndPoint endp, Executor executor) + public BlockheadClientConnection(WebSocketPolicy policy, + ByteBufferPool bufferPool, + ExtensionStack extensionStack, + CompletableFuture openFut, + EndPoint endp, + Executor executor) { - super(policy, bufferPool, extensionStack, endp, executor); + super(policy, bufferPool, extensionStack, openFut, endp, executor); } @Override diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java index 57381ddb3db..2f81c5bc2ab 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClientRequest.java @@ -222,6 +222,7 @@ public class BlockheadClientRequest extends HttpRequest implements Response.Comp client.getPolicy(), client.getBufferPool(), extensionStack, + fut, endp, client.getExecutor()); @@ -232,8 +233,6 @@ public class BlockheadClientRequest extends HttpRequest implements Response.Comp // Now swap out the connection endp.upgrade(connection); - - fut.complete(connection); } /** diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java index 93e5fc3c822..52a1f9852ad 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadConnection.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.websocket.common.test; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.concurrent.LinkedBlockingQueue; import java.util.function.Consumer; @@ -57,11 +58,12 @@ public class BlockheadConnection extends AbstractConnection implements Connectio private final ExtensionStack extensionStack; private final OutgoingNetwork networkOutgoing; private final IncomingCapture incomingCapture; + private final CompletableFuture openFuture; private ByteBuffer networkBuffer; private HttpFields upgradeResponseHeaders; private HttpFields upgradeRequestHeaders; - public BlockheadConnection(WebSocketPolicy policy, ByteBufferPool bufferPool, ExtensionStack extensionStack, EndPoint endp, Executor executor) + public BlockheadConnection(WebSocketPolicy policy, ByteBufferPool bufferPool, ExtensionStack extensionStack, CompletableFuture openFut, EndPoint endp, Executor executor) { super(endp, executor); this.LOG = Log.getLogger(this.getClass()); @@ -70,6 +72,7 @@ public class BlockheadConnection extends AbstractConnection implements Connectio this.parser = new Parser(policy, bufferPool); this.generator = new Generator(policy, bufferPool, false); this.extensionStack = extensionStack; + this.openFuture = openFut; this.extensionStack.configure(this.parser); this.extensionStack.configure(this.generator); @@ -179,22 +182,26 @@ public class BlockheadConnection extends AbstractConnection implements Connectio public void onOpen() { super.onOpen(); + if(this.openFuture != null) + this.openFuture.complete(this); fillInterested(); } public void processConnectionError(Throwable cause) { LOG.warn("Connection Error", cause); + if(this.openFuture != null) + this.openFuture.completeExceptionally(cause); } public void setUpgradeRequestHeaders(HttpFields upgradeRequestHeaders) { - this.upgradeRequestHeaders = upgradeRequestHeaders; + this.upgradeRequestHeaders = new HttpFields(upgradeRequestHeaders); } public void setUpgradeResponseHeaders(HttpFields upgradeResponseHeaders) { - this.upgradeResponseHeaders = upgradeResponseHeaders; + this.upgradeResponseHeaders = new HttpFields(upgradeResponseHeaders); } public void setIncomingFrameConsumer(Consumer consumer) @@ -209,7 +216,11 @@ public class BlockheadConnection extends AbstractConnection implements Connectio public void writeRaw(ByteBuffer buf) throws IOException { - getEndPoint().flush(buf); + boolean done = false; + while (!done) + { + done = getEndPoint().flush(buf); + } } public void writeRaw(ByteBuffer buf, int numBytes) throws IOException diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServer.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServer.java index 832a15422e1..b671eb9d334 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServer.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServer.java @@ -241,6 +241,7 @@ public class BlockheadServer policy, bufferPool, extensionStack, + connFut, endp, executor); @@ -258,10 +259,6 @@ public class BlockheadServer if (LOG.isDebugEnabled()) LOG.debug("Websocket upgrade {} {}", request.getRequestURI(), wsConnection); - - if(connFut != null) - connFut.complete(wsConnection); - } catch(Throwable cause) { diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java index a0a02ca77ae..fa4445743c4 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadServerConnection.java @@ -18,6 +18,7 @@ package org.eclipse.jetty.websocket.common.test; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import org.eclipse.jetty.io.ByteBufferPool; @@ -27,8 +28,13 @@ import org.eclipse.jetty.websocket.common.extensions.ExtensionStack; public class BlockheadServerConnection extends BlockheadConnection { - public BlockheadServerConnection(WebSocketPolicy policy, ByteBufferPool bufferPool, ExtensionStack extensionStack, EndPoint endp, Executor executor) + public BlockheadServerConnection(WebSocketPolicy policy, + ByteBufferPool bufferPool, + ExtensionStack extensionStack, + CompletableFuture openFut, + EndPoint endp, + Executor executor) { - super(policy, bufferPool, extensionStack, endp, executor); + super(policy, bufferPool, extensionStack, openFut, endp, executor); } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java index d83ddabe863..16982e294d2 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/Fuzzer.java @@ -20,6 +20,7 @@ package org.eclipse.jetty.websocket.common.test; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; import java.io.IOException; import java.net.SocketException; @@ -184,6 +185,7 @@ public class Fuzzer implements AutoCloseable LOG.debug("{} {}",prefix,actual); + Assert.assertThat(prefix, actual, is(notNullValue())); Assert.assertThat(prefix + ".opcode",OpCode.name(actual.getOpCode()),is(OpCode.name(expected.getOpCode()))); prefix += "/" + actual.getOpCode(); if (expected.getOpCode() == OpCode.CLOSE) diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java index 998922e20d1..68b798f9648 100644 --- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java +++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/ab/TestABCase9.java @@ -34,6 +34,7 @@ import org.eclipse.jetty.websocket.common.frames.ContinuationFrame; import org.eclipse.jetty.websocket.common.frames.DataFrame; import org.eclipse.jetty.websocket.common.frames.TextFrame; import org.eclipse.jetty.websocket.common.test.Fuzzer; +import org.eclipse.jetty.websocket.common.test.Timeouts; import org.junit.Test; /** @@ -176,7 +177,7 @@ public class TestABCase9 extends AbstractABCase fuzzer.connect(); fuzzer.setSendMode(Fuzzer.SendMode.BULK); fuzzer.send(send); - fuzzer.expect(expect); + fuzzer.expect(expect, Timeouts.POLL_EVENT*2, Timeouts.POLL_EVENT_UNIT); } } From 5541fcbdba7c58ab441f78e881ba034b7320e9be Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Wed, 7 Mar 2018 18:34:03 -0600 Subject: [PATCH 7/7] Issue #2282 - final testing tweaks Signed-off-by: Joakim Erdfelt --- .../jetty/websocket/jsr356/DecoderReaderTest.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderTest.java index 3d0f70ae66d..cf7f6106a30 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderTest.java @@ -207,8 +207,16 @@ public class DecoderReaderTest } } + /** + * Test that multiple quotes can go through decoder without issue. + *

    + * Since this decoder is Reader based, this is a useful test to ensure + * that the Reader creation / dispatch / hand off to the user endpoint + * works properly. + *

    + * @throws Exception + */ @Test - // @Ignore ("Quotes appear to be able to arrive in any order?") public void testTwoQuotes() throws Exception { // Hook into server connection creation @@ -221,10 +229,11 @@ public class DecoderReaderTest try (BlockheadConnection serverConn = serverConnFut.get(Timeouts.CONNECT, Timeouts.CONNECT_UNIT)) { writeQuotes( serverConn,"quotes-ben.txt"); - writeQuotes( serverConn,"quotes-twain.txt"); Quotes quotes = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Quotes Author", quotes.author, is("Benjamin Franklin")); Assert.assertThat("Quotes Count", quotes.quotes.size(), is(3)); + + writeQuotes( serverConn,"quotes-twain.txt"); quotes = quoter.messageQueue.poll(Timeouts.POLL_EVENT, Timeouts.POLL_EVENT_UNIT); Assert.assertThat("Quotes Author", quotes.author, is("Mark Twain")); }