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:
parent
4a4069d0c2
commit
79f30041a1
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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++)
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
|
@ -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
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
{
|
|
@ -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
Loading…
Reference in New Issue