Issue #207 - More test fixes

# Conflicts:
#	jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/BinaryStreamTest.java
#	jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/TextStreamTest.java
This commit is contained in:
Joakim Erdfelt 2017-05-03 16:59:54 -07:00
parent 4a4069d0c2
commit 79f30041a1
103 changed files with 4431 additions and 3681 deletions

View File

@ -125,6 +125,7 @@ public class JsrSessionTest
// Whole Message
session.addMessageHandler(String.class, (msg) -> received.add(msg));
session.connect();
session.open();
FrameCallback callback = new FrameCallback.Adapter();
@ -155,7 +156,8 @@ public class JsrSessionTest
copy.flip();
received.add(new Object[]{copy, isLast});
});
session.connect();
session.open();
FrameCallback callback = new FrameCallback.Adapter();

View File

@ -34,8 +34,8 @@ import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;
import org.eclipse.jetty.toolchain.test.Hex;
import org.eclipse.jetty.websocket.api.InvalidWebSocketException;
import org.eclipse.jetty.websocket.common.util.Hex;
import org.eclipse.jetty.websocket.jsr356.client.EmptyClientEndpointConfig;
import org.junit.BeforeClass;
import org.junit.Rule;

View File

@ -35,8 +35,8 @@ import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
import org.eclipse.jetty.toolchain.test.Hex;
import org.eclipse.jetty.websocket.api.InvalidWebSocketException;
import org.eclipse.jetty.websocket.common.util.Hex;
import org.eclipse.jetty.websocket.jsr356.client.EmptyClientEndpointConfig;
import org.junit.BeforeClass;
import org.junit.Rule;
@ -81,7 +81,7 @@ public class AvailableEncodersTest
Encoder.Binary<T> encoder = (Encoder.Binary<T>) encoders.getInstanceFor(type);
assertThat("Encoder", encoder, notNullValue());
ByteBuffer encoded = encoder.encode(value);
String hexEncoded = Hex.asHex(encoded);
assertThat("Encoded", hexEncoded, is(expectedEncodedHex));
}
@ -92,7 +92,7 @@ public class AvailableEncodersTest
assertThat("Encoder", encoder, notNullValue());
ByteArrayOutputStream out = new ByteArrayOutputStream();
encoder.encode(value, out);
String hexEncoded = Hex.asHex(out.toByteArray());
assertThat("Encoded", hexEncoded, is(expectedEncodedHex));

View File

@ -24,6 +24,7 @@ import java.util.Map;
import javax.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.websocket.jsr356.PathParamProvider;
/**
@ -42,7 +43,9 @@ public class PathParamServerEndpointConfig extends ServerEndpointConfigWrapper i
pathParamMap = new HashMap<>();
if (pathMap != null)
{
pathParamMap.putAll(pathMap);
pathMap.entrySet().stream().forEach(
entry -> pathParamMap.put(entry.getKey(), URIUtil.decodePath(entry.getValue()))
);
}
}

View File

@ -1,177 +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.server;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
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 javax.websocket.server.ServerEndpoint;
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.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class BinaryStreamTest
{
private static final String PATH = "/echo";
private Server server;
private ServerConnector connector;
private WebSocketContainer wsClient;
@Before
public void prepare() throws Exception
{
server = new Server();
connector = new ServerConnector(server);
server.addConnector(connector);
ServletContextHandler context = new ServletContextHandler(server, "/", true, false);
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
ServerEndpointConfig config = ServerEndpointConfig.Builder.create(ServerBinaryStreamer.class, PATH).build();
container.addEndpoint(config);
server.start();
wsClient = ContainerProvider.getWebSocketContainer();
}
@After
public void dispose() throws Exception
{
server.stop();
}
@Test
public void testEchoWithMediumMessage() throws Exception
{
testEcho(1024);
}
@Test
public void testLargestMessage() throws Exception
{
testEcho(wsClient.getDefaultMaxBinaryMessageBufferSize());
}
private void testEcho(int size) throws Exception
{
byte[] data = randomBytes(size);
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + PATH);
ClientBinaryStreamer client = new ClientBinaryStreamer();
Session session = wsClient.connectToServer(client, uri);
try (OutputStream output = session.getBasicRemote().getSendStream())
{
output.write(data);
}
Assert.assertTrue(client.await(5, TimeUnit.SECONDS));
Assert.assertArrayEquals(data, client.getEcho());
}
@Test
public void testMoreThanLargestMessageOneByteAtATime() throws Exception
{
int size = wsClient.getDefaultMaxBinaryMessageBufferSize() + 16;
byte[] data = randomBytes(size);
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + PATH);
ClientBinaryStreamer client = new ClientBinaryStreamer();
Session session = wsClient.connectToServer(client, uri);
try (OutputStream output = session.getBasicRemote().getSendStream())
{
for (int i = 0; i < size; ++i)
output.write(data[i]);
}
Assert.assertTrue(client.await(5, TimeUnit.SECONDS));
Assert.assertArrayEquals(data, client.getEcho());
}
private byte[] randomBytes(int size)
{
byte[] data = new byte[size];
new Random().nextBytes(data);
return data;
}
@ClientEndpoint
public static class ClientBinaryStreamer
{
private final CountDownLatch latch = new CountDownLatch(1);
private final ByteArrayOutputStream output = new ByteArrayOutputStream();
@OnMessage
public void echoed(InputStream input) throws IOException
{
while (true)
{
int read = input.read();
if (read < 0)
break;
output.write(read);
}
latch.countDown();
}
public byte[] getEcho()
{
return output.toByteArray();
}
public boolean await(long timeout, TimeUnit unit) throws InterruptedException
{
return latch.await(timeout, unit);
}
}
@ServerEndpoint(PATH)
public static class ServerBinaryStreamer
{
@OnMessage
public void echo(Session session, InputStream input) throws IOException
{
byte[] buffer = new byte[128];
try (OutputStream output = session.getBasicRemote().getSendStream())
{
int read;
while ((read = input.read(buffer)) >= 0)
output.write(buffer, 0, read);
}
}
}
}

View File

@ -1,181 +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.server;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import javax.websocket.server.ServerEndpoint;
public class EchoCase
{
public static class PartialBinary
{
ByteBuffer part;
boolean fin;
public PartialBinary(ByteBuffer part, boolean fin)
{
this.part = part;
this.fin = fin;
}
}
public static class PartialText
{
String part;
boolean fin;
public PartialText(String part, boolean fin)
{
this.part = part;
this.fin = fin;
}
}
public static EchoCase add(List<EchoCase[]> data, Class<?> serverPojo)
{
EchoCase ecase = new EchoCase();
ecase.serverPojo = serverPojo;
data.add(new EchoCase[]
{ ecase });
ServerEndpoint endpoint = serverPojo.getAnnotation(ServerEndpoint.class);
ecase.path = endpoint.value();
return ecase;
}
public static EchoCase add(List<EchoCase[]> data, Class<?> serverPojo, String path)
{
EchoCase ecase = new EchoCase();
ecase.serverPojo = serverPojo;
ecase.path = path;
data.add(new EchoCase[]
{ ecase });
return ecase;
}
// The websocket server pojo to test against
public Class<?> serverPojo;
// The (relative) URL path to hit
public String path;
// The messages to transmit
public List<Object> messages = new ArrayList<>();
// The expected Strings (that are echoed back)
public List<String> expectedStrings = new ArrayList<>();
public EchoCase addMessage(Object msg)
{
messages.add(msg);
return this;
}
public EchoCase addSplitMessage(ByteBuffer... parts)
{
int len = parts.length;
for (int i = 0; i < len; i++)
{
addMessage(new PartialBinary(parts[i],(i == (len-1))));
}
return this;
}
public EchoCase addSplitMessage(String... parts)
{
int len = parts.length;
for (int i = 0; i < len; i++)
{
addMessage(new PartialText(parts[i],(i == (len-1))));
}
return this;
}
public EchoCase expect(String message)
{
expectedStrings.add(message);
return this;
}
public EchoCase requestPath(String path)
{
this.path = path;
return this;
}
@Override
public String toString()
{
StringBuilder str = new StringBuilder();
str.append("EchoCase['");
str.append(path);
str.append("',").append(serverPojo.getSimpleName());
str.append(",messages[").append(messages.size());
str.append("]=");
boolean delim = false;
for (Object msg : messages)
{
if (delim)
{
str.append(",");
}
if (msg instanceof String)
{
str.append("'").append(msg).append("'");
}
else
{
str.append("(").append(msg.getClass().getName()).append(")");
str.append(msg);
}
delim = true;
}
str.append("]");
return str.toString();
}
public int getMessageCount()
{
int messageCount = 0;
for (Object msg : messages)
{
if (msg instanceof PartialText)
{
PartialText pt = (PartialText)msg;
if (pt.fin)
{
messageCount++;
}
}
else if (msg instanceof PartialBinary)
{
PartialBinary pb = (PartialBinary)msg;
if (pb.fin)
{
messageCount++;
}
}
else
{
messageCount++;
}
}
return messageCount;
}
}

View File

@ -1,341 +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.server;
import static org.junit.Assert.assertThat;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.websocket.ContainerProvider;
import javax.websocket.WebSocketContainer;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.webapp.WebAppContext;
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.beans.DateTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.binary.ByteBufferSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.echo.EchoAsyncTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.echo.EchoBasicTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.echo.EchoReturnTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.echo.EchoStatelessAsyncTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.echo.EchoStatelessBasicTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.partial.PartialTextSessionSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.partial.PartialTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.BooleanObjectTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.BooleanTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ByteObjectTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ByteTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.CharTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.CharacterObjectTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.DoubleObjectTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.DoubleTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.FloatObjectTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.FloatTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.IntParamTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.IntTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.IntegerObjectTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.LongObjectTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.LongTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ShortObjectTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ShortTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.InputStreamSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.ReaderParamSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.ReaderSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.StringReturnReaderParamSocket;
import org.hamcrest.Matchers;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class EchoTest
{
private static final List<EchoCase[]> TESTCASES = new ArrayList<>();
private static WSServer server;
private static URI serverUri;
private static WebSocketContainer client;
static
{
EchoCase.add(TESTCASES,BooleanTextSocket.class).addMessage(true).expect("true");
EchoCase.add(TESTCASES,BooleanTextSocket.class).addMessage(false).expect("false");
EchoCase.add(TESTCASES,BooleanTextSocket.class).addMessage(Boolean.TRUE).expect("true");
EchoCase.add(TESTCASES,BooleanTextSocket.class).addMessage(Boolean.FALSE).expect("false");
EchoCase.add(TESTCASES,BooleanTextSocket.class).addMessage("true").expect("true");
EchoCase.add(TESTCASES,BooleanTextSocket.class).addMessage("TRUe").expect("true");
EchoCase.add(TESTCASES,BooleanTextSocket.class).addMessage("Apple").expect("false");
EchoCase.add(TESTCASES,BooleanTextSocket.class).addMessage("false").expect("false");
EchoCase.add(TESTCASES,BooleanObjectTextSocket.class).addMessage(true).expect("true");
EchoCase.add(TESTCASES,BooleanObjectTextSocket.class).addMessage(false).expect("false");
EchoCase.add(TESTCASES,BooleanObjectTextSocket.class).addMessage(Boolean.TRUE).expect("true");
EchoCase.add(TESTCASES,BooleanObjectTextSocket.class).addMessage(Boolean.FALSE).expect("false");
EchoCase.add(TESTCASES,BooleanObjectTextSocket.class).addMessage("true").expect("true");
EchoCase.add(TESTCASES,BooleanObjectTextSocket.class).addMessage("false").expect("false");
EchoCase.add(TESTCASES,BooleanObjectTextSocket.class).addMessage("FaLsE").expect("false");
EchoCase.add(TESTCASES,ByteTextSocket.class).addMessage((byte)88).expect("0x58");
EchoCase.add(TESTCASES,ByteTextSocket.class).addMessage((byte)101).expect("0x65");
EchoCase.add(TESTCASES,ByteTextSocket.class).addMessage((byte)202).expect("0xCA");
EchoCase.add(TESTCASES,ByteTextSocket.class).addMessage(Byte.valueOf((byte)33)).expect("0x21");
EchoCase.add(TESTCASES,ByteTextSocket.class).addMessage(Byte.valueOf((byte)131)).expect("0x83");
EchoCase.add(TESTCASES,ByteTextSocket.class).addMessage(Byte.valueOf((byte)232)).expect("0xE8");
EchoCase.add(TESTCASES,ByteObjectTextSocket.class).addMessage((byte)88).expect("0x58");
EchoCase.add(TESTCASES,ByteObjectTextSocket.class).addMessage((byte)101).expect("0x65");
EchoCase.add(TESTCASES,ByteObjectTextSocket.class).addMessage((byte)202).expect("0xCA");
EchoCase.add(TESTCASES,ByteObjectTextSocket.class).addMessage(Byte.valueOf((byte)33)).expect("0x21");
EchoCase.add(TESTCASES,ByteObjectTextSocket.class).addMessage(Byte.valueOf((byte)131)).expect("0x83");
EchoCase.add(TESTCASES,ByteObjectTextSocket.class).addMessage(Byte.valueOf((byte)232)).expect("0xE8");
EchoCase.add(TESTCASES,CharTextSocket.class).addMessage((char)40).expect("(");
EchoCase.add(TESTCASES,CharTextSocket.class).addMessage((char)106).expect("j");
EchoCase.add(TESTCASES,CharTextSocket.class).addMessage((char)126).expect("~");
EchoCase.add(TESTCASES,CharTextSocket.class).addMessage(Character.valueOf((char)41)).expect(")");
EchoCase.add(TESTCASES,CharTextSocket.class).addMessage(Character.valueOf((char)74)).expect("J");
EchoCase.add(TESTCASES,CharTextSocket.class).addMessage(Character.valueOf((char)64)).expect("@");
EchoCase.add(TESTCASES,CharacterObjectTextSocket.class).addMessage((char)40).expect("(");
EchoCase.add(TESTCASES,CharacterObjectTextSocket.class).addMessage((char)106).expect("j");
EchoCase.add(TESTCASES,CharacterObjectTextSocket.class).addMessage((char)126).expect("~");
EchoCase.add(TESTCASES,CharacterObjectTextSocket.class).addMessage("E").expect("E");
EchoCase.add(TESTCASES,CharacterObjectTextSocket.class).addMessage(Character.valueOf((char)41)).expect(")");
EchoCase.add(TESTCASES,CharacterObjectTextSocket.class).addMessage(Character.valueOf((char)74)).expect("J");
EchoCase.add(TESTCASES,CharacterObjectTextSocket.class).addMessage(Character.valueOf((char)64)).expect("@");
EchoCase.add(TESTCASES,DoubleTextSocket.class).addMessage((double)3.1459).expect("3.1459");
EchoCase.add(TESTCASES,DoubleTextSocket.class).addMessage((double)123.456).expect("123.4560");
EchoCase.add(TESTCASES,DoubleTextSocket.class).addMessage(Double.valueOf(55)).expect("55.0000");
EchoCase.add(TESTCASES,DoubleTextSocket.class).addMessage(Double.valueOf(1.0E8)).expect("100000000.0000");
EchoCase.add(TESTCASES,DoubleTextSocket.class).addMessage("42").expect("42.0000");
EchoCase.add(TESTCASES,DoubleTextSocket.class).addMessage(".123").expect("0.1230");
EchoCase.add(TESTCASES,DoubleObjectTextSocket.class).addMessage((double)3.1459).expect("3.1459");
EchoCase.add(TESTCASES,DoubleObjectTextSocket.class).addMessage((double)123.456).expect("123.4560");
EchoCase.add(TESTCASES,DoubleObjectTextSocket.class).addMessage(Double.valueOf(55)).expect("55.0000");
EchoCase.add(TESTCASES,DoubleObjectTextSocket.class).addMessage(Double.valueOf(1.0E8)).expect("100000000.0000");
EchoCase.add(TESTCASES,DoubleObjectTextSocket.class).addMessage("42").expect("42.0000");
EchoCase.add(TESTCASES,DoubleObjectTextSocket.class).addMessage(".123").expect("0.1230");
EchoCase.add(TESTCASES,FloatTextSocket.class).addMessage((float)3.1459).expect("3.1459");
EchoCase.add(TESTCASES,FloatTextSocket.class).addMessage((float)123.456).expect("123.4560");
EchoCase.add(TESTCASES,FloatTextSocket.class).addMessage(Float.valueOf(55)).expect("55.0000");
EchoCase.add(TESTCASES,FloatTextSocket.class).addMessage(Float.valueOf(1.0E8f)).expect("100000000.0000");
EchoCase.add(TESTCASES,FloatTextSocket.class).addMessage("42").expect("42.0000");
EchoCase.add(TESTCASES,FloatTextSocket.class).addMessage(".123").expect("0.1230");
EchoCase.add(TESTCASES,FloatTextSocket.class).addMessage("50505E-6").expect("0.0505");
EchoCase.add(TESTCASES,FloatObjectTextSocket.class).addMessage((float)3.1459).expect("3.1459");
EchoCase.add(TESTCASES,FloatObjectTextSocket.class).addMessage((float)123.456).expect("123.4560");
EchoCase.add(TESTCASES,FloatObjectTextSocket.class).addMessage(Float.valueOf(55)).expect("55.0000");
EchoCase.add(TESTCASES,FloatObjectTextSocket.class).addMessage(Float.valueOf(1.0E8f)).expect("100000000.0000");
EchoCase.add(TESTCASES,FloatObjectTextSocket.class).addMessage("42").expect("42.0000");
EchoCase.add(TESTCASES,FloatObjectTextSocket.class).addMessage(".123").expect("0.1230");
EchoCase.add(TESTCASES,FloatObjectTextSocket.class).addMessage("50505E-6").expect("0.0505");
EchoCase.add(TESTCASES,IntTextSocket.class).addMessage((int)8).expect("8");
EchoCase.add(TESTCASES,IntTextSocket.class).addMessage((int)22).expect("22");
EchoCase.add(TESTCASES,IntTextSocket.class).addMessage("12345678").expect("12345678");
EchoCase.add(TESTCASES,IntegerObjectTextSocket.class).addMessage((int)8).expect("8");
EchoCase.add(TESTCASES,IntegerObjectTextSocket.class).addMessage((int)22).expect("22");
EchoCase.add(TESTCASES,IntegerObjectTextSocket.class).addMessage("12345678").expect("12345678");
EchoCase.add(TESTCASES,LongTextSocket.class).addMessage((int)789).expect("789");
EchoCase.add(TESTCASES,LongTextSocket.class).addMessage((long)123456L).expect("123456");
EchoCase.add(TESTCASES,LongTextSocket.class).addMessage(-456).expect("-456");
EchoCase.add(TESTCASES,LongObjectTextSocket.class).addMessage((int)789).expect("789");
EchoCase.add(TESTCASES,LongObjectTextSocket.class).addMessage((long)123456L).expect("123456");
EchoCase.add(TESTCASES,LongObjectTextSocket.class).addMessage(-234).expect("-234");
EchoCase.add(TESTCASES,ShortTextSocket.class).addMessage((int)4).expect("4");
EchoCase.add(TESTCASES,ShortTextSocket.class).addMessage((long)987).expect("987");
EchoCase.add(TESTCASES,ShortTextSocket.class).addMessage("32001").expect("32001");
EchoCase.add(TESTCASES,ShortObjectTextSocket.class).addMessage((int)4).expect("4");
EchoCase.add(TESTCASES,ShortObjectTextSocket.class).addMessage((int)987).expect("987");
EchoCase.add(TESTCASES,ShortObjectTextSocket.class).addMessage(-32001L).expect("-32001");
// PathParam based
EchoCase.add(TESTCASES,IntParamTextSocket.class).requestPath("/echo/primitives/integer/params/5678").addMessage(1234).expect("1234|5678");
// Text based
EchoCase.add(TESTCASES,EchoBasicTextSocket.class).addMessage("Hello").expect("Hello");
EchoCase.add(TESTCASES,EchoStatelessBasicTextSocket.class).addMessage("Hello").expect("Hello");
EchoCase.add(TESTCASES,EchoAsyncTextSocket.class).addMessage("Hello").expect("Hello");
EchoCase.add(TESTCASES,EchoStatelessAsyncTextSocket.class).addMessage("Hello").expect("Hello");
EchoCase.add(TESTCASES,EchoReturnTextSocket.class).addMessage("Hello").expect("Hello");
// ByteBuffer based
EchoCase.add(TESTCASES,ByteBufferSocket.class).addMessage(BufferUtil.toBuffer("Hello World")).expect("Hello World");
// InputStream based
EchoCase.add(TESTCASES,InputStreamSocket.class).addMessage(BufferUtil.toBuffer("Hello World")).expect("Hello World");
// Reader based
EchoCase.add(TESTCASES,ReaderSocket.class).addMessage("Hello World").expect("Hello World");
EchoCase.add(TESTCASES,ReaderParamSocket.class).requestPath("/echo/streaming/readerparam/OhNo").addMessage("Hello World").expect("Hello World|OhNo");
EchoCase.add(TESTCASES,StringReturnReaderParamSocket.class).requestPath("/echo/streaming/readerparam2/OhMy").addMessage("Hello World")
.expect("Hello World|OhMy");
// Partial message based
EchoCase.add(TESTCASES,PartialTextSocket.class)
.addSplitMessage("Saved"," by ","zero")
.expect("('Saved',false)(' by ',false)('zero',true)");
EchoCase.add(TESTCASES,PartialTextSessionSocket.class)
.addSplitMessage("Built"," for"," the"," future")
.expect("('Built',false)(' for',false)(' the',false)(' future',true)");
// Beans
EchoCase.add(TESTCASES, DateTextSocket.class).addMessage("1995.08.01").expect("[1995/08/01]");
}
@BeforeClass
public static void startServer() throws Exception
{
Path testdir = MavenTestingUtils.getTargetTestingPath(EchoTest.class.getName());
server = new WSServer(testdir,"app");
server.copyWebInf("empty-web.xml");
for (EchoCase cases[] : TESTCASES)
{
for (EchoCase ecase : cases)
{
server.copyClass(ecase.serverPojo);
}
}
server.start();
serverUri = server.getServerBaseURI();
WebAppContext webapp = server.createWebAppContext();
server.deployWebapp(webapp);
}
@BeforeClass
public static void startClient() throws Exception
{
client = ContainerProvider.getWebSocketContainer();
}
@AfterClass
public static void stopServer()
{
server.stop();
}
@Parameters(name = "{0}")
public static Collection<EchoCase[]> data() throws Exception
{
return TESTCASES;
}
private EchoCase testcase;
public EchoTest(EchoCase testcase)
{
this.testcase = testcase;
System.err.println(testcase);
}
@Test(timeout=10000)
public void testEcho() throws Exception
{
EchoClientSocket socket = new EchoClientSocket();
URI toUri = serverUri.resolve(testcase.path.substring(1));
try
{
Future<List<String>> clientMessagesFuture = socket.expectedMessages(testcase.expectedStrings.size());
// Connect
client.connectToServer(socket,toUri);
// Send Messages
for (Object msg : testcase.messages)
{
if (msg instanceof PartialText)
{
PartialText pt = (PartialText)msg;
socket.sendPartialText(pt.part,pt.fin);
}
else if (msg instanceof PartialBinary)
{
PartialBinary pb = (PartialBinary)msg;
socket.sendPartialBinary(pb.part,pb.fin);
}
else if (msg instanceof ByteBuffer)
{
socket.sendBinary((ByteBuffer) msg);
}
else if (msg instanceof String)
{
socket.sendText((String) msg);
}
else
{
socket.sendObject(msg);
}
}
// Collect Responses
List<String> received = clientMessagesFuture.get(5, TimeUnit.SECONDS);
// Validate Responses
assertOrdered("Received Events", testcase.expectedStrings, received);
}
finally
{
// Close
socket.close();
}
}
@SuppressWarnings("Duplicates")
public static void assertOrdered(String msg, List<String> expectedList, List<String> actualList)
{
try
{
Assert.assertEquals(msg, expectedList.size(), actualList.size());
if (!expectedList.isEmpty())
assertThat(msg, actualList, Matchers.contains(expectedList.toArray()));
}
catch (AssertionError e)
{
System.err.println("Expected: " + expectedList);
System.err.println("Actual : " + actualList);
throw e;
}
}
}

View File

@ -1,232 +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.server;
import static org.hamcrest.Matchers.is;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
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.LeakTrackingBufferPoolRule;
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;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class SessionTest
{
private interface Case
{
void customize(WebAppContext context);
}
@Parameters
public static Collection<Case[]> data()
{
List<Case[]> cases = new ArrayList<>();
cases.add(new Case[]
{context ->
{
// no customization
}});
cases.add(new Case[]
{context ->
{
// Test with DefaultServlet only
context.addServlet(DefaultServlet.class,"/");
}});
cases.add(new Case[]
{context ->
{
// Test with Servlet mapped to "/*"
context.addServlet(DefaultServlet.class,"/*");
}});
cases.add(new Case[]
{context ->
{
// Test with Servlet mapped to "/info/*"
context.addServlet(DefaultServlet.class,"/info/*");
}});
return cases;
}
@Rule
public LeakTrackingBufferPoolRule bufferPool = new LeakTrackingBufferPoolRule("Test");
private final Case testcase;
private final static AtomicInteger ID = new AtomicInteger(0);
private WSServer server;
private URI serverUri;
public SessionTest(Case testcase)
{
this.testcase = testcase;
}
@Before
public void startServer() throws Exception
{
server = new WSServer(MavenTestingUtils.getTargetTestingPath(SessionTest.class.getSimpleName() + "-" + ID.incrementAndGet()),"app");
server.copyWebInf("empty-web.xml");
server.copyClass(SessionInfoSocket.class);
server.copyClass(SessionAltConfig.class);
server.start();
serverUri = server.getServerBaseURI();
WebAppContext webapp = server.createWebAppContext();
testcase.customize(webapp);
server.deployWebapp(webapp);
}
@After
public void stopServer()
{
server.stop();
}
private void assertResponse(String requestPath, String requestMessage, String expectedResponse) throws Exception
{
WebSocketClient client = new WebSocketClient(bufferPool);
try
{
client.start();
JettyEchoSocket clientSocket = new JettyEchoSocket();
Future<Session> clientConnectFuture = client.connect(clientSocket,serverUri.resolve(requestPath));
// wait for connect
Session clientSession = clientConnectFuture.get(5,TimeUnit.SECONDS);
clientSocket.sendMessage(requestMessage);
String incomingMessage = clientSocket.messageQueue.poll(5, TimeUnit.SECONDS);
Assert.assertThat("Expected message",incomingMessage,is(expectedResponse));
clientSession.close();
clientSocket.awaitCloseEvent("Client");
}
finally
{
client.stop();
}
}
@Test
public void testPathParams_Annotated_Empty() throws Exception
{
assertResponse("info/","pathParams","pathParams[0]");
}
@Test
public void testPathParams_Annotated_Single() throws Exception
{
assertResponse("info/apple/","pathParams","pathParams[1]: 'a'=apple");
}
@Test
public void testPathParams_Annotated_Double() throws Exception
{
assertResponse("info/apple/pear/","pathParams","pathParams[2]: 'a'=apple: 'b'=pear");
}
@Test
public void testPathParams_Annotated_Triple() throws Exception
{
assertResponse("info/apple/pear/cherry/","pathParams","pathParams[3]: 'a'=apple: 'b'=pear: 'c'=cherry");
}
@Test
public void testPathParams_Endpoint_Empty() throws Exception
{
assertResponse("einfo/","pathParams","pathParams[0]");
}
@Test
public void testPathParams_Endpoint_Single() throws Exception
{
assertResponse("einfo/apple/","pathParams","pathParams[1]: 'a'=apple");
}
@Test
public void testPathParams_Endpoint_Double() throws Exception
{
assertResponse("einfo/apple/pear/","pathParams","pathParams[2]: 'a'=apple: 'b'=pear");
}
@Test
public void testPathParams_Endpoint_Triple() throws Exception
{
assertResponse("einfo/apple/pear/cherry/","pathParams","pathParams[3]: 'a'=apple: 'b'=pear: 'c'=cherry");
}
@Test
public void testRequestUri_Annotated_Basic() throws Exception
{
URI expectedUri = serverUri.resolve("info/");
assertResponse("info/","requestUri","requestUri=" + expectedUri.toASCIIString());
}
@Test
public void testRequestUri_Annotated_WithPathParam() throws Exception
{
URI expectedUri = serverUri.resolve("info/apple/banana/");
assertResponse("info/apple/banana/","requestUri","requestUri=" + expectedUri.toASCIIString());
}
@Test
public void testRequestUri_Annotated_WithPathParam_WithQuery() throws Exception
{
URI expectedUri = serverUri.resolve("info/apple/banana/?fruit=fresh&store=grandmasfarm");
assertResponse("info/apple/banana/?fruit=fresh&store=grandmasfarm","requestUri","requestUri=" + expectedUri.toASCIIString());
}
@Test
public void testRequestUri_Endpoint_Basic() throws Exception
{
URI expectedUri = serverUri.resolve("einfo/");
assertResponse("einfo/","requestUri","requestUri=" + expectedUri.toASCIIString());
}
@Test
public void testRequestUri_Endpoint_WithPathParam() throws Exception
{
URI expectedUri = serverUri.resolve("einfo/apple/banana/");
assertResponse("einfo/apple/banana/","requestUri","requestUri=" + expectedUri.toASCIIString());
}
@Test
public void testRequestUri_Endpoint_WithPathParam_WithQuery() throws Exception
{
URI expectedUri = serverUri.resolve("einfo/apple/banana/?fruit=fresh&store=grandmasfarm");
assertResponse("einfo/apple/banana/?fruit=fresh&store=grandmasfarm","requestUri","requestUri=" + expectedUri.toASCIIString());
}
}

View File

@ -1,179 +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.server;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.net.URI;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
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 javax.websocket.server.ServerEndpoint;
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.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class TextStreamTest
{
private static final String PATH = "/echo";
private static final String CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private Server server;
private ServerConnector connector;
private WebSocketContainer wsClient;
@Before
public void prepare() throws Exception
{
server = new Server();
connector = new ServerConnector(server);
server.addConnector(connector);
ServletContextHandler context = new ServletContextHandler(server, "/", true, false);
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
ServerEndpointConfig config = ServerEndpointConfig.Builder.create(ServerTextStreamer.class, PATH).build();
container.addEndpoint(config);
server.start();
wsClient = ContainerProvider.getWebSocketContainer();
}
@After
public void dispose() throws Exception
{
server.stop();
}
@Test
public void testEchoWithMediumMessage() throws Exception
{
testEcho(1024);
}
@Test
public void testLargestMessage() throws Exception
{
testEcho(wsClient.getDefaultMaxBinaryMessageBufferSize());
}
private void testEcho(int size) throws Exception
{
char[] data = randomChars(size);
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + PATH);
ClientTextStreamer client = new ClientTextStreamer();
Session session = wsClient.connectToServer(client, uri);
try (Writer output = session.getBasicRemote().getSendWriter())
{
output.write(data);
}
Assert.assertTrue(client.await(5, TimeUnit.SECONDS));
Assert.assertArrayEquals(data, client.getEcho());
}
@Test
public void testMoreThanLargestMessageOneByteAtATime() throws Exception
{
int size = wsClient.getDefaultMaxBinaryMessageBufferSize() + 16;
char[] data = randomChars(size);
URI uri = URI.create("ws://localhost:" + connector.getLocalPort() + PATH);
ClientTextStreamer client = new ClientTextStreamer();
Session session = wsClient.connectToServer(client, uri);
try (Writer output = session.getBasicRemote().getSendWriter())
{
for (int i = 0; i < size; ++i)
output.write(data[i]);
}
Assert.assertTrue(client.await(5, TimeUnit.SECONDS));
Assert.assertArrayEquals(data, client.getEcho());
}
private char[] randomChars(int size)
{
char[] data = new char[size];
Random random = new Random();
for (int i = 0; i < data.length; ++i)
data[i] = CHARS.charAt(random.nextInt(CHARS.length()));
return data;
}
@ClientEndpoint
public static class ClientTextStreamer
{
private final CountDownLatch latch = new CountDownLatch(1);
private final StringBuilder output = new StringBuilder();
@OnMessage
public void echoed(Reader input) throws IOException
{
while (true)
{
int read = input.read();
if (read < 0)
break;
output.append((char)read);
}
latch.countDown();
}
public char[] getEcho()
{
return output.toString().toCharArray();
}
public boolean await(long timeout, TimeUnit unit) throws InterruptedException
{
return latch.await(timeout, unit);
}
}
@ServerEndpoint(PATH)
public static class ServerTextStreamer
{
@OnMessage
public void echo(Session session, Reader input) throws IOException
{
char[] buffer = new char[128];
try (Writer output = session.getBasicRemote().getSendWriter())
{
int read;
while ((read = input.read(buffer)) >= 0)
output.write(buffer, 0, read);
}
}
}
}

View File

@ -26,10 +26,10 @@ import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
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.util.StackUtil;
@ServerEndpoint("/echo/binary/bytebuffer")
public class ByteBufferSocket
@ -46,6 +46,6 @@ public class ByteBufferSocket
public void onError(Session session, Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -25,9 +25,9 @@ import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/partial/textsession")
public class PartialTextSessionSocket
@ -50,6 +50,6 @@ public class PartialTextSessionSocket
public void onError(Throwable cause, Session session) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -26,9 +26,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/partial/text")
public class PartialTextSocket
@ -58,6 +58,6 @@ public class PartialTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -27,9 +27,9 @@ import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/booleanobject/params/{a}")
public class BooleanObjectTextParamSocket
@ -62,6 +62,6 @@ public class BooleanObjectTextParamSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -26,9 +26,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/booleanobject")
public class BooleanObjectTextSocket
@ -61,6 +61,6 @@ public class BooleanObjectTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -27,9 +27,9 @@ import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/boolean/params/{a}")
public class BooleanTextParamSocket
@ -55,6 +55,6 @@ public class BooleanTextParamSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -26,9 +26,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/boolean")
public class BooleanTextSocket
@ -54,6 +54,6 @@ public class BooleanTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -26,9 +26,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/byteobject")
public class ByteObjectTextSocket
@ -61,6 +61,6 @@ public class ByteObjectTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -26,9 +26,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/byte")
public class ByteTextSocket
@ -54,6 +54,6 @@ public class ByteTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -26,9 +26,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/char")
public class CharTextSocket
@ -54,6 +54,6 @@ public class CharTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -26,9 +26,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/characterobject")
public class CharacterObjectTextSocket
@ -61,6 +61,6 @@ public class CharacterObjectTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -27,9 +27,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/doubleobject")
public class DoubleObjectTextSocket
@ -62,6 +62,6 @@ public class DoubleObjectTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -27,9 +27,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/double")
public class DoubleTextSocket
@ -55,6 +55,6 @@ public class DoubleTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -27,9 +27,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/floatobject")
public class FloatObjectTextSocket
@ -62,6 +62,6 @@ public class FloatObjectTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -27,9 +27,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/float")
public class FloatTextSocket
@ -55,6 +55,6 @@ public class FloatTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -27,9 +27,9 @@ import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/integer/params/{a}")
public class IntParamTextSocket
@ -55,6 +55,6 @@ public class IntParamTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -26,9 +26,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/integer")
public class IntTextSocket
@ -54,6 +54,6 @@ public class IntTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -27,9 +27,9 @@ import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/integerobject/params/{a}")
public class IntegerObjectParamTextSocket
@ -62,6 +62,6 @@ public class IntegerObjectParamTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -26,9 +26,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/integerobject")
public class IntegerObjectTextSocket
@ -61,6 +61,6 @@ public class IntegerObjectTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -26,9 +26,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/longobject")
public class LongObjectTextSocket
@ -61,6 +61,6 @@ public class LongObjectTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -26,9 +26,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/long")
public class LongTextSocket
@ -54,6 +54,6 @@ public class LongTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -26,9 +26,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/shortobject")
public class ShortObjectTextSocket
@ -61,6 +61,6 @@ public class ShortObjectTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -26,9 +26,9 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
@ServerEndpoint("/echo/primitives/short")
public class ShortTextSocket
@ -54,6 +54,6 @@ public class ShortTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -26,11 +26,11 @@ import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
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.common.util.StackUtil;
@ServerEndpoint("/echo/streaming/inputstream")
public class InputStreamSocket
@ -47,6 +47,6 @@ public class InputStreamSocket
public void onError(Session session, Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -28,10 +28,10 @@ import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
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.common.util.StackUtil;
@ServerEndpoint("/echo/streaming/readerparam/{param}")
public class ReaderParamSocket
@ -60,6 +60,6 @@ public class ReaderParamSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -26,10 +26,10 @@ import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
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.common.util.StackUtil;
@ServerEndpoint("/echo/streaming/reader")
public class ReaderSocket
@ -46,6 +46,6 @@ public class ReaderSocket
public void onError(Session session, Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -27,10 +27,10 @@ import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
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.common.util.StackUtil;
@ServerEndpoint("/echo/streaming/readerparam2/{param}")
public class StringReturnReaderParamSocket
@ -51,6 +51,6 @@ public class StringReturnReaderParamSocket
public void onError(Session session, Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -23,5 +23,9 @@ public final class WebSocketConstants
public static final String SEC_WEBSOCKET_EXTENSIONS = "Sec-WebSocket-Extensions";
public static final String SEC_WEBSOCKET_PROTOCOL = "Sec-WebSocket-Protocol";
public static final String SEC_WEBSOCKET_VERSION = "Sec-WebSocket-Version";
public static final String SEC_WEBSOCKET_ACCEPT = "Sec-WebSocket-Accept";
public static final String SEC_WEBSOCKET_ORIGIN = "Sec-WebSocket-Origin";
public static final String SEC_WEBSOCKET_KEY = "Sec-WebSocket-Key";
public static final int SPEC_VERSION = 13;
}

View File

@ -140,13 +140,9 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
// close FrameFlusher, we cannot write anymore at this point.
flusher.close();
EndPoint endPoint = getEndPoint();
// We need to gently close first, to allow
// SSL close alerts to be sent by Jetty
if (LOG.isDebugEnabled())
LOG.debug("Shutting down output {}",endPoint);
endPoint.close();
getEndPoint().close();
closed.set(true);
}

View File

@ -48,9 +48,7 @@ public class MessageInputStream extends InputStream implements MessageSink
public void accept(Frame frame, FrameCallback callback)
{
if (LOG.isDebugEnabled())
{
LOG.debug("accepting {}", frame);
}
// If closed, we should just toss incoming payloads into the bit bucket.
if (closed.get())
@ -83,6 +81,9 @@ public class MessageInputStream extends InputStream implements MessageSink
@Override
public void close() throws IOException
{
if(LOG.isDebugEnabled())
LOG.debug("close()");
if (closed.compareAndSet(false, true))
{
synchronized (buffers)
@ -96,6 +97,8 @@ public class MessageInputStream extends InputStream implements MessageSink
private void shutdown()
{
if(LOG.isDebugEnabled())
LOG.debug("shutdown()");
closed.set(true);
// Removed buffers that may have remained in the queue.
buffers.clear();
@ -144,7 +147,7 @@ public class MessageInputStream extends InputStream implements MessageSink
{
try
{
while ((result = buffers.poll()) == null)
while ((result = buffers.peek()) == null)
{
// TODO: handle read timeout here?
buffers.wait();
@ -159,6 +162,8 @@ public class MessageInputStream extends InputStream implements MessageSink
if (result == EOF)
{
if (LOG.isDebugEnabled())
LOG.debug("Read EOF");
shutdown();
return -1;
}
@ -166,10 +171,11 @@ public class MessageInputStream extends InputStream implements MessageSink
// We have content
int fillLen = Math.min(result.buffer.remaining(), len);
result.buffer.get(b, off, fillLen);
if (!result.buffer.hasRemaining())
{
result.callback.succeed();
buffers.pop();
}
// return number of bytes actually copied into buffer

View File

@ -45,6 +45,7 @@ public class MessageOutputStream extends OutputStream
private final ByteBufferPool bufferPool;
private final BlockingWriteCallback blocker;
private long frameCount;
private long bytesSent;
private BinaryFrame frame;
private ByteBuffer buffer;
private WriteCallback callback;
@ -118,7 +119,7 @@ public class MessageOutputStream extends OutputStream
flush(true);
bufferPool.release(buffer);
if (LOG.isDebugEnabled())
LOG.debug("Stream closed, {} frames sent", frameCount);
LOG.debug("Stream closed, {} frames ({} bytes) sent", frameCount, bytesSent);
// Notify without holding locks.
notifySuccess();
}
@ -160,29 +161,32 @@ public class MessageOutputStream extends OutputStream
}
}
private void send(byte[] bytes, int offset, int length) throws IOException
private void send(byte[] bytes, final int offset, final int length) throws IOException
{
synchronized (this)
{
if (closed)
throw new IOException("Stream is closed");
while (length > 0)
int remaining = length;
int off = offset;
while (remaining > 0)
{
// There may be no space available, we want
// to handle correctly when space == 0.
int space = buffer.remaining();
int size = Math.min(space, length);
buffer.put(bytes, offset, size);
offset += size;
length -= size;
if (length > 0)
buffer.put(bytes, off, size);
off += size;
remaining -= size;
if (remaining > 0)
{
// If we could not write everything, it means
// that the buffer was full, so flush it.
flush(false);
}
}
bytesSent += length;
}
}

View File

@ -24,6 +24,7 @@ import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import org.eclipse.jetty.toolchain.test.Hex;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
@ -43,7 +44,6 @@ import org.eclipse.jetty.websocket.common.test.ByteBufferAssert;
import org.eclipse.jetty.websocket.common.test.ParserCapture;
import org.eclipse.jetty.websocket.common.test.UnitGenerator;
import org.eclipse.jetty.websocket.common.test.UnitParser;
import org.eclipse.jetty.websocket.common.util.Hex;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;

View File

@ -31,6 +31,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jetty.toolchain.test.Hex;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.api.MessageTooLargeException;
@ -47,7 +48,6 @@ import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.common.test.ParserCapture;
import org.eclipse.jetty.websocket.common.test.UnitGenerator;
import org.eclipse.jetty.websocket.common.test.UnitParser;
import org.eclipse.jetty.websocket.common.util.Hex;
import org.eclipse.jetty.websocket.common.util.MaskedByteBuffer;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;

View File

@ -22,6 +22,7 @@ import static org.hamcrest.Matchers.is;
import java.nio.ByteBuffer;
import org.eclipse.jetty.toolchain.test.Hex;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
@ -30,7 +31,6 @@ import org.eclipse.jetty.websocket.common.frames.CloseFrame;
import org.eclipse.jetty.websocket.common.frames.PingFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.common.test.LeakTrackingBufferPoolRule;
import org.eclipse.jetty.websocket.common.util.Hex;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;

View File

@ -21,11 +21,11 @@ package org.eclipse.jetty.websocket.common.extensions.compress;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.toolchain.test.Hex;
import org.eclipse.jetty.websocket.api.BatchMode;
import org.eclipse.jetty.websocket.api.FrameCallback;
import org.eclipse.jetty.websocket.api.extensions.Frame;
import org.eclipse.jetty.websocket.api.extensions.OutgoingFrames;
import org.eclipse.jetty.websocket.common.util.Hex;
public class CapturedHexPayloads implements OutgoingFrames
{

View File

@ -23,6 +23,7 @@ import static org.hamcrest.Matchers.is;
import java.nio.ByteBuffer;
import java.util.Arrays;
import org.eclipse.jetty.toolchain.test.Hex;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
@ -31,7 +32,6 @@ import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.common.test.ByteBufferAssert;
import org.eclipse.jetty.websocket.common.test.UnitGenerator;
import org.eclipse.jetty.websocket.common.util.Hex;
import org.junit.Assert;
import org.junit.Test;
@ -80,7 +80,7 @@ public class DeMaskProcessorTest
payload.position(6); // where payload starts
LOG.debug("Payload: {}",BufferUtil.toDetailString(payload));
LOG.debug("Pre-Processed: {}",Hex.asHex(payload));
LOG.debug("Pre-Processed: {}", Hex.asHex(payload));
DeMaskProcessor demask = new DeMaskProcessor();
demask.reset(frame);
@ -97,8 +97,8 @@ public class DeMaskProcessorTest
demask.process(slice1);
demask.process(slice2);
LOG.debug("Post-Processed: {}",Hex.asHex(payload));
LOG.debug("Post-Processed: {}", Hex.asHex(payload));
Assert.assertThat("Payload.remaining",payload.remaining(),is(messageSize));
for (int i = payload.position(); i < payload.limit(); i++)

View File

@ -1,80 +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.common.util;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.BufferUtil;
public final class Hex
{
private static final char[] hexcodes = "0123456789ABCDEF".toCharArray();
public static byte[] asByteArray(String hstr)
{
if ((hstr.length() < 0) || ((hstr.length() % 2) != 0))
{
throw new IllegalArgumentException(String.format("Invalid string length of <%d>",hstr.length()));
}
int size = hstr.length() / 2;
byte buf[] = new byte[size];
byte hex;
int len = hstr.length();
int idx = (int)Math.floor(((size * 2) - (double)len) / 2);
for (int i = 0; i < len; i++)
{
hex = 0;
if (i >= 0)
{
hex = (byte)(Character.digit(hstr.charAt(i),16) << 4);
}
i++;
hex += (byte)(Character.digit(hstr.charAt(i),16));
buf[idx] = hex;
idx++;
}
return buf;
}
public static ByteBuffer asByteBuffer(String hstr)
{
return ByteBuffer.wrap(asByteArray(hstr));
}
public static String asHex(byte buf[])
{
int len = buf.length;
char out[] = new char[len * 2];
for (int i = 0; i < len; i++)
{
out[i * 2] = hexcodes[(buf[i] & 0xF0) >> 4];
out[(i * 2) + 1] = hexcodes[(buf[i] & 0x0F)];
}
return String.valueOf(out);
}
public static String asHex(ByteBuffer buffer)
{
return asHex(BufferUtil.toArray(buffer));
}
}

View File

@ -31,6 +31,7 @@ import java.security.NoSuchAlgorithmException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jetty.toolchain.test.Hex;
import org.eclipse.jetty.toolchain.test.IO;
import org.junit.Assert;

View File

@ -1,42 +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.common.util;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
public final class StackUtil
{
public static String toString(Throwable t)
{
try (StringWriter w = new StringWriter())
{
try (PrintWriter out = new PrintWriter(w))
{
t.printStackTrace(out);
return w.toString();
}
}
catch (IOException e)
{
return "Unable to get stacktrace for: " + t;
}
}
}

View File

@ -18,12 +18,13 @@
package org.eclipse.jetty.websocket.common.util;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import org.eclipse.jetty.toolchain.test.Hex;
import org.eclipse.jetty.util.BufferUtil;
import org.junit.Test;

View File

@ -488,9 +488,10 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
/**
* Upgrade the request/response to a WebSocket Connection.
* <p/>
* <p>
* This method will not normally return, but will instead throw a UpgradeConnectionException, to exit HTTP handling and initiate WebSocket handling of the
* connection.
* </p>
*
* @param http the raw http connection
* @param request the request to upgrade

View File

@ -55,7 +55,7 @@
<artifactId>jetty-http</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>

View File

@ -0,0 +1,56 @@
//
// ========================================================================
// 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 java.nio.ByteBuffer;
import java.util.Arrays;
public final class DataUtils
{
/**
* Make a copy of a byte buffer.
* <p>
* This is important in some tests, as the underlying byte buffer contained in a Frame can be modified through
* masking and make it difficult to compare the results in the fuzzer.
*
* @param payload the payload to copy
* @return a new byte array of the payload contents
*/
public static ByteBuffer copyOf(ByteBuffer payload)
{
ByteBuffer copy = ByteBuffer.allocate(payload.remaining());
copy.put(payload.slice());
copy.flip();
return copy;
}
/**
* Make a copy of a byte buffer.
* <p>
* This is important in some tests, as the underlying byte buffer contained in a Frame can be modified through
* masking and make it difficult to compare the results in the fuzzer.
*
* @param payload the payload to copy
* @return a new byte array of the payload contents
*/
public static ByteBuffer copyOf(byte[] payload)
{
return ByteBuffer.wrap(Arrays.copyOf(payload, payload.length));
}
}

