Issue #207 - moved some JSR356 tests to websocket-tests

This commit is contained in:
Joakim Erdfelt 2017-04-26 18:13:56 -07:00
parent e276705948
commit 641d051e97
18 changed files with 1217 additions and 1138 deletions

View File

@ -1,221 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2017 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.jsr356;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.websocket.ClientEndpoint;
import javax.websocket.CloseReason;
import javax.websocket.ContainerProvider;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;
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.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.common.test.XBlockheadServer;
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("Not working atm")
public class DecoderReaderManySmallTest
{
public static class EventId
{
public int eventId;
}
public static class EventIdDecoder implements Decoder.TextStream<EventId>
{
@Override
public void init(EndpointConfig config)
{
}
@Override
public void destroy()
{
}
@Override
public EventId decode(Reader reader) throws DecodeException, IOException
{
EventId id = new EventId();
try (BufferedReader buf = new BufferedReader(reader))
{
String line;
while ((line = buf.readLine()) != null)
{
id.eventId = Integer.parseInt(line);
}
}
return id;
}
}
@ClientEndpoint(decoders = { EventIdDecoder.class })
public static class EventIdSocket
{
public EventQueue<EventId> messageQueue = new EventQueue<>();
private CountDownLatch closeLatch = new CountDownLatch(1);
@OnClose
public void onClose(CloseReason close)
{
closeLatch.countDown();
}
@OnMessage
public void onMessage(EventId msg)
{
messageQueue.add(msg);
}
public void awaitClose() throws InterruptedException
{
closeLatch.await(4,TimeUnit.SECONDS);
}
}
private static class EventIdServer implements Runnable
{
private XBlockheadServer server;
private IBlockheadServerConnection sconnection;
private CountDownLatch connectLatch = new CountDownLatch(1);
public EventIdServer(XBlockheadServer 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);
@Rule
public TestTracker tt = new TestTracker();
private XBlockheadServer server;
private WebSocketContainer client;
@Before
public void initClient()
{
client = ContainerProvider.getWebSocketContainer();
}
@Before
public void startServer() throws Exception
{
server = new XBlockheadServer();
server.start();
}
@After
public void stopServer() throws Exception
{
server.stop();
}
@Test
public void testManyIds() throws Exception
{
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.messageQueue.awaitEventCount(count,4,TimeUnit.SECONDS);
ids.awaitClose();
// collect seen ids
List<Integer> seen = new ArrayList<>();
for(EventId id: ids.messageQueue)
{
// 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));
}
}
}

View File

@ -1,293 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2017 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.jsr356;
import static org.hamcrest.Matchers.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.websocket.ClientEndpoint;
import javax.websocket.CloseReason;
import javax.websocket.ContainerProvider;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;
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.MavenTestingUtils;
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;
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.XBlockheadServer;
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;
public class DecoderReaderTest
{
public static class Quotes
{
private String author;
private List<String> quotes = new ArrayList<>();
public String getAuthor()
{
return author;
}
public void setAuthor(String author)
{
this.author = author;
}
public List<String> getQuotes()
{
return quotes;
}
public void addQuote(String quote)
{
quotes.add(quote);
}
}
public static class QuotesDecoder implements Decoder.TextStream<Quotes>
{
@Override
public void init(EndpointConfig config)
{
}
@Override
public void destroy()
{
}
@Override
public Quotes decode(Reader reader) throws DecodeException, IOException
{
Quotes quotes = new Quotes();
try (BufferedReader buf = new BufferedReader(reader))
{
String line;
while ((line = buf.readLine()) != null)
{
switch (line.charAt(0))
{
case 'a':
quotes.setAuthor(line.substring(2));
break;
case 'q':
quotes.addQuote(line.substring(2));
break;
}
}
}
return quotes;
}
}
@ClientEndpoint(decoders = { QuotesDecoder.class })
public static class QuotesSocket
{
public EventQueue<Quotes> messageQueue = new EventQueue<>();
private CountDownLatch closeLatch = new CountDownLatch(1);
@OnClose
public void onClose(CloseReason close)
{
closeLatch.countDown();
}
@OnMessage
public synchronized void onMessage(Quotes msg)
{
Integer h=hashCode();
messageQueue.add(msg);
System.out.printf("%x: Quotes from: %s%n",h,msg.author);
for (String quote : msg.quotes)
{
System.out.printf("%x: - %s%n",h,quote);
}
}
public void awaitClose() throws InterruptedException
{
closeLatch.await(4,TimeUnit.SECONDS);
}
}
private static class QuoteServer implements Runnable
{
private XBlockheadServer server;
private IBlockheadServerConnection sconnection;
private CountDownLatch connectLatch = new CountDownLatch(1);
public QuoteServer(XBlockheadServer 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<String> 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);
@Rule
public TestTracker tt = new TestTracker();
private XBlockheadServer server;
private WebSocketContainer client;
@Before
public void initClient()
{
client = ContainerProvider.getWebSocketContainer();
}
@Before
public void startServer() throws Exception
{
server = new XBlockheadServer();
server.start();
}
@After
public void stopServer() throws Exception
{
server.stop();
}
// TODO analyse and fix
@Ignore
@Test
public void testSingleQuotes() throws Exception
{
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");
quoter.messageQueue.awaitEventCount(1,1000,TimeUnit.MILLISECONDS);
qserver.close();
quoter.awaitClose();
Quotes quotes = quoter.messageQueue.poll();
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?")
public void testTwoQuotes() throws Exception
{
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");
quoter.messageQueue.awaitEventCount(2,1000,TimeUnit.MILLISECONDS);
qserver.close();
quoter.awaitClose();
Quotes quotes = quoter.messageQueue.poll();
Assert.assertThat("Quotes Author",quotes.author,is("Benjamin Franklin"));
Assert.assertThat("Quotes Count",quotes.quotes.size(),is(3));
}
}

View File

@ -1,318 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2017 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.jsr356;
import static org.hamcrest.Matchers.containsString;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.websocket.ClientEndpointConfig;
import javax.websocket.ContainerProvider;
import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
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.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.test.XBlockheadServer;
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 EncoderTest
{
private static class EchoServer implements Runnable
{
private Thread thread;
private XBlockheadServer server;
private IBlockheadServerConnection sconnection;
private CountDownLatch connectLatch = new CountDownLatch(1);
public EchoServer(XBlockheadServer server)
{
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();
}
public void stop()
{
if (this.sconnection != null)
{
this.sconnection.stopEcho();
try
{
this.sconnection.close();
}
catch (IOException ignore)
{
/* ignore */
}
}
}
}
public static class Quotes
{
private String author;
private List<String> quotes = new ArrayList<>();
public void addQuote(String quote)
{
quotes.add(quote);
}
public String getAuthor()
{
return author;
}
public List<String> getQuotes()
{
return quotes;
}
public void setAuthor(String author)
{
this.author = author;
}
}
public static class QuotesEncoder implements Encoder.Text<Quotes>
{
@Override
public void destroy()
{
}
@Override
public String encode(Quotes q) throws EncodeException
{
StringBuilder buf = new StringBuilder();
buf.append("Author: ").append(q.getAuthor());
buf.append(System.lineSeparator());
for (String quote : q.quotes)
{
buf.append("Quote: ").append(quote);
buf.append(System.lineSeparator());
}
return buf.toString();
}
@Override
public void init(EndpointConfig config)
{
}
}
public static class QuotesSocket extends Endpoint implements MessageHandler.Whole<String>
{
private Session session;
private EventQueue<String> messageQueue = new EventQueue<>();
@Override
public void onMessage(String message)
{
messageQueue.add(message);
}
@Override
public void onOpen(Session session, EndpointConfig config)
{
this.session = session;
this.session.addMessageHandler(this);
}
public void write(Quotes quotes) throws IOException, EncodeException
{
if (LOG.isDebugEnabled())
LOG.debug("Writing Quotes: {}",quotes);
this.session.getBasicRemote().sendObject(quotes);
}
}
private static final Logger LOG = Log.getLogger(EncoderTest.class);
@Rule
public TestTracker tt = new TestTracker();
private XBlockheadServer server;
private WebSocketContainer client;
private void assertReceivedQuotes(String result, Quotes quotes)
{
Assert.assertThat("Quote Author",result,containsString("Author: " + quotes.getAuthor()));
for (String quote : quotes.quotes)
{
Assert.assertThat("Quote",result,containsString("Quote: " + quote));
}
}
@SuppressWarnings("Duplicates")
private Quotes getQuotes(String filename) throws IOException
{
Quotes quotes = new Quotes();
// read file
File qfile = MavenTestingUtils.getTestResourceFile(filename);
try (FileReader reader = new FileReader(qfile); BufferedReader buf = new BufferedReader(reader))
{
String line;
while ((line = buf.readLine()) != null)
{
switch (line.charAt(0))
{
case 'a':
quotes.setAuthor(line.substring(2));
break;
case 'q':
quotes.addQuote(line.substring(2));
break;
}
}
}
return quotes;
}
@Before
public void initClient()
{
client = ContainerProvider.getWebSocketContainer();
}
@Before
public void startServer() throws Exception
{
server = new XBlockheadServer();
server.start();
}
@After
public void stopServer() throws Exception
{
server.stop();
}
@Test
public void testSingleQuotes() throws Exception
{
EchoServer echoServer = new EchoServer(server);
try
{
echoServer.start();
QuotesSocket quoter = new QuotesSocket();
ClientEndpointConfig.Builder builder = ClientEndpointConfig.Builder.create();
List<Class<? extends Encoder>> encoders = new ArrayList<>();
encoders.add(QuotesEncoder.class);
builder.encoders(encoders);
ClientEndpointConfig cec = builder.build();
client.connectToServer(quoter,cec,server.getWsUri());
Quotes ben = getQuotes("quotes-ben.txt");
quoter.write(ben);
quoter.messageQueue.awaitEventCount(1,1000,TimeUnit.MILLISECONDS);
String result = quoter.messageQueue.poll();
assertReceivedQuotes(result,ben);
}
finally
{
echoServer.stop();
}
}
@Test
public void testTwoQuotes() throws Exception
{
EchoServer echoServer = new EchoServer(server);
try
{
echoServer.start();
QuotesSocket quoter = new QuotesSocket();
ClientEndpointConfig.Builder builder = ClientEndpointConfig.Builder.create();
List<Class<? extends Encoder>> encoders = new ArrayList<>();
encoders.add(QuotesEncoder.class);
builder.encoders(encoders);
ClientEndpointConfig cec = builder.build();
client.connectToServer(quoter,cec,server.getWsUri());
Quotes ben = getQuotes("quotes-ben.txt");
Quotes twain = getQuotes("quotes-twain.txt");
quoter.write(ben);
quoter.write(twain);
quoter.messageQueue.awaitEventCount(2,1000,TimeUnit.MILLISECONDS);
String result = quoter.messageQueue.poll();
assertReceivedQuotes(result,ben);
result = quoter.messageQueue.poll();
assertReceivedQuotes(result,twain);
}
finally
{
echoServer.stop();
}
}
}

View File

@ -1 +0,0 @@
org.eclipse.jetty.websocket.jsr356.server.PathParamArgIdentifier

View File

@ -20,6 +20,11 @@
<artifactId>websocket-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>javax-websocket-client-impl</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-client</artifactId>
@ -30,6 +35,11 @@
<artifactId>websocket-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>javax-websocket-server-impl</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>

View File

@ -0,0 +1,46 @@
//
// ========================================================================
// Copyright (c) 1995-2017 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.tests;
import javax.websocket.CloseReason;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnOpen;
import javax.websocket.Session;
@SuppressWarnings("unused")
public abstract class AbstractJsrTrackingEndpoint extends AbstractTrackingEndpoint<Session>
{
public AbstractJsrTrackingEndpoint(String id)
{
super(id);
}
@OnOpen
public void onOpen(Session session, EndpointConfig config)
{
super.onWSOpen(session);
}
@OnClose
public void onClose(CloseReason closeReason)
{
super.onWSClose(closeReason.getCloseCode().getCode(), closeReason.getReasonPhrase());
}
}

View File

@ -0,0 +1,119 @@
//
// ========================================================================
// Copyright (c) 1995-2017 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.tests;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
public abstract class AbstractTrackingEndpoint<T>
{
public final Logger LOG;
public T session;
public CountDownLatch openLatch = new CountDownLatch(1);
public CountDownLatch closeLatch = new CountDownLatch(1);
public AtomicReference<CloseInfo> closeInfo = new AtomicReference<>();
public AtomicReference<Throwable> error = new AtomicReference<>();
public AbstractTrackingEndpoint(String id)
{
LOG = Log.getLogger(this.getClass().getName() + "." + id);
}
public void assertCloseInfo(String prefix, int expectedCloseStatusCode, Matcher<String> reasonMatcher) throws InterruptedException
{
CloseInfo close = closeInfo.get();
assertThat(prefix + " close info", close, Matchers.notNullValue());
assertThat(prefix + " received close code", close.getStatusCode(), Matchers.is(expectedCloseStatusCode));
assertThat(prefix + " received close reason", close.getReason(), reasonMatcher);
}
public void assertErrorEvent(String prefix, Matcher<Throwable> throwableMatcher, Matcher<? super String> messageMatcher)
{
assertThat(prefix + " error event type", error.get(), throwableMatcher);
assertThat(prefix + " error event message", error.get().getMessage(), messageMatcher);
}
public void assertNoErrorEvents(String prefix)
{
assertTrue(prefix + " error event should not have occurred", error.get() == null);
}
public void assertNotClosed(String prefix)
{
assertTrue(prefix + " close event should not have occurred", closeLatch.getCount() > 0);
}
public void assertNotOpened(String prefix)
{
assertTrue(prefix + " open event should not have occurred", openLatch.getCount() > 0);
}
public void awaitCloseEvent(String prefix) throws InterruptedException
{
assertTrue(prefix + " onClose event", closeLatch.await(Defaults.CLOSE_EVENT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
public void awaitOpenEvent(String prefix) throws InterruptedException
{
assertTrue(prefix + " onOpen event", openLatch.await(Defaults.OPEN_EVENT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
protected void onWSOpen(T session)
{
this.session = session;
if (LOG.isDebugEnabled())
{
LOG.debug("onWSOpen()");
}
this.openLatch.countDown();
}
protected void onWSClose(int statusCode, String reason)
{
CloseInfo close = new CloseInfo(statusCode, reason);
boolean closeTracked = closeInfo.compareAndSet(null, close);
this.closeLatch.countDown();
assertTrue("Close only happened once", closeTracked);
}
protected void onWSError(Throwable cause)
{
assertThat("Error must have value", cause, notNullValue());
if (error.compareAndSet(null, cause) == false)
{
LOG.warn("onError should only happen once - Original Cause", error.get());
LOG.warn("onError should only happen once - Extra/Excess Cause", cause);
fail("onError should only happen once!");
}
}
}

View File

@ -19,23 +19,14 @@
package org.eclipse.jetty.websocket.tests;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.nio.ByteBuffer;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.io.EndPoint;
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.RemoteEndpoint;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.UpgradeRequest;
@ -43,75 +34,23 @@ import org.eclipse.jetty.websocket.api.UpgradeResponse;
import org.eclipse.jetty.websocket.api.WebSocketFrameListener;
import org.eclipse.jetty.websocket.api.WebSocketListener;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.LogicalConnection;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection;
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
public class TrackingEndpoint implements WebSocketListener, WebSocketFrameListener
public class TrackingEndpoint extends AbstractTrackingEndpoint<WebSocketSession> implements WebSocketListener, WebSocketFrameListener
{
public final Logger LOG;
public CountDownLatch openLatch = new CountDownLatch(1);
public UpgradeRequest openUpgradeRequest;
public UpgradeResponse openUpgradeResponse;
public CountDownLatch closeLatch = new CountDownLatch(1);
public AtomicReference<CloseInfo> closeInfo = new AtomicReference<>();
public AtomicReference<Throwable> error = new AtomicReference<>();
public BlockingQueue<WebSocketFrame> framesQueue = new LinkedBlockingDeque<>();
public BlockingQueue<String> messageQueue = new LinkedBlockingDeque<>();
public BlockingQueue<ByteBuffer> bufferQueue = new LinkedBlockingDeque<>();
public BlockingQueue<WebSocketFrame> framesQueue = new LinkedBlockingDeque<>();
public WebSocketSession session;
public TrackingEndpoint(String id)
{
LOG = Log.getLogger(this.getClass().getName() + "." + id);
}
public void assertCloseInfo(String prefix, int expectedCloseStatusCode, Matcher<String> reasonMatcher) throws InterruptedException
{
CloseInfo close = closeInfo.get();
assertThat(prefix + " close info", close, Matchers.notNullValue());
assertThat(prefix + " received close code", close.getStatusCode(), Matchers.is(expectedCloseStatusCode));
assertThat(prefix + " received close reason", close.getReason(), reasonMatcher);
}
public void assertNotOpened(String prefix)
{
assertTrue(prefix + " open event should not have occurred", openLatch.getCount() > 0);
}
public void assertNotClosed(String prefix)
{
assertTrue(prefix + " close event should not have occurred", closeLatch.getCount() > 0);
}
public void assertNoErrorEvents(String prefix)
{
assertTrue(prefix + " error event should not have occurred", error.get() == null);
}
public void assertErrorEvent(String prefix, Matcher<Throwable> throwableMatcher, Matcher<? super String> messageMatcher)
{
assertThat(prefix + " error event type", error.get(), throwableMatcher);
assertThat(prefix + " error event message", error.get().getMessage(), messageMatcher);
}
public void awaitOpenEvent(String prefix) throws InterruptedException
{
assertTrue(prefix + " onOpen event", openLatch.await(Defaults.OPEN_EVENT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
public void awaitCloseEvent(String prefix) throws InterruptedException
{
assertTrue(prefix + " onClose event", closeLatch.await(Defaults.CLOSE_EVENT_TIMEOUT_MS, TimeUnit.MILLISECONDS));
super(id);
}
public void close(int statusCode, String reason)
@ -138,35 +77,22 @@ public class TrackingEndpoint implements WebSocketListener, WebSocketFrameListen
@Override
public void onWebSocketClose(int statusCode, String reason)
{
this.closeLatch.countDown();
CloseInfo close = new CloseInfo(statusCode, reason);
assertThat("Close only happened once", closeInfo.compareAndSet(null, close), is(true));
super.onWSClose(statusCode, reason);
}
@Override
public void onWebSocketConnect(Session session)
{
assertThat("Session type", session, instanceOf(WebSocketSession.class));
this.session = (WebSocketSession) session;
super.onWSOpen((WebSocketSession) session);
this.openUpgradeRequest = session.getUpgradeRequest();
this.openUpgradeResponse = session.getUpgradeResponse();
if (LOG.isDebugEnabled())
{
LOG.debug("onWebSocketConnect()");
}
this.openLatch.countDown();
}
@Override
public void onWebSocketError(Throwable cause)
{
assertThat("Error must have value", cause, notNullValue());
if (error.compareAndSet(null, cause) == false)
{
LOG.warn("onError should only happen once - Original Cause", error.get());
LOG.warn("onError should only happen once - Extra/Excess Cause", cause);
fail("onError should only happen once!");
}
super.onWSError(cause);
}
@Override

View File

@ -0,0 +1,202 @@
//
// ========================================================================
// Copyright (c) 1995-2017 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.tests.client.jsr356;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import javax.websocket.ClientEndpoint;
import javax.websocket.ContainerProvider;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
import org.eclipse.jetty.websocket.api.BatchMode;
import org.eclipse.jetty.websocket.api.WebSocketBehavior;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
import org.eclipse.jetty.websocket.tests.AbstractJsrTrackingEndpoint;
import org.eclipse.jetty.websocket.tests.UntrustedWSEndpoint;
import org.eclipse.jetty.websocket.tests.UntrustedWSServer;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
public class DecoderReaderManySmallTest
{
public static class EventId
{
public int eventId;
}
public static class EventIdDecoder implements Decoder.TextStream<EventId>
{
@Override
public void init(EndpointConfig config)
{
}
@Override
public void destroy()
{
}
@Override
public EventId decode(Reader reader) throws DecodeException, IOException
{
EventId id = new EventId();
try (BufferedReader buf = new BufferedReader(reader))
{
String line;
while ((line = buf.readLine()) != null)
{
id.eventId = Integer.parseInt(line);
}
}
return id;
}
}
@ClientEndpoint(decoders = EventIdDecoder.class, subprotocols = "eventids")
public static class EventIdSocket extends AbstractJsrTrackingEndpoint
{
public BlockingQueue<EventId> messageQueue = new LinkedBlockingDeque<>();
public EventIdSocket(String id)
{
super(id);
}
@SuppressWarnings("unused")
@OnMessage
public void onMessage(EventId msg)
{
messageQueue.offer(msg);
}
}
public static class EventIdServerCreator implements WebSocketCreator
{
@Override
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
{
EventIdServerEndpoint endpoint = new EventIdServerEndpoint(WebSocketBehavior.SERVER.name());
resp.setAcceptedSubProtocol("eventids");
return endpoint;
}
}
private static class EventIdServerEndpoint extends UntrustedWSEndpoint
{
public EventIdServerEndpoint(String id)
{
super(id);
}
@Override
public void onWebSocketText(String text)
{
super.onWebSocketText(text);
if (text.startsWith("seq|"))
{
String parts[] = text.split("\\|");
int from = Integer.parseInt(parts[1]);
int to = Integer.parseInt(parts[2]);
session.getRemote().setBatchMode(BatchMode.OFF);
for (int id = from; id < to; id++)
{
session.getRemote().sendStringByFuture(Integer.toString(id));
}
}
}
}
@Rule
public TestName testname = new TestName();
private UntrustedWSServer server;
private WebSocketContainer client;
@Before
public void initClient()
{
client = ContainerProvider.getWebSocketContainer();
}
@Before
public void startServer() throws Exception
{
server = new UntrustedWSServer();
server.start();
}
@After
public void stopServer() throws Exception
{
server.stop();
}
@Test
public void testManyIds() throws Exception
{
server.registerWebSocket("/eventids", new EventIdServerCreator());
URI wsUri = server.getWsUri().resolve("/eventids");
EventIdSocket clientSocket = new EventIdSocket(testname.getMethodName());
Session clientSession = client.connectToServer(clientSocket, wsUri);
final int from = 1000;
final int to = 2000;
clientSession.getAsyncRemote().sendText("seq|" + from + "|" + to);
// collect seen ids
List<Integer> seen = new ArrayList<>();
for (int i = from; i < to; i++)
{
// validate that ids don't repeat.
EventId receivedId = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
Assert.assertFalse("Already saw ID: " + receivedId.eventId, seen.contains(receivedId.eventId));
seen.add(receivedId.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));
}
}
}

View File

@ -0,0 +1,48 @@
//
// ========================================================================
// Copyright (c) 1995-2017 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.tests.client.jsr356;
import java.util.ArrayList;
import java.util.List;
public class Quotes
{
private String author;
private List<String> quotes = new ArrayList<>();
public void addQuote(String quote)
{
quotes.add(quote);
}
public String getAuthor()
{
return author;
}
public List<String> getQuotes()
{
return quotes;
}
public void setAuthor(String author)
{
this.author = author;
}
}

View File

@ -0,0 +1,73 @@
//
// ========================================================================
// Copyright (c) 1995-2017 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.tests.client.jsr356;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class QuotesDecoder implements Decoder.TextStream<Quotes>
{
private static final Logger LOG = Log.getLogger(QuotesDecoder.class);
@Override
public void init(EndpointConfig config)
{
// TODO: verify init called
}
@Override
public void destroy()
{
// TODO: verify destroy called
}
@Override
public Quotes decode(Reader reader) throws DecodeException, IOException
{
Quotes quotes = new Quotes();
try (BufferedReader buf = new BufferedReader(reader))
{
LOG.debug("decode() begin");
String line;
while ((line = buf.readLine()) != null)
{
LOG.debug("decode() line = {}", line);
switch (line.charAt(0))
{
case 'a':
quotes.setAuthor(line.substring(2));
break;
case 'q':
quotes.addQuote(line.substring(2));
break;
}
}
LOG.debug("decode() complete");
}
return quotes;
}
}

View File

@ -0,0 +1,215 @@
//
// ========================================================================
// Copyright (c) 1995-2017 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.tests.client.jsr356;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import javax.websocket.ClientEndpoint;
import javax.websocket.ContainerProvider;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
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.WebSocketBehavior;
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.servlet.ServletUpgradeRequest;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
import org.eclipse.jetty.websocket.tests.AbstractJsrTrackingEndpoint;
import org.eclipse.jetty.websocket.tests.UntrustedWSConnection;
import org.eclipse.jetty.websocket.tests.UntrustedWSEndpoint;
import org.eclipse.jetty.websocket.tests.UntrustedWSServer;
import org.eclipse.jetty.websocket.tests.UntrustedWSSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
public class QuotesDecoderTest
{
@ClientEndpoint(decoders = QuotesDecoder.class, subprotocols = "quotes")
public static class QuotesSocket extends AbstractJsrTrackingEndpoint
{
public BlockingQueue<Quotes> messageQueue = new LinkedBlockingDeque<>();
public QuotesSocket(String id)
{
super(id);
}
@SuppressWarnings("unused")
@OnMessage
public void onMessage(Quotes quote)
{
System.err.printf("QuotesSocket.onMessage(%s)%n",quote);
messageQueue.offer(quote);
}
}
public static class QuoteServingCreator implements WebSocketCreator
{
@Override
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
{
QuoterServerEndpoint endpoint = new QuoterServerEndpoint(WebSocketBehavior.SERVER.name());
resp.setAcceptedSubProtocol("quotes");
return endpoint;
}
}
public static class QuoterServerEndpoint extends UntrustedWSEndpoint
{
public QuoterServerEndpoint(String id)
{
super(id);
}
@Override
public void onWebSocketText(String filename)
{
super.onWebSocketText(filename);
try
{
UntrustedWSSession untrustedWSSession = (UntrustedWSSession) session;
UntrustedWSConnection untrustedWSConnection = untrustedWSSession.getUntrustedConnection();
writeQuotes(filename, untrustedWSConnection);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void writeQuotes(String filename, UntrustedWSConnection connection) throws Exception
{
// read file
File qfile = MavenTestingUtils.getTestResourceFile(filename);
List<String> 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"));
connection.write(frame);
}
}
}
private static final Logger LOG = Log.getLogger(QuotesDecoderTest.class);
@Rule
public TestName testname = new TestName();
private UntrustedWSServer server;
private WebSocketContainer client;
@Before
public void initClient()
{
client = ContainerProvider.getWebSocketContainer();
}
@Before
public void startServer() throws Exception
{
server = new UntrustedWSServer();
server.start();
}
@After
public void stopServer() throws Exception
{
server.stop();
}
@Test
public void testSingleQuotes() throws Exception
{
server.registerWebSocket("/quoter", new QuoteServingCreator());
URI wsUri = server.getWsUri().resolve("/quoter");
QuotesSocket clientSocket = new QuotesSocket(testname.getMethodName());
Session clientSession = client.connectToServer(clientSocket, wsUri);
clientSession.getAsyncRemote().sendText("quotes-ben.txt");
Quotes quotes = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat("Quotes Author", quotes.getAuthor(), is("Benjamin Franklin"));
assertThat("Quotes Count", quotes.getQuotes().size(), is(3));
}
@Test
public void testTwoQuotes() throws Exception
{
server.registerWebSocket("/quoter", new QuoteServingCreator());
URI wsUri = server.getWsUri().resolve("/quoter");
QuotesSocket clientSocket = new QuotesSocket(testname.getMethodName());
Session clientSession = client.connectToServer(clientSocket, wsUri);
clientSession.getAsyncRemote().sendText("quotes-ben.txt");
clientSession.getAsyncRemote().sendText("quotes-twain.txt");
Quotes quotes;
quotes = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat("Quotes Author", quotes.getAuthor(), is("Benjamin Franklin"));
assertThat("Quotes Count", quotes.getQuotes().size(), is(3));
quotes = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat("Quotes Author", quotes.getAuthor(), is("Mark Twain"));
assertThat("Quotes Count", quotes.getQuotes().size(), is(4));
}
}

View File

@ -0,0 +1,52 @@
//
// ========================================================================
// Copyright (c) 1995-2017 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.tests.client.jsr356;
import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
public class QuotesEncoder implements Encoder.Text<Quotes>
{
@Override
public void destroy()
{
// TODO: verify destroy called
}
@Override
public String encode(Quotes q) throws EncodeException
{
StringBuilder buf = new StringBuilder();
buf.append("Author: ").append(q.getAuthor());
buf.append(System.lineSeparator());
for (String quote : q.getQuotes())
{
buf.append("Quote: ").append(quote);
buf.append(System.lineSeparator());
}
return buf.toString();
}
@Override
public void init(EndpointConfig config)
{
// TODO: verify init called
}
}

View File

@ -0,0 +1,197 @@
//
// ========================================================================
// Copyright (c) 1995-2017 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.tests.client.jsr356;
import static org.hamcrest.Matchers.containsString;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import javax.websocket.ClientEndpoint;
import javax.websocket.ContainerProvider;
import javax.websocket.EncodeException;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.websocket.tests.AbstractJsrTrackingEndpoint;
import org.eclipse.jetty.websocket.tests.UntrustedWSServer;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
public class QuotesEncoderTest
{
@ClientEndpoint(encoders = QuotesEncoder.class, subprotocols = "echo")
public static class QuotesSocket extends AbstractJsrTrackingEndpoint
{
public BlockingQueue<String> messageQueue = new LinkedBlockingDeque<>();
public QuotesSocket(String id)
{
super(id);
}
@SuppressWarnings("unused")
@OnMessage
public void onMessage(String message)
{
messageQueue.offer(message);
}
public void write(Quotes quotes) throws IOException, EncodeException
{
if (LOG.isDebugEnabled())
LOG.debug("Writing Quotes: {}", quotes);
this.session.getBasicRemote().sendObject(quotes);
}
}
@Rule
public TestName testname = new TestName();
private UntrustedWSServer server;
private WebSocketContainer client;
@Before
public void initClient()
{
client = ContainerProvider.getWebSocketContainer();
}
@Before
public void startServer() throws Exception
{
server = new UntrustedWSServer();
server.start();
}
@After
public void stopServer() throws Exception
{
server.stop();
}
private void assertReceivedQuotes(String result, Quotes quotes)
{
Assert.assertThat("Quote Author", result, containsString("Author: " + quotes.getAuthor()));
for (String quote : quotes.getQuotes())
{
Assert.assertThat("Quote", result, containsString("Quote: " + quote));
}
}
@SuppressWarnings("Duplicates")
private Quotes getQuotes(String filename) throws IOException
{
Quotes quotes = new Quotes();
// read file
File qfile = MavenTestingUtils.getTestResourceFile(filename);
try (FileReader reader = new FileReader(qfile); BufferedReader buf = new BufferedReader(reader))
{
String line;
while ((line = buf.readLine()) != null)
{
switch (line.charAt(0))
{
case 'a':
quotes.setAuthor(line.substring(2));
break;
case 'q':
quotes.addQuote(line.substring(2));
break;
}
}
}
return quotes;
}
private void close(Session session) throws IOException
{
if (session != null)
{
session.close();
}
}
@Test
public void testSingleQuotes() throws Exception
{
URI wsUri = server.getUntrustedWsUri(this.getClass(), testname);
QuotesSocket quoter = new QuotesSocket(testname.getMethodName());
Session session = null;
try
{
session = client.connectToServer(quoter, wsUri);
Quotes ben = getQuotes("quotes-ben.txt");
quoter.write(ben);
String incomingMessage = quoter.messageQueue.poll(5, TimeUnit.SECONDS);
assertReceivedQuotes(incomingMessage, ben);
}
finally
{
close(session);
}
}
@Test
public void testTwoQuotes() throws Exception
{
URI wsUri = server.getUntrustedWsUri(this.getClass(), testname);
QuotesSocket quoter = new QuotesSocket(testname.getMethodName());
Session session = null;
try
{
session = client.connectToServer(quoter, wsUri);
Quotes ben = getQuotes("quotes-ben.txt");
Quotes twain = getQuotes("quotes-twain.txt");
quoter.write(ben);
quoter.write(twain);
String incomingQuote;
incomingQuote = quoter.messageQueue.poll(5, TimeUnit.SECONDS);
assertReceivedQuotes(incomingQuote, ben);
incomingQuote = quoter.messageQueue.poll(5, TimeUnit.SECONDS);
assertReceivedQuotes(incomingQuote, twain);
}
finally
{
close(session);
}
}
}

View File

@ -16,10 +16,10 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356.server;
package org.eclipse.jetty.websocket.tests.server.jsr356;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import java.io.PrintWriter;
@ -35,6 +35,7 @@ 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.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@ -54,29 +55,34 @@ 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.extensions.ExtensionConfig;
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.XBlockheadClient;
import org.eclipse.jetty.websocket.common.test.HttpResponse;
import org.eclipse.jetty.websocket.common.test.IBlockheadClient;
import org.eclipse.jetty.websocket.api.util.WSURI;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.eclipse.jetty.websocket.jsr356.server.JsrCreator;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.eclipse.jetty.websocket.tests.Defaults;
import org.eclipse.jetty.websocket.tests.TrackingEndpoint;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
public class ConfiguratorTest
{
private static final Logger LOG = Log.getLogger(ConfiguratorTest.class);
public static class EmptyConfigurator extends ServerEndpointConfig.Configurator
{
}
@ServerEndpoint(value = "/empty", configurator = EmptyConfigurator.class)
public static class EmptySocket
{
@ -86,7 +92,7 @@ public class ConfiguratorTest
return message;
}
}
public static class NoExtensionsConfigurator extends ServerEndpointConfig.Configurator
{
@Override
@ -95,7 +101,7 @@ public class ConfiguratorTest
return Collections.emptyList();
}
}
@ServerEndpoint(value = "/no-extensions", configurator = NoExtensionsConfigurator.class)
public static class NoExtensionsSocket
{
@ -115,7 +121,7 @@ public class ConfiguratorTest
}
}
}
public static class CaptureHeadersConfigurator extends ServerEndpointConfig.Configurator
{
@Override
@ -125,7 +131,7 @@ public class ConfiguratorTest
sec.getUserProperties().put("request-headers", request.getHeaders());
}
}
@ServerEndpoint(value = "/capture-request-headers", configurator = CaptureHeadersConfigurator.class)
public static class CaptureHeadersSocket
{
@ -133,7 +139,7 @@ public class ConfiguratorTest
public String getHeaders(Session session, String headerKey)
{
StringBuilder response = new StringBuilder();
response.append("Request Header [").append(headerKey).append("]: ");
@SuppressWarnings("unchecked")
Map<String, List<String>> headers = (Map<String, List<String>>) session.getUserProperties().get("request-headers");
@ -153,11 +159,11 @@ public class ConfiguratorTest
response.append(QuoteUtil.join(values, ","));
}
}
return response.toString();
}
}
public static class ProtocolsConfigurator extends ServerEndpointConfig.Configurator
{
public static AtomicReference<String> seenProtocols = new AtomicReference<>();
@ -176,7 +182,7 @@ public class ConfiguratorTest
return super.getNegotiatedSubprotocol(supported, requested);
}
}
@ServerEndpoint(value = "/protocols", configurator = ProtocolsConfigurator.class)
public static class ProtocolsSocket
{
@ -268,17 +274,17 @@ public class ConfiguratorTest
appendPropValue(session, response, "found.remote");
return response.toString();
}
private void appendPropValue(Session session, StringBuilder response, String key)
{
InetSocketAddress value = (InetSocketAddress) session.getUserProperties().get(key);
response.append("[").append(key).append("] = ");
response.append(toSafeAddr(value));
response.append(System.lineSeparator());
}
}
public static class SelectedProtocolConfigurator extends ServerEndpointConfig.Configurator
{
@Override
@ -291,11 +297,11 @@ public class ConfiguratorTest
config.getUserProperties().put("selected-subprotocol", protocol);
}
}
public static class GmtTimeDecoder implements Decoder.Text<Calendar>
{
private TimeZone TZ;
@Override
public Calendar decode(String s) throws DecodeException
{
@ -316,39 +322,39 @@ public class ConfiguratorTest
throw new DecodeException(s, "Unable to decode Time", e);
}
}
@Override
public void init(EndpointConfig config)
{
TZ = TimeZone.getTimeZone("GMT+0");
}
@Override
public void destroy()
{
}
@Override
public boolean willDecode(String s)
{
return true;
}
}
@ServerEndpoint(value = "/timedecoder",
subprotocols = { "time", "gmt" },
subprotocols = {"time", "gmt"},
configurator = SelectedProtocolConfigurator.class,
decoders = {GmtTimeDecoder.class})
public static class TimeDecoderSocket
{
private TimeZone TZ = TimeZone.getTimeZone("GMT+0");
@OnMessage
public String onMessage(Calendar cal)
{
return String.format("cal=%s", newDateFormat().format(cal.getTime()));
}
private SimpleDateFormat newDateFormat()
{
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss Z", Locale.ENGLISH);
@ -359,7 +365,7 @@ public class ConfiguratorTest
private static Server server;
private static URI baseServerUri;
@BeforeClass
public static void startServer() throws Exception
{
@ -367,11 +373,11 @@ public class ConfiguratorTest
ServerConnector connector = new ServerConnector(server);
connector.setPort(0);
server.addConnector(connector);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
container.addEndpoint(CaptureHeadersSocket.class);
container.addEndpoint(EmptySocket.class);
@ -380,19 +386,13 @@ public class ConfiguratorTest
container.addEndpoint(UniqueUserPropsSocket.class);
container.addEndpoint(AddressSocket.class);
container.addEndpoint(TimeDecoderSocket.class);
server.start();
String host = connector.getHost();
if (host == null)
{
host = "localhost";
}
int port = connector.getLocalPort();
baseServerUri = new URI(String.format("ws://%s:%d/", host, port));
baseServerUri = WSURI.toWebsocket(server.getURI()).resolve("/");
if (LOG.isDebugEnabled())
LOG.debug("Server started on {}", baseServerUri);
}
public static String toSafeAddr(InetSocketAddress addr)
{
if (addr == null)
@ -401,250 +401,273 @@ public class ConfiguratorTest
}
return String.format("%s:%d", addr.getAddress().getHostAddress(), addr.getPort());
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
}
@Rule
public TestName testname = new TestName();
private WebSocketClient client;
@Before
public void startClient() throws Exception
{
client = new WebSocketClient();
client.start();
}
@After
public void stopClient() throws Exception
{
client.stop();
}
@Test
public void testEmptyConfigurator() throws Exception
{
URI uri = baseServerUri.resolve("/empty");
try (IBlockheadClient client = new XBlockheadClient(uri))
{
client.addExtensions("identity");
client.connect();
client.sendStandardRequest();
HttpResponse response = client.readResponseHeader();
Assert.assertThat("response.extensions", response.getExtensionsHeader(), is("identity"));
}
URI wsUri = baseServerUri.resolve("/empty");
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
upgradeRequest.addExtensions("identity");
Future<org.eclipse.jetty.websocket.api.Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
org.eclipse.jetty.websocket.api.Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
List<ExtensionConfig> negotiatedExtensions = clientSession.getUpgradeResponse().getExtensions();
assertThat("UpgradeResponse.extensions", negotiatedExtensions, notNullValue());
assertThat("UpgradeResponse.extensions.size", negotiatedExtensions.size(), is(1));
assertThat("UpgradeResponse.extensions[0]", negotiatedExtensions.get(0).toString(), is("identity"));
clientSession.close();
}
@Test
public void testNoExtensionsConfigurator() throws Exception
{
URI uri = baseServerUri.resolve("/no-extensions");
try (IBlockheadClient client = new XBlockheadClient(uri))
{
client.addExtensions("identity");
client.connect();
client.sendStandardRequest();
HttpResponse response = client.expectUpgradeResponse();
assertThat("response.extensions", response.getExtensionsHeader(), nullValue());
client.write(new TextFrame().setPayload("NegoExts"));
EventQueue<WebSocketFrame> frames = client.readFrames(1, 1, TimeUnit.SECONDS);
WebSocketFrame frame = frames.poll();
assertThat("Frame Response", frame.getPayloadAsUTF8(), is("negotiatedExtensions=[]"));
}
URI wsUri = baseServerUri.resolve("/no-extensions");
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
upgradeRequest.addExtensions("identity");
Future<org.eclipse.jetty.websocket.api.Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
org.eclipse.jetty.websocket.api.Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
clientSession.getRemote().sendString("NegoExts");
String incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat("Incoming Message", incomingMessage, is("negotiatedExtensions=[]"));
clientSession.close();
}
@Test
public void testCaptureRequestHeadersConfigurator() throws Exception
{
URI uri = baseServerUri.resolve("/capture-request-headers");
try (IBlockheadClient client = new XBlockheadClient(uri))
{
client.addHeader("X-Dummy: Bogus\r\n");
client.connect();
client.sendStandardRequest();
client.expectUpgradeResponse();
client.write(new TextFrame().setPayload("X-Dummy"));
EventQueue<WebSocketFrame> frames = client.readFrames(1, 1, TimeUnit.SECONDS);
WebSocketFrame frame = frames.poll();
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Request Header [X-Dummy]: \"Bogus\""));
}
URI wsUri = baseServerUri.resolve("/capture-request-headers");
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
upgradeRequest.setHeader("X-Dummy", "Bogus");
Future<org.eclipse.jetty.websocket.api.Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
org.eclipse.jetty.websocket.api.Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
clientSession.getRemote().sendString("X-Dummy");
String incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat("Incoming Message", incomingMessage, is("Request Header [X-Dummy]: \"Bogus\""));
clientSession.close();
}
@Test
public void testUniqueUserPropsConfigurator() throws Exception
{
URI uri = baseServerUri.resolve("/unique-user-props");
// First request
try (IBlockheadClient client = new XBlockheadClient(uri))
{
client.connect();
client.sendStandardRequest();
client.expectUpgradeResponse();
client.write(new TextFrame().setPayload("apple"));
EventQueue<WebSocketFrame> frames = client.readFrames(1, 1, TimeUnit.SECONDS);
WebSocketFrame frame = frames.poll();
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested User Property: [apple] = \"fruit from tree\""));
}
URI wsUri = baseServerUri.resolve("/unique-user-props");
// First Request
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
Future<org.eclipse.jetty.websocket.api.Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
org.eclipse.jetty.websocket.api.Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
clientSession.getRemote().sendString("apple"); // first request has this UserProperty
String incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat("Incoming Message", incomingMessage, is("Requested User Property: [apple] = \"fruit from tree\""));
clientSession.close();
// Second request
try (IBlockheadClient client = new XBlockheadClient(uri))
{
client.connect();
client.sendStandardRequest();
client.expectUpgradeResponse();
client.write(new TextFrame().setPayload("apple"));
client.write(new TextFrame().setPayload("blueberry"));
EventQueue<WebSocketFrame> frames = client.readFrames(2, 1, TimeUnit.SECONDS);
WebSocketFrame frame = frames.poll();
// should have no value
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested User Property: [apple] = <null>"));
frame = frames.poll();
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested User Property: [blueberry] = \"fruit from bush\""));
}
clientSocket = new TrackingEndpoint(testname.getMethodName());
upgradeRequest = new ClientUpgradeRequest();
clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
clientSession.getRemote().sendString("apple"); // as this is second request, this should be null
clientSession.getRemote().sendString("blueberry"); // second request has this UserProperty
incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat("Incoming Message", incomingMessage, is("Requested User Property: [apple] = <null>"));
incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat("Incoming Message", incomingMessage, is("Requested User Property: [blueberry] = \"fruit from bush\""));
clientSession.close();
}
@Test
public void testUserPropsAddress() throws Exception
{
URI uri = baseServerUri.resolve("/addr");
// First request
try (IBlockheadClient client = new XBlockheadClient(uri))
{
client.connect();
client.sendStandardRequest();
client.expectUpgradeResponse();
InetSocketAddress expectedLocal = client.getLocalSocketAddress();
InetSocketAddress expectedRemote = client.getRemoteSocketAddress();
client.write(new TextFrame().setPayload("addr"));
EventQueue<WebSocketFrame> frames = client.readFrames(1, 1, TimeUnit.SECONDS);
WebSocketFrame frame = frames.poll();
StringWriter expected = new StringWriter();
PrintWriter out = new PrintWriter(expected);
// local <-> remote are opposite on server (duh)
out.printf("[javax.websocket.endpoint.localAddress] = %s%n", toSafeAddr(expectedRemote));
out.printf("[javax.websocket.endpoint.remoteAddress] = %s%n", toSafeAddr(expectedLocal));
out.printf("[found.local] = %s%n", toSafeAddr(expectedRemote));
out.printf("[found.remote] = %s%n", toSafeAddr(expectedLocal));
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is(expected.toString()));
}
URI wsUri = baseServerUri.resolve("/addr");
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
Future<org.eclipse.jetty.websocket.api.Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
org.eclipse.jetty.websocket.api.Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
InetSocketAddress expectedLocal = clientSession.getLocalAddress();
InetSocketAddress expectedRemote = clientSession.getRemoteAddress();
clientSession.getRemote().sendString("addr");
String incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
StringWriter expected = new StringWriter();
PrintWriter out = new PrintWriter(expected);
// local <-> remote are opposite on server (duh)
out.printf("[javax.websocket.endpoint.localAddress] = %s%n", toSafeAddr(expectedRemote));
out.printf("[javax.websocket.endpoint.remoteAddress] = %s%n", toSafeAddr(expectedLocal));
out.printf("[found.local] = %s%n", toSafeAddr(expectedRemote));
out.printf("[found.remote] = %s%n", toSafeAddr(expectedLocal));
assertThat("Frame Response", incomingMessage, is(expected.toString()));
clientSession.close();
}
/**
* Test of Sec-WebSocket-Protocol, as seen in RFC-6455, 1 protocol
*
* @throws Exception on test failure
*/
@Test
public void testProtocol_Single() throws Exception
{
URI uri = baseServerUri.resolve("/protocols");
URI wsUri = baseServerUri.resolve("/protocols");
ProtocolsConfigurator.seenProtocols.set(null);
try (IBlockheadClient client = new XBlockheadClient(uri))
{
client.addHeader("Sec-WebSocket-Protocol: echo\r\n");
client.connect();
client.sendStandardRequest();
client.expectUpgradeResponse();
client.write(new TextFrame().setPayload("getProtocols"));
EventQueue<WebSocketFrame> frames = client.readFrames(1, 1, TimeUnit.SECONDS);
WebSocketFrame frame = frames.poll();
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\"]"));
}
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
upgradeRequest.setSubProtocols("echo");
Future<org.eclipse.jetty.websocket.api.Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
org.eclipse.jetty.websocket.api.Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
clientSession.getRemote().sendString("getProtocols");
String incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat("Incoming message", incomingMessage, is("Requested Protocols: [\"echo\"]"));
clientSession.close();
}
/**
* Test of Sec-WebSocket-Protocol, as seen in RFC-6455, 3 protocols
*
* @throws Exception on test failure
*/
@Test
public void testProtocol_Triple() throws Exception
{
URI uri = baseServerUri.resolve("/protocols");
URI wsUri = baseServerUri.resolve("/protocols");
ProtocolsConfigurator.seenProtocols.set(null);
try (IBlockheadClient client = new XBlockheadClient(uri))
{
client.addHeader("Sec-WebSocket-Protocol: echo, chat, status\r\n");
client.connect();
client.sendStandardRequest();
client.expectUpgradeResponse();
client.write(new TextFrame().setPayload("getProtocols"));
EventQueue<WebSocketFrame> frames = client.readFrames(1, 1, TimeUnit.SECONDS);
WebSocketFrame frame = frames.poll();
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]"));
}
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
upgradeRequest.setSubProtocols("echo", "chat", "status");
Future<org.eclipse.jetty.websocket.api.Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
org.eclipse.jetty.websocket.api.Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
clientSession.getRemote().sendString("getProtocols");
String incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat("Incoming message", incomingMessage, is("Requested Protocols: [\"echo\",\"chat\",\"status\"]"));
clientSession.close();
}
/**
* Test of Sec-WebSocket-Protocol, using all lowercase header
*
* @throws Exception on test failure
*/
@Test
public void testProtocol_LowercaseHeader() throws Exception
{
URI uri = baseServerUri.resolve("/protocols");
URI wsUri = baseServerUri.resolve("/protocols");
ProtocolsConfigurator.seenProtocols.set(null);
try (IBlockheadClient client = new XBlockheadClient(uri))
{
client.addHeader("sec-websocket-protocol: echo, chat, status\r\n");
client.connect();
client.sendStandardRequest();
client.expectUpgradeResponse();
client.write(new TextFrame().setPayload("getProtocols"));
EventQueue<WebSocketFrame> frames = client.readFrames(1, 1, TimeUnit.SECONDS);
WebSocketFrame frame = frames.poll();
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]"));
}
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
upgradeRequest.setHeader("sec-websocket-protocol", "echo, chat, status");
Future<org.eclipse.jetty.websocket.api.Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
org.eclipse.jetty.websocket.api.Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
clientSession.getRemote().sendString("getProtocols");
String incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat("Incoming message", incomingMessage, is("Requested Protocols: [\"echo\",\"chat\",\"status\"]"));
clientSession.close();
}
/**
* Test of Sec-WebSocket-Protocol, using non-spec case header
*
* @throws Exception on test failure
*/
@Test
public void testProtocol_AltHeaderCase() throws Exception
{
URI uri = baseServerUri.resolve("/protocols");
URI wsUri = baseServerUri.resolve("/protocols");
ProtocolsConfigurator.seenProtocols.set(null);
try (IBlockheadClient client = new XBlockheadClient(uri))
{
client.addHeader("Sec-Websocket-Protocol: echo, chat, status\r\n");
client.connect();
client.sendStandardRequest();
client.expectUpgradeResponse();
client.write(new TextFrame().setPayload("getProtocols"));
EventQueue<WebSocketFrame> frames = client.readFrames(1, 1, TimeUnit.SECONDS);
WebSocketFrame frame = frames.poll();
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("Requested Protocols: [\"echo\",\"chat\",\"status\"]"));
}
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
// header name is not to spec (case wise)
upgradeRequest.setHeader("Sec-Websocket-Protocol", "echo, chat, status");
Future<org.eclipse.jetty.websocket.api.Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
org.eclipse.jetty.websocket.api.Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
clientSession.getRemote().sendString("getProtocols");
String incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat("Incoming message", incomingMessage, is("Requested Protocols: [\"echo\",\"chat\",\"status\"]"));
clientSession.close();
}
/**
* Test of Sec-WebSocket-Protocol, using non-spec case header
*/
@Test
public void testDecoderWithProtocol() throws Exception
{
URI uri = baseServerUri.resolve("/timedecoder");
try (XBlockheadClient client = new XBlockheadClient(uri))
{
client.addHeader("Sec-Websocket-Protocol: gmt\r\n");
client.connect();
client.sendStandardRequest();
client.expectUpgradeResponse();
client.write(new TextFrame().setPayload("2016-06-20T14:27:44"));
EventQueue<WebSocketFrame> frames = client.readFrames(1, 1, TimeUnit.SECONDS);
WebSocketFrame frame = frames.poll();
Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is("cal=2016.06.20 AD at 14:27:44 +0000"));
}
URI wsUri = baseServerUri.resolve("/timedecoder");
TrackingEndpoint clientSocket = new TrackingEndpoint(testname.getMethodName());
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
upgradeRequest.setSubProtocols("gmt");
Future<org.eclipse.jetty.websocket.api.Session> clientConnectFuture = client.connect(clientSocket, wsUri, upgradeRequest);
org.eclipse.jetty.websocket.api.Session clientSession = clientConnectFuture.get(Defaults.CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
clientSession.getRemote().sendString("2016-06-20T14:27:44");
String incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
assertThat("Incoming message", incomingMessage, is("cal=2016.06.20 AD at 14:27:44 +0000"));
clientSession.close();
}
}