View File

@ -1,273 +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.tests;
import static org.eclipse.jetty.websocket.tests.Fuzzer.SendMode.BULK;
import static org.eclipse.jetty.websocket.tests.Fuzzer.SendMode.PER_FRAME;
import static org.eclipse.jetty.websocket.tests.Fuzzer.SendMode.SLOW;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.toolchain.test.ByteBufferAssert;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
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.extensions.Frame;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
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;
/**
* Fuzzing utility for the AB tests.
*/
public class Fuzzer extends ContainerLifeCycle
{
public static class Session implements AutoCloseable
{
// Client side framing mask
private static final byte[] MASK = {0x11, 0x22, 0x33, 0x44};
private final Fuzzed testcase;
private final UntrustedWSSession session;
private final Generator generator;
private SendMode sendMode = SendMode.BULK;
private int slowSendSegmentSize = 5;
public Session(Fuzzed testcase, UntrustedWSSession session)
{
this.testcase = testcase;
this.session = session;
this.generator = testcase.getLaxGenerator();
}
@Override
public void close() throws Exception
{
session.close();
}
public Session slowMode(int slowSendSegmentSize)
{
this.sendMode = SLOW;
this.slowSendSegmentSize = slowSendSegmentSize;
return this;
}
public Session bulkMode()
{
this.sendMode = BULK;
return this;
}
public Session perFrameMode()
{
this.sendMode = PER_FRAME;
return this;
}
private void assertIsOpen() throws Exception
{
assertThat("Session exists", session, notNullValue());
assertThat("Session is open", session.isOpen(), is(true));
assertThat("Endpoint is open", session.getUntrustedEndpoint().openLatch.await(5, TimeUnit.SECONDS), is(true));
}
public ByteBuffer asNetworkBuffer(List<WebSocketFrame> send)
{
int buflen = 0;
for (Frame f : send)
{
buflen += f.getPayloadLength() + Generator.MAX_HEADER_LENGTH;
}
ByteBuffer buf = session.getBufferPool().acquire(buflen, false);
BufferUtil.clearToFill(buf);
// Generate frames
for (WebSocketFrame f : send)
{
setClientMask(f);
generator.generateWholeFrame(f, buf);
}
buf.flip();
return buf;
}
private void setClientMask(WebSocketFrame f)
{
if (LOG.isDebugEnabled())
{
f.setMask(new byte[]
{0x00, 0x00, 0x00, 0x00});
}
else
{
f.setMask(MASK); // make sure we have mask set
}
}
public void expect(List<WebSocketFrame> expect) throws Exception
{
expect(expect, 10, TimeUnit.SECONDS);
}
public void expect(List<WebSocketFrame> expect, int duration, TimeUnit unit) throws Exception
{
int expectedCount = expect.size();
LOG.debug("expect() {} frame(s)", expect.size());
// Read frames
UntrustedWSEndpoint endpoint = session.getUntrustedEndpoint();
String prefix = "";
for (int i = 0; i < expectedCount; i++)
{
WebSocketFrame expected = expect.get(i);
WebSocketFrame actual = endpoint.framesQueue.poll(5, TimeUnit.SECONDS);
prefix = "Frame[" + i + "]";
LOG.debug("{} {}", prefix, actual);
assertThat(prefix + ".opcode", OpCode.name(actual.getOpCode()), is(OpCode.name(expected.getOpCode())));
prefix += "/" + actual.getOpCode();
if (expected.getOpCode() == OpCode.CLOSE)
{
CloseInfo expectedClose = new CloseInfo(expected);
CloseInfo actualClose = new CloseInfo(actual);
assertThat(prefix + ".statusCode", actualClose.getStatusCode(), is(expectedClose.getStatusCode()));
}
else
{
assertThat(prefix + ".payloadLength", actual.getPayloadLength(), is(expected.getPayloadLength()));
ByteBufferAssert.assertEquals(prefix + ".payload", expected.getPayload(), actual.getPayload());
}
}
}
public void expect(WebSocketFrame expect) throws Exception
{
expect(Collections.singletonList(expect));
}
public Session send(WebSocketFrame send) throws Exception
{
send(Collections.singletonList(send));
return this;
}
public Session send(ByteBuffer buf) throws Exception
{
assertIsOpen();
LOG.debug("Sending bytes {}", BufferUtil.toDetailString(buf));
if (sendMode == SLOW)
{
session.getUntrustedConnection().writeRawSlowly(buf, slowSendSegmentSize);
}
else
{
session.getUntrustedConnection().writeRaw(buf);
}
return this;
}
public Session send(ByteBuffer buf, int numBytes) throws IOException
{
session.getUntrustedConnection().writeRaw(buf, numBytes);
return this;
}
public Session send(List<WebSocketFrame> send) throws Exception
{
assertIsOpen();
LOG.debug("[{}] Sending {} frames (mode {})", testcase.getTestMethodName(), send.size(), sendMode);
session.getUntrustedConnection();
for (WebSocketFrame f : send)
{
BlockerFrameCallback blocker = new BlockerFrameCallback();
session.getOutgoingHandler().outgoingFrame(f, blocker, BatchMode.OFF);
blocker.block();
}
return this;
}
}
public enum SendMode
{
BULK,
PER_FRAME,
SLOW
}
private static final int KBYTE = 1024;
private static final int MBYTE = KBYTE * KBYTE;
private static final Logger LOG = Log.getLogger(Fuzzer.class);
private final UntrustedWSClient client;
private long connectTimeout = 2;
private TimeUnit connectTimeoutUnit = TimeUnit.SECONDS;
public Fuzzer() throws Exception
{
this.client = new UntrustedWSClient();
int bigMessageSize = 20 * MBYTE;
this.client.getPolicy().setMaxTextMessageSize(bigMessageSize);
this.client.getPolicy().setMaxBinaryMessageSize(bigMessageSize);
this.client.getPolicy().setIdleTimeout(5000);
this.client.setMaxIdleTimeout(TimeUnit.SECONDS.toMillis(2));
addBean(this.client);
}
public UntrustedWSClient getWSClient()
{
return this.client;
}
public Fuzzer.Session connect(Fuzzed testcase) throws Exception
{
// TODO: handle EndPoint behavior here. (BULK/SLOW/FRAME)
// BULK = AggregatingEndpoint write (aggregate until .flush() call)
// SLOW = FixedBufferEndpoint write (send fixed buffer size)
// PERFRAME = No change to Endpoint
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
upgradeRequest.setHeader("X-TestCase", testcase.getTestMethodName());
UntrustedWSSession session = client.connect(testcase.getServerURI(), upgradeRequest).get(connectTimeout, connectTimeoutUnit);
return new Fuzzer.Session(testcase, session);
}
}