View File

@ -26,6 +26,10 @@ org.eclipse.jetty.LEVEL=WARN
# org.eclipse.jetty.websocket.LEVEL=DEBUG
# org.eclipse.jetty.websocket.LEVEL=INFO
# org.eclipse.jetty.websocket.tests.LEVEL=DEBUG
# org.eclipse.jetty.websocket.tests.client.LEVEL=DEBUG
# org.eclipse.jetty.websocket.tests.client.jsr356.LEVEL=DEBUG
# org.eclipse.jetty.websocket.tests.server.LEVEL=DEBUG
# org.eclipse.jetty.websocket.tests.server.jsr356.LEVEL=DEBUG
# org.eclipse.jetty.websocket.common.io.LEVEL=DEBUG
# org.eclipse.jetty.websocket.server.ab.LEVEL=DEBUG
# org.eclipse.jetty.websocket.common.WebSocketSession.LEVEL=DEBUG
@ -36,17 +40,5 @@ org.eclipse.jetty.LEVEL=WARN
# org.eclipse.jetty.websocket.server.helper.LEVEL=DEBUG
org.eclipse.jetty.websocket.common.CompletionCallback.LEVEL=ALL
# org.eclipse.jetty.websocket.client.io.ConnectPromise.LEVEL=DEBUG
# org.eclipse.jetty.websocket.common.WebSocketSession_OPEN.LEVEL=DEBUG
# org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection_OPEN.LEVEL=DEBUG
### Show state changes on BrowserDebugTool
# -- LEAVE THIS AT DEBUG LEVEL --
org.eclipse.jetty.websocket.server.browser.LEVEL=DEBUG
### Disabling intentional error out of RFCSocket
org.eclipse.jetty.websocket.server.helper.RFCSocket.LEVEL=OFF
### Hiding Stack Traces from various test cases
org.eclipse.jetty.websocket.tests.server.ABSocket.STACKS=OFF
org.eclipse.jetty.websocket.server.WebSocketCloseTest$FastFailSocket.STACKS=OFF

View File

@ -0,0 +1,4 @@
a|Benjamin Franklin
q|There never was a good war or a bad peace.
q|We must, indeed, all hang together, or assuredly we shall all hang separately.
q|Our new Constitution is now established, and has an appearance that promises permanency; but in this world nothing can be said to be certain, except death and taxes.

View File

@ -0,0 +1,5 @@
a|Mark Twain
q|He is now fast rising from affluence to poverty.
q|A baby is an inestimable blessing and bother.
q|As I slowly grow wise I briskly grow cautious.
q|A circle is a round straight line with a hole in the middle.