View File

@ -0,0 +1,346 @@
//
// ========================================================================
// 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.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.toolchain.test.ByteBufferAssert;
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.WebSocketConstants;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
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.hamcrest.Matchers;
public class LocalFuzzer implements AutoCloseable
{
private static final Logger LOG = Log.getLogger(LocalFuzzer.class);
public final LocalFuzzer.Provider provider;
public final UnitGenerator generator;
public final LocalConnector.LocalEndPoint endPoint;
public LocalFuzzer(LocalFuzzer.Provider provider) throws Exception
{
this(provider, null);
}
public LocalFuzzer(LocalFuzzer.Provider provider, CharSequence requestPath) throws Exception
{
this(provider, requestPath, UpgradeUtils.newDefaultUpgradeRequestHeaders());
}
public LocalFuzzer(LocalFuzzer.Provider provider, CharSequence requestPath, Map<String, String> headers) throws Exception
{
this.provider = provider;
String upgradeRequest = UpgradeUtils.generateUpgradeRequest(requestPath, headers);
LOG.debug("Request: {}", upgradeRequest);
ByteBuffer upgradeRequestBytes = BufferUtil.toBuffer(upgradeRequest.toString(), StandardCharsets.UTF_8);
this.endPoint = this.provider.newLocalConnection();
performUpgrade(endPoint, upgradeRequestBytes);
this.generator = new UnitGenerator(WebSocketPolicy.newClientPolicy());
}
public void addInputInSegments(LocalConnector.LocalEndPoint endPoint, ByteBuffer outgoing, int segmentSize)
{
while (outgoing.remaining() > 0)
{
int len = Math.min(segmentSize, outgoing.remaining());
ByteBuffer slice = outgoing.slice();
slice.limit(len);
endPoint.addInput(slice);
outgoing.position(outgoing.position() + len);
}
}
public void expectMessage(BlockingQueue<WebSocketFrame> framesQueue, byte expectedDataOp, ByteBuffer expectedMessage) throws InterruptedException
{
ByteBuffer actualPayload = ByteBuffer.allocate(expectedMessage.remaining());
WebSocketFrame frame = framesQueue.poll(1, TimeUnit.SECONDS);
assertThat("Initial Frame.opCode", frame.getOpCode(), is(expectedDataOp));
actualPayload.put(frame.getPayload());
while (!frame.isFin())
{
frame = framesQueue.poll(1, TimeUnit.SECONDS);
assertThat("Frame.opCode", frame.getOpCode(), is(OpCode.CONTINUATION));
actualPayload.put(frame.getPayload());
}
actualPayload.flip();
ByteBufferAssert.assertEquals("Actual Message Payload", actualPayload, expectedMessage);
}
public ByteBuffer asNetworkBuffer(List<WebSocketFrame> frames)
{
int bufferLength = 0;
for (WebSocketFrame f : frames)
{
bufferLength += f.getPayloadLength() + Generator.MAX_HEADER_LENGTH;
}
ByteBuffer buffer = ByteBuffer.allocate(bufferLength);
for (WebSocketFrame f : frames)
{
generator.generate(buffer, f);
}
BufferUtil.flipToFlush(buffer, 0);
return buffer;
}
public void assertExpected(BlockingQueue<WebSocketFrame> framesQueue, List<WebSocketFrame> expect) throws InterruptedException
{
int expectedCount = expect.size();
String prefix;
for (int i = 0; i < expectedCount; i++)
{
prefix = "Frame[" + i + "]";
WebSocketFrame expected = expect.get(i);
WebSocketFrame actual = framesQueue.poll(1, TimeUnit.SECONDS);
assertThat(prefix + ".poll", actual, notNullValue());
if (LOG.isDebugEnabled())
{
if (actual.getOpCode() == OpCode.CLOSE)
LOG.debug("{} CloseFrame: {}", prefix, new CloseInfo(actual));
else
LOG.debug("{} {}", prefix, actual);
}
assertThat(prefix + ".opcode", OpCode.name(actual.getOpCode()), Matchers.is(OpCode.name(expected.getOpCode())));
prefix += "(op=" + actual.getOpCode() + "," + (actual.isFin() ? "" : "!") + "fin)";
if (expected.getOpCode() == OpCode.CLOSE)
{
CloseInfo expectedClose = new CloseInfo(expected);
CloseInfo actualClose = new CloseInfo(actual);
assertThat(prefix + ".statusCode", actualClose.getStatusCode(), Matchers.is(expectedClose.getStatusCode()));
}
else if (expected.hasPayload())
{
if (expected.getOpCode() == OpCode.TEXT)
{
String expectedText = expected.getPayloadAsUTF8();
String actualText = actual.getPayloadAsUTF8();
assertThat(prefix + ".text-payload", actualText, is(expectedText));
}
else
{
assertThat(prefix + ".payloadLength", actual.getPayloadLength(), Matchers.is(expected.getPayloadLength()));
ByteBufferAssert.assertEquals(prefix + ".payload", expected.getPayload(), actual.getPayload());
}
}
else
{
assertThat(prefix + ".payloadLength", actual.getPayloadLength(), Matchers.is(0));
}
}
}
public void close() throws Exception
{
endPoint.close();
}
/**
* Send the EOF signal
*/
public void eof()
{
endPoint.addInputEOF();
}
public void expect(List<WebSocketFrame> expected) throws InterruptedException
{
// Get incoming frames
// Wait for server to close
endPoint.waitUntilClosed();
// Get the server send echo bytes
ByteBuffer incoming = endPoint.getOutput();
// Parse those bytes into frames
ParserCapture capture = new ParserCapture();
Parser parser = provider.newClientParser(capture);
parser.parse(incoming);
assertExpected(capture.framesQueue, expected);
}
public BlockingQueue<WebSocketFrame> getOutputFrames()
{
// Get incoming frames
// Wait for server to close
endPoint.waitUntilClosed();
// Get the server send echo bytes
ByteBuffer incoming = endPoint.getOutput();
// Parse those bytes into frames
ParserCapture capture = new ParserCapture();
Parser parser = provider.newClientParser(capture);
parser.parse(incoming);
return capture.framesQueue;
}
/**
* Send raw bytes
*/
public void send(ByteBuffer buffer)
{
endPoint.addInput(buffer);
}
/**
* Send some of the raw bytes
*
* @param buffer the buffer
* @param length the number of bytes to send from buffer
*/
public void send(ByteBuffer buffer, int length)
{
int limit = Math.min(length, buffer.remaining());
ByteBuffer sliced = buffer.slice();
sliced.limit(limit);
endPoint.addInput(sliced);
buffer.position(buffer.position() + limit);
}
/**
* Generate a single ByteBuffer representing the entire
* list of generated frames, and submit it to {@link org.eclipse.jetty.server.LocalConnector.LocalEndPoint#addInput(ByteBuffer)}
*
* @param frames the list of frames to send
*/
public void sendBulk(List<WebSocketFrame> frames)
{
int bufferLength = 0;
for (WebSocketFrame f : frames)
{
bufferLength += f.getPayloadLength() + Generator.MAX_HEADER_LENGTH;
}
ByteBuffer outgoing = ByteBuffer.allocate(bufferLength);
boolean eof = false;
for (WebSocketFrame f : frames)
{
generator.generate(outgoing, f);
if (f.getOpCode() == OpCode.CLOSE)
eof = true;
}
BufferUtil.flipToFlush(outgoing, 0);
endPoint.addInput(outgoing);
if (eof)
endPoint.addInputEOF();
}
/**
* Generate a ByteBuffer for each frame, and submit each to
* {@link org.eclipse.jetty.server.LocalConnector.LocalEndPoint#addInput(ByteBuffer)}
*
* @param frames the list of frames to send
*/
public void sendFrames(List<WebSocketFrame> frames)
{
boolean eof = false;
for (WebSocketFrame f : frames)
{
ByteBuffer buffer = generator.generate(f);
endPoint.addInput(buffer);
if (f.getOpCode() == OpCode.CLOSE)
eof = true;
}
if (eof)
endPoint.addInputEOF();
}
/**
* Generate a ByteBuffer for each frame, and submit each to
* {@link org.eclipse.jetty.server.LocalConnector.LocalEndPoint#addInput(ByteBuffer)}
*
* @param frames the list of frames to send
*/
public void sendSegmented(List<WebSocketFrame> frames, int segmentSize)
{
int bufferLength = 0;
for (WebSocketFrame f : frames)
{
bufferLength += f.getPayloadLength() + Generator.MAX_HEADER_LENGTH;
}
ByteBuffer outgoing = ByteBuffer.allocate(bufferLength);
boolean eof = false;
for (WebSocketFrame f : frames)
{
generator.generate(outgoing, f);
if (f.getOpCode() == OpCode.CLOSE)
eof = true;
}
BufferUtil.flipToFlush(outgoing, 0);
addInputInSegments(endPoint, outgoing, segmentSize);
if (eof)
endPoint.addInputEOF();
}
private HttpTester.Response performUpgrade(LocalConnector.LocalEndPoint endPoint, ByteBuffer buf) throws Exception
{
endPoint.addInput(buf);
// Get response
ByteBuffer response = endPoint.waitForResponse(false, 1, TimeUnit.SECONDS);
HttpTester.Response parsedResponse = HttpTester.parseResponse(response);
LOG.debug("Response: {}", parsedResponse);
assertThat("Is Switching Protocols", parsedResponse.getStatus(), is(101));
assertThat("Is Connection Upgrade", parsedResponse.get(WebSocketConstants.SEC_WEBSOCKET_ACCEPT), notNullValue());
assertThat("Is Connection Upgrade", parsedResponse.get("Connection"), is("Upgrade"));
assertThat("Is WebSocket Upgrade", parsedResponse.get("Upgrade"), is("WebSocket"));
return parsedResponse;
}
public interface Provider
{
Parser newClientParser(Parser.Handler parserHandler);
LocalConnector.LocalEndPoint newLocalConnection();
}
}

View File

@ -0,0 +1,194 @@
//
// ========================================================================
// 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 java.net.URI;
import java.util.Map;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.common.Parser;
public class LocalServer extends ContainerLifeCycle implements LocalFuzzer.Provider
{
private static final Logger LOG = Log.getLogger(LocalServer.class);
private final ByteBufferPool bufferPool = new MappedByteBufferPool();
private final WebSocketPolicy serverPolicy = WebSocketPolicy.newServerPolicy();
private Server server;
private ServerConnector connector;
private LocalConnector localConnector;
private ServletContextHandler servletContextHandler;
private URI serverUri;
private boolean ssl = false;
private SslContextFactory sslContextFactory;
public void enableSsl(boolean ssl)
{
this.ssl = ssl;
}
public LocalConnector getLocalConnector()
{
return localConnector;
}
public WebSocketPolicy getServerDefaultPolicy()
{
return serverPolicy;
}
public URI getServerUri()
{
return serverUri;
}
public ServletContextHandler getServletContextHandler()
{
return servletContextHandler;
}
public SslContextFactory getSslContextFactory()
{
return sslContextFactory;
}
public boolean isSslEnabled()
{
return ssl;
}
@Override
public Parser newClientParser(Parser.Handler parserHandler)
{
return new Parser(WebSocketPolicy.newClientPolicy(), bufferPool, parserHandler);
}
@Override
public LocalConnector.LocalEndPoint newLocalConnection()
{
return getLocalConnector().connect();
}
public LocalFuzzer newLocalFuzzer() throws Exception
{
return new LocalFuzzer(this);
}
public LocalFuzzer newLocalFuzzer(CharSequence requestPath) throws Exception
{
return new LocalFuzzer(this, requestPath);
}
public LocalFuzzer newLocalFuzzer(CharSequence requestPath, Map<String,String> upgradeRequest) throws Exception
{
return new LocalFuzzer(this, requestPath, upgradeRequest);
}
protected void configureServletContextHandler(ServletContextHandler context) throws Exception
{
/* override to change context handler */
}
@Override
protected void doStart() throws Exception
{
// Configure Server
server = new Server();
if (ssl)
{
// HTTP Configuration
HttpConfiguration http_config = new HttpConfiguration();
http_config.setSecureScheme("https");
http_config.setSecurePort(0);
http_config.setOutputBufferSize(32768);
http_config.setRequestHeaderSize(8192);
http_config.setResponseHeaderSize(8192);
http_config.setSendServerVersion(true);
http_config.setSendDateHeader(false);
sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath(MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath());
sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd");
sslContextFactory.setExcludeCipherSuites("SSL_RSA_WITH_DES_CBC_SHA", "SSL_DHE_RSA_WITH_DES_CBC_SHA", "SSL_DHE_DSS_WITH_DES_CBC_SHA",
"SSL_RSA_EXPORT_WITH_RC4_40_MD5", "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
// SSL HTTP Configuration
HttpConfiguration https_config = new HttpConfiguration(http_config);
https_config.addCustomizer(new SecureRequestCustomizer());
// SSL Connector
connector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), new HttpConnectionFactory(https_config));
connector.setPort(0);
}
else
{
// Basic HTTP connector
connector = new ServerConnector(server);
connector.setPort(0);
}
// Add network connector
server.addConnector(connector);
// Add Local Connector
localConnector = new LocalConnector(server);
server.addConnector(localConnector);
servletContextHandler = new ServletContextHandler(server, "/", true, false);
servletContextHandler.setContextPath("/");
configureServletContextHandler(servletContextHandler);
server.setHandler(servletContextHandler);
// Start Server
addBean(server);
super.doStart();
// Establish the Server URI
String host = connector.getHost();
if (host == null)
{
host = "localhost";
}
int port = connector.getLocalPort();
serverUri = new URI(String.format("%s://%s:%d/", ssl ? "wss" : "ws", host, port));
// Some debugging
if (LOG.isDebugEnabled())
{
LOG.debug(server.dump());
}
}
}

View File

@ -18,159 +18,39 @@
package org.eclipse.jetty.websocket.tests;
import java.net.URI;
import javax.servlet.http.HttpServlet;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
public class SimpleServletServer extends ContainerLifeCycle
public class SimpleServletServer extends LocalServer implements LocalFuzzer.Provider
{
private static final Logger LOG = Log.getLogger(SimpleServletServer.class);
private Server server;
private ServerConnector connector;
private LocalConnector localConnector;
private URI serverUri;
private HttpServlet servlet;
private boolean ssl = false;
private SslContextFactory sslContextFactory;
private final HttpServlet servlet;
public SimpleServletServer(HttpServlet servlet)
{
super();
this.servlet = servlet;
}
public void enableSsl(boolean ssl)
{
this.ssl = ssl;
}
public LocalConnector getLocalConnector()
{
return localConnector;
}
public URI getServerUri()
{
return serverUri;
}
public SslContextFactory getSslContextFactory()
{
return sslContextFactory;
}
public boolean isSslEnabled()
{
return ssl;
}
@Override
protected void doStart() throws Exception
{
// Configure Server
server = new Server();
if (ssl)
{
// HTTP Configuration
HttpConfiguration http_config = new HttpConfiguration();
http_config.setSecureScheme("https");
http_config.setSecurePort(0);
http_config.setOutputBufferSize(32768);
http_config.setRequestHeaderSize(8192);
http_config.setResponseHeaderSize(8192);
http_config.setSendServerVersion(true);
http_config.setSendDateHeader(false);
sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath(MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath());
sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd");
sslContextFactory.setExcludeCipherSuites("SSL_RSA_WITH_DES_CBC_SHA","SSL_DHE_RSA_WITH_DES_CBC_SHA","SSL_DHE_DSS_WITH_DES_CBC_SHA",
"SSL_RSA_EXPORT_WITH_RC4_40_MD5","SSL_RSA_EXPORT_WITH_DES40_CBC_SHA","SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA");
// SSL HTTP Configuration
HttpConfiguration https_config = new HttpConfiguration(http_config);
https_config.addCustomizer(new SecureRequestCustomizer());
// SSL Connector
connector = new ServerConnector(server,new SslConnectionFactory(sslContextFactory,HttpVersion.HTTP_1_1.asString()),new HttpConnectionFactory(https_config));
connector.setPort(0);
}
else
{
// Basic HTTP connector
connector = new ServerConnector(server);
connector.setPort(0);
}
// Add network connector
server.addConnector(connector);
// Add Local Connector
localConnector = new LocalConnector(server);
server.addConnector(localConnector);
ServletContextHandler context = new ServletContextHandler();
context.setContextPath("/");
configureServletContextHandler(context);
server.setHandler(context);
// Serve capture servlet
context.addServlet(new ServletHolder(servlet),"/*");
// Start Server
addBean(server);
super.doStart();
// Establish the Server URI
String host = connector.getHost();
if (host == null)
{
host = "localhost";
}
int port = connector.getLocalPort();
serverUri = new URI(String.format("%s://%s:%d/",ssl?"wss":"ws",host,port));
// Some debugging
if (LOG.isDebugEnabled())
{
LOG.debug(server.dump());
}
}
protected void configureServletContextHandler(ServletContextHandler context)
{
/* override to change context handler */
// Serve capture servlet
context.addServlet(new ServletHolder(servlet),"/*");
}
public WebSocketServletFactory getWebSocketServletFactory()
{
// Try filter approach first
WebSocketUpgradeFilter filter = (WebSocketUpgradeFilter)this.servlet.getServletContext().getAttribute(WebSocketUpgradeFilter.class.getName());
WebSocketUpgradeFilter filter = (WebSocketUpgradeFilter) this.servlet.getServletContext().getAttribute(WebSocketUpgradeFilter.class.getName());
if (filter != null)
{
return filter.getFactory();
}
// Try servlet next
return (WebSocketServletFactory)this.servlet.getServletContext().getAttribute(WebSocketServletFactory.class.getName());
return (WebSocketServletFactory) this.servlet.getServletContext().getAttribute(WebSocketServletFactory.class.getName());
}
}

View File

@ -0,0 +1,62 @@
//
// ========================================================================
// 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 java.util.Map;
import java.util.TreeMap;
import org.eclipse.jetty.websocket.api.WebSocketConstants;
public class UpgradeUtils
{
public static String generateUpgradeRequest(CharSequence requestPath, Map<String, String> headers)
{
StringBuilder upgradeRequest = new StringBuilder();
upgradeRequest.append("GET ");
upgradeRequest.append(requestPath == null ? "/" : requestPath);
upgradeRequest.append(" HTTP/1.1\r\n");
headers.entrySet().stream().forEach(e ->
upgradeRequest.append(e.getKey()).append(": ").append(e.getValue()).append("\r\n"));
upgradeRequest.append("\r\n");
return upgradeRequest.toString();
}
public static String generateUpgradeRequest()
{
return generateUpgradeRequest("/", newDefaultUpgradeRequestHeaders());
}
public static String generateUpgradeRequest(CharSequence requestPath)
{
return generateUpgradeRequest(requestPath, newDefaultUpgradeRequestHeaders());
}
public static Map<String, String> newDefaultUpgradeRequestHeaders()
{
Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
headers.put("Host", "local");
headers.put("Connection", "Upgrade");
headers.put("Upgrade", "WebSocket");
headers.put(WebSocketConstants.SEC_WEBSOCKET_KEY, "dGhlIHNhbXBsZSBub25jZQ==");
headers.put(WebSocketConstants.SEC_WEBSOCKET_ORIGIN, "ws://local/");
// headers.put(WebSocketConstants.SEC_WEBSOCKET_PROTOCOL, "echo");
headers.put(WebSocketConstants.SEC_WEBSOCKET_VERSION, "13");
return headers;
}
}

View File

@ -24,14 +24,18 @@ import static org.junit.Assert.assertThat;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.util.Map;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
@ -40,58 +44,66 @@ import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.IO;
import org.eclipse.jetty.toolchain.test.JAR;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.OS;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.PathResource;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.FragmentConfiguration;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
import org.eclipse.jetty.websocket.common.Parser;
/**
* Utility to build out exploded directory WebApps, in the /target/tests/ directory, for testing out servers that use javax.websocket endpoints.
* <p>
* This is particularly useful when the WebSocket endpoints are discovered via the javax.websocket annotation scanning.
*/
public class WSServer
public class WSServer implements LocalFuzzer.Provider
{
private static final Logger LOG = Log.getLogger(WSServer.class);
private final File contextDir;
private final Path contextDir;
private final String contextPath;
private final ByteBufferPool bufferPool = new MappedByteBufferPool();
private Server server;
private URI serverUri;
private ContextHandlerCollection contexts;
private File webinf;
private File classesDir;
private LocalConnector localConnector;
private Path webinf;
private Path classesDir;
public WSServer(TestingDir testdir, String contextName)
{
this(testdir.getPath().toFile(),contextName);
this(testdir.getPath(), contextName);
}
public WSServer(File testdir, String contextName)
{
this.contextDir = new File(testdir,contextName);
this(testdir.toPath(), contextName);
}
public WSServer(Path testdir, String contextName)
{
this.contextDir = testdir.resolve(contextName);
this.contextPath = "/" + contextName;
FS.ensureEmpty(contextDir);
}
public void copyClass(Class<?> clazz) throws Exception
{
ClassLoader cl = Thread.currentThread().getContextClassLoader();
String endpointPath = clazz.getName().replace('.','/') + ".class";
String endpointPath = clazz.getName().replace('.', '/') + ".class";
URL classUrl = cl.getResource(endpointPath);
assertThat("Class URL for: " + clazz,classUrl,notNullValue());
File destFile = new File(classesDir,OS.separators(endpointPath));
FS.ensureDirExists(destFile.getParentFile());
assertThat("Class URL for: " + clazz, classUrl, notNullValue());
Path destFile = classesDir.resolve(endpointPath);
FS.ensureDirExists(destFile.getParent());
File srcFile = new File(classUrl.toURI());
IO.copy(srcFile,destFile);
IO.copy(srcFile, destFile.toFile());
}
public void copyEndpoint(Class<?> endpointClass) throws Exception
{
copyClass(endpointClass);
@ -99,65 +111,65 @@ public class WSServer
public void copyLib(Class<?> clazz, String jarFileName) throws URISyntaxException, IOException
{
webinf = new File(contextDir,"WEB-INF");
webinf = contextDir.resolve("WEB-INF");
FS.ensureDirExists(webinf);
File libDir = new File(webinf,"lib");
Path libDir = webinf.resolve("lib");
FS.ensureDirExists(libDir);
File jarFile = new File(libDir, jarFileName);
Path jarFile = libDir.resolve(jarFileName);
URL codeSourceURL = clazz.getProtectionDomain().getCodeSource().getLocation();
assertThat("Class CodeSource URL is file scheme", codeSourceURL.getProtocol(), is("file"));
File sourceCodeSourceFile = new File(codeSourceURL.toURI());
if (sourceCodeSourceFile.isDirectory())
{
LOG.info("Creating " + jarFile + " from " + sourceCodeSourceFile);
JAR.create(sourceCodeSourceFile, jarFile);
JAR.create(sourceCodeSourceFile, jarFile.toFile());
}
else
{
LOG.info("Copying " + sourceCodeSourceFile + " to " + jarFile);
IO.copy(sourceCodeSourceFile, jarFile);
IO.copy(sourceCodeSourceFile, jarFile.toFile());
}
}
public void copyWebInf(String testResourceName) throws IOException
{
webinf = new File(contextDir,"WEB-INF");
webinf = contextDir.resolve("WEB-INF");
FS.ensureDirExists(webinf);
classesDir = new File(webinf,"classes");
classesDir = webinf.resolve("classes");
FS.ensureDirExists(classesDir);
File webxml = new File(webinf,"web.xml");
Path webxml = webinf.resolve("web.xml");
File testWebXml = MavenTestingUtils.getTestResourceFile(testResourceName);
IO.copy(testWebXml,webxml);
IO.copy(testWebXml, webxml.toFile());
}
public WebAppContext createWebAppContext() throws MalformedURLException, IOException
public WebAppContext createWebAppContext() throws IOException
{
WebAppContext context = new WebAppContext();
context.setContextPath(this.contextPath);
context.setBaseResource(Resource.newResource(this.contextDir));
context.setAttribute("org.eclipse.jetty.websocket.jsr356",Boolean.TRUE);
context.setBaseResource(new PathResource(this.contextDir));
context.setAttribute("org.eclipse.jetty.websocket.jsr356", Boolean.TRUE);
// @formatter:off
context.setConfigurations(new Configuration[] {
context.setConfigurations(new Configuration[]{
new AnnotationConfiguration(),
new WebXmlConfiguration(),
new WebInfConfiguration(),
new PlusConfiguration(),
new PlusConfiguration(),
new MetaInfConfiguration(),
new FragmentConfiguration(),
new FragmentConfiguration(),
new EnvConfiguration()});
// @formatter:on
return context;
}
public void createWebInf() throws IOException
{
copyWebInf("empty-web.xml");
}
public void deployWebapp(WebAppContext webapp) throws Exception
{
contexts.addHandler(webapp);
@ -169,12 +181,44 @@ public class WSServer
webapp.dump(System.err);
}
}
public void dump()
{
server.dumpStdErr();
}
public LocalConnector getLocalConnector()
{
return localConnector;
}
@Override
public Parser newClientParser(Parser.Handler parserHandler)
{
return new Parser(WebSocketPolicy.newClientPolicy(), bufferPool, parserHandler);
}
@Override
public LocalConnector.LocalEndPoint newLocalConnection()
{
return getLocalConnector().connect();
}
public LocalFuzzer newLocalFuzzer() throws Exception
{
return new LocalFuzzer(this);
}
public LocalFuzzer newLocalFuzzer(CharSequence requestPath) throws Exception
{
return new LocalFuzzer(this, requestPath);
}
public LocalFuzzer newLocalFuzzer(CharSequence requestPath, Map<String,String> upgradeRequest) throws Exception
{
return new LocalFuzzer(this, requestPath, upgradeRequest);
}
public URI getServerBaseURI()
{
return serverUri;
@ -184,49 +228,57 @@ public class WSServer
{
return server;
}
public File getWebAppDir()
public Path getWebAppDir()
{
return this.contextDir;
}
public void start() throws Exception
{
server = new Server();
// Main network connector
ServerConnector connector = new ServerConnector(server);
connector.setPort(0);
server.addConnector(connector);
// Add Local Connector
localConnector = new LocalConnector(server);
server.addConnector(localConnector);
HandlerCollection handlers = new HandlerCollection();
contexts = new ContextHandlerCollection();
handlers.addHandler(contexts);
server.setHandler(handlers);
server.start();
String host = connector.getHost();
if (host == null)
{
host = "localhost";
}
int port = connector.getLocalPort();
serverUri = new URI(String.format("ws://%s:%d%s/",host,port,contextPath));
serverUri = new URI(String.format("ws://%s:%d%s/", host, port, contextPath));
if (LOG.isDebugEnabled())
LOG.debug("Server started on {}",serverUri);
LOG.debug("Server started on {}", serverUri);
}
public void stop()
{
if (server != null)
if (server == null)
{
try
{
server.stop();
}
catch (Exception e)
{
e.printStackTrace(System.err);
}
return;
}
try
{
server.stop();
}
catch (Exception e)
{
e.printStackTrace(System.err);
}
}
}

View File

@ -1,35 +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.tests.server;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
/**
* Servlet with bigger message policy sizes, with registered simple echo socket.
*/
@SuppressWarnings("serial")
public class ABServlet extends WebSocketServlet
{
@Override
public void configure(WebSocketServletFactory factory)
{
factory.register(ABSocket.class);
}
}

View File

@ -1,84 +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.tests.server;
import java.nio.ByteBuffer;
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.WebSocketException;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.common.util.TextUtil;
/**
* Simple Echo WebSocket, using async writes of echo
*/
@WebSocket(maxTextMessageSize = 20 * 1024 * 1024,
maxBinaryMessageSize = 20 * 1024 * 1024)
public class ABSocket
{
private static Logger LOG = Log.getLogger(ABSocket.class);
private Session session;
@OnWebSocketMessage
public void onBinary(byte buf[], int offset, int len)
{
LOG.debug("onBinary(byte[{}],{},{})",buf.length,offset,len);
// echo the message back.
ByteBuffer data = ByteBuffer.wrap(buf,offset,len);
this.session.getRemote().sendBytes(data,null);
}
@OnWebSocketConnect
public void onOpen(Session sess)
{
this.session = sess;
}
@OnWebSocketMessage
public void onText(String message)
{
if (LOG.isDebugEnabled())
{
if (message == null)
{
LOG.debug("onText() msg=null");
}
else
{
LOG.debug("onText() size={}, msg={}",message.length(),TextUtil.hint(message));
}
}
try
{
// echo the message back.
this.session.getRemote().sendString(message,null);
}
catch (WebSocketException e)
{
LOG.warn("Unable to echo TEXT message",e);
}
}
}

View File

@ -1,244 +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.tests.server;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.Arrays;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.StacklessLogging;
import org.eclipse.jetty.util.log.StdErrLog;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
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.tests.Fuzzed;
import org.eclipse.jetty.websocket.tests.Fuzzer;
import org.eclipse.jetty.websocket.tests.LeakTrackingBufferPoolRule;
import org.eclipse.jetty.websocket.tests.RawFrameBuilder;
import org.eclipse.jetty.websocket.tests.SimpleServletServer;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.rules.TestName;
public abstract class AbstractABCase implements Fuzzed
{
// Allow Fuzzer / Generator to create bad frames for testing frame validation
protected static class BadFrame extends WebSocketFrame
{
public BadFrame(byte opcode)
{
super(OpCode.CONTINUATION);
super.finRsvOp = (byte)((finRsvOp & 0xF0) | (opcode & 0x0F));
// NOTE: Not setting Frame.Type intentionally
}
@Override
public void assertValid()
{
}
@Override
public boolean isControlFrame()
{
return false;
}
@Override
public boolean isDataFrame()
{
return false;
}
}
protected static final byte FIN = (byte)0x80;
protected static final byte NOFIN = 0x00;
protected static final byte[] MASK =
{ 0x12, 0x34, 0x56, 0x78 };
protected Generator strictGenerator;
protected Generator laxGenerator;
protected static SimpleServletServer server;
protected Fuzzer fuzzer;
@Rule
public LeakTrackingBufferPoolRule bufferPool = new LeakTrackingBufferPoolRule("Test");
@Before
public void setup() throws Exception
{
fuzzer = new Fuzzer();
fuzzer.getWSClient().setBufferPool(bufferPool);
fuzzer.start();
WebSocketPolicy policy = WebSocketPolicy.newClientPolicy();
strictGenerator = new Generator(policy,bufferPool,true);
laxGenerator = new Generator(policy,bufferPool,false);
}
@After
public void tearDown() throws Exception
{
fuzzer.stop();
}
@BeforeClass
public static void startEnv() throws Exception
{
server = new SimpleServletServer(new ABServlet());
server.start();
}
@AfterClass
public static void stopEnv() throws Exception
{
server.stop();
}
/**
* Make a copy of a byte buffer.
* <p>
* This is important in some tests, as the underlying byte buffer contained in a Frame can be modified through
* masking and make it difficult to compare the results in the fuzzer.
*
* @param payload the payload to copy
* @return a new byte array of the payload contents
*/
protected ByteBuffer copyOf(byte[] payload)
{
return ByteBuffer.wrap(Arrays.copyOf(payload,payload.length));
}
/**
* Make a copy of a byte buffer.
* <p>
* This is important in some tests, as the underlying byte buffer contained in a Frame can be modified through
* masking and make it difficult to compare the results in the fuzzer.
*
* @param payload the payload to copy
* @return a new byte array of the payload contents
*/
protected ByteBuffer clone(ByteBuffer payload)
{
ByteBuffer copy = ByteBuffer.allocate(payload.remaining());
copy.put(payload.slice());
copy.flip();
return copy;
}
/**
* Make a copy of a byte buffer.
* <p>
* This is important in some tests, as the underlying byte buffer contained in a Frame can be modified through
* masking and make it difficult to compare the results in the fuzzer.
*
* @param payload the payload to copy
* @return a new byte array of the payload contents
*/
protected ByteBuffer copyOf(ByteBuffer payload)
{
ByteBuffer copy = ByteBuffer.allocate(payload.remaining());
BufferUtil.clearToFill(copy);
BufferUtil.put(payload,copy);
BufferUtil.flipToFlush(copy,0);
return copy;
}
public static String toUtf8String(byte[] buf)
{
String raw = StringUtil.toUTF8String(buf,0,buf.length);
StringBuilder ret = new StringBuilder();
int len = raw.length();
for (int i = 0; i < len; i++)
{
int codepoint = raw.codePointAt(i);
if (Character.isUnicodeIdentifierPart(codepoint))
{
ret.append(String.format("\\u%04X",codepoint));
}
else
{
ret.append(Character.toChars(codepoint));
}
}
return ret.toString();
}
@Rule
public TestName testname = new TestName();
/**
* @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
protected void enableStacks(Class<?> clazz, boolean enabled)
{
StdErrLog log = StdErrLog.getLogger(clazz);
log.setHideStacks(!enabled);
}
public Generator getLaxGenerator()
{
return laxGenerator;
}
public SimpleServletServer getServer()
{
return server;
}
@Override
public URI getServerURI()
{
return server.getServerUri();
}
@Override
public String getTestMethodName()
{
return testname.getMethodName();
}
public static byte[] masked(final byte[] data)
{
return RawFrameBuilder.mask(data,MASK);
}
public static void putLength(ByteBuffer buf, int length, boolean masked)
{
RawFrameBuilder.putLength(buf,length,masked);
}
public static void putMask(ByteBuffer buf)
{
buf.put(MASK);
}
public static void putPayloadLength(ByteBuffer buf, int length)
{
putLength(buf,length,true);
}
}

View File

@ -19,36 +19,29 @@
package org.eclipse.jetty.websocket.tests.server;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.toolchain.test.ByteBufferAssert;
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.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.tests.ParserCapture;
import org.eclipse.jetty.websocket.common.frames.BinaryFrame;
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.tests.SimpleServletServer;
import org.eclipse.jetty.websocket.tests.UnitGenerator;
import org.eclipse.jetty.websocket.tests.servlets.EchoServlet;
import org.hamcrest.Matchers;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
@ -59,8 +52,14 @@ import org.junit.rules.TestName;
*/
public abstract class AbstractLocalServerCase
{
@SuppressWarnings("SpellCheckingInspection")
protected static final int KBYTE = 1024;
@SuppressWarnings("SpellCheckingInspection")
protected static final int MBYTE = KBYTE * KBYTE;
protected static SimpleServletServer server;
protected final Logger LOG;
@Rule
public TestName testname = new TestName();
public UnitGenerator generator = new UnitGenerator(WebSocketPolicy.newClientPolicy());
@ -70,41 +69,6 @@ public abstract class AbstractLocalServerCase
LOG = Log.getLogger(this.getClass().getName());
}
/**
* Make a copy of a byte buffer.
* <p>
* This is important in some tests, as the underlying byte buffer contained in a Frame can be modified through
* masking and make it difficult to compare the results in the fuzzer.
*
* @param payload the payload to copy
* @return a new byte array of the payload contents
*/
public static ByteBuffer clone(ByteBuffer payload)
{
ByteBuffer copy = ByteBuffer.allocate(payload.remaining());
copy.put(payload.slice());
copy.flip();
return copy;
}
/**
* Make a copy of a byte buffer.
* <p>
* This is important in some tests, as the underlying byte buffer contained in a Frame can be modified through
* masking and make it difficult to compare the results in the fuzzer.
*
* @param payload the payload to copy
* @return a new byte array of the payload contents
*/
public static ByteBuffer copyOf(ByteBuffer payload)
{
ByteBuffer copy = ByteBuffer.allocate(payload.remaining());
BufferUtil.clearToFill(copy);
BufferUtil.put(payload, copy);
BufferUtil.flipToFlush(copy, 0);
return copy;
}
@BeforeClass
public static void startServer() throws Exception
{
@ -118,91 +82,57 @@ public abstract class AbstractLocalServerCase
server.stop();
}
public void addInputInSegments(LocalConnector.LocalEndPoint endPoint, ByteBuffer outgoing, int segmentSize)
public DataFrame toDataFrame(byte op)
{
while (outgoing.remaining() > 0)
switch (op)
{
int len = Math.min(segmentSize, outgoing.remaining());
ByteBuffer slice = outgoing.slice();
slice.limit(len);
endPoint.addInput(slice);
outgoing.position(outgoing.position() + len);
}
}
public void assertExpected(BlockingQueue<WebSocketFrame> framesQueue, List<WebSocketFrame> expect) throws InterruptedException
{
int expectedCount = expect.size();
String prefix;
for (int i = 0; i < expectedCount; i++)
{
prefix = "Frame[" + i + "]";
WebSocketFrame expected = expect.get(i);
WebSocketFrame actual = framesQueue.poll(1, TimeUnit.SECONDS);
assertThat(prefix + ".poll", actual, notNullValue());
if (LOG.isDebugEnabled())
{
if (actual.getOpCode() == OpCode.CLOSE)
LOG.debug("{} CloseFrame: {}", prefix, new CloseInfo(actual));
else
LOG.debug("{} {}", prefix, actual);
}
assertThat(prefix + ".opcode", OpCode.name(actual.getOpCode()), Matchers.is(OpCode.name(expected.getOpCode())));
prefix += "/" + actual.getOpCode();
if (expected.getOpCode() == OpCode.CLOSE)
{
CloseInfo expectedClose = new CloseInfo(expected);
CloseInfo actualClose = new CloseInfo(actual);
assertThat(prefix + ".statusCode", actualClose.getStatusCode(), Matchers.is(expectedClose.getStatusCode()));
}
else if (expected.hasPayload())
{
assertThat(prefix + ".payloadLength", actual.getPayloadLength(), Matchers.is(expected.getPayloadLength()));
ByteBufferAssert.assertEquals(prefix + ".payload", expected.getPayload(), actual.getPayload());
}
else
{
assertThat(prefix + ".payloadLength", actual.getPayloadLength(), Matchers.is(0));
}
case OpCode.BINARY:
return new BinaryFrame();
case OpCode.TEXT:
return new TextFrame();
case OpCode.CONTINUATION:
return new ContinuationFrame();
default:
throw new IllegalArgumentException("Not a data frame: " + op);
}
}
/**
* Make a copy of a byte buffer.
* <p>
* This is important in some tests, as the underlying byte buffer contained in a Frame can be modified through
* masking and make it difficult to compare the results in the fuzzer.
* Create a new multi-frame data message (TEXT or BINARY with CONTINUATIONS).
*
* @param payload the payload to copy
* @return a new byte array of the payload contents
* @param send the list to add the individual frames making up the message
* @param opcode the opcode (message type: TEXT or BINARY)
* @param overallSize the overall size of the message
* @param frameSize the individual frame size to utilize
* @return the overall message payload (useful for expectation checks)
*/
public ByteBuffer copyOf(byte[] payload)
public ByteBuffer newMultiFrameMessage(List<WebSocketFrame> send, byte opcode, int overallSize, int frameSize)
{
return ByteBuffer.wrap(Arrays.copyOf(payload, payload.length));
}
public String generateUpgradeRequest(String requestPath, Map<String, String> headers)
{
StringBuilder upgradeRequest = new StringBuilder();
upgradeRequest.append("GET ").append(requestPath).append(" HTTP/1.1\r\n");
headers.entrySet().stream().forEach(e ->
upgradeRequest.append(e.getKey()).append(": ").append(e.getValue()).append("\r\n"));
upgradeRequest.append("\r\n");
return upgradeRequest.toString();
}
public String generateUpgradeRequest()
{
return generateUpgradeRequest("/", newDefaultUpgradeRequestHeaders());
}
public String generateUpgradeRequest(String requestPath)
{
return generateUpgradeRequest(requestPath, newDefaultUpgradeRequestHeaders());
byte msg[] = new byte[overallSize];
Arrays.fill(msg, (byte) 'M');
byte frag[];
int remaining = msg.length;
int offset = 0;
boolean fin;
ByteBuffer buf;
byte op = opcode;
while (remaining > 0)
{
int len = Math.min(remaining, frameSize);
frag = new byte[len];
System.arraycopy(msg, offset, frag, 0, len);
remaining -= len;
fin = (remaining <= 0);
buf = ByteBuffer.wrap(frag);
send.add(toDataFrame(op).setPayload(buf).setFin(fin));
offset += len;
op = OpCode.CONTINUATION;
}
return ByteBuffer.wrap(msg);
}
public Parser newClientParser(Parser.Handler parserHandler)
@ -210,31 +140,6 @@ public abstract class AbstractLocalServerCase
return new Parser(WebSocketPolicy.newClientPolicy(), new MappedByteBufferPool(), parserHandler);
}
public Map<String, String> newDefaultUpgradeRequestHeaders()
{
Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
headers.put("Host", "local");
headers.put("Connection", "Upgrade");
headers.put("Upgrade", "WebSocket");
headers.put("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==");
headers.put("Sec-WebSocket-Origin", "ws://local/");
headers.put("Sec-WebSocket-Protocol", "echo");
headers.put("Sec-WebSocket-Version", "13");
return headers;
}
public LocalConnector.LocalEndPoint newLocalConnection()
{
LocalConnector connector = server.getLocalConnector();
LocalConnector.LocalEndPoint endPoint = connector.connect();
return endPoint;
}
public LocalFuzzer newLocalFuzzer() throws Exception
{
return new LocalFuzzer(this);
}
public HttpTester.Response performUpgrade(LocalConnector.LocalEndPoint endPoint, ByteBuffer buf) throws Exception
{
endPoint.addInput(buf);
@ -247,169 +152,4 @@ public abstract class AbstractLocalServerCase
assertThat("Is WebSocket Upgrade", parsedResponse.get("Upgrade"), is("WebSocket"));
return parsedResponse;
}
public static class LocalFuzzer implements AutoCloseable
{
private final AbstractLocalServerCase testcase;
private final LocalConnector.LocalEndPoint endPoint;
public LocalFuzzer(AbstractLocalServerCase testcase) throws Exception
{
this.testcase = testcase;
String upgradeRequest = testcase.generateUpgradeRequest("/");
ByteBuffer upgradeRequestBytes = BufferUtil.toBuffer(upgradeRequest.toString(), StandardCharsets.UTF_8);
this.endPoint = testcase.newLocalConnection();
testcase.performUpgrade(endPoint, upgradeRequestBytes);
}
public ByteBuffer asNetworkBuffer(List<WebSocketFrame> frames)
{
int bufferLength = 0;
for (WebSocketFrame f : frames)
{
bufferLength += f.getPayloadLength() + Generator.MAX_HEADER_LENGTH;
}
ByteBuffer buffer = ByteBuffer.allocate(bufferLength);
for (WebSocketFrame f : frames)
{
testcase.generator.generate(buffer, f);
}
BufferUtil.flipToFlush(buffer, 0);
return buffer;
}
public void close() throws Exception
{
endPoint.close();
}
/**
* Send the EOF signal
*/
public void eof()
{
endPoint.addInputEOF();
}
public void expect(List<WebSocketFrame> expected) throws InterruptedException
{
// Get incoming frames
// Wait for server to close
endPoint.waitUntilClosed();
// Get the server send echo bytes
ByteBuffer incoming = endPoint.getOutput();
// Parse those bytes into frames
ParserCapture capture = new ParserCapture();
Parser parser = testcase.newClientParser(capture);
parser.parse(incoming);
testcase.assertExpected(capture.framesQueue, expected);
}
/**
* Send raw bytes
*/
public void send(ByteBuffer buffer)
{
endPoint.addInput(buffer);
}
/**
* Send some of the raw bytes
*
* @param buffer the buffer
* @param length the number of bytes to send from buffer
*/
public void send(ByteBuffer buffer, int length)
{
int limit = Math.min(length, buffer.remaining());
ByteBuffer sliced = buffer.slice();
sliced.limit(limit);
endPoint.addInput(sliced);
buffer.position(buffer.position() + limit);
}
/**
* Generate a single ByteBuffer representing the entire
* list of generated frames, and submit it to {@link org.eclipse.jetty.server.LocalConnector.LocalEndPoint#addInput(ByteBuffer)}
*
* @param frames the list of frames to send
*/
public void sendBulk(List<WebSocketFrame> frames)
{
int bufferLength = 0;
for (WebSocketFrame f : frames)
{
bufferLength += f.getPayloadLength() + Generator.MAX_HEADER_LENGTH;
}
ByteBuffer outgoing = ByteBuffer.allocate(bufferLength);
boolean eof = false;
for (WebSocketFrame f : frames)
{
testcase.generator.generate(outgoing, f);
if (f.getOpCode() == OpCode.CLOSE)
eof = true;
}
BufferUtil.flipToFlush(outgoing, 0);
endPoint.addInput(outgoing);
if (eof)
endPoint.addInputEOF();
}
/**
* Generate a ByteBuffer for each frame, and submit each to
* {@link org.eclipse.jetty.server.LocalConnector.LocalEndPoint#addInput(ByteBuffer)}
*
* @param frames the list of frames to send
*/
public void sendFrames(List<WebSocketFrame> frames)
{
boolean eof = false;
for (WebSocketFrame f : frames)
{
ByteBuffer buffer = testcase.generator.generate(f);
endPoint.addInput(buffer);
if (f.getOpCode() == OpCode.CLOSE)
eof = true;
}
if (eof)
endPoint.addInputEOF();
}
/**
* Generate a ByteBuffer for each frame, and submit each to
* {@link org.eclipse.jetty.server.LocalConnector.LocalEndPoint#addInput(ByteBuffer)}
*
* @param frames the list of frames to send
*/
public void sendSegmented(List<WebSocketFrame> frames, int segmentSize)
{
int bufferLength = 0;
for (WebSocketFrame f : frames)
{
bufferLength += f.getPayloadLength() + Generator.MAX_HEADER_LENGTH;
}
ByteBuffer outgoing = ByteBuffer.allocate(bufferLength);
boolean eof = false;
for (WebSocketFrame f : frames)
{
testcase.generator.generate(outgoing, f);
if (f.getOpCode() == OpCode.CLOSE)
eof = true;
}
BufferUtil.flipToFlush(outgoing, 0);
testcase.addInputInSegments(endPoint, outgoing, segmentSize);
if (eof)
endPoint.addInputEOF();
}
}
}

View File

@ -31,6 +31,7 @@ import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.PingFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.tests.BadFrame;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@ -70,9 +71,9 @@ public class BadOpCodesTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -92,9 +93,9 @@ public class BadOpCodesTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("hello")); // echo
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);

View File

@ -0,0 +1,437 @@
//
// ========================================================================
// 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.server;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
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.BinaryFrame;
import org.eclipse.jetty.websocket.tests.DataUtils;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.junit.Test;
/**
* Binary message / frame tests
*/
public class BinaryTest extends AbstractLocalServerCase
{
/**
* Echo 16MB binary message (1 frame)
* <p>
* From Autobahn WebSocket Server Testcase 9.2.6
* </p>
* @throws Exception on test failure
*/
@Test
public void testBinary_16mb_SingleFrame() throws Exception
{
byte data[] = new byte[16 * MBYTE];
Arrays.fill(data,(byte)0x26);
ByteBuffer buf = ByteBuffer.wrap(data);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(DataUtils.copyOf(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Echo 1MB binary message (1 frame)
* <p>
* From Autobahn WebSocket Server Testcase 9.2.3
* </p>
* @throws Exception on test failure
*/
@Test
public void testBinary_1mb_SingleFrame() throws Exception
{
byte data[] = new byte[1 * MBYTE];
Arrays.fill(data,(byte)0x23);
ByteBuffer buf = ByteBuffer.wrap(data);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(DataUtils.copyOf(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Echo 256KB binary message (1 frame)
* <p>
* From Autobahn WebSocket Server Testcase 9.2.2
* </p>
* @throws Exception on test failure
*/
@Test
public void testBinary_256kb_SingleFrame() throws Exception
{
byte data[] = new byte[256 * KBYTE];
Arrays.fill(data,(byte)0x22);
ByteBuffer buf = ByteBuffer.wrap(data);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(DataUtils.copyOf(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Send 4MB binary message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 9.4.5
* </p>
* @throws Exception on test failure
*/
@Test
public void testBinary_4mb_Frames_16kb() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.BINARY, 4 * MBYTE, 16 * KBYTE);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Send 4MB binary message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 9.4.3
* </p>
* @throws Exception on test failure
*/
@Test
public void testBinary_4mb_Frames_1kb() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.BINARY, 4 * MBYTE, 1 * KBYTE);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Send 4MB binary message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 9.4.8
* </p>
* @throws Exception on test failure
*/
@Test
public void testBinary_4mb_Frames_1mb() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.BINARY, 4 * MBYTE, 1 * MBYTE);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Send 4MB binary message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 9.4.2
* </p>
* @throws Exception on test failure
*/
@Test
public void testBinary_4mb_Frames_256b() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.BINARY, 4 * MBYTE, 256);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Send 4MB binary message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 9.4.7
* </p>
* @throws Exception on test failure
*/
@Test
public void testBinary_4mb_Frames_256kb() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.BINARY, 4 * MBYTE, 256 * KBYTE);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Send 4MB binary message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 9.4.4
* </p>
* @throws Exception on test failure
*/
@Test
public void testBinary_4mb_Frames_4kb() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.BINARY, 4 * MBYTE, 4 * KBYTE);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Send 4MB binary message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 9.4.9
* </p>
* @throws Exception on test failure
*/
@Test
public void testBinary_4mb_Frames_4mb() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.BINARY, 4 * MBYTE, 4 * MBYTE);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Send 4MB binary message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 9.4.1
* </p>
* @throws Exception on test failure
*/
@Test
public void testBinary_4mb_Frames_64b() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.BINARY, 4 * MBYTE, 64);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Send 4MB binary message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 9.4.6
* </p>
* @throws Exception on test failure
*/
@Test
public void testBinary_4mb_Frames_64kb() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.BINARY, 4 * MBYTE, 64 * KBYTE);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Echo 4MB binary message (1 frame)
* <p>
* From Autobahn WebSocket Server Testcase 9.2.4
* </p>
* @throws Exception on test failure
*/
@Test
public void testBinary_4mb_SingleFrame() throws Exception
{
byte data[] = new byte[4 * MBYTE];
Arrays.fill(data,(byte)0x24);
ByteBuffer buf = ByteBuffer.wrap(data);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(DataUtils.copyOf(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Echo 64KB binary message (1 frame)
* <p>
* From Autobahn WebSocket Server Testcase 9.2.1
* </p>
* @throws Exception on test failure
*/
@Test
public void testBinary_64kb_SingleFrame() throws Exception
{
byte data[] = new byte[64 * KBYTE];
Arrays.fill(data,(byte)0x21);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload(data));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(DataUtils.copyOf(data)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Echo 8MB binary message (1 frame)
* <p>
* From Autobahn WebSocket Server Testcase 9.2.5
* </p>
* @throws Exception on test failure
*/
@Test
public void testBinary_8mb_SingleFrame() throws Exception
{
byte data[] = new byte[8 * MBYTE];
Arrays.fill(data,(byte)0x25);
ByteBuffer buf = ByteBuffer.wrap(data);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(DataUtils.copyOf(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
}

View File

@ -38,6 +38,8 @@ import org.eclipse.jetty.websocket.common.frames.PingFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection;
import org.eclipse.jetty.websocket.tests.BadFrame;
import org.eclipse.jetty.websocket.tests.DataUtils;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.junit.Test;
/**
@ -63,9 +65,9 @@ public class CloseHandlingTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -95,9 +97,9 @@ public class CloseHandlingTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class,CloseInfo.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -120,7 +122,7 @@ public class CloseHandlingTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -146,9 +148,9 @@ public class CloseHandlingTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL,reason).asFrame());
try (StacklessLogging ignored = new StacklessLogging(AbstractWebSocketConnection.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -173,7 +175,7 @@ public class CloseHandlingTest extends AbstractLocalServerCase
expect.add(new TextFrame().setPayload("Hello World"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -197,7 +199,7 @@ public class CloseHandlingTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -220,7 +222,7 @@ public class CloseHandlingTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -243,7 +245,7 @@ public class CloseHandlingTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL,"Hic").asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -267,7 +269,7 @@ public class CloseHandlingTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -291,7 +293,7 @@ public class CloseHandlingTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -316,7 +318,7 @@ public class CloseHandlingTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -343,10 +345,10 @@ public class CloseHandlingTest extends AbstractLocalServerCase
send.add(new PingFrame().setPayload("out of band"));
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new TextFrame().setPayload(DataUtils.copyOf(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);

View File

@ -25,13 +25,11 @@ import java.util.List;
import org.eclipse.jetty.util.BufferUtil;
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.StatusCode;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.CloseFrame;
import org.eclipse.jetty.websocket.tests.Fuzzer;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@ -41,11 +39,9 @@ import org.junit.runners.Parameterized.Parameters;
* Test Bad Close Status Codes
*/
@RunWith(value = Parameterized.class)
public class TestABCase7_BadStatusCodes extends AbstractABCase
public class CloseHandling_BadStatusCodesTest extends AbstractLocalServerCase
{
private static final Logger LOG = Log.getLogger(TestABCase7_GoodStatusCodes.class);
@Parameters
@Parameters(name = "{0} {1}")
public static Collection<Object[]> data()
{
// The various Good UTF8 sequences as a String (hex form)
@ -75,7 +71,7 @@ public class TestABCase7_BadStatusCodes extends AbstractABCase
private final int statusCode;
public TestABCase7_BadStatusCodes(String testId, int statusCode)
public CloseHandling_BadStatusCodesTest(String testId, int statusCode)
{
LOG.debug("Test ID: {}", testId);
this.statusCode = statusCode;
@ -99,11 +95,10 @@ public class TestABCase7_BadStatusCodes extends AbstractABCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (Fuzzer.Session session = fuzzer.connect(this))
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.bulkMode();
session.send(send);
session.sendBulk(send);
session.expect(expect);
}
}
@ -127,11 +122,10 @@ public class TestABCase7_BadStatusCodes extends AbstractABCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (Fuzzer.Session session = fuzzer.connect(this))
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.bulkMode();
session.send(send);
session.sendBulk(send);
session.expect(expect);
}
}

View File

@ -29,7 +29,8 @@ 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.CloseFrame;
import org.eclipse.jetty.websocket.tests.Fuzzer;
import org.eclipse.jetty.websocket.tests.DataUtils;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@ -39,11 +40,11 @@ import org.junit.runners.Parameterized.Parameters;
* Test Good Close Status Codes
*/
@RunWith(value = Parameterized.class)
public class TestABCase7_GoodStatusCodes extends AbstractABCase
public class CloseHandling_GoodStatusCodesTest extends AbstractLocalServerCase
{
private static final Logger LOG = Log.getLogger(TestABCase7_GoodStatusCodes.class);
private static final Logger LOG = Log.getLogger(CloseHandling_GoodStatusCodesTest.class);
@Parameters
@Parameters(name = "{0} {1}")
public static Collection<Object[]> data()
{
// The various Good UTF8 sequences as a String (hex form)
@ -70,7 +71,7 @@ public class TestABCase7_GoodStatusCodes extends AbstractABCase
private final int statusCode;
public TestABCase7_GoodStatusCodes(String testId, int statusCode)
public CloseHandling_GoodStatusCodesTest(String testId, int statusCode)
{
LOG.debug("Test ID: {}", testId);
this.statusCode = statusCode;
@ -93,12 +94,11 @@ public class TestABCase7_GoodStatusCodes extends AbstractABCase
send.add(new CloseFrame().setPayload(payload.slice()));
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseFrame().setPayload(clone(payload)));
try (Fuzzer.Session session = fuzzer.connect(this))
expect.add(new CloseFrame().setPayload(DataUtils.copyOf(payload)));
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.bulkMode();
session.send(send);
session.sendBulk(send);
session.expect(expect);
}
}
@ -120,12 +120,11 @@ public class TestABCase7_GoodStatusCodes extends AbstractABCase
send.add(new CloseFrame().setPayload(payload.slice()));
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseFrame().setPayload(clone(payload)));
try (Fuzzer.Session session = fuzzer.connect(this))
expect.add(new CloseFrame().setPayload(DataUtils.copyOf(payload)));
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.bulkMode();
session.send(send);
session.sendBulk(send);
session.expect(expect);
}
}

View File

@ -36,6 +36,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.tests.ParserCapture;
import org.eclipse.jetty.websocket.tests.UpgradeUtils;
import org.junit.Test;
/**
@ -57,7 +58,7 @@ public class ConnectionUpgradeToBufferTest extends AbstractLocalServerCase
ByteBuffer buf = ByteBuffer.allocate(4096);
// Create Upgrade Request Header
String upgradeRequest = generateUpgradeRequest("/");
String upgradeRequest = UpgradeUtils.generateUpgradeRequest("/");
ByteBuffer upgradeRequestBytes = BufferUtil.toBuffer(upgradeRequest.toString(), StandardCharsets.UTF_8);
BufferUtil.put(upgradeRequestBytes, buf);
@ -70,7 +71,7 @@ public class ConnectionUpgradeToBufferTest extends AbstractLocalServerCase
generator.generate(buf, frames);
// Send this buffer to the server
LocalConnector.LocalEndPoint endPoint = newLocalConnection();
LocalConnector.LocalEndPoint endPoint = server.newLocalConnection();
BufferUtil.flipToFlush(buf,0);
performUpgrade(endPoint, buf);

View File

@ -31,6 +31,7 @@ import org.eclipse.jetty.websocket.common.frames.ContinuationFrame;
import org.eclipse.jetty.websocket.common.frames.PingFrame;
import org.eclipse.jetty.websocket.common.frames.PongFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.junit.Test;
/**
@ -55,9 +56,9 @@ public class ContinuationTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -81,9 +82,9 @@ public class ContinuationTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendFrames(send);
session.expect(expect);
@ -107,9 +108,9 @@ public class ContinuationTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendSegmented(send,1 );
session.expect(expect);
@ -135,7 +136,7 @@ public class ContinuationTest extends AbstractLocalServerCase
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -162,9 +163,9 @@ public class ContinuationTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("fragment1fragment2"));
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -188,9 +189,9 @@ public class ContinuationTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendFrames(send);
session.expect(expect);
@ -218,9 +219,9 @@ public class ContinuationTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -244,9 +245,9 @@ public class ContinuationTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendSegmented(send,1);
session.expect(expect);
@ -274,9 +275,9 @@ public class ContinuationTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -300,9 +301,9 @@ public class ContinuationTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -326,9 +327,9 @@ public class ContinuationTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -352,9 +353,9 @@ public class ContinuationTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -381,7 +382,7 @@ public class ContinuationTest extends AbstractLocalServerCase
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -406,9 +407,9 @@ public class ContinuationTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("hello, world"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendFrames(send);
session.expect(expect);
@ -441,9 +442,9 @@ public class ContinuationTest extends AbstractLocalServerCase
expect.add(new PongFrame().setPayload("pong-2"));
expect.add(new TextFrame().setPayload("f1,f2,f3,f4,f5"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -468,9 +469,9 @@ public class ContinuationTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("hello, world"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendSegmented(send,1);
session.expect(expect);
@ -499,7 +500,7 @@ public class ContinuationTest extends AbstractLocalServerCase
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -526,9 +527,9 @@ public class ContinuationTest extends AbstractLocalServerCase
expect.add(new PongFrame().setPayload("ping"));
expect.add(new TextFrame().setPayload("hello, world"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendFrames(send);
session.expect(expect);
@ -555,9 +556,9 @@ public class ContinuationTest extends AbstractLocalServerCase
expect.add(new PongFrame().setPayload("ping"));
expect.add(new TextFrame().setPayload("hello, world"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendSegmented(send,1);
session.expect(expect);

View File

@ -28,6 +28,8 @@ import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.BinaryFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.tests.DataUtils;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@ -69,10 +71,10 @@ public class PayloadLengthTest extends AbstractLocalServerCase
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new TextFrame().setPayload(DataUtils.copyOf(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -91,10 +93,10 @@ public class PayloadLengthTest extends AbstractLocalServerCase
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new TextFrame().setPayload(DataUtils.copyOf(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendSegmented(send, 10);
session.expect(expect);
@ -113,10 +115,10 @@ public class PayloadLengthTest extends AbstractLocalServerCase
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new BinaryFrame().setPayload(DataUtils.copyOf(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -135,10 +137,10 @@ public class PayloadLengthTest extends AbstractLocalServerCase
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new BinaryFrame().setPayload(DataUtils.copyOf(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendSegmented(send, 10);
session.expect(expect);

View File

@ -33,6 +33,8 @@ 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.tests.BadFrame;
import org.eclipse.jetty.websocket.tests.DataUtils;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.junit.Test;
public class PingPongTest extends AbstractLocalServerCase
@ -66,8 +68,8 @@ public class PingPongTest extends AbstractLocalServerCase
}
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -103,8 +105,8 @@ public class PingPongTest extends AbstractLocalServerCase
}
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendSegmented(send, 5);
session.expect(expect);
@ -130,10 +132,10 @@ public class PingPongTest extends AbstractLocalServerCase
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new PongFrame().setPayload(copyOf(payload)));
expect.add(new PongFrame().setPayload(DataUtils.copyOf(payload)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -159,10 +161,10 @@ public class PingPongTest extends AbstractLocalServerCase
send.add(new CloseInfo(StatusCode.NORMAL, "Test 2.6").asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new PongFrame().setPayload(copyOf(payload)));
expect.add(new PongFrame().setPayload(DataUtils.copyOf(payload)));
expect.add(new CloseInfo(StatusCode.NORMAL, "Test 2.6").asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendSegmented(send, 1);
session.expect(expect);
@ -187,8 +189,8 @@ public class PingPongTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new PongFrame());
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -219,8 +221,8 @@ public class PingPongTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -246,10 +248,10 @@ public class PingPongTest extends AbstractLocalServerCase
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new PongFrame().setPayload(copyOf(payload)));
expect.add(new PongFrame().setPayload(DataUtils.copyOf(payload)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -274,10 +276,10 @@ public class PingPongTest extends AbstractLocalServerCase
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new PongFrame().setPayload(copyOf(payload)));
expect.add(new PongFrame().setPayload(DataUtils.copyOf(payload)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -301,8 +303,8 @@ public class PingPongTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -326,8 +328,8 @@ public class PingPongTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -353,8 +355,8 @@ public class PingPongTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new PongFrame().setPayload("our ping")); // our pong
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);

View File

@ -30,6 +30,7 @@ import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.BinaryFrame;
import org.eclipse.jetty.websocket.common.frames.PingFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.junit.Test;
/**
@ -54,7 +55,7 @@ public class ReservedBitTest extends AbstractLocalServerCase
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -81,7 +82,7 @@ public class ReservedBitTest extends AbstractLocalServerCase
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -106,9 +107,9 @@ public class ReservedBitTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("small")); // echo on good frame
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendFrames(send);
session.expect(expect);
@ -133,9 +134,9 @@ public class ReservedBitTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("small")); // echo on good frame
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendSegmented(send, 1);
session.expect(expect);
@ -162,7 +163,7 @@ public class ReservedBitTest extends AbstractLocalServerCase
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -187,9 +188,9 @@ public class ReservedBitTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -217,7 +218,7 @@ public class ReservedBitTest extends AbstractLocalServerCase
expect.add(new CloseInfo(StatusCode.PROTOCOL).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);

View File

@ -1,787 +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.tests.server;
import java.nio.ByteBuffer;
import java.util.ArrayList;
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;
import org.eclipse.jetty.websocket.common.OpCode;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.BinaryFrame;
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.tests.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;
private static final int MBYTE = KBYTE * KBYTE;
private DataFrame toDataFrame(byte op)
{
switch (op)
{
case OpCode.BINARY:
return new BinaryFrame();
case OpCode.TEXT:
return new TextFrame();
case OpCode.CONTINUATION:
return new ContinuationFrame();
default:
throw new IllegalArgumentException("Not a data frame: " + op);
}
}
private void assertMultiFrameEcho(byte opcode, int overallMsgSize, int fragmentSize) throws Exception
{
byte msg[] = new byte[overallMsgSize];
Arrays.fill(msg,(byte)'M');
List<WebSocketFrame> send = new ArrayList<>();
byte frag[];
int remaining = msg.length;
int offset = 0;
boolean fin;
ByteBuffer buf;
;
byte op = opcode;
while (remaining > 0)
{
int len = Math.min(remaining,fragmentSize);
frag = new byte[len];
System.arraycopy(msg,offset,frag,0,len);
remaining -= len;
fin = (remaining <= 0);
buf = ByteBuffer.wrap(frag);
send.add(toDataFrame(op).setPayload(buf).setFin(fin));
offset += len;
op = OpCode.CONTINUATION;
}
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(toDataFrame(opcode).setPayload(copyOf(msg)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(Fuzzer.Session session = fuzzer.connect(this))
{
session.bulkMode();
session.send(send);
session.expect(expect, 32, TimeUnit.SECONDS);
}
}
private void assertSlowFrameEcho(byte opcode, int overallMsgSize, int segmentSize) throws Exception
{
byte msg[] = new byte[overallMsgSize];
Arrays.fill(msg,(byte)'M');
ByteBuffer buf = ByteBuffer.wrap(msg);
List<WebSocketFrame> send = new ArrayList<>();
send.add(toDataFrame(opcode).setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(toDataFrame(opcode).setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(Fuzzer.Session session = fuzzer.connect(this))
{
session.slowMode(segmentSize);
session.send(send);
session.expect(expect, 32, TimeUnit.SECONDS);
}
}
/**
* Echo 64KB text message (1 frame)
* @throws Exception on test failure
*/
@Test
public void testCase9_1_1() throws Exception
{
byte utf[] = new byte[64 * KBYTE];
Arrays.fill(utf,(byte)'y');
String msg = StringUtil.toUTF8String(utf,0,utf.length);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(msg));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(msg));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(Fuzzer.Session session = fuzzer.connect(this))
{
session.bulkMode();
session.send(send);
session.expect(expect);
}
}
/**
* Echo 256KB text message (1 frame)
* @throws Exception on test failure
*/
@Test
public void testCase9_1_2() throws Exception
{
byte utf[] = new byte[256 * KBYTE];
Arrays.fill(utf,(byte)'y');
ByteBuffer buf = ByteBuffer.wrap(utf);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(Fuzzer.Session session = fuzzer.connect(this))
{
session.bulkMode();
session.send(send);
session.expect(expect);
}
}
/**
* Echo 1MB text message (1 frame)
* @throws Exception on test failure
*/
@Test
public void testCase9_1_3() throws Exception
{
byte utf[] = new byte[1 * MBYTE];
Arrays.fill(utf,(byte)'y');
ByteBuffer buf = ByteBuffer.wrap(utf);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(Fuzzer.Session session = fuzzer.connect(this))
{
session.bulkMode();
session.send(send);
session.expect(expect);
}
}
/**
* Echo 4MB text message (1 frame)
* @throws Exception on test failure
*/
@Test
public void testCase9_1_4() throws Exception
{
byte utf[] = new byte[4 * MBYTE];
Arrays.fill(utf,(byte)'y');
ByteBuffer buf = ByteBuffer.wrap(utf);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(Fuzzer.Session session = fuzzer.connect(this))
{
session.bulkMode();
session.send(send);
session.expect(expect);
}
}
/**
* Echo 8MB text message (1 frame)
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_1_5() throws Exception
{
byte utf[] = new byte[8 * MBYTE];
Arrays.fill(utf,(byte)'y');
ByteBuffer buf = ByteBuffer.wrap(utf);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(Fuzzer.Session session = fuzzer.connect(this))
{
session.bulkMode();
session.send(send);
session.expect(expect, 16, TimeUnit.SECONDS);
}
}
/**
* Echo 16MB text message (1 frame)
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_1_6() throws Exception
{
byte utf[] = new byte[16 * MBYTE];
Arrays.fill(utf,(byte)'y');
ByteBuffer buf = ByteBuffer.wrap(utf);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(Fuzzer.Session session = fuzzer.connect(this))
{
session.bulkMode();
session.send(send);
session.expect(expect, 32, TimeUnit.SECONDS);
}
}
/**
* Echo 64KB binary message (1 frame)
* @throws Exception on test failure
*/
@Test
public void testCase9_2_1() throws Exception
{
byte data[] = new byte[64 * KBYTE];
Arrays.fill(data,(byte)0x21);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload(data));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(copyOf(data)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(Fuzzer.Session session = fuzzer.connect(this))
{
session.bulkMode();
session.send(send);
session.expect(expect);
}
}
/**
* Echo 256KB binary message (1 frame)
* @throws Exception on test failure
*/
@Test
public void testCase9_2_2() throws Exception
{
byte data[] = new byte[256 * KBYTE];
Arrays.fill(data,(byte)0x22);
ByteBuffer buf = ByteBuffer.wrap(data);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(Fuzzer.Session session = fuzzer.connect(this))
{
session.bulkMode();
session.send(send);
session.expect(expect);
}
}
/**
* Echo 1MB binary message (1 frame)
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_2_3() throws Exception
{
byte data[] = new byte[1 * MBYTE];
Arrays.fill(data,(byte)0x23);
ByteBuffer buf = ByteBuffer.wrap(data);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(Fuzzer.Session session = fuzzer.connect(this))
{
session.bulkMode();
session.send(send);
session.expect(expect);
}
}
/**
* Echo 4MB binary message (1 frame)
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_2_4() throws Exception
{
byte data[] = new byte[4 * MBYTE];
Arrays.fill(data,(byte)0x24);
ByteBuffer buf = ByteBuffer.wrap(data);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(Fuzzer.Session session = fuzzer.connect(this))
{
session.bulkMode();
session.send(send);
session.expect(expect);
}
}
/**
* Echo 8MB binary message (1 frame)
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_2_5() throws Exception
{
byte data[] = new byte[8 * MBYTE];
Arrays.fill(data,(byte)0x25);
ByteBuffer buf = ByteBuffer.wrap(data);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(Fuzzer.Session session = fuzzer.connect(this))
{
session.bulkMode();
session.send(send);
session.expect(expect,16,TimeUnit.SECONDS);
}
}
/**
* Echo 16MB binary message (1 frame)
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_2_6() throws Exception
{
byte data[] = new byte[16 * MBYTE];
Arrays.fill(data,(byte)0x26);
ByteBuffer buf = ByteBuffer.wrap(data);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(clone(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(Fuzzer.Session session = fuzzer.connect(this))
{
session.bulkMode();
session.send(send);
session.expect(expect,32,TimeUnit.SECONDS);
}
}
/**
* Send 4MB text message in multiple frames.
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_3_1() throws Exception
{
assertMultiFrameEcho(OpCode.TEXT,4 * MBYTE,64);
}
/**
* Send 4MB text message in multiple frames.
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_3_2() throws Exception
{
assertMultiFrameEcho(OpCode.TEXT,4 * MBYTE,256);
}
/**
* Send 4MB text message in multiple frames.
* @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);
}
/**
* Send 4MB text message in multiple frames.
* @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);
}
/**
* Send 4MB text message in multiple frames.
* @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);
}
/**
* Send 4MB text message in multiple frames.
* @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);
}
/**
* Send 4MB text message in multiple frames.
* @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);
}
/**
* Send 4MB text message in multiple frames.
* @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);
}
/**
* Send 4MB text message in multiple frames.
* @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);
}
/**
* Send 4MB binary message in multiple frames.
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_4_1() throws Exception
{
assertMultiFrameEcho(OpCode.BINARY,4 * MBYTE,64);
}
/**
* Send 4MB binary message in multiple frames.
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_4_2() throws Exception
{
assertMultiFrameEcho(OpCode.BINARY,4 * MBYTE,256);
}
/**
* Send 4MB binary message in multiple frames.
* @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);
}
/**
* Send 4MB binary message in multiple frames.
* @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);
}
/**
* Send 4MB binary message in multiple frames.
* @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);
}
/**
* Send 4MB binary message in multiple frames.
* @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);
}
/**
* Send 4MB binary message in multiple frames.
* @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);
}
/**
* Send 4MB binary message in multiple frames.
* @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);
}
/**
* Send 4MB binary message in multiple frames.
* @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);
}
/**
* Send 1MB text message in 1 frame, but slowly
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_5_1() throws Exception
{
assertSlowFrameEcho(OpCode.TEXT,1 * MBYTE,64);
}
/**
* Send 1MB text message in 1 frame, but slowly
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_5_2() throws Exception
{
assertSlowFrameEcho(OpCode.TEXT,1 * MBYTE,128);
}
/**
* Send 1MB text message in 1 frame, but slowly
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_5_3() throws Exception
{
assertSlowFrameEcho(OpCode.TEXT,1 * MBYTE,256);
}
/**
* Send 1MB text message in 1 frame, but slowly
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_5_4() throws Exception
{
assertSlowFrameEcho(OpCode.TEXT,1 * MBYTE,512);
}
/**
* Send 1MB text message in 1 frame, but slowly
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_5_5() throws Exception
{
assertSlowFrameEcho(OpCode.TEXT,1 * MBYTE,1024);
}
/**
* Send 1MB text message in 1 frame, but slowly
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_5_6() throws Exception
{
assertSlowFrameEcho(OpCode.TEXT,1 * MBYTE,2048);
}
/**
* Send 1MB binary message in 1 frame, but slowly
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_6_1() throws Exception
{
assertSlowFrameEcho(OpCode.BINARY,1 * MBYTE,64);
}
/**
* Send 1MB binary message in 1 frame, but slowly
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_6_2() throws Exception
{
assertSlowFrameEcho(OpCode.BINARY,1 * MBYTE,128);
}
/**
* Send 1MB binary message in 1 frame, but slowly
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_6_3() throws Exception
{
assertSlowFrameEcho(OpCode.BINARY,1 * MBYTE,256);
}
/**
* Send 1MB binary message in 1 frame, but slowly
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_6_4() throws Exception
{
assertSlowFrameEcho(OpCode.BINARY,1 * MBYTE,512);
}
/**
* Send 1MB binary message in 1 frame, but slowly
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_6_5() throws Exception
{
assertSlowFrameEcho(OpCode.BINARY,1 * MBYTE,1024);
}
/**
* Send 1MB binary message in 1 frame, but slowly
* @throws Exception on test failure
*/
@Test
@Stress("High I/O use")
public void testCase9_6_6() throws Exception
{
assertSlowFrameEcho(OpCode.BINARY,1 * MBYTE,2048);
}
}

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.websocket.tests.server;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
@ -30,69 +31,44 @@ import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.StacklessLogging;
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.Parser;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
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.tests.DataUtils;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.junit.Test;
/**
* UTF-8 Tests
*/
public class TextUTF8Test extends AbstractLocalServerCase
public class TextTest extends AbstractLocalServerCase
{
/**
* Split a message byte array into a series of fragments (frames + continuations) of 1 byte message contents each.
*
* @param frames the frames
* @param msg the message
*/
private void fragmentText(List<WebSocketFrame> frames, byte msg[])
{
int len = msg.length;
boolean continuation = false;
byte mini[];
for (int i = 0; i < len; i++)
{
DataFrame frame;
if (continuation)
{
frame = new ContinuationFrame();
}
else
{
frame = new TextFrame();
}
mini = new byte[1];
mini[0] = msg[i];
frame.setPayload(ByteBuffer.wrap(mini));
boolean isLast = (i >= (len - 1));
frame.setFin(isLast);
frames.add(frame);
continuation = true;
}
}
/**
* text message, 1 frame, 0 length
* Echo 16MB text message (1 frame)
* <p>
* From Autobahn WebSocket Server Testcase 6.1.1
* From Autobahn WebSocket Server Testcase 9.1.6
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_Empty() throws Exception
public void testText_16mb_SingleFrame() throws Exception
{
byte utf[] = new byte[16 * MBYTE];
Arrays.fill(utf,(byte)'y');
ByteBuffer buf = ByteBuffer.wrap(utf);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame());
send.add(new TextFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame());
expect.add(new TextFrame().setPayload(DataUtils.copyOf(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -100,26 +76,29 @@ public class TextUTF8Test extends AbstractLocalServerCase
}
/**
* text message, 0 length, 3 fragments
* Echo 1MB text message (1 frame)
* <p>
* From Autobahn WebSocket Server Testcase 6.1.2
* From Autobahn WebSocket Server Testcase 9.1.3
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_Continuation_Continuation_AllEmpty() throws Exception
public void testText_1mb_SingleFrame() throws Exception
{
//noinspection PointlessArithmeticExpression
byte utf[] = new byte[1 * MBYTE];
Arrays.fill(utf,(byte)'y');
ByteBuffer buf = ByteBuffer.wrap(utf);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setFin(false));
send.add(new ContinuationFrame().setFin(false));
send.add(new ContinuationFrame().setFin(true));
send.add(new TextFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame());
expect.add(new TextFrame().setPayload(DataUtils.copyOf(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -127,26 +106,28 @@ public class TextUTF8Test extends AbstractLocalServerCase
}
/**
* text message, small length, 3 fragments (only middle frame has payload)
* Echo 256KB text message (1 frame)
* <p>
* From Autobahn WebSocket Server Testcase 6.1.3
* From Autobahn WebSocket Server Testcase 9.1.2
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_ContinuationWithPayload_Continuation() throws Exception
public void testText_256k_SingleFrame() throws Exception
{
byte utf[] = new byte[256 * KBYTE];
Arrays.fill(utf,(byte)'y');
ByteBuffer buf = ByteBuffer.wrap(utf);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setFin(false));
send.add(new ContinuationFrame().setPayload("middle").setFin(false));
send.add(new ContinuationFrame().setFin(true));
send.add(new TextFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("middle"));
expect.add(new TextFrame().setPayload(DataUtils.copyOf(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -154,35 +135,24 @@ public class TextUTF8Test extends AbstractLocalServerCase
}
/**
* valid utf8 text message, 2 fragments (on UTF8 code point boundary)
* Send 4MB text message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 6.2.2
* From Autobahn WebSocket Server Testcase 9.3.5
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_SplitOnCodePointBoundary() throws Exception
public void testText_4mb_Frames_16kb() throws Exception
{
String utf1 = "Hello-\uC2B5@\uC39F\uC3A4";
String utf2 = "\uC3BC\uC3A0\uC3A1-UTF-8!!";
ByteBuffer b1 = ByteBuffer.wrap(StringUtil.getUtf8Bytes(utf1));
ByteBuffer b2 = ByteBuffer.wrap(StringUtil.getUtf8Bytes(utf2));
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(b1).setFin(false));
send.add(new ContinuationFrame().setPayload(b2).setFin(true));
ByteBuffer payload = newMultiFrameMessage(send, OpCode.TEXT, 4 * MBYTE, 16 * KBYTE);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
ByteBuffer e1 = ByteBuffer.allocate(100);
e1.put(StringUtil.getUtf8Bytes(utf1));
e1.put(StringUtil.getUtf8Bytes(utf2));
e1.flip();
expect.add(new TextFrame().setPayload(e1));
expect.add(new TextFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -190,27 +160,24 @@ public class TextUTF8Test extends AbstractLocalServerCase
}
/**
* valid utf8 text message, many fragments (1 byte each)
* Send 4MB text message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 6.2.3
* From Autobahn WebSocket Server Testcase 9.3.3
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_ManyContinuationsNotOnCodePoints_Hello() throws Exception
public void testText_4mb_Frames_1kb() throws Exception
{
String utf8 = "Hello-\uC2B5@\uC39F\uC3A4\uC3BC\uC3A0\uC3A1-UTF-8!!";
byte msg[] = StringUtil.getUtf8Bytes(utf8);
List<WebSocketFrame> send = new ArrayList<>();
fragmentText(send, msg);
ByteBuffer payload = newMultiFrameMessage(send, OpCode.TEXT, 4 * MBYTE, 1 * KBYTE);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(ByteBuffer.wrap(msg)));
expect.add(new TextFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -218,26 +185,261 @@ public class TextUTF8Test extends AbstractLocalServerCase
}
/**
* valid utf8 text message, many fragments (1 byte each)
* Send 4MB text message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 6.2.4
* From Autobahn WebSocket Server Testcase 9.3.8
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_ManyContinuationsNotOnCodePoints() throws Exception
public void testText_4mb_Frames_1mb() throws Exception
{
byte msg[] = Hex.asByteArray("CEBAE1BDB9CF83CEBCCEB5");
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.TEXT, 4 * MBYTE, 1 * MBYTE);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Send 4MB text message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 9.3.2
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_4mb_Frames_256b() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.TEXT, 4 * MBYTE, 256);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Send 4MB text message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 9.3.7
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_4mb_Frames_256kb() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.TEXT, 4 * MBYTE, 256 * KBYTE);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Send 4MB text message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 9.3.4
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_4mb_Frames_4kb() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.TEXT, 4 * MBYTE, 4 * KBYTE);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Send 4MB text message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 9.3.9
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_4mb_Frames_4mb() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.TEXT, 4 * MBYTE, 4 * MBYTE);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Send 4MB text message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 9.3.1
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_4mb_Frames_64b() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.TEXT, 4*MBYTE, 64);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Send 4MB text message in multiple frames.
* <p>
* From Autobahn WebSocket Server Testcase 9.3.6
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_4mb_Frames_64kb() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
ByteBuffer payload = newMultiFrameMessage(send, OpCode.TEXT, 4 * MBYTE, 64 * KBYTE);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(payload));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Echo 4MB text message (1 frame)
* <p>
* From Autobahn WebSocket Server Testcase 9.1.4
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_4mb_SingleFrame() throws Exception
{
byte utf[] = new byte[4 * MBYTE];
Arrays.fill(utf,(byte)'y');
ByteBuffer buf = ByteBuffer.wrap(utf);
List<WebSocketFrame> send = new ArrayList<>();
fragmentText(send, msg);
send.add(new TextFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(ByteBuffer.wrap(msg)));
expect.add(new TextFrame().setPayload(DataUtils.copyOf(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Echo 64KB text message (1 frame)
* <p>
* From Autobahn WebSocket Server Testcase 9.1.1
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_64k_SingleFrame() throws Exception
{
byte utf[] = new byte[64 * KBYTE];
Arrays.fill(utf,(byte)'y');
String msg = StringUtil.toUTF8String(utf,0,utf.length);
try (LocalFuzzer session = newLocalFuzzer())
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(msg));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(msg));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Echo 8MB text message (1 frame)
* <p>
* From Autobahn WebSocket Server Testcase 9.1.5
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_8mb_SingleFrame() throws Exception
{
byte utf[] = new byte[8 * MBYTE];
Arrays.fill(utf,(byte)'y');
ByteBuffer buf = ByteBuffer.wrap(utf);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(buf));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(DataUtils.copyOf(buf)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
@ -262,14 +464,68 @@ public class TextUTF8Test extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* invalid text message, 1 frame/fragment (slowly, and split within code points)
* <p>
* From Autobahn WebSocket Server Testcase 6.4.3
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_BadUtf8_ByteWise() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
try (StacklessLogging ignored = new StacklessLogging(Parser.class))
{
ByteBuffer payload = ByteBuffer.allocate(64);
BufferUtil.clearToFill(payload);
payload.put(TypeUtil.fromHexString("cebae1bdb9cf83cebcceb5")); // good
payload.put(TypeUtil.fromHexString("f4908080")); // INVALID
payload.put(TypeUtil.fromHexString("656469746564")); // good
BufferUtil.flipToFlush(payload, 0);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(payload));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer())
{
ByteBuffer net = session.asNetworkBuffer(send);
int splits[] = {17, 21, net.limit()};
ByteBuffer part1 = net.slice(); // Header + good UTF
part1.limit(splits[0]);
ByteBuffer part2 = net.slice(); // invalid UTF
part2.position(splits[0]);
part2.limit(splits[1]);
ByteBuffer part3 = net.slice(); // good UTF
part3.position(splits[1]);
part3.limit(splits[2]);
session.send(part1); // the header + good utf
TimeUnit.MILLISECONDS.sleep(500);
session.send(part2); // the bad UTF
TimeUnit.MILLISECONDS.sleep(500);
session.send(part3); // the rest (shouldn't work)
session.eof();
session.expect(expect);
}
}
}
/**
* invalid text message, 3 fragments.
* <p>
@ -297,8 +553,8 @@ public class TextUTF8Test extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendFrames(send);
session.expect(expect);
@ -335,68 +591,14 @@ public class TextUTF8Test extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendFrames(send);
session.expect(expect);
}
}
/**
* invalid text message, 1 frame/fragment (slowly, and split within code points)
* <p>
* From Autobahn WebSocket Server Testcase 6.4.3
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_BadUtf8_ByteWise() throws Exception
{
// Disable Long Stacks from Parser (we know this test will throw an exception)
try (StacklessLogging ignored = new StacklessLogging(Parser.class))
{
ByteBuffer payload = ByteBuffer.allocate(64);
BufferUtil.clearToFill(payload);
payload.put(TypeUtil.fromHexString("cebae1bdb9cf83cebcceb5")); // good
payload.put(TypeUtil.fromHexString("f4908080")); // INVALID
payload.put(TypeUtil.fromHexString("656469746564")); // good
BufferUtil.flipToFlush(payload, 0);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(payload));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
{
ByteBuffer net = session.asNetworkBuffer(send);
int splits[] = {17, 21, net.limit()};
ByteBuffer part1 = net.slice(); // Header + good UTF
part1.limit(splits[0]);
ByteBuffer part2 = net.slice(); // invalid UTF
part2.position(splits[0]);
part2.limit(splits[1]);
ByteBuffer part3 = net.slice(); // good UTF
part3.position(splits[1]);
part3.limit(splits[2]);
session.send(part1); // the header + good utf
TimeUnit.MILLISECONDS.sleep(500);
session.send(part2); // the bad UTF
TimeUnit.MILLISECONDS.sleep(500);
session.send(part3); // the rest (shouldn't work)
session.eof();
session.expect(expect);
}
}
}
/**
* invalid text message, 1 frame/fragment (slowly, and split within code points)
* <p>
@ -415,9 +617,9 @@ public class TextUTF8Test extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
ByteBuffer net = session.asNetworkBuffer(send);
session.send(net, 6);
@ -428,4 +630,206 @@ public class TextUTF8Test extends AbstractLocalServerCase
session.expect(expect);
}
}
/**
* text message, small length, 3 fragments (only middle frame has payload)
* <p>
* From Autobahn WebSocket Server Testcase 6.1.3
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_ContinuationWithPayload_Continuation() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setFin(false));
send.add(new ContinuationFrame().setPayload("middle").setFin(false));
send.add(new ContinuationFrame().setFin(true));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("middle"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* text message, 0 length, 3 fragments
* <p>
* From Autobahn WebSocket Server Testcase 6.1.2
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_Continuation_Continuation_AllEmpty() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setFin(false));
send.add(new ContinuationFrame().setFin(false));
send.add(new ContinuationFrame().setFin(true));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame());
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* text message, 1 frame, 0 length
* <p>
* From Autobahn WebSocket Server Testcase 6.1.1
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_Empty() throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame());
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame());
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* valid utf8 text message, many fragments (1 byte each)
* <p>
* From Autobahn WebSocket Server Testcase 6.2.4
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_Utf8ContinuationsNotOnCodePoints() throws Exception
{
byte msg[] = Hex.asByteArray("CEBAE1BDB9CF83CEBCCEB5");
List<WebSocketFrame> send = new ArrayList<>();
fragmentText(send, msg);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(ByteBuffer.wrap(msg)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* valid utf8 text message, many fragments (1 byte each)
* <p>
* From Autobahn WebSocket Server Testcase 6.2.3
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_Utf8ContinuationsNotOnCodePoints_Hello() throws Exception
{
String utf8 = "Hello-\uC2B5@\uC39F\uC3A4\uC3BC\uC3A0\uC3A1-UTF-8!!";
byte msg[] = StringUtil.getUtf8Bytes(utf8);
List<WebSocketFrame> send = new ArrayList<>();
fragmentText(send, msg);
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(ByteBuffer.wrap(msg)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* valid utf8 text message, 2 fragments (on UTF8 code point boundary)
* <p>
* From Autobahn WebSocket Server Testcase 6.2.2
* </p>
* @throws Exception on test failure
*/
@Test
public void testText_Utf8SplitOnCodePointBoundary() throws Exception
{
String utf1 = "Hello-\uC2B5@\uC39F\uC3A4";
String utf2 = "\uC3BC\uC3A0\uC3A1-UTF-8!!";
ByteBuffer b1 = ByteBuffer.wrap(StringUtil.getUtf8Bytes(utf1));
ByteBuffer b2 = ByteBuffer.wrap(StringUtil.getUtf8Bytes(utf2));
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(b1).setFin(false));
send.add(new ContinuationFrame().setPayload(b2).setFin(true));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
ByteBuffer e1 = ByteBuffer.allocate(100);
e1.put(StringUtil.getUtf8Bytes(utf1));
e1.put(StringUtil.getUtf8Bytes(utf2));
e1.flip();
expect.add(new TextFrame().setPayload(e1));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);
}
}
/**
* Split a message byte array into a series of fragments (frames + continuations) of 1 byte message contents each.
*
* @param frames the frames
* @param msg the message
*/
private void fragmentText(List<WebSocketFrame> frames, byte msg[])
{
int len = msg.length;
boolean continuation = false;
byte mini[];
for (int i = 0; i < len; i++)
{
DataFrame frame;
if (continuation)
{
frame = new ContinuationFrame();
}
else
{
frame = new TextFrame();
}
mini = new byte[1];
mini[0] = msg[i];
frame.setPayload(ByteBuffer.wrap(mini));
boolean isLast = (i >= (len - 1));
frame.setFin(isLast);
frames.add(frame);
continuation = true;
}
}
}

View File

@ -28,6 +28,8 @@ import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.tests.DataUtils;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@ -39,7 +41,7 @@ import org.junit.runners.Parameterized.Parameters;
* Should be preserved / echoed back, with normal close code.
*/
@RunWith(Parameterized.class)
public class TextUTF8_GoodValuesTest extends AbstractLocalServerCase
public class Text_GoodUtf8Test extends AbstractLocalServerCase
{
@Parameters(name = "{0} - {1}")
public static Collection<String[]> data()
@ -117,7 +119,7 @@ public class TextUTF8_GoodValuesTest extends AbstractLocalServerCase
private final ByteBuffer msg;
public TextUTF8_GoodValuesTest(String testId, String hexMsg)
public Text_GoodUtf8Test(String testId, String hexMsg)
{
LOG.debug("Test ID: {}", testId);
this.msg = Hex.asByteBuffer(hexMsg);
@ -131,10 +133,10 @@ public class TextUTF8_GoodValuesTest extends AbstractLocalServerCase
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(clone(msg)));
expect.add(new TextFrame().setPayload(DataUtils.copyOf(msg)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = newLocalFuzzer())
try (LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);

View File

@ -30,6 +30,7 @@ import org.eclipse.jetty.websocket.common.CloseInfo;
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.tests.LocalFuzzer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@ -39,7 +40,7 @@ import org.junit.runners.Parameterized.Parameters;
* Tests of Known Bad UTF8 sequences that should trigger a {@link StatusCode#BAD_PAYLOAD} close and early connection termination
*/
@RunWith(Parameterized.class)
public class TextUTF8_InvalidValuesTest extends AbstractLocalServerCase
public class Text_InvalidUtf8Test extends AbstractLocalServerCase
{
@Parameters(name = "{0} - {1}")
public static Collection<String[]> data()
@ -142,7 +143,7 @@ public class TextUTF8_InvalidValuesTest extends AbstractLocalServerCase
private final byte[] invalid;
public TextUTF8_InvalidValuesTest(String testId, String hexMsg)
public Text_InvalidUtf8Test(String testId, String hexMsg)
{
LOG.debug("Test ID: {}",testId);
this.invalid = Hex.asByteArray(hexMsg);
@ -157,9 +158,9 @@ public class TextUTF8_InvalidValuesTest extends AbstractLocalServerCase
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new CloseInfo(StatusCode.BAD_PAYLOAD).asFrame());
try (StacklessLogging ignored = new StacklessLogging(Parser.class);
LocalFuzzer session = newLocalFuzzer())
LocalFuzzer session = server.newLocalFuzzer())
{
session.sendBulk(send);
session.expect(expect);

View File

@ -16,24 +16,25 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356.server;
package org.eclipse.jetty.websocket.tests.server.jsr356;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.net.URI;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.servlet.FilterHolder;
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.LeakTrackingBufferPoolRule;
import org.eclipse.jetty.websocket.jsr356.server.samples.echo.BasicEchoSocket;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.eclipse.jetty.websocket.tests.WSServer;
import org.eclipse.jetty.websocket.tests.server.jsr356.sockets.BasicEchoSocket;
import org.junit.Rule;
import org.junit.Test;
@ -60,7 +61,6 @@ public class AltFilterTest
try
{
wsb.start();
URI uri = wsb.getServerBaseURI();
WebAppContext webapp = wsb.createWebAppContext();
wsb.deployWebapp(webapp);
@ -71,24 +71,18 @@ public class AltFilterTest
FilterHolder filterSCI = webapp.getServletHandler().getFilter("Jetty_WebSocketUpgradeFilter");
assertThat("Filter[Jetty_WebSocketUpgradeFilter]", filterSCI, nullValue());
WebSocketClient client = new WebSocketClient(bufferPool);
try
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload("Hello Echo"));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("Hello Echo"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try(LocalFuzzer session = wsb.newLocalFuzzer("/app/echo;jsession=xyz"))
{
client.start();
JettyEchoSocket clientSocket = new JettyEchoSocket();
Future<Session> clientConnectFuture = client.connect(clientSocket,uri.resolve("echo"));
// wait for connect
Session clientSession = clientConnectFuture.get(5,TimeUnit.SECONDS);
clientSocket.sendMessage("Hello Echo");
String incomingMessage = clientSocket.messageQueue.poll(1, TimeUnit.SECONDS);
assertEquals("Expected message","Hello Echo",incomingMessage);
clientSession.close();
clientSocket.awaitCloseEvent("Client");
}
finally
{
client.stop();
session.sendFrames(send);
session.expect(expect);
}
}
finally

View File

@ -16,27 +16,29 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356.server;
package org.eclipse.jetty.websocket.tests.server.jsr356;
import static org.hamcrest.Matchers.containsString;
import java.net.URI;
import java.nio.file.Path;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
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.LeakTrackingBufferPoolRule;
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;
import org.eclipse.jetty.websocket.jsr356.server.samples.echo.EchoSocketConfigurator;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketConstants;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.tests.LeakTrackingBufferPoolRule;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.eclipse.jetty.websocket.tests.UpgradeUtils;
import org.eclipse.jetty.websocket.tests.WSServer;
import org.eclipse.jetty.websocket.tests.server.jsr356.coders.DateDecoder;
import org.eclipse.jetty.websocket.tests.server.jsr356.coders.TimeEncoder;
import org.eclipse.jetty.websocket.tests.server.jsr356.configs.EchoSocketConfigurator;
import org.eclipse.jetty.websocket.tests.server.jsr356.sockets.ConfiguredEchoSocket;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
@ -48,94 +50,85 @@ public class AnnotatedServerEndpointTest
{
@Rule
public LeakTrackingBufferPoolRule bufferPool = new LeakTrackingBufferPoolRule("Test");
private static WSServer server;
@BeforeClass
public static void startServer() throws Exception
{
Path testdir = MavenTestingUtils.getTargetTestingPath(AnnotatedServerEndpointTest.class.getName());
server = new WSServer(testdir,"app");
server = new WSServer(testdir, "app");
server.createWebInf();
server.copyEndpoint(ConfiguredEchoSocket.class);
server.copyClass(EchoSocketConfigurator.class);
server.copyClass(DateDecoder.class);
server.copyClass(TimeEncoder.class);
server.start();
WebAppContext webapp = server.createWebAppContext();
server.deployWebapp(webapp);
}
@AfterClass
public static void stopServer()
{
server.stop();
}
private void assertResponse(String message, String expectedText) throws Exception
{
WebSocketClient client = new WebSocketClient(bufferPool);
try
Map<String, String> upgradeRequest = UpgradeUtils.newDefaultUpgradeRequestHeaders();
upgradeRequest.put(WebSocketConstants.SEC_WEBSOCKET_PROTOCOL, "echo");
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(message));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(expectedText));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer("/app/echo", upgradeRequest))
{
client.start();
JettyEchoSocket clientSocket = new JettyEchoSocket();
URI uri = server.getServerBaseURI().resolve("echo");
ClientUpgradeRequest req = new ClientUpgradeRequest();
req.setSubProtocols("echo");
Future<Session> clientConnectFuture = client.connect(clientSocket,uri,req);
// wait for connect
Session clientSession = clientConnectFuture.get(5,TimeUnit.SECONDS);
clientSocket.sendMessage(message);
String incomingMessage = clientSocket.messageQueue.poll(1, TimeUnit.SECONDS);
Assert.assertThat("Expected message",incomingMessage,containsString(expectedText));
clientSession.close();
clientSocket.awaitCloseEvent("Client");
}
finally
{
client.stop();
session.sendFrames(send);
session.expect(expect);
}
}
@Test
public void testConfigurator() throws Exception
{
assertResponse("configurator",EchoSocketConfigurator.class.getName());
assertResponse("configurator", EchoSocketConfigurator.class.getName());
}
@Test
public void testTextMax() throws Exception
{
assertResponse("text-max","111,222");
assertResponse("text-max", "111,222");
}
@Test
public void testBinaryMax() throws Exception
{
assertResponse("binary-max","333,444");
assertResponse("binary-max", "333,444");
}
@Test
public void testDecoders() throws Exception
{
assertResponse("decoders",DateDecoder.class.getName());
assertResponse("decoders", DateDecoder.class.getName());
}
@Test
public void testEncoders() throws Exception
{
assertResponse("encoders",TimeEncoder.class.getName());
assertResponse("encoders", TimeEncoder.class.getName());
}
@Test
public void testSubProtocols() throws Exception
{
assertResponse("subprotocols","chat, echo, test");
assertResponse("subprotocols", "chat, echo, test");
}
}

View File

@ -0,0 +1,164 @@
//
// ========================================================================
// 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.server.jsr356;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.servlet.ServletContextHandler;
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.BinaryFrame;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.eclipse.jetty.websocket.tests.DataUtils;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.eclipse.jetty.websocket.tests.LocalServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class BinaryStreamTest
{
private static final String PATH = "/echo";
private static LocalServer server;
private static ServerContainer container;
@BeforeClass
public static void startServer() throws Exception
{
server = new LocalServer()
{
@Override
protected void configureServletContextHandler(ServletContextHandler context) throws Exception
{
container = WebSocketServerContainerInitializer.configureContext(context);
ServerEndpointConfig config = ServerEndpointConfig.Builder.create(ServerBinaryStreamer.class, PATH).build();
container.addEndpoint(config);
}
};
server.start();
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
}
@Test
public void testEchoWithMediumMessage() throws Exception
{
testEcho(1024);
}
@Test
public void testLargestMessage() throws Exception
{
testEcho(container.getDefaultMaxBinaryMessageBufferSize());
}
private byte[] newData(int size)
{
byte[] pattern = "01234567890abcdefghijlklmopqrstuvwxyz".getBytes(StandardCharsets.UTF_8);
byte[] data = new byte[size];
for (int i = 0; i < size; i++)
{
data[i] = pattern[i % pattern.length];
}
return data;
}
private void testEcho(int size) throws Exception
{
byte[] data = newData(size);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload(data));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
ByteBuffer expectedMessage = DataUtils.copyOf(data);
try (LocalFuzzer session = server.newLocalFuzzer("/echo"))
{
session.sendBulk(send);
BlockingQueue<WebSocketFrame> receivedFrames = session.getOutputFrames();
session.expectMessage(receivedFrames, OpCode.BINARY, expectedMessage);
}
}
@Test
public void testMoreThanLargestMessageOneByteAtATime() throws Exception
{
int size = container.getDefaultMaxBinaryMessageBufferSize() + 16;
byte[] data = newData(size);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload(data));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
ByteBuffer expectedMessage = DataUtils.copyOf(data);
try (LocalFuzzer session = server.newLocalFuzzer("/echo"))
{
session.sendSegmented(send, 1);
BlockingQueue<WebSocketFrame> receivedFrames = session.getOutputFrames();
session.expectMessage(receivedFrames, OpCode.BINARY, expectedMessage);
}
}
@ServerEndpoint(PATH)
public static class ServerBinaryStreamer
{
private static final Logger LOG = Log.getLogger(ServerBinaryStreamer.class);
@OnMessage
public void echo(Session session, InputStream input) throws IOException
{
byte[] buffer = new byte[128];
try (OutputStream output = session.getBasicRemote().getSendStream())
{
int readCount = 0;
int read;
while ((read = input.read(buffer)) >= 0)
{
output.write(buffer, 0, read);
readCount += read;
}
LOG.debug("Read {} bytes", readCount);
}
}
}
}

View File

@ -83,6 +83,7 @@ public class ConfiguratorTest
{
}
@SuppressWarnings("unused")
@ServerEndpoint(value = "/empty", configurator = EmptyConfigurator.class)
public static class EmptySocket
{
@ -102,6 +103,7 @@ public class ConfiguratorTest
}
}
@SuppressWarnings("unused")
@ServerEndpoint(value = "/no-extensions", configurator = NoExtensionsConfigurator.class)
public static class NoExtensionsSocket
{
@ -132,6 +134,7 @@ public class ConfiguratorTest
}
}
@SuppressWarnings("unused")
@ServerEndpoint(value = "/capture-request-headers", configurator = CaptureHeadersConfigurator.class)
public static class CaptureHeadersSocket
{
@ -183,6 +186,7 @@ public class ConfiguratorTest
}
}
@SuppressWarnings("unused")
@ServerEndpoint(value = "/protocols", configurator = ProtocolsConfigurator.class)
public static class ProtocolsSocket
{
@ -225,6 +229,7 @@ public class ConfiguratorTest
}
}
@SuppressWarnings("unused")
@ServerEndpoint(value = "/unique-user-props", configurator = UniqueUserPropsConfigurator.class)
public static class UniqueUserPropsSocket
{
@ -261,6 +266,7 @@ public class ConfiguratorTest
}
}
@SuppressWarnings("unused")
@ServerEndpoint(value = "/addr", configurator = AddrConfigurator.class)
public static class AddressSocket
{
@ -341,6 +347,7 @@ public class ConfiguratorTest
}
}
@SuppressWarnings("unused")
@ServerEndpoint(value = "/timedecoder",
subprotocols = {"time", "gmt"},
configurator = SelectedProtocolConfigurator.class,

View File

@ -0,0 +1,153 @@
//
// ========================================================================
// 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.server.jsr356;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.servlet.ServletContextHandler;
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.StatusCode;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.BinaryFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.eclipse.jetty.websocket.tests.LocalServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Test various {@link javax.websocket.Decoder.BinaryStream Decoder.BinaryStream} echo behavior of Java InputStreams
*/
public class InputStreamEchoTest
{
private static final Logger LOG = Log.getLogger(InputStreamEchoTest.class);
public static class BaseSocket
{
@OnError
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error", cause);
}
}
@SuppressWarnings("unused")
@ServerEndpoint("/echo/stream")
public static class InputStreamSocket extends BaseSocket
{
@OnMessage
public String onStream(InputStream stream) throws IOException
{
return IO.toString(stream);
}
}
@SuppressWarnings("unused")
@ServerEndpoint("/echo/stream-param/{param}")
public static class InputStreamParamSocket extends BaseSocket
{
@OnMessage
public String onStream(InputStream stream, @PathParam("param") String param) throws IOException
{
StringBuilder msg = new StringBuilder();
msg.append(IO.toString(stream));
msg.append('|');
msg.append(param);
return msg.toString();
}
}
private static LocalServer server;
@BeforeClass
public static void startServer() throws Exception
{
server = new LocalServer()
{
@Override
protected void configureServletContextHandler(ServletContextHandler context) throws Exception
{
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
container.addEndpoint(InputStreamSocket.class);
container.addEndpoint(InputStreamParamSocket.class);
}
};
server.start();
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
}
@Test
public void testInputStreamSocket() throws Exception
{
String requestPath = "/echo/stream";
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload("Hello World"));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("Hello World"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer(requestPath))
{
session.sendBulk(send);
session.expect(expect);
}
}
@Test
public void testInputStreamParamSocket() throws Exception
{
String requestPath = "/echo/stream-param/Every%20Person";
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload("Hello World"));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("Hello World|Every Person"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer(requestPath))
{
session.sendBulk(send);
session.expect(expect);
}
}
}

View File

@ -0,0 +1,226 @@
//
// ========================================================================
// 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.server.jsr356;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.websocket.CloseReason;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.eclipse.jetty.websocket.tests.LocalServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
/**
* Tests various ways to echo with JSR356
*/
@RunWith(Parameterized.class)
public class JsrEchoTest
{
@SuppressWarnings("unused")
@ServerEndpoint("/echo/basic")
public static class EchoBasicTextSocket
{
private Session session;
@OnOpen
public void onOpen(Session session)
{
this.session = session;
}
@OnMessage
public void onText(String msg)
{
try
{
session.getBasicRemote().sendText(msg);
}
catch (IOException esend)
{
esend.printStackTrace(System.err);
try
{
session.close(new CloseReason(CloseReason.CloseCodes.getCloseCode(4001), "Unable to echo msg"));
}
catch (IOException eclose)
{
eclose.printStackTrace();
}
}
}
}
@SuppressWarnings("unused")
@ServerEndpoint("/echo/basic-stateless")
public static class EchoBasicStatelessTextSocket
{
@OnMessage
public void onText(Session session, String msg)
{
try
{
session.getBasicRemote().sendText(msg);
}
catch (IOException esend)
{
esend.printStackTrace(System.err);
try
{
session.close(new CloseReason(CloseReason.CloseCodes.getCloseCode(4001), "Unable to echo msg"));
}
catch (IOException eclose)
{
eclose.printStackTrace();
}
}
}
}
@SuppressWarnings("unused")
@ServerEndpoint("/echo/async")
public static class EchoAsyncTextSocket
{
private Session session;
@OnOpen
public void onOpen(Session session)
{
this.session = session;
}
@OnMessage
public void onText(String msg)
{
session.getAsyncRemote().sendText(msg);
}
}
@SuppressWarnings("unused")
@ServerEndpoint("/echo/async-stateless")
public static class EchoAsyncStatelessSocket
{
@OnMessage
public void onText(Session session, String msg)
{
session.getAsyncRemote().sendText(msg);
}
}
@SuppressWarnings("unused")
@ServerEndpoint("/echo/text/return")
public static class EchoReturnTextSocket
{
@OnMessage
public String onText(String msg)
{
return msg;
}
}
private static final List<Class<?>> TESTCLASSES = Arrays.asList(
EchoBasicTextSocket.class,
EchoBasicStatelessTextSocket.class,
EchoAsyncTextSocket.class,
EchoAsyncStatelessSocket.class,
EchoReturnTextSocket.class);
@Parameterized.Parameters(name = "{0}")
public static List<Object[]> data()
{
List<Object[]> data = new ArrayList<>();
for (Class<?> clazz : TESTCLASSES)
{
data.add(new Object[]{clazz.getSimpleName(), clazz});
}
return data;
}
private static LocalServer server;
@BeforeClass
public static void startServer() throws Exception
{
server = new LocalServer()
{
@Override
protected void configureServletContextHandler(ServletContextHandler context) throws Exception
{
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
for (Class<?> clazz : TESTCLASSES)
{
container.addEndpoint(clazz);
}
}
};
server.start();
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
}
@Parameterized.Parameter
public String endpointClassname;
@Parameterized.Parameter(1)
public Class<?> endpointClass;
@Test
public void testTextEcho() throws Exception
{
String requestPath = endpointClass.getAnnotation(ServerEndpoint.class).value();
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload("Hello Echo"));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("Hello Echo"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer(requestPath))
{
session.sendBulk(send);
session.expect(expect);
}
}
}

View File

@ -0,0 +1,176 @@
//
// ========================================================================
// 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.server.jsr356;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.servlet.ServletContextHandler;
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.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.ContinuationFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.eclipse.jetty.websocket.tests.LocalServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Sends raw TEXT or BINARY messages to server.
* <p>
* JSR356 Decoder resolves it to an object, and uses the JSR356 Encoder to produce an echo response.
* </p>
*/
public class PartialEchoTest
{
private static final Logger LOG = Log.getLogger(PartialEchoTest.class);
public static class BaseSocket
{
@OnError
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error", cause);
}
}
@SuppressWarnings("unused")
@ServerEndpoint("/echo/partial/text")
public static class PartialTextSocket extends BaseSocket
{
private Session session;
private StringBuilder buf = new StringBuilder();
@OnOpen
public void onOpen(Session session)
{
this.session = session;
}
@OnMessage
public void onPartial(String msg, boolean fin) throws IOException
{
buf.append("('").append(msg).append("',").append(fin).append(')');
if (fin)
{
session.getBasicRemote().sendText(buf.toString());
buf.setLength(0);
}
}
}
@SuppressWarnings("unused")
@ServerEndpoint("/echo/partial/text-session")
public static class PartialTextSessionSocket extends BaseSocket
{
private StringBuilder buf = new StringBuilder();
@OnMessage
public void onPartial(String msg, boolean fin, Session session) throws IOException
{
buf.append("('").append(msg).append("',").append(fin).append(')');
if (fin)
{
session.getBasicRemote().sendText(buf.toString());
buf.setLength(0);
}
}
}
private static LocalServer server;
@BeforeClass
public static void startServer() throws Exception
{
server = new LocalServer()
{
@Override
protected void configureServletContextHandler(ServletContextHandler context) throws Exception
{
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
container.addEndpoint(PartialTextSocket.class);
container.addEndpoint(PartialTextSessionSocket.class);
}
};
server.start();
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
}
@Test
public void testPartialText() throws Exception
{
String requestPath = "/echo/partial/text";
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload("Hello").setFin(false));
send.add(new ContinuationFrame().setPayload(", ").setFin(false));
send.add(new ContinuationFrame().setPayload("World").setFin(true));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("('Hello',false)(', ',false)('World',true)"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer(requestPath))
{
session.sendBulk(send);
session.expect(expect);
}
}
@Test
public void testPartialTextSession() throws Exception
{
String requestPath = "/echo/partial/text-session";
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload("Hello").setFin(false));
send.add(new ContinuationFrame().setPayload(", ").setFin(false));
send.add(new ContinuationFrame().setPayload("World").setFin(true));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("('Hello',false)(', ',false)('World',true)"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer(requestPath))
{
session.sendBulk(send);
session.expect(expect);
}
}
}

View File

@ -0,0 +1,169 @@
//
// ========================================================================
// 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.server.jsr356;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.toolchain.test.Hex;
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.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.BinaryFrame;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.eclipse.jetty.websocket.tests.LocalServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
/**
* Test various {@link javax.websocket.Decoder.Binary Decoder.Binary} / {@link javax.websocket.Encoder.Binary Encoder.Binary} echo behavior of Java Primitives
*/
@RunWith(Parameterized.class)
public class PrimitivesBinaryEchoTest
{
private static final Logger LOG = Log.getLogger(PrimitivesBinaryEchoTest.class);
public static class BaseSocket
{
@OnError
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error", cause);
}
}
@ServerEndpoint("/echo/bytebuffer")
public static class ByteBufferEchoSocket extends BaseSocket
{
@OnMessage
public ByteBuffer onMessage(ByteBuffer buf) throws IOException
{
ByteBuffer ret = ByteBuffer.allocate(buf.remaining() + 1);
ret.put((byte) 0xFF); // proof that this endpoint got it
ret.put(buf);
ret.flip();
return ret;
}
}
@ServerEndpoint("/echo/bytearray")
public static class ByteArrayEchoSocket extends BaseSocket
{
@OnMessage
public byte[] onMessage(byte[] buf) throws IOException
{
byte ret[] = new byte[buf.length + 1];
ret[0] = (byte) 0xFE; // proof that this endpoint got it
System.arraycopy(buf, 0, ret, 1, buf.length);
return ret;
}
}
private static void addCase(List<Object[]> data, Class<?> endpointClass, String sendHex, String expectHex)
{
data.add(new Object[]{endpointClass.getSimpleName(), endpointClass, sendHex, expectHex});
}
@Parameterized.Parameters(name = "{0}: {2}")
public static List<Object[]> data()
{
List<Object[]> data = new ArrayList<>();
addCase(data, ByteBufferEchoSocket.class, "00", "FF00");
addCase(data, ByteBufferEchoSocket.class, "001133445566778899AA", "FF001133445566778899AA");
addCase(data, ByteBufferEchoSocket.class, "11112222333344445555", "FF11112222333344445555");
addCase(data, ByteArrayEchoSocket.class, "00", "FE00");
addCase(data, ByteArrayEchoSocket.class, "001133445566778899AA", "FE001133445566778899AA");
addCase(data, ByteArrayEchoSocket.class, "11112222333344445555", "FE11112222333344445555");
return data;
}
private static LocalServer server;
@BeforeClass
public static void startServer() throws Exception
{
server = new LocalServer()
{
@Override
protected void configureServletContextHandler(ServletContextHandler context) throws Exception
{
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
container.addEndpoint(ByteBufferEchoSocket.class);
container.addEndpoint(ByteArrayEchoSocket.class);
}
};
server.start();
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
}
@Parameterized.Parameter
public String endpointClassname;
@Parameterized.Parameter(1)
public Class<?> endpointClass;
@Parameterized.Parameter(2)
public String sendHex;
@Parameterized.Parameter(3)
public String expectHex;
@Test
public void testPrimitiveEcho() throws Exception
{
String requestPath = endpointClass.getAnnotation(ServerEndpoint.class).value();
List<WebSocketFrame> send = new ArrayList<>();
send.add(new BinaryFrame().setPayload(Hex.asByteBuffer(sendHex)));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new BinaryFrame().setPayload(Hex.asByteBuffer(expectHex)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer(requestPath))
{
session.sendBulk(send);
session.expect(expect);
}
}
}

View File

@ -0,0 +1,418 @@
//
// ========================================================================
// 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.server.jsr356;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.servlet.ServletContextHandler;
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.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.eclipse.jetty.websocket.tests.LocalServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
/**
* Test various {@link javax.websocket.Decoder.Text Decoder.Text} / {@link javax.websocket.Encoder.Text Encoder.Text} echo behavior of Java Primitives
*/
@RunWith(Parameterized.class)
public class PrimitivesTextEchoTest
{
private static final Logger LOG = Log.getLogger(PrimitivesTextEchoTest.class);
public static class BaseSocket
{
@OnError
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error", cause);
}
}
@ServerEndpoint("/echo/boolean")
public static class BooleanEchoSocket extends BaseSocket
{
@OnMessage
public boolean onMessage(boolean b) throws IOException
{
return b;
}
}
@ServerEndpoint("/echo/boolean-obj")
public static class BooleanObjEchoSocket extends BaseSocket
{
@OnMessage
public Boolean onMessage(Boolean b) throws IOException
{
return b;
}
}
@ServerEndpoint("/echo/byte")
public static class ByteEchoSocket extends BaseSocket
{
@OnMessage
public byte onMessage(byte b) throws IOException
{
return b;
}
}
@ServerEndpoint("/echo/byte-obj")
public static class ByteObjEchoSocket extends BaseSocket
{
@OnMessage
public byte onMessage(byte b) throws IOException
{
return b;
}
}
@ServerEndpoint("/echo/char")
public static class CharacterEchoSocket extends BaseSocket
{
@OnMessage
public char onMessage(char c) throws IOException
{
return c;
}
}
@ServerEndpoint("/echo/char-obj")
public static class CharacterObjEchoSocket extends BaseSocket
{
@OnMessage
public Character onMessage(Character c) throws IOException
{
return c;
}
}
@ServerEndpoint("/echo/double")
public static class DoubleEchoSocket extends BaseSocket
{
@OnMessage
public double onMessage(double d) throws IOException
{
return d;
}
}
@ServerEndpoint("/echo/double-obj")
public static class DoubleObjEchoSocket extends BaseSocket
{
@OnMessage
public Double onMessage(Double d) throws IOException
{
return d;
}
}
@ServerEndpoint("/echo/float")
public static class FloatEchoSocket extends BaseSocket
{
@OnMessage
public float onMessage(float f) throws IOException
{
return f;
}
}
@ServerEndpoint("/echo/float-obj")
public static class FloatObjEchoSocket extends BaseSocket
{
@OnMessage
public Float onMessage(Float f) throws IOException
{
return f;
}
}
@ServerEndpoint("/echo/short")
public static class ShortEchoSocket extends BaseSocket
{
@OnMessage
public short onMessage(short s) throws IOException
{
return s;
}
}
@ServerEndpoint("/echo/short-obj")
public static class ShortObjEchoSocket extends BaseSocket
{
@OnMessage
public Short onMessage(Short s) throws IOException
{
return s;
}
}
@ServerEndpoint("/echo/integer")
public static class IntegerEchoSocket extends BaseSocket
{
@OnMessage
public int onMessage(int i) throws IOException
{
return i;
}
}
@ServerEndpoint("/echo/integer-obj")
public static class IntegerObjEchoSocket extends BaseSocket
{
@OnMessage
public Integer onMessage(Integer i) throws IOException
{
return i;
}
}
@ServerEndpoint("/echo/long")
public static class LongEchoSocket extends BaseSocket
{
@OnMessage
public long onMessage(long l) throws IOException
{
return l;
}
}
@ServerEndpoint("/echo/long-obj")
public static class LongObjEchoSocket extends BaseSocket
{
@OnMessage
public Long onMessage(Long l) throws IOException
{
return l;
}
}
@ServerEndpoint("/echo/string")
public static class StringEchoSocket extends BaseSocket
{
@OnMessage
public String onMessage(String s) throws IOException
{
return s;
}
}
private static void addCase(List<Object[]> data, Class<?> endpointClass, String sendText, String expectText)
{
data.add(new Object[]{endpointClass.getSimpleName(), endpointClass, sendText, expectText});
}
@Parameterized.Parameters(name = "{0}: {2}")
public static List<Object[]> data()
{
List<Object[]> data = new ArrayList<>();
addCase(data, BooleanEchoSocket.class, "true", "true");
addCase(data, BooleanEchoSocket.class, "TRUE", "true");
addCase(data, BooleanEchoSocket.class, "false", "false");
addCase(data, BooleanEchoSocket.class, "FALSE", "false");
addCase(data, BooleanEchoSocket.class, "TRue", "true");
addCase(data, BooleanEchoSocket.class, Boolean.toString(Boolean.TRUE), "true");
addCase(data, BooleanEchoSocket.class, Boolean.toString(Boolean.FALSE), "false");
addCase(data, BooleanEchoSocket.class, "Apple", "false");
addCase(data, BooleanObjEchoSocket.class, "true", "true");
addCase(data, BooleanObjEchoSocket.class, "TRUE", "true");
addCase(data, BooleanObjEchoSocket.class, "false", "false");
addCase(data, BooleanObjEchoSocket.class, "FALSE", "false");
addCase(data, BooleanObjEchoSocket.class, "TRue", "true");
addCase(data, BooleanObjEchoSocket.class, Boolean.toString(Boolean.TRUE), "true");
addCase(data, BooleanObjEchoSocket.class, Boolean.toString(Boolean.FALSE), "false");
addCase(data, BooleanObjEchoSocket.class, "Apple", "false");
addCase(data, ByteEchoSocket.class, Byte.toString((byte)0x00), "0");
addCase(data, ByteEchoSocket.class, Byte.toString((byte)0x58), "88");
addCase(data, ByteEchoSocket.class, Byte.toString((byte)0x65), "101");
addCase(data, ByteEchoSocket.class, Byte.toString(Byte.MAX_VALUE), "127");
addCase(data, ByteEchoSocket.class, Byte.toString(Byte.MIN_VALUE), "-128");
addCase(data, ByteObjEchoSocket.class, Byte.toString((byte)0x00), "0");
addCase(data, ByteObjEchoSocket.class, Byte.toString((byte)0x58), "88");
addCase(data, ByteObjEchoSocket.class, Byte.toString((byte)0x65), "101");
addCase(data, ByteObjEchoSocket.class, Byte.toString(Byte.MAX_VALUE), "127");
addCase(data, ByteObjEchoSocket.class, Byte.toString(Byte.MIN_VALUE), "-128");
addCase(data, CharacterEchoSocket.class, Character.toString((char) 40), "(");
addCase(data, CharacterEchoSocket.class, Character.toString((char) 106), "j");
addCase(data, CharacterEchoSocket.class, Character.toString((char) 64), "@");
addCase(data, CharacterEchoSocket.class, Character.toString((char) 0x262f), "\u262f");
addCase(data, CharacterObjEchoSocket.class, Character.toString((char) 40), "(");
addCase(data, CharacterObjEchoSocket.class, Character.toString((char) 106), "j");
addCase(data, CharacterObjEchoSocket.class, Character.toString((char) 64), "@");
addCase(data, CharacterObjEchoSocket.class, Character.toString((char) 0x262f), "\u262f");
addCase(data, DoubleEchoSocket.class, Double.toString(3.1459), "3.1459");
addCase(data, DoubleEchoSocket.class, Double.toString(123.456), "123.456");
addCase(data, DoubleEchoSocket.class, Double.toString(55), "55.0");
addCase(data, DoubleEchoSocket.class, Double.toString(.123), "0.123");
addCase(data, DoubleEchoSocket.class, Double.toString(Double.MAX_VALUE), Double.toString(Double.MAX_VALUE));
addCase(data, DoubleEchoSocket.class, Double.toString(Double.MIN_VALUE), Double.toString(Double.MIN_VALUE));
addCase(data, DoubleObjEchoSocket.class, Double.toString(3.1459), "3.1459");
addCase(data, DoubleObjEchoSocket.class, Double.toString(123.456), "123.456");
addCase(data, DoubleObjEchoSocket.class, Double.toString(55), "55.0");
addCase(data, DoubleObjEchoSocket.class, Double.toString(.123), "0.123");
addCase(data, DoubleObjEchoSocket.class, Double.toString(Double.MAX_VALUE), Double.toString(Double.MAX_VALUE));
addCase(data, DoubleObjEchoSocket.class, Double.toString(Double.MIN_VALUE), Double.toString(Double.MIN_VALUE));
addCase(data, FloatEchoSocket.class, Float.toString(3.1459f), "3.1459");
addCase(data, FloatEchoSocket.class, Float.toString(0.0f), "0.0");
addCase(data, FloatEchoSocket.class, Float.toString(Float.MAX_VALUE), Float.toString(Float.MAX_VALUE));
addCase(data, FloatEchoSocket.class, Float.toString(Float.MIN_VALUE), Float.toString(Float.MIN_VALUE));
addCase(data, FloatObjEchoSocket.class, Float.toString(3.1459f), "3.1459");
addCase(data, FloatObjEchoSocket.class, Float.toString(0.0f), "0.0");
addCase(data, FloatObjEchoSocket.class, Float.toString(Float.MAX_VALUE), Float.toString(Float.MAX_VALUE));
addCase(data, FloatObjEchoSocket.class, Float.toString(Float.MIN_VALUE), Float.toString(Float.MIN_VALUE));
addCase(data, ShortEchoSocket.class, Short.toString((short) 0), "0");
addCase(data, ShortEchoSocket.class, Short.toString((short) 30000), "30000");
addCase(data, ShortEchoSocket.class, Short.toString(Short.MAX_VALUE), Short.toString(Short.MAX_VALUE));
addCase(data, ShortEchoSocket.class, Short.toString(Short.MIN_VALUE), Short.toString(Short.MIN_VALUE));
addCase(data, ShortObjEchoSocket.class, Short.toString((short) 0), "0");
addCase(data, ShortObjEchoSocket.class, Short.toString((short) 30000), "30000");
addCase(data, ShortObjEchoSocket.class, Short.toString(Short.MAX_VALUE), Short.toString(Short.MAX_VALUE));
addCase(data, ShortObjEchoSocket.class, Short.toString(Short.MIN_VALUE), Short.toString(Short.MIN_VALUE));
addCase(data, IntegerEchoSocket.class, Integer.toString(0), "0");
addCase(data, IntegerEchoSocket.class, Integer.toString(100_000), "100000");
addCase(data, IntegerEchoSocket.class, Integer.toString(-2_000_000), "-2000000");
addCase(data, IntegerEchoSocket.class, Integer.toString(Integer.MAX_VALUE), Integer.toString(Integer.MAX_VALUE));
addCase(data, IntegerEchoSocket.class, Integer.toString(Integer.MIN_VALUE), Integer.toString(Integer.MIN_VALUE));
addCase(data, IntegerObjEchoSocket.class, Integer.toString(0), "0");
addCase(data, IntegerObjEchoSocket.class, Integer.toString(100_000), "100000");
addCase(data, IntegerObjEchoSocket.class, Integer.toString(-2_000_000), "-2000000");
addCase(data, IntegerObjEchoSocket.class, Integer.toString(Integer.MAX_VALUE), Integer.toString(Integer.MAX_VALUE));
addCase(data, IntegerObjEchoSocket.class, Integer.toString(Integer.MIN_VALUE), Integer.toString(Integer.MIN_VALUE));
addCase(data, LongEchoSocket.class, Long.toString(0), "0");
addCase(data, LongEchoSocket.class, Long.toString(100_000), "100000");
addCase(data, LongEchoSocket.class, Long.toString(-2_000_000), "-2000000");
addCase(data, LongEchoSocket.class, Long.toString(300_000_000_000l), "300000000000");
addCase(data, LongEchoSocket.class, Long.toString(Long.MAX_VALUE), Long.toString(Long.MAX_VALUE));
addCase(data, LongEchoSocket.class, Long.toString(Long.MIN_VALUE), Long.toString(Long.MIN_VALUE));
addCase(data, LongObjEchoSocket.class, Long.toString(0), "0");
addCase(data, LongObjEchoSocket.class, Long.toString(100_000), "100000");
addCase(data, LongObjEchoSocket.class, Long.toString(-2_000_000), "-2000000");
addCase(data, LongObjEchoSocket.class, Long.toString(300_000_000_000l), "300000000000");
addCase(data, LongObjEchoSocket.class, Long.toString(Long.MAX_VALUE), Long.toString(Long.MAX_VALUE));
addCase(data, LongObjEchoSocket.class, Long.toString(Long.MIN_VALUE), Long.toString(Long.MIN_VALUE));
addCase(data, StringEchoSocket.class, "Hello World", "Hello World");
return data;
}
private static LocalServer server;
@BeforeClass
public static void startServer() throws Exception
{
server = new LocalServer()
{
@Override
protected void configureServletContextHandler(ServletContextHandler context) throws Exception
{
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
container.addEndpoint(BooleanEchoSocket.class);
container.addEndpoint(BooleanObjEchoSocket.class);
container.addEndpoint(ByteEchoSocket.class);
container.addEndpoint(ByteObjEchoSocket.class);
container.addEndpoint(CharacterEchoSocket.class);
container.addEndpoint(CharacterObjEchoSocket.class);
container.addEndpoint(DoubleEchoSocket.class);
container.addEndpoint(DoubleObjEchoSocket.class);
container.addEndpoint(FloatEchoSocket.class);
container.addEndpoint(FloatObjEchoSocket.class);
container.addEndpoint(ShortEchoSocket.class);
container.addEndpoint(ShortObjEchoSocket.class);
container.addEndpoint(IntegerEchoSocket.class);
container.addEndpoint(IntegerObjEchoSocket.class);
container.addEndpoint(LongEchoSocket.class);
container.addEndpoint(LongObjEchoSocket.class);
container.addEndpoint(StringEchoSocket.class);
}
};
server.start();
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
}
@Parameterized.Parameter
public String endpointClassname;
@Parameterized.Parameter(1)
public Class<?> endpointClass;
@Parameterized.Parameter(2)
public String sendText;
@Parameterized.Parameter(3)
public String expectText;
@Test
public void testPrimitiveEcho() throws Exception
{
String requestPath = endpointClass.getAnnotation(ServerEndpoint.class).value();
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(sendText));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(expectText));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer(requestPath))
{
session.sendBulk(send);
session.expect(expect);
}
}
}

View File

@ -0,0 +1,207 @@
//
// ========================================================================
// 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.server.jsr356;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.servlet.ServletContextHandler;
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.StatusCode;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.eclipse.jetty.websocket.tests.DataUtils;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.eclipse.jetty.websocket.tests.LocalServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
/**
* Test various {@link javax.websocket.Decoder.TextStream Decoder.TextStream} and {@link javax.websocket.Encoder.TextStream Encoder.TextStream} echo behavior of Java Readers
*/
public class ReaderEchoTest
{
private static final Logger LOG = Log.getLogger(ReaderEchoTest.class);
public static class BaseSocket
{
@OnError
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error", cause);
}
}
@SuppressWarnings("unused")
@ServerEndpoint("/echo/reader")
public static class ReaderSocket extends BaseSocket
{
@OnMessage
public String onReader(Reader reader) throws IOException
{
return IO.toString(reader);
}
}
@SuppressWarnings("unused")
@ServerEndpoint("/echo/reader-self")
public static class ReaderSelfSocket extends BaseSocket
{
@OnMessage
public Writer onReader(Session session, Reader reader) throws IOException
{
final Writer writer = session.getBasicRemote().getSendWriter();
new Thread(() ->
{
try
{
IO.copy(reader, writer);
}
catch (IOException e)
{
LOG.warn(e);
}
}).start();
return writer;
}
}
@SuppressWarnings("unused")
@ServerEndpoint("/echo/reader-param/{param}")
public static class ReaderParamSocket extends BaseSocket
{
@OnMessage
public String onReader(Reader reader, @PathParam("param") String param) throws IOException
{
StringBuilder msg = new StringBuilder();
msg.append(IO.toString(reader));
msg.append('|');
msg.append(param);
return msg.toString();
}
}
private static LocalServer server;
@BeforeClass
public static void startServer() throws Exception
{
server = new LocalServer()
{
@Override
protected void configureServletContextHandler(ServletContextHandler context) throws Exception
{
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
container.addEndpoint(ReaderSocket.class);
// TODO: container.addEndpoint(ReaderSelfSocket.class);
container.addEndpoint(ReaderParamSocket.class);
}
};
server.start();
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
}
@Test
public void testReaderSocket() throws Exception
{
String requestPath = "/echo/reader";
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload("Hello World"));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("Hello World"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer(requestPath))
{
session.sendBulk(send);
session.expect(expect);
}
}
@Test
@Ignore("TODO: Need Encoder for Writer?")
public void testReaderSelfSocket() throws Exception
{
String requestPath = "/echo/reader-self";
byte data[] = new byte[1024 * 1024];
Arrays.fill(data, (byte) 'x');
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(DataUtils.copyOf(data)));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(DataUtils.copyOf(data)));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer(requestPath))
{
session.sendBulk(send);
session.expect(expect);
}
}
@Test
public void testReaderParamSocket() throws Exception
{
String requestPath = "/echo/reader-param/Every%20Person";
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload("Hello World"));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("Hello World|Every Person"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer(requestPath))
{
session.sendBulk(send);
session.expect(expect);
}
}
}

View File

@ -0,0 +1,368 @@
//
// ========================================================================
// 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.server.jsr356;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.MessageHandler;
import javax.websocket.OnMessage;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.common.CloseInfo;
import org.eclipse.jetty.websocket.common.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.eclipse.jetty.websocket.tests.LocalServer;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class SessionTest
{
@ServerEndpoint(value = "/info/")
public static class SessionInfoSocket
{
@OnMessage
public String onMessage(javax.websocket.Session session, String message)
{
if ("pathParams".equalsIgnoreCase(message))
{
StringBuilder ret = new StringBuilder();
ret.append("pathParams");
Map<String, String> pathParams = session.getPathParameters();
if (pathParams == null)
{
ret.append("=<null>");
}
else
{
ret.append('[').append(pathParams.size()).append(']');
List<String> keys = new ArrayList<>();
for (String key : pathParams.keySet())
{
keys.add(key);
}
Collections.sort(keys);
for (String key : keys)
{
String value = pathParams.get(key);
ret.append(": '").append(key).append("'=").append(value);
}
}
return ret.toString();
}
if ("requestUri".equalsIgnoreCase(message))
{
StringBuilder ret = new StringBuilder();
ret.append("requestUri=");
URI uri = session.getRequestURI();
if (uri == null)
{
ret.append("=<null>");
}
else
{
ret.append(uri.toASCIIString());
}
return ret.toString();
}
// simple echo
return "echo:'" + message + "'";
}
}
public static class SessionInfoEndpoint extends Endpoint implements MessageHandler.Whole<String>
{
private javax.websocket.Session session;
@Override
public void onOpen(javax.websocket.Session session, EndpointConfig config)
{
this.session = session;
this.session.addMessageHandler(this);
}
@Override
public void onMessage(String message)
{
try
{
if ("pathParams".equalsIgnoreCase(message))
{
StringBuilder ret = new StringBuilder();
ret.append("pathParams");
Map<String, String> pathParams = session.getPathParameters();
if (pathParams == null)
{
ret.append("=<null>");
}
else
{
ret.append('[').append(pathParams.size()).append(']');
List<String> keys = new ArrayList<>();
for (String key : pathParams.keySet())
{
keys.add(key);
}
Collections.sort(keys);
for (String key : keys)
{
String value = pathParams.get(key);
ret.append(": '").append(key).append("'=").append(value);
}
}
session.getBasicRemote().sendText(ret.toString());
return;
}
if ("requestUri".equalsIgnoreCase(message))
{
StringBuilder ret = new StringBuilder();
ret.append("requestUri=");
URI uri = session.getRequestURI();
if (uri == null)
{
ret.append("=<null>");
}
else
{
ret.append(uri.toASCIIString());
}
session.getBasicRemote().sendText(ret.toString());
return;
}
// simple echo
session.getBasicRemote().sendText("echo:'" + message + "'");
}
catch (IOException e)
{
e.printStackTrace(System.err);
}
}
}
private interface Case
{
void customize(ServletContextHandler context);
}
@Parameters
public static Collection<Case[]> data()
{
List<Case[]> cases = new ArrayList<>();
cases.add(new Case[]
{context ->
{
// no customization
}});
cases.add(new Case[]
{context ->
{
// Test with DefaultServlet only
context.addServlet(DefaultServlet.class,"/");
}});
cases.add(new Case[]
{context ->
{
// Test with Servlet mapped to "/*"
context.addServlet(DefaultServlet.class,"/*");
}});
cases.add(new Case[]
{context ->
{
// Test with Servlet mapped to "/info/*"
context.addServlet(DefaultServlet.class,"/info/*");
}});
return cases;
}
private LocalServer server;
@After
public void stopServer() throws Exception
{
server.stop();
}
public SessionTest(final Case testcase) throws Exception
{
server = new LocalServer()
{
@Override
protected void configureServletContextHandler(ServletContextHandler context) throws Exception
{
testcase.customize(context);
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
container.addEndpoint(SessionInfoSocket.class); // default behavior
Class<?> endpointClass = SessionInfoSocket.class;
container.addEndpoint(ServerEndpointConfig.Builder.create(endpointClass,"/info/{a}/").build());
container.addEndpoint(ServerEndpointConfig.Builder.create(endpointClass,"/info/{a}/{b}/").build());
container.addEndpoint(ServerEndpointConfig.Builder.create(endpointClass,"/info/{a}/{b}/{c}/").build());
container.addEndpoint(ServerEndpointConfig.Builder.create(endpointClass,"/info/{a}/{b}/{c}/{d}/").build());
endpointClass = SessionInfoEndpoint.class;
container.addEndpoint(ServerEndpointConfig.Builder.create(endpointClass,"/einfo/").build());
container.addEndpoint(ServerEndpointConfig.Builder.create(endpointClass,"/einfo/{a}/").build());
container.addEndpoint(ServerEndpointConfig.Builder.create(endpointClass,"/einfo/{a}/{b}/").build());
container.addEndpoint(ServerEndpointConfig.Builder.create(endpointClass,"/einfo/{a}/{b}/{c}/").build());
container.addEndpoint(ServerEndpointConfig.Builder.create(endpointClass,"/einfo/{a}/{b}/{c}/{d}/").build());
}
};
server.start();
}
private void assertResponse(String requestPath, String requestMessage,
String expectedResponse) throws Exception
{
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(requestMessage));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload(expectedResponse));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer(requestPath))
{
session.sendBulk(send);
session.expect(expect);
}
}
@Test
public void testPathParams_Annotated_Empty() throws Exception
{
assertResponse("/info/","pathParams",
"pathParams[0]");
}
@Test
public void testPathParams_Annotated_Single() throws Exception
{
assertResponse("/info/apple/","pathParams",
"pathParams[1]: 'a'=apple");
}
@Test
public void testPathParams_Annotated_Double() throws Exception
{
assertResponse("/info/apple/pear/","pathParams",
"pathParams[2]: 'a'=apple: 'b'=pear");
}
@Test
public void testPathParams_Annotated_Triple() throws Exception
{
assertResponse("/info/apple/pear/cherry/","pathParams",
"pathParams[3]: 'a'=apple: 'b'=pear: 'c'=cherry");
}
@Test
public void testPathParams_Endpoint_Empty() throws Exception
{
assertResponse("/einfo/","pathParams",
"pathParams[0]");
}
@Test
public void testPathParams_Endpoint_Single() throws Exception
{
assertResponse("/einfo/apple/","pathParams",
"pathParams[1]: 'a'=apple");
}
@Test
public void testPathParams_Endpoint_Double() throws Exception
{
assertResponse("/einfo/apple/pear/","pathParams",
"pathParams[2]: 'a'=apple: 'b'=pear");
}
@Test
public void testPathParams_Endpoint_Triple() throws Exception
{
assertResponse("/einfo/apple/pear/cherry/","pathParams",
"pathParams[3]: 'a'=apple: 'b'=pear: 'c'=cherry");
}
@Test
public void testRequestUri_Annotated_Basic() throws Exception
{
assertResponse("/info/","requestUri",
"requestUri=ws://local/info/");
}
@Test
public void testRequestUri_Annotated_WithPathParam() throws Exception
{
assertResponse("/info/apple/banana/","requestUri",
"requestUri=ws://local/info/apple/banana/");
}
@Test
public void testRequestUri_Annotated_WithPathParam_WithQuery() throws Exception
{
assertResponse("/info/apple/banana/?fruit=fresh&store=grandmasfarm",
"requestUri",
"requestUri=ws://local/info/apple/banana/?fruit=fresh&store=grandmasfarm");
}
@Test
public void testRequestUri_Endpoint_Basic() throws Exception
{
assertResponse("/einfo/","requestUri",
"requestUri=ws://local/einfo/");
}
@Test
public void testRequestUri_Endpoint_WithPathParam() throws Exception
{
assertResponse("/einfo/apple/banana/","requestUri",
"requestUri=ws://local/einfo/apple/banana/");
}
@Test
public void testRequestUri_Endpoint_WithPathParam_WithQuery() throws Exception
{
assertResponse("/einfo/apple/banana/?fruit=fresh&store=grandmasfarm",
"requestUri",
"requestUri=ws://local/einfo/apple/banana/?fruit=fresh&store=grandmasfarm");
}
}

View File

@ -0,0 +1,156 @@
//
// ========================================================================
// 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.server.jsr356;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.servlet.ServletContextHandler;
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.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.eclipse.jetty.websocket.tests.DataUtils;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.eclipse.jetty.websocket.tests.LocalServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class TextStreamTest
{
private static final String PATH = "/echo";
private static final String CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private static LocalServer server;
private static ServerContainer container;
@BeforeClass
public static void startServer() throws Exception
{
server = new LocalServer()
{
@Override
protected void configureServletContextHandler(ServletContextHandler context) throws Exception
{
container = WebSocketServerContainerInitializer.configureContext(context);
ServerEndpointConfig config = ServerEndpointConfig.Builder.create(ServerTextStreamer.class, PATH).build();
container.addEndpoint(config);
}
};
server.start();
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
}
@Test
public void testEchoWithMediumMessage() throws Exception
{
testEcho(1024);
}
@Test
public void testLargestMessage() throws Exception
{
testEcho(container.getDefaultMaxTextMessageBufferSize());
}
private byte[] newData(int size)
{
byte[] pattern = "01234567890abcdefghijlklmopqrstuvwxyz".getBytes(StandardCharsets.UTF_8);
byte[] data = new byte[size];
for (int i = 0; i < size; i++)
{
data[i] = pattern[i % pattern.length];
}
return data;
}
private void testEcho(int size) throws Exception
{
byte[] data = newData(size);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(ByteBuffer.wrap(data)));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
ByteBuffer expectedMessage = DataUtils.copyOf(data);
try (LocalFuzzer session = server.newLocalFuzzer("/echo"))
{
session.sendBulk(send);
BlockingQueue<WebSocketFrame> receivedFrames = session.getOutputFrames();
session.expectMessage(receivedFrames, OpCode.TEXT, expectedMessage);
}
}
@Test
public void testMoreThanLargestMessageOneByteAtATime() throws Exception
{
int size = container.getDefaultMaxTextMessageBufferSize() + 16;
byte[] data = newData(size);
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload(ByteBuffer.wrap(data)));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
ByteBuffer expectedMessage = DataUtils.copyOf(data);
try (LocalFuzzer session = server.newLocalFuzzer("/echo"))
{
session.sendBulk(send);
BlockingQueue<WebSocketFrame> receivedFrames = session.getOutputFrames();
session.expectMessage(receivedFrames, OpCode.TEXT, expectedMessage);
}
}
@ServerEndpoint(PATH)
public static class ServerTextStreamer
{
@OnMessage
public void echo(Session session, Reader input) throws IOException
{
char[] buffer = new char[128];
try (Writer output = session.getBasicRemote().getSendWriter())
{
int read;
while ((read = input.read(buffer)) >= 0)
output.write(buffer, 0, read);
}
}
}
}

View File

@ -0,0 +1,107 @@
//
// ========================================================================
// 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.server.jsr356;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.servlet.ServletContextHandler;
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.WebSocketFrame;
import org.eclipse.jetty.websocket.common.frames.TextFrame;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.eclipse.jetty.websocket.tests.LocalFuzzer;
import org.eclipse.jetty.websocket.tests.LocalServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class UriTemplateParameterTest
{
private static final Logger LOG = Log.getLogger(UriTemplateParameterTest.class);
@ServerEndpoint("/echo/params/{a}/{b}")
public static class IntParamTextSocket
{
@OnMessage
public String onMessage(int i, @PathParam("a") int paramA, @PathParam("b") int paramB) throws IOException
{
return String.format("%,d|%,d|%,d", i, paramA, paramB);
}
@OnError
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error", cause);
}
}
private static LocalServer server;
@BeforeClass
public static void startServer() throws Exception
{
server = new LocalServer()
{
@Override
protected void configureServletContextHandler(ServletContextHandler context) throws Exception
{
ServerContainer container = WebSocketServerContainerInitializer.configureContext(context);
container.addEndpoint(IntParamTextSocket.class);
}
};
server.start();
}
@AfterClass
public static void stopServer() throws Exception
{
server.stop();
}
@Test
public void testIntParams() throws Exception
{
String requestPath = "/echo/params/1234/5678";
List<WebSocketFrame> send = new ArrayList<>();
send.add(new TextFrame().setPayload("9999"));
send.add(new CloseInfo(StatusCode.NORMAL).asFrame());
List<WebSocketFrame> expect = new ArrayList<>();
expect.add(new TextFrame().setPayload("9,999|1,234|5,678"));
expect.add(new CloseInfo(StatusCode.NORMAL).asFrame());
try (LocalFuzzer session = server.newLocalFuzzer(requestPath))
{
session.sendBulk(send);
session.expect(expect);
}
}
}

View File

@ -16,7 +16,7 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356.server.samples.beans;
package org.eclipse.jetty.websocket.tests.server.jsr356.coders;
import java.text.ParseException;
import java.text.SimpleDateFormat;

View File

@ -16,7 +16,7 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356.server.samples.beans;
package org.eclipse.jetty.websocket.tests.server.jsr356.coders;
import java.text.SimpleDateFormat;
import java.util.Date;

View File

@ -16,7 +16,7 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356.server.samples.beans;
package org.eclipse.jetty.websocket.tests.server.jsr356.coders;
import java.text.ParseException;
import java.text.SimpleDateFormat;

View File

@ -16,7 +16,7 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356.server.samples.beans;
package org.eclipse.jetty.websocket.tests.server.jsr356.coders;
import java.text.SimpleDateFormat;
import java.util.Date;

View File

@ -16,7 +16,7 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356.server.samples.beans;
package org.eclipse.jetty.websocket.tests.server.jsr356.coders;
import java.text.ParseException;
import java.text.SimpleDateFormat;

View File

@ -16,7 +16,7 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356.server.samples.beans;
package org.eclipse.jetty.websocket.tests.server.jsr356.coders;
import java.text.SimpleDateFormat;
import java.util.Date;

View File

@ -16,7 +16,7 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356.server.samples.echo;
package org.eclipse.jetty.websocket.tests.server.jsr356.configs;
import java.util.Collections;

View File

@ -16,17 +16,22 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.tests;
package org.eclipse.jetty.websocket.tests.server.jsr356.sockets;
import java.net.URI;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.websocket.common.Generator;
public interface Fuzzed
/**
* Annotated echo socket
*/
@ServerEndpoint("/echo")
public class BasicEchoSocket
{
URI getServerURI();
Generator getLaxGenerator();
String getTestMethodName();
@OnMessage
public void echo(Session session, String msg)
{
// reply with echo
session.getAsyncRemote().sendText(msg);
}
}

View File

@ -0,0 +1,51 @@
//
// ========================================================================
// 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.server.jsr356.sockets;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ServerEndpoint("/echo/binary/bytebuffer")
public class ByteBufferSocket
{
private static final Logger LOG = Log.getLogger(ByteBufferSocket.class);
@OnMessage
public String onByteBuffer(ByteBuffer bbuf)
{
return BufferUtil.toUTF8String(bbuf);
}
@OnError
public void onError(Session session, Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

View File

@ -16,15 +16,13 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356.server.samples.echo;
package org.eclipse.jetty.websocket.tests.server.jsr356.sockets;
import static java.util.Comparator.naturalOrder;
import static java.util.stream.Collectors.joining;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import javax.websocket.EndpointConfig;
import javax.websocket.OnMessage;
@ -33,8 +31,9 @@ import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;
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.tests.server.jsr356.coders.DateDecoder;
import org.eclipse.jetty.websocket.tests.server.jsr356.coders.TimeEncoder;
import org.eclipse.jetty.websocket.tests.server.jsr356.configs.EchoSocketConfigurator;
/**
* Annotated echo socket, using all of the annotation configurations
@ -51,6 +50,7 @@ public class ConfiguredEchoSocket
private EndpointConfig config;
private ServerEndpointConfig serverConfig;
@SuppressWarnings("unused")
@OnOpen
public void onOpen(Session session, EndpointConfig config)
{
@ -61,7 +61,8 @@ public class ConfiguredEchoSocket
this.serverConfig = (ServerEndpointConfig)config;
}
}
@SuppressWarnings("unused")
@OnMessage(maxMessageSize = 111222)
public String echoText(String msg)
{
@ -72,9 +73,9 @@ public class ConfiguredEchoSocket
case "binary-max":
return String.format(Locale.US, "%,d",session.getMaxBinaryMessageBufferSize());
case "decoders":
return join(config.getDecoders(),", ");
return config.getDecoders().stream().map(Class::getName).collect(joining(", "));
case "encoders":
return join(config.getEncoders(),", ");
return config.getEncoders().stream().map(Class::getName).collect(joining(", "));
case "subprotocols":
if (serverConfig == null)
{
@ -82,10 +83,7 @@ public class ConfiguredEchoSocket
}
else
{
List<String> protocols = new ArrayList<>();
protocols.addAll(serverConfig.getSubprotocols());
Collections.sort(protocols);
return join(protocols,", ");
return serverConfig.getSubprotocols().stream().sorted(naturalOrder()).collect(joining(", "));
}
case "configurator":
if (serverConfig == null)
@ -102,23 +100,7 @@ public class ConfiguredEchoSocket
}
}
private String join(Collection<?> coll, String delim)
{
StringBuilder buf = new StringBuilder();
boolean needDelim = false;
for (Object obj : coll)
{
if (needDelim)
{
buf.append(delim);
}
buf.append(Objects.toString(obj));
needDelim = true;
}
return buf.toString();
}
@SuppressWarnings("unused")
@OnMessage(maxMessageSize = 333444)
public ByteBuffer echoBinary(ByteBuffer buf)
{

View File

@ -16,7 +16,7 @@
// ========================================================================
//
package org.eclipse.jetty.websocket.jsr356.server.samples.beans;
package org.eclipse.jetty.websocket.tests.server.jsr356.sockets;
import java.io.IOException;
import java.util.Date;
@ -27,9 +27,11 @@ import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.toolchain.test.StackUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.util.StackUtil;
import org.eclipse.jetty.websocket.tests.server.jsr356.coders.DateDecoder;
import org.eclipse.jetty.websocket.tests.server.jsr356.coders.DateEncoder;
@ServerEndpoint(value = "/echo/beans/date", decoders = { DateDecoder.class }, encoders = { DateEncoder.class })
public class DateTextSocket
@ -63,6 +65,6 @@ public class DateTextSocket
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
session.getBasicRemote().sendText("Exception: " + StackUtils.toString(cause));
}
}

Some files were not shown because too many files have changed in this diff Show More